sforkowany z mirror/meshtastic-android
				
			update targetSdkVersion to 31
							rodzic
							
								
									cbb8e5f7db
								
							
						
					
					
						commit
						00de511907
					
				|  | @ -42,7 +42,7 @@ android { | |||
|     defaultConfig { | ||||
|         applicationId "com.geeksville.mesh" | ||||
|         minSdkVersion 21 // The oldest emulator image I have tried is 22 (though 21 probably works) | ||||
|         targetSdkVersion 30 | ||||
|         targetSdkVersion 31 | ||||
|         versionCode 30000 // format is Mmmss (where M is 1+the numeric major number | ||||
|         versionName "2.0.0" | ||||
|         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" | ||||
|  |  | |||
|  | @ -11,23 +11,21 @@ | |||
|         android:name="android.hardware.location.gps" | ||||
|         android:required="false" /> | ||||
| 
 | ||||
| <!-- TODO - wait for targetSdkVersion 31 | ||||
|     <!– Request legacy Bluetooth permissions on older devices –> | ||||
|     <!-- Request legacy Bluetooth permissions on older devices --> | ||||
|     <uses-permission android:name="android.permission.BLUETOOTH" | ||||
|         android:maxSdkVersion="30" /> | ||||
|     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" | ||||
|         android:maxSdkVersion="30" /> | ||||
| 
 | ||||
|     <!– API 31+ Bluetooth permissions –> | ||||
|     <!-- API 31+ Bluetooth permissions --> | ||||
|     <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> | ||||
|     <uses-permission android:name="android.permission.BLUETOOTH_SCAN" | ||||
|         android:usesPermissionFlags="neverForLocation" /> | ||||
| --> | ||||
|     <uses-permission android:name="android.permission.BLUETOOTH" /> | ||||
|     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> | ||||
|         android:usesPermissionFlags="neverForLocation" | ||||
|         tools:targetApi="s" /> | ||||
| 
 | ||||
|     <!-- Permissions required for providing location (from phone GPS) to mesh --> | ||||
|     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> | ||||
|     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> | ||||
|     <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> | ||||
| 
 | ||||
|     <!-- This permission is required for analytics - and soon the MQTT gateway --> | ||||
|  |  | |||
|  | @ -8,7 +8,10 @@ import android.content.pm.PackageManager | |||
| import android.hardware.usb.UsbDevice | ||||
| import android.hardware.usb.UsbManager | ||||
| import android.net.Uri | ||||
| import android.os.* | ||||
| import android.os.Bundle | ||||
| import android.os.Handler | ||||
| import android.os.Looper | ||||
| import android.os.RemoteException | ||||
| import android.text.method.LinkMovementMethod | ||||
| import android.view.Menu | ||||
| import android.view.MenuItem | ||||
|  | @ -19,20 +22,14 @@ import androidx.activity.result.contract.ActivityResultContracts | |||
| import androidx.activity.viewModels | ||||
| import androidx.appcompat.app.AppCompatDelegate | ||||
| import androidx.appcompat.widget.Toolbar | ||||
| import androidx.core.app.ActivityCompat | ||||
| import androidx.core.content.ContextCompat | ||||
| import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen | ||||
| import androidx.fragment.app.Fragment | ||||
| import androidx.fragment.app.FragmentManager | ||||
| import androidx.fragment.app.FragmentTransaction | ||||
| import androidx.viewpager2.adapter.FragmentStateAdapter | ||||
| import com.geeksville.mesh.android.BindFailedException | ||||
| import com.geeksville.mesh.android.GeeksvilleApplication | ||||
| import com.geeksville.mesh.android.Logging | ||||
| import com.geeksville.mesh.android.ServiceClient | ||||
| import com.geeksville.mesh.android.* | ||||
| import com.geeksville.mesh.concurrent.handledLaunch | ||||
| import com.geeksville.mesh.android.getMissingPermissions | ||||
| import com.geeksville.mesh.android.isGooglePlayAvailable | ||||
| import com.geeksville.mesh.databinding.ActivityMainBinding | ||||
| import com.geeksville.mesh.model.BTScanModel | ||||
| import com.geeksville.mesh.model.BluetoothViewModel | ||||
|  | @ -130,8 +127,9 @@ class MainActivity : BaseActivity(), Logging { | |||
|         registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions -> | ||||
|             if (!permissions.entries.all { it.value }) { | ||||
|                 errormsg("User denied permissions") | ||||
|                 showSnackbar(getString(R.string.permission_missing_31)) | ||||
|                 showSnackbar(permissionMissing) | ||||
|             } | ||||
|             requestedEnable = false | ||||
|             bluetoothViewModel.permissionsUpdated() | ||||
|         } | ||||
| 
 | ||||
|  | @ -181,71 +179,6 @@ class MainActivity : BaseActivity(), Logging { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** Get the minimum permissions our app needs to run correctly | ||||
|      */ | ||||
|     private fun getMinimumPermissions(): Array<String> { | ||||
|         val perms = mutableListOf<String>() | ||||
| 
 | ||||
|         // We only need this for logging to capture files for the simulator - turn off for production | ||||
|         // perms.add(Manifest.permission.WRITE_EXTERNAL_STORAGE) | ||||
| 
 | ||||
| /*      TODO - wait for targetSdkVersion 31 | ||||
|         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { | ||||
|             perms.add(Manifest.permission.BLUETOOTH_SCAN) | ||||
|             perms.add(Manifest.permission.BLUETOOTH_CONNECT) | ||||
|         } | ||||
| */ | ||||
|         return getMissingPermissions(perms) | ||||
|     } | ||||
| 
 | ||||
|     /** Possibly prompt user to grant permissions | ||||
|      * @param shouldShowDialog usually true, but in cases where we've already shown a dialog elsewhere we skip it. | ||||
|      * | ||||
|      * @return true if we already have the needed permissions | ||||
|      */ | ||||
|     private fun requestPermission( | ||||
|         missingPerms: Array<String> = getMinimumPermissions(), | ||||
|         shouldShowDialog: Boolean = true | ||||
|     ): Boolean = | ||||
|         if (missingPerms.isNotEmpty()) { | ||||
|             val shouldShow = missingPerms.filter { | ||||
|                 ActivityCompat.shouldShowRequestPermissionRationale(this, it) | ||||
|             } | ||||
| 
 | ||||
|             fun doRequest() { | ||||
|                 info("requesting permissions") | ||||
|                 // Ask for all the missing perms | ||||
|                 requestPermissionsLauncher.launch(missingPerms) | ||||
|             } | ||||
| 
 | ||||
|             if (shouldShow.isNotEmpty() && shouldShowDialog) { | ||||
|                 // DID_REQUEST_PERM is an | ||||
|                 // app-defined int constant. The callback method gets the | ||||
|                 // result of the request. | ||||
|                 warn("Permissions $shouldShow missing, we should show dialog") | ||||
| 
 | ||||
|                 MaterialAlertDialogBuilder(this) | ||||
|                     .setTitle(getString(R.string.required_permissions)) | ||||
|                     .setMessage(getString(R.string.permission_missing_31)) | ||||
|                     .setNeutralButton(R.string.cancel) { _, _ -> | ||||
|                         warn("User bailed due to permissions") | ||||
|                     } | ||||
|                     .setPositiveButton(R.string.accept) { _, _ -> | ||||
|                         doRequest() | ||||
|                     } | ||||
|                     .show() | ||||
|             } else { | ||||
|                 info("Permissions $missingPerms missing, no need to show dialog, just asking OS") | ||||
|                 doRequest() | ||||
|             } | ||||
| 
 | ||||
|             false | ||||
|         } else { | ||||
|             // Permission has already been granted | ||||
|             debug("We have our required permissions") | ||||
|             true | ||||
|         } | ||||
| 
 | ||||
|     /// Ask user to rate in play store | ||||
|     private fun askToRate() { | ||||
|         exceptionReporter { // we don't want to crash our app because of bugs in this optional feature | ||||
|  | @ -296,9 +229,6 @@ class MainActivity : BaseActivity(), Logging { | |||
|         handleIntent(intent) | ||||
| 
 | ||||
|         if (isGooglePlayAvailable(this)) askToRate() | ||||
| 
 | ||||
|         // if (!isInTestLab) - very important - even in test lab we must request permissions because we need location perms for some of our tests to pass | ||||
|         requestPermission() | ||||
|     } | ||||
| 
 | ||||
|     private fun initToolbar() { | ||||
|  | @ -728,11 +658,22 @@ class MainActivity : BaseActivity(), Logging { | |||
|         super.onStart() | ||||
| 
 | ||||
|         bluetoothViewModel.enabled.observe(this) { enabled -> | ||||
|             if (!enabled && !requestedEnable) { | ||||
|                 if (!isInTestLab && scanModel.selectedBluetooth) { | ||||
|                     requestedEnable = true | ||||
|             if (!enabled && !requestedEnable && scanModel.selectedBluetooth) { | ||||
|                 requestedEnable = true | ||||
|                 if (hasBluetoothPermission()) { | ||||
|                     val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) | ||||
|                     bleRequestEnable.launch(enableBtIntent) | ||||
|                 } else { | ||||
|                     MaterialAlertDialogBuilder(this) | ||||
|                         .setTitle(getString(R.string.required_permissions)) | ||||
|                         .setMessage(permissionMissing) | ||||
|                         .setNeutralButton(R.string.cancel) { _, _ -> | ||||
|                             warn("User bailed due to permissions") | ||||
|                         } | ||||
|                         .setPositiveButton(R.string.accept) { _, _ -> | ||||
|                             info("requesting permissions") | ||||
|                             requestPermissionsLauncher.launch(getBluetoothPermissions())                    } | ||||
|                         .show() | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  |  | |||
|  | @ -8,14 +8,15 @@ import android.companion.CompanionDeviceManager | |||
| import android.content.Context | ||||
| import android.content.pm.PackageManager | ||||
| import android.hardware.usb.UsbManager | ||||
| import android.os.Build | ||||
| import androidx.core.content.ContextCompat | ||||
| import com.geeksville.mesh.MainActivity | ||||
| import com.geeksville.mesh.R | ||||
| 
 | ||||
| /** | ||||
|  * @return null on platforms without a BlueTooth driver (i.e. the emulator) | ||||
|  */ | ||||
| val Context.bluetoothManager: BluetoothManager? get() = getSystemService(Context.BLUETOOTH_SERVICE) as? BluetoothManager? | ||||
| val Context.bluetoothManager: BluetoothManager? | ||||
|     get() = getSystemService(Context.BLUETOOTH_SERVICE).takeIf { hasBluetoothPermission() } as? BluetoothManager? | ||||
| 
 | ||||
| val Context.deviceManager: CompanionDeviceManager? | ||||
|     get() { | ||||
|  | @ -36,7 +37,7 @@ val Context.locationManager: LocationManager get() = requireNotNull(getSystemSer | |||
|  * @return true if CompanionDeviceManager API is present | ||||
|  */ | ||||
| fun Context.hasCompanionDeviceApi(): Boolean = | ||||
|     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) | ||||
|     if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) | ||||
|         packageManager.hasSystemFeature(PackageManager.FEATURE_COMPANION_DEVICE_SETUP) | ||||
|     else false | ||||
| 
 | ||||
|  | @ -51,6 +52,16 @@ fun Context.hasGps(): Boolean = locationManager.allProviders.contains(LocationMa | |||
| fun Context.gpsDisabled(): Boolean = | ||||
|     if (hasGps()) !locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) else false | ||||
| 
 | ||||
| /** | ||||
|  * return the text string of the permissions missing | ||||
|  */ | ||||
| val Context.permissionMissing: String | ||||
|     get() = if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.S) { | ||||
|         getString(R.string.permission_missing) | ||||
|     } else { | ||||
|         getString(R.string.permission_missing_31) | ||||
|     } | ||||
| 
 | ||||
| /** | ||||
|  * return a list of the permissions we don't have | ||||
|  */ | ||||
|  | @ -67,12 +78,12 @@ fun Context.getMissingPermissions(perms: List<String>): Array<String> = perms.fi | |||
| fun Context.getBluetoothPermissions(): Array<String> { | ||||
|     val perms = mutableListOf<String>() | ||||
| 
 | ||||
| /*  TODO - wait for targetSdkVersion 31 | ||||
|     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { | ||||
|     if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { | ||||
|         perms.add(Manifest.permission.BLUETOOTH_SCAN) | ||||
|         perms.add(Manifest.permission.BLUETOOTH_CONNECT) | ||||
|     } else if (!hasCompanionDeviceApi()) { | ||||
|         perms.add(Manifest.permission.ACCESS_FINE_LOCATION) | ||||
|     } | ||||
| */ | ||||
|     return getMissingPermissions(perms) | ||||
| } | ||||
| 
 | ||||
|  | @ -109,7 +120,7 @@ fun Context.hasLocationPermission() = getLocationPermissions().isEmpty() | |||
| fun Context.getBackgroundPermissions(): Array<String> { | ||||
|     val perms = mutableListOf(Manifest.permission.ACCESS_FINE_LOCATION) | ||||
| 
 | ||||
|     if (Build.VERSION.SDK_INT >= 29) // only added later | ||||
|     if (android.os.Build.VERSION.SDK_INT >= 29) // only added later | ||||
|         perms.add(Manifest.permission.ACCESS_BACKGROUND_LOCATION) | ||||
| 
 | ||||
|     return getMissingPermissions(perms) | ||||
|  |  | |||
|  | @ -128,10 +128,9 @@ class BTScanModel @Inject constructor( | |||
|         debug("BTScanModel cleared") | ||||
|     } | ||||
| 
 | ||||
|     private val bluetoothAdapter = context.bluetoothManager?.adapter | ||||
|     private val deviceManager get() = context.deviceManager | ||||
|     val hasCompanionDeviceApi get() = context.hasCompanionDeviceApi() | ||||
|     private val hasBluetoothPermission get() = application.hasBluetoothPermission() | ||||
|     val hasCompanionDeviceApi get() = application.hasCompanionDeviceApi() | ||||
|     val hasBluetoothPermission get() = application.hasBluetoothPermission() | ||||
|     private val usbManager get() = context.usbManager | ||||
| 
 | ||||
|     var selectedAddress: String? = null | ||||
|  | @ -219,8 +218,8 @@ class BTScanModel @Inject constructor( | |||
|     fun setupScan(): Boolean { | ||||
|         selectedAddress = radioInterfaceService.getDeviceAddress() | ||||
| 
 | ||||
|         return if (bluetoothAdapter == null || MockInterface.addressValid(context, usbRepository, "")) { | ||||
|             warn("No bluetooth adapter.  Running under emulation?") | ||||
|         return if (MockInterface.addressValid(context, usbRepository, "")) { | ||||
|             warn("Running under emulator/test lab") | ||||
| 
 | ||||
|             val testnodes = listOf( | ||||
|                 DeviceListEntry("Included simulator", "m", true), | ||||
|  | @ -273,14 +272,16 @@ class BTScanModel @Inject constructor( | |||
| 
 | ||||
|     private var networkDiscovery: Job? = null | ||||
|     fun startScan() { | ||||
|         _spinner.value = true | ||||
| 
 | ||||
|         // Start Network Service Discovery (find TCP devices) | ||||
|         networkDiscovery = nsdRepository.networkDiscoveryFlow() | ||||
|             .onEach { addDevice(TCPDeviceListEntry(it)) } | ||||
|             .launchIn(CoroutineScope(Dispatchers.Main)) | ||||
| 
 | ||||
|         if (hasCompanionDeviceApi) { | ||||
|             startCompanionScan() | ||||
|         } else startClassicScan() | ||||
|         if (hasBluetoothPermission) { | ||||
|             if (hasCompanionDeviceApi) startCompanionScan() else startClassicScan() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @SuppressLint("MissingPermission") | ||||
|  | @ -290,7 +291,6 @@ class BTScanModel @Inject constructor( | |||
| 
 | ||||
|         if (bluetoothLeScanner != null) { // could be null if bluetooth is disabled | ||||
|             debug("starting classic scan") | ||||
|             _spinner.value = true | ||||
| 
 | ||||
|             // filter and only accept devices that have our service | ||||
|             val filter = | ||||
|  | @ -373,7 +373,6 @@ class BTScanModel @Inject constructor( | |||
|     @SuppressLint("NewApi") | ||||
|     private fun startCompanionScan() { | ||||
|         debug("starting companion scan") | ||||
|         _spinner.value = true | ||||
|         deviceManager?.associate( | ||||
|             associationRequest(), | ||||
|             @SuppressLint("NewApi") | ||||
|  | @ -479,7 +478,11 @@ class BTScanModel @Inject constructor( | |||
|                 } | ||||
| 
 | ||||
|                 val permissionIntent = | ||||
|                     if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.S) { | ||||
|                     PendingIntent.getBroadcast(activity, 0, Intent(ACTION_USB_PERMISSION), 0) | ||||
|                 } else { | ||||
|                     PendingIntent.getBroadcast(activity, 0, Intent(ACTION_USB_PERMISSION), PendingIntent.FLAG_IMMUTABLE) | ||||
|                 } | ||||
|                 val filter = IntentFilter(ACTION_USB_PERMISSION) | ||||
|                 activity.registerReceiver(usbReceiver, filter) | ||||
|                 usbManager.requestPermission(it.usb.device, permissionIntent) | ||||
|  |  | |||
|  | @ -56,7 +56,9 @@ class BluetoothRepository @Inject constructor( | |||
|     } | ||||
| 
 | ||||
|     fun getRemoteDevice(address: String): BluetoothDevice? { | ||||
|         return bluetoothAdapterLazy.get()?.takeIf { isValid(address) }?.getRemoteDevice(address) | ||||
|         return bluetoothAdapterLazy.get() | ||||
|             ?.takeIf { application.hasBluetoothPermission() && isValid(address) } | ||||
|             ?.getRemoteDevice(address) | ||||
|     } | ||||
| 
 | ||||
|     fun getBluetoothLeScanner(): BluetoothLeScanner? { | ||||
|  |  | |||
|  | @ -1,12 +1,10 @@ | |||
| package com.geeksville.mesh.repository.radio | ||||
| 
 | ||||
| import android.annotation.SuppressLint | ||||
| import android.bluetooth.BluetoothAdapter | ||||
| import android.bluetooth.BluetoothGattCharacteristic | ||||
| import android.bluetooth.BluetoothGattService | ||||
| import android.bluetooth.BluetoothManager | ||||
| import android.content.Context | ||||
| import com.geeksville.mesh.android.Logging | ||||
| import com.geeksville.mesh.android.bluetoothManager | ||||
| import com.geeksville.mesh.concurrent.handledLaunch | ||||
| import com.geeksville.mesh.repository.usb.UsbRepository | ||||
| import com.geeksville.mesh.service.* | ||||
|  | @ -110,22 +108,15 @@ class BluetoothInterface( | |||
|         val BTM_FROMNUM_CHARACTER: UUID = | ||||
|             UUID.fromString("ed9da18c-a800-4f66-a670-aa7547e34453") | ||||
| 
 | ||||
|         /// Get our bluetooth adapter (should always succeed except on emulator | ||||
|         private fun getBluetoothAdapter(context: Context): BluetoothAdapter? { | ||||
|             val bluetoothManager = | ||||
|                 context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager | ||||
|             return bluetoothManager.adapter | ||||
|         } | ||||
| 
 | ||||
|         /** Return true if this address is still acceptable. For BLE that means, still bonded */ | ||||
|         @SuppressLint("NewApi", "MissingPermission") | ||||
|         override fun addressValid( | ||||
|             context: Context, | ||||
|             usbRepository: UsbRepository, // Temporary until dependency injection transition is completed | ||||
|             rest: String | ||||
|         ): Boolean { | ||||
|             val allPaired = getBluetoothAdapter(context)?.bondedDevices.orEmpty() | ||||
|                     .map { it.address }.toSet() | ||||
|             /// Get our bluetooth adapter (should always succeed except on emulator | ||||
|             val allPaired = context.bluetoothManager?.adapter?.bondedDevices.orEmpty() | ||||
|                 .map { it.address }.toSet() | ||||
|             return if (!allPaired.contains(rest)) { | ||||
|                 warn("Ignoring stale bond to ${rest.anonymize}") | ||||
|                 false | ||||
|  | @ -170,7 +161,7 @@ class BluetoothInterface( | |||
|     init { | ||||
|         // Note: this call does no comms, it just creates the device object (even if the | ||||
|         // device is off/not connected) | ||||
|         val device = getBluetoothAdapter(context)?.getRemoteDevice(address) | ||||
|         val device = context.bluetoothManager?.adapter?.getRemoteDevice(address) | ||||
|         if (device != null) { | ||||
|             info("Creating radio interface service.  device=${address.anonymize}") | ||||
| 
 | ||||
|  |  | |||
|  | @ -106,7 +106,11 @@ class MeshServiceNotifications( | |||
|         ) | ||||
| 
 | ||||
|     private val openAppIntent: PendingIntent by lazy { | ||||
|         PendingIntent.getActivity(context, 0, Intent(context, MainActivity::class.java), 0) | ||||
|         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { | ||||
|             PendingIntent.getActivity(context, 0, Intent(context, MainActivity::class.java), 0) | ||||
|         } else { | ||||
|             PendingIntent.getActivity(context, 0, Intent(context, MainActivity::class.java), PendingIntent.FLAG_IMMUTABLE) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  |  | |||
|  | @ -261,7 +261,10 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { | |||
|             registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions -> | ||||
|                 if (permissions.entries.all { it.value }) { | ||||
|                     binding.provideLocationCheckbox.isChecked = true | ||||
|                 } else debug("User denied background permission") | ||||
|                 } else { | ||||
|                     debug("User denied background permission") | ||||
|                     showSnackbar(getString(R.string.why_background_required)) | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|         val requestLocationAndBackgroundLauncher = | ||||
|  | @ -271,7 +274,10 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { | |||
|                     if (myActivity.hasBackgroundPermission()) { | ||||
|                         binding.provideLocationCheckbox.isChecked = true | ||||
|                     } else requestBackgroundAndCheckLauncher.launch(myActivity.getBackgroundPermissions()) | ||||
|                 } else debug("User denied location permission") | ||||
|                 } else { | ||||
|                     debug("User denied location permission") | ||||
|                     showSnackbar(getString(R.string.why_background_required)) | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|         // init our region spinner | ||||
|  | @ -506,37 +512,34 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { | |||
|         val requestPermissionAndScanLauncher = | ||||
|             registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions -> | ||||
|                 if (permissions.entries.all { it.value }) { | ||||
|                     checkLocationEnabled() | ||||
|                     checkBTEnabled() | ||||
|                     if (!scanModel.hasCompanionDeviceApi) checkLocationEnabled() | ||||
|                     scanLeDevice() | ||||
|                 } else { | ||||
|                     errormsg("User denied scan permissions") | ||||
|                     showSnackbar(getString(R.string.permission_missing)) | ||||
|                     showSnackbar(requireContext().permissionMissing) | ||||
|                 } | ||||
|                 bluetoothViewModel.permissionsUpdated() | ||||
|             } | ||||
| 
 | ||||
|         binding.changeRadioButton.setOnClickListener { | ||||
|             debug("User clicked changeRadioButton") | ||||
|             checkBTEnabled() | ||||
|             if ((scanModel.hasCompanionDeviceApi)) { | ||||
|                 scanLeDevice() | ||||
|             } else  { | ||||
|                 // Location is the only runtime permission for classic bluetooth scan | ||||
|                 if (myActivity.hasLocationPermission()) { | ||||
|                     checkLocationEnabled() | ||||
|                     scanLeDevice() | ||||
|                 } else { | ||||
|                     MaterialAlertDialogBuilder(requireContext()) | ||||
|                         .setTitle(getString(R.string.required_permissions)) | ||||
|                         .setMessage(getString(R.string.permission_missing)) | ||||
|                         .setNeutralButton(R.string.cancel) { _, _ -> | ||||
|                             warn("User bailed due to permissions") | ||||
|                         } | ||||
|                         .setPositiveButton(R.string.accept) { _, _ -> | ||||
|                             info("requesting scan permissions") | ||||
|                             requestPermissionAndScanLauncher.launch(myActivity.getLocationPermissions()) | ||||
|                         } | ||||
|                         .show() | ||||
|                 } | ||||
|             scanLeDevice() | ||||
|             if (scanModel.hasBluetoothPermission) { | ||||
|                 checkBTEnabled() | ||||
|                 if (!scanModel.hasCompanionDeviceApi) checkLocationEnabled() | ||||
|             } else { | ||||
|                 MaterialAlertDialogBuilder(requireContext()) | ||||
|                     .setTitle(getString(R.string.required_permissions)) | ||||
|                     .setMessage(requireContext().permissionMissing) | ||||
|                     .setNeutralButton(R.string.cancel) { _, _ -> | ||||
|                         warn("User bailed due to permissions") | ||||
|                     } | ||||
|                     .setPositiveButton(R.string.accept) { _, _ -> | ||||
|                         info("requesting scan permissions") | ||||
|                         requestPermissionAndScanLauncher.launch(myActivity.getBluetoothPermissions()) | ||||
|                     } | ||||
|                     .show() | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  |  | |||
		Ładowanie…
	
		Reference in New Issue
	
	 andrekir
						andrekir