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

Android SDK 33定位权限始终被拒问题求助

Target SDK 33下定位权限请求无弹窗且被拒的解决方案

问题描述

将应用迁移至Target SDK 33后,请求ACCESS_COARSE_LOCATION或ACCESS_FINE_LOCATION权限时,权限始终被拒且未弹出请求对话框。已在Manifest中添加对应权限,使用官方推荐的ActivityResultContracts.RequestMultiplePermissions方式请求,迁移前(Target SDK 32)一切正常,相机、蓝牙权限请求正常,仅定位权限无效。

已配置的Manifest权限:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

权限请求核心代码:

private ActivityResultLauncher<String[]> locationPermissionRequest =
        registerForActivityResult(new ActivityResultContracts
                        .RequestMultiplePermissions(), result -> {
                    Boolean fineLocationGranted = result.getOrDefault(
                            Manifest.permission.ACCESS_FINE_LOCATION, false);
                    Boolean coarseLocationGranted = result.getOrDefault(
                            Manifest.permission.ACCESS_COARSE_LOCATION, false);
                    if (fineLocationGranted != null && fineLocationGranted) {
                        Log.d(TAG, "permissions granted");
                        // 执行定位相关操作
                    } else if (coarseLocationGranted != null && coarseLocationGranted) {
                        Log.d(TAG, "Only approximate location access granted");
                    } else {
                        Log.e(TAG, "location permission denied");
                    }
                }
        );

// 权限检查与请求触发逻辑
if (ActivityCompat.checkSelfPermission(DashboardActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ||
        ActivityCompat.checkSelfPermission(DashboardActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
    ModalDialog.Builder permissionInfoDialogBuilder = new ModalDialog.Builder(DashboardActivity.this);
    permissionInfoDialogBuilder.setType(ModalDialog.Type.DEFAULT_INFO)
            .setPositiveButton(android.R.string.ok, v -> {
                Log.d(TAG, "requesting location permission");
                locationPermissionRequest.launch(new String[]{
                        Manifest.permission.ACCESS_COARSE_LOCATION,
                        Manifest.permission.ACCESS_FINE_LOCATION
                });
            })
            .setTextNegative(android.R.string.cancel)
            .setTitle(R.string.dashboard_request_location_permission_title)
            .setMessage(R.string.dashboard_request_location_permission_text)
            .setCloseable(false);
    permissionInfoDialogBuilder.create().show();
    return;
}

核心原因及解决办法

1. 未同步升级compileSdkVersion至33

当targetSdkVersion设置为33,但compileSdkVersion仍低于33时,权限请求逻辑会出现兼容性问题,系统无法正确解析SDK33的权限规则,导致直接返回拒绝且不弹窗。

解决步骤:
修改Module级别的build.gradle文件,将compileSdkVersion升级至33:

android {
    compileSdkVersion 33
    // 其他配置...
    defaultConfig {
        targetSdkVersion 33
        // 其他配置...
    }
}

2. 未处理权限永久拒绝的场景

如果用户之前已拒绝权限并勾选“不再询问”,此时直接发起权限请求,系统不会弹出对话框,直接返回拒绝。需要提前判断权限状态,引导用户到设置页开启权限。

优化后的权限检查逻辑:

boolean fineLocationDenied = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED;
boolean coarseLocationDenied = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED;

if (fineLocationDenied || coarseLocationDenied) {
    // 判断是否需要显示权限解释(用户未勾选"不再询问")
    boolean shouldShowRationale = ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION) 
            || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_COARSE_LOCATION);
    
    if (shouldShowRationale) {
        // 显示自定义提示后发起请求
        ModalDialog.Builder permissionInfoDialogBuilder = new ModalDialog.Builder(DashboardActivity.this);
        permissionInfoDialogBuilder.setType(ModalDialog.Type.DEFAULT_INFO)
                .setPositiveButton(android.R.string.ok, v -> {
                    Log.d(TAG, "requesting location permission");
                    locationPermissionRequest.launch(new String[]{
                            Manifest.permission.ACCESS_COARSE_LOCATION,
                            Manifest.permission.ACCESS_FINE_LOCATION
                    });
                })
                .setTextNegative(android.R.string.cancel)
                .setTitle(R.string.dashboard_request_location_permission_title)
                .setMessage(R.string.dashboard_request_location_permission_text)
                .setCloseable(false);
        permissionInfoDialogBuilder.create().show();
    } else {
        // 权限已被永久拒绝,引导用户到应用设置页
        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        Uri uri = Uri.fromParts("package", getPackageName(), null);
        intent.setData(uri);
        startActivity(intent);
    }
    return;
}

3. 后台位置权限的额外需求(若应用需要后台定位)

如果你的应用需要在后台访问位置,除了前台权限,还需在Manifest中添加ACCESS_BACKGROUND_LOCATION权限,且Android 13要求后台权限必须在获得前台权限后单独请求。

Manifest添加后台权限:

<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

单独请求后台权限示例:

// 确保已获得前台位置权限后再发起请求
if (fineLocationGranted != null && fineLocationGranted || coarseLocationGranted != null && coarseLocationGranted) {
    ActivityResultLauncher<String> backgroundLocationLauncher = registerForActivityResult(
            new ActivityResultContracts.RequestPermission(),
            isGranted -> {
                if (isGranted) {
                    Log.d(TAG, "Background location access granted");
                } else {
                    Log.e(TAG, "Background location access denied");
                }
            }
    );
    backgroundLocationLauncher.launch(Manifest.permission.ACCESS_BACKGROUND_LOCATION);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 11:20:03