You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android 10中用户关闭位置权限后如何再次请求该权限?

解决Android蓝牙扫描位置权限重复请求问题

我完全懂你的困扰——用户第一次拒绝位置权限后,应用没法自动弹出请求弹窗,只能手动提醒,体验确实不够顺畅。咱们一步步来修复这个问题:

首先得明确Android权限请求的两种拒绝场景:

  • 用户单纯拒绝权限,但没勾选「不再询问」:此时shouldShowRequestPermissionRationale()会返回true,我们还能再次发起权限请求
  • 用户拒绝且勾选了「不再询问」:此时shouldShowRequestPermissionRationale()返回false,系统不会再自动弹出权限弹窗,必须引导用户前往应用设置手动开启权限

接下来我们基于你的代码做针对性修改,完善权限处理逻辑:

第一步:重构权限检查逻辑

把直接在onStart()请求权限的逻辑,改成先判断权限状态的统一方法:

override fun onStart() {
    super.onStart()
    checkLocationPermission()
}

private fun checkLocationPermission() {
    when {
        // 权限已授予,直接处理蓝牙初始化
        ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED -> {
            handleBluetoothSetup()
        }
        // 用户之前拒绝过但未勾选「不再询问」,先弹说明再请求权限
        shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION) -> {
            AlertDialog.Builder(this)
                .setTitle("需要位置权限")
                .setMessage("扫描蓝牙设备依赖位置权限,请允许以正常使用功能")
                .setPositiveButton("确定") { _, _ ->
                    requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), PERMISSION_REQUEST_CODE)
                }
                .setNegativeButton("取消", null)
                .show()
        }
        // 用户拒绝且勾选「不再询问」,引导前往应用设置开启
        else -> {
            AlertDialog.Builder(this)
                .setTitle("权限已被禁用")
                .setMessage("扫描蓝牙需要位置权限,请前往应用设置手动开启")
                .setPositiveButton("去设置") { _, _ ->
                    val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
                        data = Uri.fromParts("package", packageName, null)
                    }
                    startActivity(intent)
                }
                .setNegativeButton("取消", null)
                .show()
        }
    }
}

private fun handleBluetoothSetup() {
    if (!BluetoothAdapter.getDefaultAdapter().isEnabled) {
        startActivityForResult(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), ENABLE_BLT_REQUEST_CODE)
    } else {
        viewModel.discoverBLTDevices()
    }
}

第二步:修改权限回调逻辑

在权限请求结果回调里,重新调用权限检查方法,确保状态变化后能走正确流程:

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (requestCode == PERMISSION_REQUEST_CODE) {
        checkLocationPermission() // 重新检查权限状态,处理后续逻辑
    }
}

第三步:保留蓝牙开启逻辑

你的onActivityResult逻辑可以保持不变,它负责处理蓝牙开启的结果:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == ENABLE_BLT_REQUEST_CODE) {
        if (resultCode == Activity.RESULT_OK) {
            viewModel.discoverBLTDevices()
        } else if (resultCode == Activity.RESULT_CANCELED) {
            finish()
        }
    }
}

关键优化点说明

  • checkLocationPermission()统一处理三种权限状态,让代码逻辑更清晰易维护
  • 针对不同拒绝场景给出不同引导:未勾选「不再询问」时先做权限用途说明,勾选后直接引导到设置,比单纯Toast提示更友好
  • 权限回调后重新检查状态,确保无论用户允许还是拒绝,都能触发对应流程

这样修改后,不管用户第一次如何处理权限,应用都能自动给出合适的引导,不用每次手动告知用户开启权限啦!

内容的提问来源于stack exchange,提问作者Netheru

火山引擎 最新活动