ActivityCompat.requestPermissions对于targetSdkVersion 30不起作用。

8

我拥有以下权限:

private static final String[] LOCATION_PERMISSIONS = {
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_BACKGROUND_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION,
};

我尝试在我的代码中使用以下行来请求权限(activity 是当前活动的引用):

ActivityCompat.requestPermissions(activity, LOCATION_PERMISSIONS, 1);

如果我在 build.gradle 文件中设置 targetSdkVersion 为 29 或更低版本,一切都正常。权限对话框会出现,我可以点击其中的按钮来授予权限。一切都很好。

但是!当我将目标 sdk 更改为 Android 11: targetSdkVersion 30 后,这个功能就停止工作了。权限系统对话框不会出现,我无法为我的应用程序授予位置权限。

那么有谁能帮助我吗?我做错了什么?我应该在我的代码中做出哪些改变 - 才能正确地处理 Android 11?

现在,我可以在 Android 11 模拟器下运行我的应用程序,只要将 targetSdkVersion 设置为 29 即可。也许我根本不需要将目标 sdk 版本增加到:30?


解决方案如下:

步骤1:应用程序应请求前台位置权限:

private static final String[] FOREGROUND_LOCATION_PERMISSIONS = {
            Manifest.permission.ACCESS_FINE_LOCATION,       // GPS
            Manifest.permission.ACCESS_COARSE_LOCATION,     // GPS approximate location
    };

第二步:应用程序应请求后台定位权限:

@RequiresApi(api = Build.VERSION_CODES.Q)
    private static final String[] BACKGROUND_LOCATION_PERMISSIONS = {
            Manifest.permission.ACCESS_BACKGROUND_LOCATION,
    };    

只有按照这个顺序!

ActivityCompat.requestPermissions(activity, FOREGROUND_LOCATION_PERMISSIONS, 1);
// Check the first statement grant needed permissions, and then run the second line:
ActivityCompat.requestPermissions(activity, BACKGROUND_LOCATION_PERMISSIONS, 1);

如果我首先尝试请求后台权限 - 这将不起作用。

如果我只请求后台权限(没有已授予的前台权限)- 这将不起作用。

我应该先请求前台权限,然后再逐个请求后台权限。

1个回答

9
在Android 11中,如果用户还没有授予前台位置权限,则后台位置权限请求将被隐式拒绝。同时包含前台和后台位置权限的请求被视为无效:
如果您的应用程序针对Android 11(API级别30)或更高版本,则系统会执行此最佳做法。如果您同时请求前台位置权限和后台位置权限,则系统会忽略该请求,并且不会授予您的应用程序任何权限。
请参阅“运行时请求位置访问权限”。

1
@RussiaDroneFlights ACCESS_BACKGROUND_LOCATION与普通权限不同。根据我刚刚测试的结果,您的应用程序需要已经持有前台位置权限,否则此请求将立即被拒绝。如果您已经持有前台位置权限,则系统窗口将打开,允许用户将位置权限提升为“始终允许”。但是,如果用户没有这样做,那么您将无法再次请求它,用户必须手动导航到您的应用程序权限设置,如果他希望启用它。 - Pawel
1
是的,我已经理解了。第一步。应用程序应请求前台位置权限:             Manifest.permission.ACCESS_FINE_LOCATION,             Manifest.permission.ACCESS_COARSE_LOCATION,location第二步。应用程序应请求后台位置权限: @RequiresApi(api = Build.VERSION_CODES.Q)     private static final String [] BACKGROUND_LOCATION_PERMISSIONS = {             Manifest.permission.ACCESS_BACKGROUND_LOCATION,     };只有按照这个顺序! 如果我首先尝试请求后台权限-它将无法工作。 - Vitaly
1
我的应用程序需要位置权限,但从不需要或使用位置信息。这是因为 Android 愚蠢地要求获取位置权限才能扫描(而非传输)BLE 设备。这意味着用户除了运行该应用程序以外,将永远不会进行任何需要位置权限的操作,因为该应用程序只是在寻找蓝牙设备。因此,在 Android 11 上无法显示权限对话框,我只请求后台权限而非前台权限。 - Brian Reinhold
@BrianReinhold 是的,你必须执行两次权限请求 - 一次是前台位置请求,如果被授予,则可以跟进后台请求。 - Pawel
是的,我继续实现了我猜测你的意思,并且确实有效。真是太麻烦了。而且我甚至没有使用位置信息或公开它!我只是扫描BTLE健康设备。 - Brian Reinhold
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接