原文链接 Exploring Android Q: Location Permissions。
目录
前台位置权限
后台位置权限
本文最初发表于 https://joebirch.co/
上周(本文发表于2019.3.29)我们看到了 Android Q 测试版的发布
这个 Android 版本带来了一系列令人兴奋的变化,我们需要让我们的 apps 为这些变化做好准备。在这个文章系列中,我将深入讨论其中的每个变更,以便我们充分准备好来让我们的 apps 就绪!
注意:您可以在这儿找到本文的代码。
正如 Android Q 的测试版发行说明中所述,我们看到的一个变化是我们在应用程序内部处理用户位置的方式 - 这些更改会影响在前台和后台中位置的访问。这使我们的用户可以更好地控制他们希望 apps 能够访问其位置的时机 - 允许他们将其限制为仅当 app 当前正在使用时。在这篇文章中,我想快速了解这些变更将如何影响应用程序,以及我们需要做些什么来适应这些变化。
在某些情况下您的应用程序需要在前台运行时访问用户位置。例如,您的 app 可能会向用户提供导航功能 - 一旦用户从您的 app 导航到其主屏幕,您就会希望继续访问其位置以继续向他们提供导航。如果您的应用程序需要访问此位置数据,那么当访问它时,让您的用户知道原因是非常重要的。
首先,需要将使用用户位置的任何此类服务声明为位置前台服务。 这可以通过在清单文件中声明服务时使用 foregroundServiceType 来完成。
在我们尝试启动前台服务之前,我们需要确保我们拥有用户所需的权限。我们可以通过检查 ACCESS_COARSE_LOCATION 权限来完成此操作。现在,这不是一个新的权限 - 事实上,它从API level1 时就已经存在了。但是,我们之前只需要在我们应用程序的清单文件中定义 - 现在我们必须在运行时请求此权限。您可以看到它现在如何让我们的用户更好地控制如何使用此权限。
val hasLocationPermission = ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED
if (hasLocationPermission) {
// 处理位置更新
} else {
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION), REQUEST_CODE_FOREGROUND)
}
在上面的代码中,您可以看到我们首先检查是否具有位置权限。如果有,那么我们可以继续处理位置流程,否则我们必须从用户那里请求权限。如果是这种情况,那么我们将在调用的类中的 onRequestPermissionsResult() 回调中接收权限状态。
当我们请求此权限时,我们的用户将看到以下对话框:
如你所见,权限的意图已经非常明确了 - 我们的 app 只能在前台访问他们的位置(例如,该 app 正在被使用)。如果用户在任何时候拒绝了此权限,并且我们再次请求它,那么他们(用户)将看到对话框的略微变化:
与 android 中的 运行时权限 通常的工作方式类似,我们知道显示了一个让用户能请求不再被询问的选项。由于此功能,只有在需要该权限的时候,才请求该前台位置访问,这一点很重要。这将指导您的用户了解为什么在当前情境中需要权限,而不是让人觉得无缘无故地要求权限。
当我们的 app 在后台访问用户位置时,情况会有所不同。我们首先需要向清单文件添加一个新的权限,即 ACCESS_BACKGROUND_LOCATION 权限。尽管在清单中声明了这个权限,但用户仍然可以随时撤销它。
注意,这里我们不需要将 foregroundServiceType 服务类型添加到我们的服务声明中,这是因为我们不需要在 app 之外运行的瞬时权限;此后台权限已经使我们的应用程序能够执行此操作。
除了上述内容之外,用户还需要在运行时授予权限。因此,在我们尝试从后台访问用户位置之前,我们需要确保我们拥有用户所需的权限。我们可以通过检查 ACCESS_BACKGROUND_LOCATION 权限来完成此操作。您可以再次看到它现在如何让我们的用户更好地控制如何使用此权限,并避免滥用后台位置访问。
我们检查权限的代码可能如下所示:
val hasForegroundLocationPermission = ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED
if (hasForegroundLocationPermission) {
val hasBackgroundLocationPermission = ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED
if (hasBackgroundLocationPermission) {
// 处理位置更新
} else {
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION), REQUEST_CODE_BACKGROUND)
}
} else {
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION), REQUEST_CODE_BACKGROUND)
}
您会注意到,此代码与我们为前台位置权限定义的检查非常相似。这里我们检查两个权限,如果用户出于某种原因拒绝我们的后台访问,我们将在位置检索中进行回退。
当我们请求此权限时,将显示以下对话框:
权限的意图已经非常明确 - 我们的 app 将能够在后台访问他们的位置。如果用户在任何时候拒绝了此权限,并且我们再次请求它,那么显示给他们的对话框会有略微变化:
与 android 中的运行时权限通常的工作方式类似,我们知道显示了一个让用户能请求不再被询问的选项。因为此功能,您只在需要时请求这个后台位置访问是很重要的。这将指导您的用户了解为什么在当前情境中需要这个权限,而不是让用户感觉它是无缘无故被请求的。
从本文中我们可以看到,Android Q 改变了我们的应用程序使用位置权限的方式。无论是在前台还是后台,我们的 apps 都将无法从服务中自由访问用户位置。为了支持向后兼容性,如果应用程序不以 Q 为目标,那么如果声明了 COARSE 或 FINE 权限,那么 ACCESS_BACKGROUND_LOCATION 权限也将被添加添加上。类似地,在运行时请求这两者中的任何一个也将授予这个权限。
这些更改使我们的用户能够更好地控制应用程序访问其位置的方式,从而使我们能够创建考虑到用户隐私和安全的 apps。