如何在Kotlin中编写统一处理SecurityException的通用函数
实现通用SecurityException捕获函数的方案
针对你需要统一处理不同类、不同返回值方法的SecurityException需求,用Kotlin的高阶函数就能轻松实现通用包装逻辑,彻底减少代码冗余。
基础版:极简通用捕获函数
这个版本能快速包装任意方法,捕获SecurityException并返回nullable结果,同时统一处理异常:
fun <T> safeBleOperation(block: () -> T): T? { return try { block() } catch (e: SecurityException) { // 这里写统一的异常处理逻辑:比如打日志、埋点、全局提示 e.printStackTrace() // 示例:全局Toast提示权限问题(需传入Context可调整) // Toast.makeText(appContext, "蓝牙权限不足,请检查权限设置", Toast.LENGTH_SHORT).show() null } }
使用示例
不管是返回布尔值的discoverServices(),还是返回Unit的disable(),都能直接用:
// 处理带返回值的方法 val discoverResult = safeBleOperation { bluetoothGatt?.discoverServices() } discoverResult?.let { // 发现服务成功的逻辑 } // 处理无返回值的方法 safeBleOperation { bluetoothAdapter?.disable() }
进阶版:支持自定义错误处理
如果不同场景需要不同的异常提示,可扩展函数加入自定义错误处理lambda:
fun <T> safeBleOperation( onSecurityError: (SecurityException) -> Unit = { it.printStackTrace() }, block: () -> T ): T? { return try { block() } catch (e: SecurityException) { onSecurityError(e) null } }
使用示例
在调用时指定当前场景的错误处理:
safeBleOperation( onSecurityError = { Toast.makeText(this, "关闭蓝牙需要权限,请授权后重试", Toast.LENGTH_SHORT).show() } ) { bluetoothAdapter?.disable() }
进阶增强:区分"原方法返回null"和"异常捕获"
如果需要明确区分「方法本身返回null(比如bluetoothGatt为空)」和「触发SecurityException」两种情况,可以用密封类包装结果:
sealed class BleOperationResult<out T> { data class Success<out T>(val data: T) : BleOperationResult<T>() data class SecurityFailure(val exception: SecurityException) : BleOperationResult<Nothing>() object NullTarget : BleOperationResult<Nothing>() // 标记原方法因对象为空返回null } fun <T> safeBleOperation(block: () -> T?): BleOperationResult<T> { return try { val result = block() result?.let { BleOperationResult.Success(it) } ?: BleOperationResult.NullTarget } catch (e: SecurityException) { BleOperationResult.SecurityFailure(e) } }
使用示例
通过when表达式清晰处理每种情况:
when (val result = safeBleOperation { bluetoothGatt?.discoverServices() }) { is BleOperationResult.Success -> { // 处理服务发现成功的逻辑 } is BleOperationResult.SecurityFailure -> { Toast.makeText(this, "权限错误:${result.exception.message}", Toast.LENGTH_SHORT).show() } BleOperationResult.NullTarget -> { // 处理bluetoothGatt为空的逻辑,比如提示设备已断开 } }
补充提醒
虽然通用捕获能兜底异常,但提前做权限检查仍是更优方案:在调用蓝牙操作前,先判断权限是否授予(比如Manifest.permission.BLUETOOTH_ADMIN、Manifest.permission.BLUETOOTH_SCAN等),配合通用捕获实现双重保障,既减少异常触发,又避免崩溃。
内容的提问来源于stack exchange,提问作者kat opp
相关产品推荐
相关产品推荐

