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

React Native 0.59安卓API29申请带始终允许的定位权限不生效怎么办

解决方案

问题根因

  • API 29(安卓10)对后台定位权限申请做了限制:必须先成功申请前台定位权限(ACCESS_FINE_LOCATION/ACCESS_COARSE_LOCATION),才能单独申请后台定位权限,两个权限同时申请会被系统直接拦截后台权限的申请请求,不会弹出带「始终允许」的弹窗。
  • 你当前代码报错的直接原因是ActivityCompat.requestPermissions的第一个参数要求传入Activity实例,你传入了自定义原生模块的实例this,类型不匹配导致崩溃。

修复步骤

第一步:调整AndroidManifest.xml权限配置

<!-- 基础定位权限 所有版本都需要 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 后台定位权限 仅API29及以上需要 -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" android:minSdkVersion="29" />
<!-- 若需要后台持续定位,需补充前台服务权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" android:minSdkVersion="26" />

第二步:修改自定义原生模块逻辑

无需修改MainActivity代码,直接通过RN自带的权限监听接口即可实现回调,修改后的Geolocation.java代码如下:
首先导入依赖包:

import android.os.Build;
import android.content.Context;
import android.content.pm.PackageManager;
import android.Manifest;
import com.facebook.react.modules.core.PermissionAwareActivity;
import com.facebook.react.modules.core.PermissionListener;

然后补充常量定义和方法实现:

// 权限请求码常量
private static final int MY_PERMISSIONS_REQUEST_LOCATION = 1001;
private static final int MY_PERMISSIONS_REQUEST_BACKGROUND_LOCATION = 1002;

@ReactMethod
public void requestForLocationPermission(Promise promise) {
    Context context = getReactApplicationContext();
    // 适配不同系统版本的权限逻辑
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
        // API28及以下,申请前台定位权限默认包含后台权限
        int permissionCheck = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION);
        if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
            promise.resolve("granted");
            return;
        }
        PermissionAwareActivity activity = (PermissionAwareActivity) getCurrentActivity();
        if (activity == null) {
            promise.reject("ACTIVITY_NULL", "当前Activity不存在");
            return;
        }
        activity.requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSIONS_REQUEST_LOCATION, new PermissionListener() {
            @Override
            public boolean onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
                if (requestCode == MY_PERMISSIONS_REQUEST_LOCATION) {
                    if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                        promise.resolve("granted");
                    } else {
                        promise.reject("PERMISSION_DENIED", "定位权限被拒绝");
                    }
                    return true;
                }
                return false;
            }
        });
    } else {
        // API29及以上,分两步申请权限
        int fineLocationCheck = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION);
        if (fineLocationCheck != PackageManager.PERMISSION_GRANTED) {
            // 先申请前台定位权限
            PermissionAwareActivity activity = (PermissionAwareActivity) getCurrentActivity();
            if (activity == null) {
                promise.reject("ACTIVITY_NULL", "当前Activity不存在");
                return;
            }
            activity.requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSIONS_REQUEST_LOCATION, new PermissionListener() {
                @Override
                public boolean onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
                    if (requestCode == MY_PERMISSIONS_REQUEST_LOCATION) {
                        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                            // 前台权限申请成功后再申请后台权限
                            requestBackgroundLocationPermission(promise);
                        } else {
                            promise.reject("PERMISSION_DENIED", "前台定位权限被拒绝");
                        }
                        return true;
                    }
                    return false;
                }
            });
        } else {
            // 已有前台权限,直接申请后台权限
            requestBackgroundLocationPermission(promise);
        }
    }
}

// 单独封装后台定位权限申请逻辑
private void requestBackgroundLocationPermission(Promise promise) {
    Context context = getReactApplicationContext();
    int backgroundCheck = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_BACKGROUND_LOCATION);
    if (backgroundCheck == PackageManager.PERMISSION_GRANTED) {
        promise.resolve("granted");
        return;
    }
    PermissionAwareActivity activity = (PermissionAwareActivity) getCurrentActivity();
    if (activity == null) {
        promise.reject("ACTIVITY_NULL", "当前Activity不存在");
        return;
    }
    activity.requestPermissions(new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, MY_PERMISSIONS_REQUEST_BACKGROUND_LOCATION, new PermissionListener() {
        @Override
        public boolean onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
            if (requestCode == MY_PERMISSIONS_REQUEST_BACKGROUND_LOCATION) {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    promise.resolve("granted");
                } else {
                    promise.reject("PERMISSION_DENIED", "后台定位权限被拒绝");
                }
                return true;
            }
            return false;
        }
    });
}

第三步:补充交互提示(可选但推荐)

申请后台定位权限之前,可先弹出自定义提示框说明权限用途,若用户首次拒绝后台权限,后续系统会直接拦截权限申请弹窗,需引导用户手动到应用设置页开启「始终允许」定位权限。

其他注意点

RN 0.59版本自带的PermissionsAndroid接口不支持ACCESS_BACKGROUND_LOCATION权限的申请,不要直接用系统自带接口申请后台定位权限。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.09 21:12:02