Android 11 用户无法授予后台位置权限?

Posted

技术标签:

【中文标题】Android 11 用户无法授予后台位置权限?【英文标题】:Android 11 users can’t grant background location permission? 【发布时间】:2021-01-22 13:51:51 【问题描述】:

android 11 开始,面向 SDK 30+ 的应用将不会向用户显示多次授予应用后台位置权限的选项。如果最初未授予,则需要用户转到设置页面。 我们如何将用户带到正确的设置页面?

当您应用中的某个功能请求运行 Android 11 或更高版本的设备上的后台位置时,系统对话框不包含用于启用后台位置访问的按钮。为了启用后台位置访问,用户必须在设置页面上为您的应用的位置权限设置“始终允许”选项,如有关如何请求后台位置的指南中所述。

https://developer.android.com/about/versions/11/privacy/location#change-details

授予背景位置的设置选项的用户可见标签(例如,图 3 中的始终允许)。您可以调用getBackgroundPermissionOptionLabel() 来获取此标签。此方法的返回值已本地化为用户的设备语言偏好。

https://developer.android.com/training/location/permissions#request-location-access-runtime

虽然 Android 提供了一个新的 API 来获取此设置页面标签,但没有记录的 API 可以直接调出此设置页面。您最接近的方法是调出应用程序特定的设置页面,如下所述。从那里,用户必须执行至少两次点击才能深入到权限 -> 位置以启用后台访问。这是一个繁重的过程,许多用户无法完成。

在这个问题中已经记录了很长一段时间以来缺少用于调出设置页面的 API,但在 Android 11 版本中更为重要,因为没有其他授予后台权限的方式。

How to programmatically open the Permission Screen for a specific app on Android Marshmallow?

在第一次询问用户时,可以使用如下代码将用户带到正确的设置页面:requestPermissions(arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION), PERMISSION_REQUEST_BACKGROUND_LOCATION)。这只会工作一次。如果用户拒绝了该权限(或者甚至在没有授予权限的情况下不小心回击或离开了屏幕),这将永远不会再次起作用,并且用户必须按照上述方式手动深入设置。

除了指示用户在“设置”中寻找正确的页面之外,真的没有其他方法可以帮助用户在初始拒绝后授予后台位置权限吗?

我错过了什么吗?如果不是,这不是 Android 11 的主要可用性问题吗?

在第一次提示中触发正确设置页面所需的完整代码示例在这里:

        if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) 
            if (checkSelfPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
                != PackageManager.PERMISSION_GRANTED
            ) 
                if (shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_BACKGROUND_LOCATION)) 
                    val builder =
                        AlertDialog.Builder(this)
                    builder.setTitle("This app needs background location access")
                    builder.setMessage("Please grant location access so this app can detect beacons in the background.")
                    builder.setPositiveButton(android.R.string.ok, null)
                    builder.setOnDismissListener 
                        requestPermissions(
                            arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION),
                            PERMISSION_REQUEST_BACKGROUND_LOCATION
                        )
                    
                    builder.show()
                 else 
                    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) 
                        val builder =
                            AlertDialog.Builder(this)
                        builder.setTitle("Functionality limited")
                        builder.setMessage("Since background location access has not been granted, this app will not be able to discover beacons in the background.  Please go to Settings -> Applications -> Permissions and grant background location access to this app.")
                        builder.setPositiveButton(android.R.string.ok, null)
                        builder.setOnDismissListener 
                            val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                            val uri: Uri = Uri.fromParts("package", packageName, null)
                            intent.data = uri
                            // This will take the user to a page where they have to click twice to drill down to grant the permission
                            startActivity(intent)
                        
                        builder.show()
                    
                
            
         else 
            if (!shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) 
                requestPermissions(
                    arrayOf(
                        Manifest.permission.ACCESS_FINE_LOCATION
                        /*Manifest.permission.ACCESS_BACKGROUND_LOCATION*/
                    ),
                    PERMISSION_REQUEST_FINE_LOCATION
                )
             else 
                val builder = AlertDialog.Builder(this)
                builder.setTitle("Functionality limited")
                builder.setMessage("Since location access has not been granted, this app will not be able to discover beacons.  Please go to Settings -> Applications -> Permissions and grant location access to this app.")
                builder.setPositiveButton(android.R.string.ok, null)
                builder.setOnDismissListener 
                    val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                    val uri: Uri = Uri.fromParts("package", packageName, null)
                    intent.data = uri
                    // This will take the user to a page where they have to click twice to drill down to grant the permission
                    startActivity(intent)
                
                builder.show()
            
        


