Android请求位置权限如何等待用户操作弹窗完成再执行后续代码
问题根因
Android的权限申请API从设计上就不是阻塞式调用:不管是已经废弃的ActivityCompat.requestPermissions(),还是当前官方推荐的ActivityResultLauncher.launch(),调用后都会立刻返回,不会暂停当前onCreate的执行流程等待用户操作权限弹窗,所以你写在权限申请调用语句后面的代码,必然会在用户完成弹窗选择前就执行,这是系统的正常行为,不是API缺陷。
千万不要尝试用循环等待、Thread.sleep之类的方式阻塞主线程等结果——主线程被阻塞时权限弹窗根本无法正常渲染响应,还会直接触发ANR(应用无响应)崩溃。
正确实现方案
由于你的应用强依赖位置权限,你需要把所有依赖权限的业务逻辑(包括你要展示的"In main"Toast)从权限申请调用的后面移走,统一放到权限结果的回调分支、以及提前检查到权限已授予的分支里执行,逻辑拆分如下:
- 应用启动先检查当前是否已经拿到位置权限,如果已经授权,直接执行主页面所有业务逻辑
- 如果未授权,再发起权限申请,此时不执行任何依赖权限的逻辑
- 等用户在权限弹窗完成操作、结果回调触发后,再根据授权结果决定:
- 授权成功:执行主页面业务逻辑
- 授权失败:展示必须授权才能使用的提示,可根据情况重新发起申请、引导用户跳设置页开权限,或直接关闭应用
参考实现代码(使用官方推荐的ActivityResult API)
首先定义权限申请启动器,在结果回调里处理后续逻辑:
private ActivityResultLauncher<String> locationPermissionLauncher = registerForActivityResult( new ActivityResultContracts.RequestPermission(), isGranted -> { if (isGranted) { // 权限申请通过,执行主逻辑 Toast.makeText(this, "In main", Toast.LENGTH_SHORT).show(); initMainFunction(); } else { // 权限被拒,强依赖场景下展示强制提示 Toast.makeText(this, "本应用必须获取位置权限才能使用,请授予权限后重试", Toast.LENGTH_LONG).show(); // 此处可补充逻辑:如判断用户是否勾选"不再询问",展示跳设置页引导 } } ); // 抽离所有需要位置权限的主业务逻辑 private void initMainFunction() { // 此处写主页面初始化、位置获取、功能加载等所有核心代码 }
然后在onCreate里做权限检查和申请触发:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 启动时先检查权限状态 if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { // 已有权限直接走主逻辑 Toast.makeText(this, "In main", Toast.LENGTH_SHORT).show(); initMainFunction(); } else { // 无权限才发起申请,此处不写任何依赖权限的逻辑 locationPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION); } }
如果你还在使用旧的已废弃onRequestPermissionsResultAPI,实现逻辑完全一致:把主逻辑代码挪到权限授予成功的回调分支里即可,不要写在requestPermissions()调用之后。
内容的提问来源于stack exchange,提问作者moustafa
相关产品推荐
相关产品推荐

