React Native 0.59升API29后位置权限桥接release模式重复弹窗问题
问题原因
- 权限申请顺序不符合Android 10(API 29)系统要求:API 29及以上版本不允许同时申请前台位置权限
ACCESS_FINE_LOCATION和背景位置权限ACCESS_BACKGROUND_LOCATION,必须先获得前台位置权限授权后才能申请背景权限。release模式下系统会将两个权限的申请拆分为两次独立弹窗,debug模式因开发者选项的权限宽松配置默认合并展示,因此只弹一次。 - 桥接方法重复触发:React Native 0.59版本的release包JS执行效率更高,若JS侧没有做防抖处理,组件重渲染、状态更新等场景可能导致原生桥接方法被连续调用两次,debug模式下JS线程负载更高,偶然掩盖了重复调用的问题。
- 权限回调逻辑缺失:当前代码调用
ActivityCompat.requestPermissions后直接resolve(false),没有等待系统权限申请的回调结果。如果JS侧接收到未授权的返回值后立刻再次触发权限申请,就会导致第二次弹窗,release模式下回调触发更快,两次请求的时间差更短,表现为连续弹出。
解决方案
- 调整权限申请顺序:拆分前台、背景权限的申请逻辑,先校验并申请前台位置权限,用户确认授权后再单独申请背景位置权限,参考调整后的代码:
// 先校验前台权限 int fineLocationCheck = ContextCompat.checkSelfPermission(this.getReactApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION); if (fineLocationCheck != PackageManager.PERMISSION_GRANTED) { // 先申请前台权限 ActivityCompat.requestPermissions( activity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSIONS_REQUEST_FINE_LOCATION ); return; } // 前台权限已授权,再申请背景权限 int backgroundCheck = ContextCompat.checkSelfPermission(this.getReactApplicationContext(), Manifest.permission.ACCESS_BACKGROUND_LOCATION); if (backgroundCheck == PackageManager.PERMISSION_GRANTED) { promise.resolve(true); } else { ActivityCompat.requestPermissions( activity, new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, MY_PERMISSIONS_REQUEST_BACKGROUND_LOCATION ); }
- 新增申请状态标记:在原生模块中新增
isRequestingPermission布尔标记,申请权限前判断如果标记为true则直接忽略请求,申请时设为true,onRequestPermissionsResult回调执行完成后再设为false,避免并发触发多次申请。 - 调整promise返回时机:不要在调用权限申请方法后立刻resolve,将promise对象缓存起来,等
onRequestPermissionsResult拿到用户授权结果后,再根据授权状态resolve对应的值,避免JS侧因提前拿到未授权结果重复调用申请方法。 - JS侧新增防抖逻辑:给调用原生权限申请的JS方法加1000ms左右的防抖,短时间内重复调用直接返回,避免组件重渲染等场景导致的重复触发。
内容的提问来源于stack exchange,提问作者Riku
相关产品推荐
相关产品推荐

