From ef6a815b4ca3dddfca73677e5cd3a5cb7d577030 Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Thu, 10 Jul 2025 14:01:42 +0200 Subject: [PATCH] bluetooth check --- .../java/com/bitchat/android/MainActivity.kt | 63 ++++++++++++++----- .../onboarding/BluetoothStatusManager.kt | 40 +++++++++--- 2 files changed, 80 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/com/bitchat/android/MainActivity.kt b/app/src/main/java/com/bitchat/android/MainActivity.kt index 99981280..a1f5390c 100644 --- a/app/src/main/java/com/bitchat/android/MainActivity.kt +++ b/app/src/main/java/com/bitchat/android/MainActivity.kt @@ -158,8 +158,17 @@ class MainActivity : ComponentActivity() { */ private fun checkBluetoothAndProceed() { android.util.Log.d("MainActivity", "Checking Bluetooth status") - bluetoothStatusManager.logBluetoothStatus() + // For first-time users, skip Bluetooth check and go straight to permissions + // We'll check Bluetooth after permissions are granted + if (permissionManager.isFirstTimeLaunch()) { + android.util.Log.d("MainActivity", "First-time launch, skipping Bluetooth check - will check after permissions") + proceedWithPermissionCheck() + return + } + + // For existing users, check Bluetooth status first + bluetoothStatusManager.logBluetoothStatus() bluetoothStatus = bluetoothStatusManager.checkBluetoothStatus() when (bluetoothStatus) { @@ -168,7 +177,7 @@ class MainActivity : ComponentActivity() { proceedWithPermissionCheck() } BluetoothStatus.DISABLED -> { - // Show Bluetooth enable screen + // Show Bluetooth enable screen (should have permissions as existing user) android.util.Log.d("MainActivity", "Bluetooth disabled, showing enable screen") onboardingState = OnboardingState.BLUETOOTH_CHECK isBluetoothLoading = false @@ -183,10 +192,10 @@ class MainActivity : ComponentActivity() { } /** - * Proceed with permission checking after Bluetooth is confirmed enabled + * Proceed with permission checking */ private fun proceedWithPermissionCheck() { - android.util.Log.d("MainActivity", "Bluetooth enabled, checking permissions") + android.util.Log.d("MainActivity", "Proceeding with permission check") lifecycleScope.launch { delay(200) // Small delay for smooth transition @@ -223,20 +232,46 @@ class MainActivity : ComponentActivity() { isBluetoothLoading = false bluetoothStatus = bluetoothStatusManager.checkBluetoothStatus() - if (bluetoothStatus == BluetoothStatus.NOT_SUPPORTED) { - // Show permanent error for unsupported devices - errorMessage = message - onboardingState = OnboardingState.ERROR - } else { - // Stay on Bluetooth check screen for retry - onboardingState = OnboardingState.BLUETOOTH_CHECK + when { + bluetoothStatus == BluetoothStatus.NOT_SUPPORTED -> { + // Show permanent error for unsupported devices + errorMessage = message + onboardingState = OnboardingState.ERROR + } + message.contains("Permission") && permissionManager.isFirstTimeLaunch() -> { + // During first-time onboarding, if Bluetooth enable fails due to permissions, + // proceed to permission explanation screen where user will grant permissions first + android.util.Log.d("MainActivity", "Bluetooth enable requires permissions, proceeding to permission explanation") + proceedWithPermissionCheck() + } + message.contains("Permission") -> { + // For existing users, redirect to permission explanation to grant missing permissions + android.util.Log.d("MainActivity", "Bluetooth enable requires permissions, showing permission explanation") + onboardingState = OnboardingState.PERMISSION_EXPLANATION + } + else -> { + // Stay on Bluetooth check screen for retry + onboardingState = OnboardingState.BLUETOOTH_CHECK + } } } private fun handleOnboardingComplete() { - android.util.Log.d("MainActivity", "Onboarding completed, initializing app") - onboardingState = OnboardingState.INITIALIZING - initializeApp() + android.util.Log.d("MainActivity", "Onboarding completed, checking Bluetooth again before initializing app") + + // After permissions are granted, re-check Bluetooth status + val currentBluetoothStatus = bluetoothStatusManager.checkBluetoothStatus() + if (currentBluetoothStatus == BluetoothStatus.ENABLED) { + // Bluetooth is enabled, proceed to app initialization + onboardingState = OnboardingState.INITIALIZING + initializeApp() + } else { + // Bluetooth still disabled, but now we have permissions to enable it + android.util.Log.d("MainActivity", "Permissions granted, but Bluetooth still disabled. Showing Bluetooth enable screen.") + bluetoothStatus = currentBluetoothStatus + onboardingState = OnboardingState.BLUETOOTH_CHECK + isBluetoothLoading = false + } } private fun handleOnboardingFailed(message: String) { diff --git a/app/src/main/java/com/bitchat/android/onboarding/BluetoothStatusManager.kt b/app/src/main/java/com/bitchat/android/onboarding/BluetoothStatusManager.kt index 32fc2193..b580ccdf 100644 --- a/app/src/main/java/com/bitchat/android/onboarding/BluetoothStatusManager.kt +++ b/app/src/main/java/com/bitchat/android/onboarding/BluetoothStatusManager.kt @@ -71,14 +71,23 @@ class BluetoothStatusManager( } /** - * Check if Bluetooth is currently enabled + * Check if Bluetooth is currently enabled (permission-safe) */ fun isBluetoothEnabled(): Boolean { - return bluetoothAdapter?.isEnabled == true + return try { + bluetoothAdapter?.isEnabled == true + } catch (securityException: SecurityException) { + // If we can't check due to permissions, assume disabled + Log.w(TAG, "Cannot check Bluetooth enabled state due to missing permissions") + false + } catch (e: Exception) { + Log.w(TAG, "Error checking Bluetooth enabled state: ${e.message}") + false + } } /** - * Check Bluetooth status and handle accordingly + * Check Bluetooth status and handle accordingly (permission-safe) * This should be called on every app startup */ fun checkBluetoothStatus(): BluetoothStatus { @@ -89,8 +98,8 @@ class BluetoothStatusManager( Log.e(TAG, "Bluetooth not supported on this device") BluetoothStatus.NOT_SUPPORTED } - !bluetoothAdapter!!.isEnabled -> { - Log.w(TAG, "Bluetooth is disabled") + !isBluetoothEnabled() -> { + Log.w(TAG, "Bluetooth is disabled or cannot be checked") BluetoothStatus.DISABLED } else -> { @@ -101,7 +110,7 @@ class BluetoothStatusManager( } /** - * Request user to enable Bluetooth + * Request user to enable Bluetooth (permission-aware) */ fun requestEnableBluetooth() { Log.d(TAG, "Requesting user to enable Bluetooth") @@ -109,6 +118,10 @@ class BluetoothStatusManager( try { val enableBluetoothIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) bluetoothEnableLauncher?.launch(enableBluetoothIntent) + } catch (securityException: SecurityException) { + // Permission not granted yet - this is expected during onboarding + Log.w(TAG, "Cannot request Bluetooth enable due to missing BLUETOOTH_CONNECT permission") + onBluetoothDisabled("Bluetooth permissions are required before enabling Bluetooth. Please grant permissions first.") } catch (e: Exception) { Log.e(TAG, "Failed to request Bluetooth enable", e) onBluetoothDisabled("Failed to request Bluetooth enable: ${e.message}") @@ -147,7 +160,7 @@ class BluetoothStatusManager( } /** - * Get detailed diagnostics + * Get detailed diagnostics (permission-safe) */ fun getDiagnostics(): String { return buildString { @@ -157,9 +170,18 @@ class BluetoothStatusManager( appendLine("Bluetooth enabled: ${isBluetoothEnabled()}") appendLine("Current status: ${checkBluetoothStatus()}") + // Only access adapter details if we have permission and adapter is available bluetoothAdapter?.let { adapter -> - appendLine("Adapter name: ${adapter.name ?: "Unknown"}") - appendLine("Adapter address: ${adapter.address ?: "Unknown"}") + try { + // These calls require BLUETOOTH_CONNECT permission on Android 12+ + appendLine("Adapter name: ${adapter.name ?: "Unknown"}") + appendLine("Adapter address: ${adapter.address ?: "Unknown"}") + } catch (securityException: SecurityException) { + // Permission not granted yet, skip detailed info + appendLine("Adapter details: [Permission required]") + } catch (e: Exception) { + appendLine("Adapter details: [Error: ${e.message}]") + } appendLine("Adapter state: ${getAdapterStateName(adapter.state)}") } }