无需延迟处理Android运行时权限的方案咨询
问题:授予Android运行时权限后立即调用API抛出SecurityException
大多数开发者处理Android运行时权限的方式是,确认权限授予后立即调用需该权限的API,但我采用此方式时抛出了如下SecurityException异常:
Fatal Exception: java.lang.SecurityException Need android.permission.BLUETOOTH_CONNECT permission for android.content.AttributionSource@d1109f50: AdapterService getBondedDevices android.os.Parcel.createExceptionOrNull (Parcel.java:2426) android.bluetooth.BluetoothAdapter.getBondedDevices (BluetoothAdapter.java:2491) com.starmicronics.stario.a.b (a.java:19) com.starmicronics.stario.StarIOPort.searchPrinter (StarIOPort.java:36) com.dd.ddmerchant.printer.StarPrinterManager.init (StarPrinterManager.kt:72) com.dd.ddmerchant.printer.StarPrinterManager.connect (StarPrinterManager.kt:43) com.dd.ddmerchant.mainactivity.presentation.MainActivity$onRequestPermissionsResult$1.invoke (MainActivity.kt:701) com.dd.ddmerchant.mainactivity.presentation.MainActivity$onRequestPermissionsResult$1.invoke (MainActivity.kt:698) com.dd.ddmerchant.mainactivity.presentation.MainActivity$delay$$inlined$postDelayed$1.run (View.kt:412) android.os.Handler.handleCallback (Handler.java:938) com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1003)
我尝试在调用API前添加延迟,虽能缓解多数设备的问题,但部分负载较高的设备仍会报错。曾试过一套复杂方案,但代码繁琐且不适用于所有场景。
以下是我的权限处理代码:
权限工具类代码
object Permissions { @JvmStatic fun checkRuntimePermission( context: Activity, permission: String, isRationaleDialogHidden: Boolean, showRationaleDialog: () -> Unit, requestPermissionBlock: () -> Unit, permissionGrantedBlock: () -> Unit ) { when (checkSelfPermission(context, permission)) { PackageManager.PERMISSION_DENIED -> { if (ActivityCompat.shouldShowRequestPermissionRationale(context, permission)) { if (isRationaleDialogHidden) { showRationaleDialog() } } else { requestPermissionBlock() } } PackageManager.PERMISSION_GRANTED -> { permissionGrantedBlock() } } } @JvmStatic fun checkRuntimePermission( context: Activity, permission: String, permissionDeniedBlock: () -> Unit, permissionGrantedBlock: () -> Unit ) { when (checkSelfPermission(context, permission)) { PackageManager.PERMISSION_DENIED -> { permissionDeniedBlock() } PackageManager.PERMISSION_GRANTED -> { permissionGrantedBlock() } } } @JvmStatic fun isPermissionGranted(grantResults: IntArray): Boolean { var isPermissionGranted = true grantResults.forEach { if (it == PackageManager.PERMISSION_DENIED) { isPermissionGranted = false } } return isPermissionGranted } @JvmStatic fun isFineLocationPermissionGranted(context: Context): Boolean { return checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED } private fun checkSelfPermission(context: Context, permission: String) = ActivityCompat.checkSelfPermission(context, permission) }
权限请求代码
val requestBluetoothConnectPermissionBlock: () -> Unit = { ActivityCompat.requestPermissions( this@DeviceListActivity, arrayOf(Manifest.permission.BLUETOOTH_CONNECT), BLUETOOTH_CONNECT_REQUEST_CODE ) } checkRuntimePermission( context = this, permission = Manifest.permission.BLUETOOTH_CONNECT, isRationaleDialogHidden = isRationaleDialogHidden(), showRationaleDialog = { showRationaleDialog(requestBluetoothConnectPermissionBlock) }, requestPermissionBlock = requestBluetoothConnectPermissionBlock, permissionGrantedBlock = { bluetoothConnectPermissionGranted = true } )
权限回调处理代码
override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) when (requestCode) { BLUETOOTH_DISCOVERY_REQUEST_CODE -> { if (isPermissionsAllowed(grantResults)) { bluetoothDiscoveryPermissionGranted = true } else { Toast.makeText( this, getString( R.string.cannot_set_up_printer_without_bluetooth_permissions ), Toast.LENGTH_LONG ).show() finish() return } } BLUETOOTH_CONNECT_REQUEST_CODE -> { if (isPermissionsAllowed(grantResults)) { bluetoothConnectPermissionGranted = true } else { Toast.makeText( this, getString( R.string.cannot_set_up_printer_without_bluetooth_permissions ), Toast.LENGTH_LONG ).show() finish() return } } } } private fun isPermissionsAllowed(grantResults: IntArray): Boolean { var isPermissionsAllowed = true grantResults.forEach { if (it == PackageManager.PERMISSION_DENIED) { isPermissionsAllowed = false } } return isPermissionsAllowed }
恳请各位提供无需延迟即可安全处理Android运行时权限的通用解决方案。
内容的提问来源于stack exchange,提问作者Etienne Lawlor
相关产品推荐
相关产品推荐