【问题讨论】:

我遇到了完全相同的问题。我同意这对于任何需要后台位置权限的开发人员来说都是一个问题。我想为其他读者添加额外的注释:(1)在 API 30+ 上,您首先需要基本的位置权限,然后再请求后台位置权限 - 否则它根本不会进入权限屏幕。 (2) 当您请求后台位置权限并将其发送到权限请求屏幕时,只有当用户只点击后退按钮时,它才会“锁定”用户。如果他们点击任何选项然后返回,请求将再次起作用。 面对同样的问题,我阅读了整个文档,但仍然不知道如何使用getBackgroundPermissionOptionLabel() @StephenRuda 您应该发布此评论作为答案。谢谢! 这必须作为 Android 11 中的一个错误来解决。如果这是预期的行为,那么 Google 的程序员不应该得到报酬。 medium.com/swlh/… 【参考方案1】:

感谢@Stephen Ruda的回答

我遇到了完全相同的问题。我同意这对于任何需要后台位置许可的开发人员来说都是一个问题。我想为其他读者添加额外的注释:

(1) 在 API 30+ 上,您首先需要基本的位置权限,然后再请求后台位置权限 - 否则,它根本不会进入权限屏幕。

(2) 当您请求后台位置权限并将其发送到权限请求屏幕时,如果用户仅点击后退按钮,它只会“锁定”用户。如果他们点击任何选项然后返回,请求将再次起作用。

【讨论】:

这对于首次提示是正确的。但是,我的具体问题是关于用户未能授予该权限(故意或意外)之后会发生什么,并且该应用程序希望帮助用户找到正确的权限屏幕以在以后授予权限。据我所知,这是不可能直接链接的。 如果您将应用程序中被拒绝的权限保存为 SharedPreference,然后,如果用户需要权限,您检查该首选项,如果之前被拒绝,您打开应用程序的意图权限,使用类似 startActivity(new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, ...); 是的,Luciano,这正是我的代码所采用的方法,如问题所示。但是,Android 上Settings.ACTION_APPLICATION_DETAILS_SETTINGS 的设置登录屏幕比需要授予后台位置权限的位置高两级。问题是许多用户即使想找也找不到。 嗯,这不是最好的解决方案,我也有这个问题。我为需要此权限的盲人用户提供了可访问性工具,现在 Android >= 11 的流程发生了变化(由于需要提供两个权限,它们使它变得更加复杂)。不知道有没有别的办法。 我体验过第 (2) 项,但不明白发生了什么……现在我知道我不是唯一一个!谢谢!...顺便说一句,我真的认为谷歌最近在搞砸事情。【参考方案2】:

应该没有什么不同,但这对我每次都有效(不仅仅是一次):

ActivityCompat.requestPermissions(activity, new String[]Manifest.permission.ACCESS_BACKGROUND_LOCATION, REQUEST_BACKGROUND_LOCATION_PERMISSION);

【讨论】:

如果之前没有给前台位置权限,后台位置权限的请求会失败。 显然,您需要先请求它。该问题抱怨无法不止一次请求后台许可。这段代码似乎每次都对我有用(在收到常规位置许可后)。 @SirCodesalot 在这种情况下,它不止一次

以上是关于Android 11 用户无法授予后台位置权限?的主要内容,如果未能解决你的问题,请参考以下文章

Android M及以上位置课程和位置精细返回权限授予true

什么条件使 iOS 13 要求用户授予“始终”位置访问权限?

这个应用程序如何立即请求后台位置权限?

Swift - 如果未授予核心位置请求权限

Android 融合位置更新

Firebase 规则:动态授予特定用户访问权限