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

升级Android targetSdkVersion至33时位置权限异常求助

升级targetSdkVersion至33后触发位置权限SecurityException问题

原配置信息

build.gradle配置

compileSdkVersion 19
buildToolsVersion '26.0.2'
defaultConfig {
  minSdkVersion 14
  targetSdkVersion 19
}

AndroidManifest.xml配置

android:minSdkVersion="14"
android:targetSdkVersion="19"
uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" 
uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" 

升级后的异常信息

升级compileSdkVersion、targetSdkVersion到33,适配更新buildToolsVersion后,在Android13设备上触发以下异常:

java.lang.RuntimeException: Unable to start activity ComponentInfo{activity.MainActivity}: 
java.lang.SecurityException: uid 10159 does not have android.permission.ACCESS_COARSE_LOCATION or android.permission.ACCESS_FINE_LOCATION.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3645)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3782)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2307)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7872)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
Caused by: java.lang.SecurityException: uid 10159 does not have android.permission.ACCESS_COARSE_LOCATION or android.permission.ACCESS_FINE_LOCATION.

补充场景说明

  • targetSdkVersion=19在Android13上启动:系统先弹出权限申请界面,再提示旧版本兼容信息,最后进入登录界面
  • targetSdkVersion=33在Android13上启动:直接进入登录界面,无权限申请弹窗;输入登录凭证后触发上述异常

异常触发代码

异常抛出在GPSManager构造方法的这一行:

Location gpsLocation = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);

相关代码片段

public abstract class MyActivity extends AnaliticsActivity implements OnRefreshListener {
    private GPSManager gpsManager;
    private Context mContext;

    @Override
    protected void onCreate(Bundle arg0) {
        super.onCreate(arg0);
        mContext = this;

        initActivity();
        initHelpers();
        initActionBar();
    }
    
    private void initActivity() {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }

    private void initHelpers() {
        gpsManager = new GPSManager(getApplicationContext());
        // ...其他初始化逻辑
    }
    // ...其他代码
}

public class GPSManager implements LocationListener {
    private LocationManager mLocationManager;

    public GPSManager(Context context) {
        mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
        Location gpsLocation = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        // ...后续逻辑
    }
    // ...其他代码
}

解决方案

1. 更新AndroidManifest权限声明

针对Android13(API33),若仅需前台位置访问,保留原有权限即可;若需后台位置访问,需额外添加对应权限:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 仅当需要后台位置时添加 -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" android:maxSdkVersion="33" />

2. 实现动态权限申请逻辑

targetSdkVersion>=23开始,系统不再自动弹出权限申请,必须由应用主动发起。修改MyActivity逻辑,在初始化GPSManager前先检查并申请权限:

public abstract class MyActivity extends AnaliticsActivity implements OnRefreshListener {
    private GPSManager gpsManager;
    private static final int LOCATION_PERMISSION_REQUEST_CODE = 1001;
    private String[] REQUIRED_LOCATION_PERMISSIONS = {
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION
    };

    @Override
    protected void onCreate(Bundle arg0) {
        super.onCreate(arg0);
        mContext = this;

        initActivity();
        checkLocationPermissions(); // 先检查权限,再初始化Helpers
        initActionBar();
    }
    
    private void checkLocationPermissions() {
        boolean hasFineLocation = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
        boolean hasCoarseLocation = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;

        if (hasFineLocation && hasCoarseLocation) {
            // 权限已获取,初始化GPSManager
            initHelpers();
        } else {
            // 申请权限
            ActivityCompat.requestPermissions(this, REQUIRED_LOCATION_PERMISSIONS, LOCATION_PERMISSION_REQUEST_CODE);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) {
            boolean allGranted = true;
            for (int result : grantResults) {
                if (result != PackageManager.PERMISSION_GRANTED) {
                    allGranted = false;
                    break;
                }
            }
            if (allGranted) {
                initHelpers();
            } else {
                // 处理权限被拒绝的情况,比如提示用户开启权限
                Toast.makeText(this, "需要位置权限才能正常使用功能", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void initHelpers() {
        gpsManager = new GPSManager(getApplicationContext());
        // ...其他初始化逻辑
    }

    // ...其他代码
}

3. 优化GPSManager初始化逻辑

避免在构造方法中直接调用需要权限的API,改为提供初始化方法,在权限获取后再执行位置相关操作:

public class GPSManager implements LocationListener {
    private LocationManager mLocationManager;
    private Context mContext;

    public GPSManager(Context context) {
        mContext = context;
        mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
    }

    // 新增初始化方法,在权限获取后调用
    public void initLocation() {
        if (checkPermission()) {
            Location gpsLocation = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            // ...后续逻辑
        }
    }

    private boolean checkPermission() {
        boolean hasFine = ContextCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
        boolean hasCoarse = ContextCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
        return hasFine || hasCoarse;
    }
    // ...其他代码
}

然后在initHelpers中调用:

private void initHelpers() {
    gpsManager = new GPSManager(getApplicationContext());
    gpsManager.initLocation();
    // ...其他初始化逻辑
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 05:24:20