diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 700655fe..e0b7ed00 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -13,8 +13,8 @@ android { applicationId = "com.bitchat.droid" minSdk = libs.versions.minSdk.get().toInt() targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = 33 - versionName = "1.7.2" + versionCode = 35 + versionName = "1.7.4" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { diff --git a/app/src/main/java/com/bitchat/android/BitchatApplication.kt b/app/src/main/java/com/bitchat/android/BitchatApplication.kt index 5d885099..ed75eb33 100644 --- a/app/src/main/java/com/bitchat/android/BitchatApplication.kt +++ b/app/src/main/java/com/bitchat/android/BitchatApplication.kt @@ -46,7 +46,7 @@ class BitchatApplication : Application() { // Initialize Wi‑Fi Aware controller with persisted default try { - val enabled = com.bitchat.android.ui.debug.DebugPreferenceManager.getWifiAwareEnabled(true) + val enabled = com.bitchat.android.ui.debug.DebugPreferenceManager.getWifiAwareEnabled(false) com.bitchat.android.wifiaware.WifiAwareController.initialize(this, enabled) } catch (_: Exception) { } diff --git a/app/src/main/java/com/bitchat/android/MainActivity.kt b/app/src/main/java/com/bitchat/android/MainActivity.kt index 3e6b482e..2345549e 100644 --- a/app/src/main/java/com/bitchat/android/MainActivity.kt +++ b/app/src/main/java/com/bitchat/android/MainActivity.kt @@ -59,6 +59,7 @@ class MainActivity : OrientationAwareActivity() { private lateinit var meshService: BluetoothMeshService private lateinit var unifiedMeshService: MeshService private val mainViewModel: MainViewModel by viewModels() + private var pendingMeshForegroundServiceStart = false private val chatViewModel: ChatViewModel by viewModels { object : ViewModelProvider.Factory { override fun create(modelClass: Class): T { @@ -114,8 +115,8 @@ class MainActivity : OrientationAwareActivity() { // Initialize permission management permissionManager = PermissionManager(this) - // Ensure foreground service is running and get mesh instance from holder - try { com.bitchat.android.service.MeshForegroundService.start(applicationContext) } catch (_: Exception) { } + // Start the foreground service when allowed, then get mesh instances from the holder. + startMeshForegroundServiceBestEffort() meshService = com.bitchat.android.service.MeshServiceHolder.getOrCreate(applicationContext) unifiedMeshService = com.bitchat.android.service.MeshServiceHolder.getUnifiedOrCreate(applicationContext) // Expose BLE mesh to Wi‑Fi Aware controller for cross-transport relays - DEPRECATED @@ -614,6 +615,22 @@ class MainActivity : OrientationAwareActivity() { mainViewModel.updateErrorMessage(message) mainViewModel.updateOnboardingState(OnboardingState.ERROR) } + + private fun startMeshForegroundServiceBestEffort() { + if (!lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) { + pendingMeshForegroundServiceStart = true + Log.i("MainActivity", "Deferring foreground mesh service start until activity is started") + return + } + + try { + com.bitchat.android.service.MeshForegroundService.start(applicationContext) + pendingMeshForegroundServiceStart = false + } catch (e: Exception) { + pendingMeshForegroundServiceStart = true + Log.w("MainActivity", "Unable to start foreground mesh service; will retry when activity is started", e) + } + } /** * Check Battery Optimization status and proceed with onboarding flow @@ -715,6 +732,7 @@ class MainActivity : OrientationAwareActivity() { // Set up unified mesh delegate and start enabled transports unifiedMeshService.delegate = chatViewModel unifiedMeshService.startServices() + startMeshForegroundServiceBestEffort() Log.d("MainActivity", "Mesh service started successfully") @@ -752,6 +770,13 @@ class MainActivity : OrientationAwareActivity() { handleVerificationIntent(intent) } } + + override fun onStart() { + super.onStart() + if (pendingMeshForegroundServiceStart) { + startMeshForegroundServiceBestEffort() + } + } override fun onResume() { super.onResume() diff --git a/app/src/main/java/com/bitchat/android/onboarding/PermissionManager.kt b/app/src/main/java/com/bitchat/android/onboarding/PermissionManager.kt index 8fcf9c31..e7e02203 100644 --- a/app/src/main/java/com/bitchat/android/onboarding/PermissionManager.kt +++ b/app/src/main/java/com/bitchat/android/onboarding/PermissionManager.kt @@ -26,9 +26,9 @@ class PermissionManager(private val context: Context) { private fun shouldRequireWifiAwarePermission(): Boolean { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) return false val enabled = try { - com.bitchat.android.ui.debug.DebugPreferenceManager.getWifiAwareEnabled(true) + com.bitchat.android.ui.debug.DebugPreferenceManager.getWifiAwareEnabled(false) } catch (_: Exception) { - true + false } if (!enabled) return false diff --git a/app/src/main/java/com/bitchat/android/service/MeshForegroundService.kt b/app/src/main/java/com/bitchat/android/service/MeshForegroundService.kt index 218631ea..d9ad2d7f 100644 --- a/app/src/main/java/com/bitchat/android/service/MeshForegroundService.kt +++ b/app/src/main/java/com/bitchat/android/service/MeshForegroundService.kt @@ -38,24 +38,20 @@ class MeshForegroundService : Service() { fun start(context: Context) { val intent = Intent(context, MeshForegroundService::class.java).apply { action = ACTION_START } - // On API >= 26, avoid background-service start restrictions by using startForegroundService - // only when we can actually post a notification (Android 13+ requires runtime notif permission) - val bgEnabled = MeshServicePreferences.isBackgroundEnabled(true) - val hasNotifPerm = hasNotificationPermissionStatic(context) + // Only launch as an FGS when onStartCommand can promote immediately. + val shouldStartForeground = shouldStartAsForeground(context) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - if (bgEnabled && hasNotifPerm) { + if (shouldStartForeground) { context.startForegroundService(intent) } else { - // Do not attempt to start a background service from headless context without notif permission - // or when background is disabled, to avoid BackgroundServiceStartNotAllowedException. android.util.Log.i( "MeshForegroundService", - "Not starting service on API>=26 (bgEnabled=$bgEnabled, hasNotifPerm=$hasNotifPerm)" + "Not starting service on API>=26 (shouldStartForeground=$shouldStartForeground)" ) } } else { - if (bgEnabled) { + if (MeshServicePreferences.isBackgroundEnabled(true)) { context.startService(intent) } else { android.util.Log.i("MeshForegroundService", "Background disabled; not starting service (pre-O)") @@ -69,12 +65,10 @@ class MeshForegroundService : Service() { */ fun onNotificationPermissionGranted(context: Context) { // If background is enabled and permission now granted, start/promo service - val hasNotifPerm = hasNotificationPermissionStatic(context) - if (!MeshServicePreferences.isBackgroundEnabled(true) || !hasNotifPerm) return + if (!shouldStartAsForeground(context)) return val intent = Intent(context, MeshForegroundService::class.java).apply { action = ACTION_UPDATE_NOTIFICATION } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - // Safe now that we can show a notification context.startForegroundService(intent) } else { context.startService(intent) diff --git a/app/src/main/java/com/bitchat/android/ui/debug/DebugPreferenceManager.kt b/app/src/main/java/com/bitchat/android/ui/debug/DebugPreferenceManager.kt index f03df3da..2d734c14 100644 --- a/app/src/main/java/com/bitchat/android/ui/debug/DebugPreferenceManager.kt +++ b/app/src/main/java/com/bitchat/android/ui/debug/DebugPreferenceManager.kt @@ -113,7 +113,7 @@ object DebugPreferenceManager { if (ready()) prefs.edit().putBoolean(KEY_BLE_ENABLED, value).apply() } - fun getWifiAwareEnabled(default: Boolean = true): Boolean = + fun getWifiAwareEnabled(default: Boolean = false): Boolean = if (ready()) prefs.getBoolean(KEY_WIFI_AWARE_ENABLED, default) else default fun setWifiAwareEnabled(value: Boolean) { diff --git a/app/src/main/java/com/bitchat/android/ui/debug/DebugSettingsManager.kt b/app/src/main/java/com/bitchat/android/ui/debug/DebugSettingsManager.kt index 82bc7fc2..80910b15 100644 --- a/app/src/main/java/com/bitchat/android/ui/debug/DebugSettingsManager.kt +++ b/app/src/main/java/com/bitchat/android/ui/debug/DebugSettingsManager.kt @@ -44,7 +44,7 @@ class DebugSettingsManager private constructor() { private val _bleEnabled = MutableStateFlow(true) val bleEnabled: StateFlow = _bleEnabled.asStateFlow() - private val _wifiAwareEnabled = MutableStateFlow(true) + private val _wifiAwareEnabled = MutableStateFlow(false) val wifiAwareEnabled: StateFlow = _wifiAwareEnabled.asStateFlow() // Master transport toggles @@ -76,7 +76,7 @@ class DebugSettingsManager private constructor() { _maxClientConnections.value = DebugPreferenceManager.getMaxConnectionsClient(8) // Transport toggles _bleEnabled.value = DebugPreferenceManager.getBleEnabled(true) - _wifiAwareEnabled.value = DebugPreferenceManager.getWifiAwareEnabled(true) + _wifiAwareEnabled.value = DebugPreferenceManager.getWifiAwareEnabled(false) _wifiAwareVerbose.value = DebugPreferenceManager.getWifiAwareVerbose(false) } catch (_: Exception) { // Preferences not ready yet; keep defaults. They will be applied on first change.