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

APP启动时请求权限:如何等待权限响应后再继续执行?

这个问题我太熟了!很多刚接触Android权限的开发者都会踩这个坑——明明权限还没处理完,应用就自顾自跑起来了,最后还要重启Activity,体验特别差。核心思路就是把所有依赖权限的后续流程,完全放在权限请求的回调里执行,确保只有用户明确授权后,才启动那些需要权限的逻辑。下面给你几种靠谱的实现方式:

解决方法

1. 使用官方推荐的Activity Result API(AndroidX)

这是现在Google主推的方案,代码更清晰,能避免旧版回调的混乱问题。

步骤1:注册权限请求回调

在你的Activity/Fragment里定义一个权限请求的Launcher,用来接收用户的权限响应:

// 作为Activity/Fragment的成员变量
private val requestPermissionLauncher = registerForActivityResult(
    ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
    if (isGranted) {
        // 用户授权成功,这里启动所有依赖权限的核心逻辑
        initAppAfterPermissionGranted()
    } else {
        // 用户拒绝权限,处理拒绝逻辑(比如提示去设置开启)
        showPermissionDeniedDialog()
    }
}

步骤2:在onCreate里先检查权限,再决定是否启动业务逻辑

不要在onCreate里直接执行依赖权限的代码,先判断权限状态:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    // 先检查权限是否已授予
    if (ContextCompat.checkSelfPermission(
            this,
            Manifest.permission.CAMERA // 替换成你需要的权限,比如存储、位置等
        ) == PackageManager.PERMISSION_GRANTED
    ) {
        // 已有权限,直接启动核心逻辑
        initAppAfterPermissionGranted()
    } else {
        // 无权限,发起请求,此时应用会等待用户操作后再继续
        requestPermissionLauncher.launch(Manifest.permission.CAMERA)
    }

    // 这里只放不需要权限的初始化,比如UI控件绑定、基础界面设置
    bindBasicUiElements()
}

步骤3:封装依赖权限的逻辑

把所有需要权限的操作(比如初始化相机、读取本地文件)都放到initAppAfterPermissionGranted()方法里,确保只有授权后才执行。

2. 旧版兼容:使用onRequestPermissionsResult

如果你的项目还在使用AndroidX之前的旧权限回调方式,也可以这样处理:

private static final int PERMISSION_REQUEST_CODE = 100;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED) {
        // 发起权限请求
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                PERMISSION_REQUEST_CODE);
    } else {
        // 已有权限,启动核心逻辑
        initAppAfterPermission();
    }

    // 仅初始化无权限依赖的UI或基础功能
    initBasicUi();
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == PERMISSION_REQUEST_CODE) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // 授权成功,启动核心逻辑
            initAppAfterPermission();
        } else {
            // 权限被拒绝,处理提示逻辑
            showPermissionDeniedTips();
        }
    }
}

3. 进阶:用Kotlin协程实现线性逻辑

如果你用Kotlin开发,可以把权限请求包装成挂起函数,让代码看起来像同步执行,更易读:

// 封装一个挂起函数,等待权限请求结果
suspend fun requestPermission(context: Context, permission: String): Boolean {
    return suspendCancellableCoroutine { continuation ->
        val launcher = context.registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
            continuation.resume(isGranted)
        }
        launcher.launch(permission)
    }
}

// 在协程中使用
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    lifecycleScope.launch {
        val hasPermission = if (ContextCompat.checkSelfPermission(this@MainActivity, Manifest.permission.ACCESS_FINE_LOCATION)
            == PackageManager.PERMISSION_GRANTED
        ) {
            true
        } else {
            requestPermission(this@MainActivity, Manifest.permission.ACCESS_FINE_LOCATION)
        }

        if (hasPermission) {
            initAppAfterPermissionGranted()
        } else {
            showPermissionDeniedDialog()
        }
    }

    // 无权限依赖的初始化操作
    bindUi()
}
关键注意事项
  • 绝对不要用Thread.sleep()这类阻塞主线程的方式等待权限,这会直接导致ANR(应用无响应),Android系统严格禁止主线程做长时间阻塞操作。
  • 如果需要请求多个权限,可以用ActivityResultContracts.RequestMultiplePermissions()一次性请求,然后在回调里检查所有权限的授权状态。
  • 对于用户拒绝权限且勾选了「不再询问」的情况,要引导用户去应用设置页面手动开启权限,而不是反复弹窗请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:58:33