You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无需延迟处理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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 01:35:26