Google Play 服务和运行时权限
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
自 Android 6.0 Marshmallow 起,Android 使用一种权限模型,可简化应用安装和自动更新流程。权限是在运行时请求的,而不是在应用安装之前请求的。此外,用户还可以选择拒绝授予特定权限。
为了让用户能够灵活地管理权限,您需要确保应用在用户启用或停用特定权限时能够按预期运行。
Google Play 服务本身具有运行时权限,用户可以选择拒绝这些权限,而无需拒绝您的应用专门请求的权限。Google Play 服务会自动获取支持其 API 所需的所有权限。不过,您的应用仍应根据需要检查和请求运行时权限,并在用户拒绝向 Google Play 服务授予应用所用 API 所需的权限时,妥善处理错误。
在设置运行时可能需要的权限时,最好管理用户的预期。以下最佳实践有助于您避免潜在问题。
前提条件
您需要在 AndroidManifest.xml
文件中声明权限。例如:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
指南
在调用 API 之前验证权限
在 AndroidManifest.xml
文件中声明要使用的 API 后,请先验证您是否拥有所需的权限,然后再调用 API。可以使用 ActivityCompat
或 ContextCompat
的 checkSelfPermission
方法来完成此操作。
如果调用返回 false,则表示权限未获授予,您应使用 requestPermissions
请求权限。此操作的响应会通过回调返回,您将在下一步中看到。
例如:
Kotlin
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Request Permissions Now
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
REQUEST_LOCATION_PERMISSION_CODE)
} else {
// permission has been granted, continue as usual
val locationResult = LocationServices
.getFusedLocationProviderClient(this /* Context */)
.lastLocation
}
Java
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Request Permissions Now
ActivityCompat.requestPermissions(
this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_LOCATION_PERMISSION_CODE);
} else {
// permission has been granted, continue as usual
Task locationResult = LocationServices
.getFusedLocationProviderClient(this /** Context */)
.getLastLocation();
}
实现请求权限回调
如果用户尚未授予应用所需的权限,则应调用 requestPermissions
方法来请求用户授予这些权限。用户的回答会捕获在 onRequestPermissionsResult
回调中。您的应用应实现此方法,并始终检查返回值,因为请求可能会被拒绝或取消。您还可以一次性请求并检查多项权限,而以下示例仅检查一项权限。
Kotlin
fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array,
grantResults: IntArray
) {
if (requestCode == REQUEST_LOCATION_PERMISSION_CODE) {
if (grantResults.singleOrNull() == PackageManager.PERMISSION_GRANTED) {
// We can now safely use the API we requested access to
val locationResult: Task = LocationServices
.getFusedLocationProviderClient(this /* Context */)
.lastLocation // Request the last known location.
} else {
// Permission was denied or request was cancelled
}
}
}
Java
public void onRequestPermissionsResult(int requestCode,
String[] permissions,
int[] grantResults) {
if (requestCode == REQUEST_LOCATION_PERMISSION_CODE) {
if(grantResults.length == 1
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// We can now safely use the API we requested access to
Task locationResult = LocationServices
.getFusedLocationProviderClient(this /** Context */)
.getLastLocation(); // Request the last known location.
} else {
// Permission was denied or request was cancelled
}
}
}
显示权限使用理由
如果应用请求的权限是应用核心功能所必需的,并且用户之前拒绝了该权限请求,则应用应在再次请求该权限之前显示额外的说明。当用户了解需要某项权限的原因以及授予该权限后可立即获得的好处时,他们更有可能会授予该权限。
在这种情况下,在调用 requestPermissions
之前,您应调用 shouldShowRequestPermissionRationale
。如果返回 true,您应创建一些界面来显示权限的其他背景信息。
例如,您的代码可能如下所示:
Kotlin
private const val REQUEST_LOCATION_PERMISSION_CODE = 2
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Check Permissions Now
if ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) {
// Display UI and wait for user interaction
} else {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
REQUEST_LOCATION_PERMISSION_CODE)
}
} else {
// Permission has already been granted, continue as usual
val locationResult: Task = LocationServices
.getFusedLocationProviderClient(this /* Context */)
.lastLocation
}
Java
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Check Permissions Now
private static final int REQUEST_LOCATION_PERMISSION_CODE = 2;
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
// Display UI and wait for user interaction
} else {
ActivityCompat.requestPermissions(
this, new String[]{Manifest.permission.LOCATION_FINE},
REQUEST_LOCATION_PERMISSION_CODE);
}
} else {
// permission has been granted, continue as usual
Task locationResult = LocationServices
.getFusedLocationProviderClient(this /** Context */)
.getLastLocation();
}
Google Play 服务 API 调用会自动显示一个对话框(如果客户端是使用 Activity
实例化的)或系统托盘通知(如果客户端是使用 Context
实例化的),用户可以点按该对话框或通知来启动权限解析 intent。获得相应权限后,系统会将调用加入队列并重试。
如未另行说明,那么本页面中的内容已根据知识共享署名 4.0 许可获得了许可,并且代码示例已根据 Apache 2.0 许可获得了许可。有关详情,请参阅 Google 开发者网站政策。Java 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2025-08-08。
[null,null,["最后更新时间 (UTC):2025-08-08。"],[[["\u003cp\u003eThe \u003ccode\u003ePlayers\u003c/code\u003e interface is deprecated and developers should use \u003ccode\u003ePlayersClient\u003c/code\u003e instead for player functionality.\u003c/p\u003e\n"],["\u003cp\u003eIt provides access to player information like the current player's profile and ID.\u003c/p\u003e\n"],["\u003cp\u003eIt allows comparing profiles and searching for players using intents.\u003c/p\u003e\n"],["\u003cp\u003eMethods related to loading connected, invitable, and recently played with players are deprecated due to the removal of Google+ integration.\u003c/p\u003e\n"]]],["Android apps, from version 6.0, manage permissions at runtime. Developers must declare permissions in `AndroidManifest.xml` and verify them using `checkSelfPermission` before API calls. If permissions are not granted, use `requestPermissions`. Handle user responses in `onRequestPermissionsResult`, addressing denials. If permissions are critical and previously denied, show rationale with `shouldShowRequestPermissionRationale`. If `connect()` fails handle it appropriately. Newer API calls automatically prompt users to resolve permission issues.\n"],null,["# Google Play services and runtime permissions\n\n\u003cbr /\u003e\n\nSince Android 6.0 Marshmallow, Android uses a\n[permissions model](https://developer.android.com/preview/features/runtime-permissions.html) that streamlines the app install and\nauto-update process. Permissions are requested at runtime instead of before\napp installation. Additionally, users can choose to deny specific permissions.\nTo give users this flexibility, you need to make sure that your app behaves as\nexpected when a user enables or disables a specific permission.\n\nGoogle Play services itself has runtime permissions that users can choose to\ndeny separately from those permissions specifically requested by your app.\nGoogle Play services automatically obtains all permissions it needs to support\nits APIs. However, your app should still check and request runtime permissions\nas necessary and appropriately handle errors in cases where a user has denied\nGoogle Play services a permission required for an API your app uses.\n\nIt's good practice to manage the user's expectations in setting permissions\nthat the runtime may require. The following best practices will help you avoid\npotential issues.\n\nPrerequisites\n-------------\n\nYou'll need to declare permissions in your `AndroidManifest.xml` file.\nFor example: \n\n \u003cuses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/\u003e\n\nGuidelines\n----------\n\n### Verify permissions before calling APIs\n\nOnce you've declared the APIs that you want to use in your `AndroidManifest.xml`\nfile, verify that you have the required permission before calling an API. This\ncan be done using the `checkSelfPermission` method of\n[`ActivityCompat`](https://developer.android.com/reference/androidx/core/app/ActivityCompat) or [`ContextCompat`](https://developer.android.com/reference/androidx/core/content/ContextCompat).\n\nIf the call returns false this means the permissions aren't granted and you\nshould use `requestPermissions` to request them. The response to this is\nreturned in a callback which you will see in the next step.\n\nFor example: \n\n### Kotlin\n\n```kotlin\n if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)\n != PackageManager.PERMISSION_GRANTED) {\n // Request Permissions Now\n ActivityCompat.requestPermissions(\n this,\n arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),\n REQUEST_LOCATION_PERMISSION_CODE)\n } else {\n // permission has been granted, continue as usual\n val locationResult = LocationServices\n .getFusedLocationProviderClient(this /* Context */)\n .lastLocation\n }\n```\n\n### Java\n\n```java\n if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)\n != PackageManager.PERMISSION_GRANTED) {\n // Request Permissions Now\n ActivityCompat.requestPermissions(\n this,\n new String[]{Manifest.permission.ACCESS_FINE_LOCATION},\n REQUEST_LOCATION_PERMISSION_CODE);\n } else {\n // permission has been granted, continue as usual\n Task locationResult = LocationServices\n .getFusedLocationProviderClient(this /** Context */)\n .getLastLocation();\n }\n```\n\n### Implement the request permission callback\n\nIf the permission your app needs hasn't been granted by the user, the\n[`requestPermissions`](https://developer.android.com/reference/androidx/core/app/ActivityCompat#requestPermissions(android.app.Activity,java.lang.String%5B%5D,int)) method should be called to ask the\nuser to grant them. The response from the user is captured in the\n[`onRequestPermissionsResult`](https://developer.android.com/reference/android/app/Activity.html#onRequestPermissionsResult(int,%20java.lang.String%5B%5D,%20int%5B%5D)) callback. Your app should\nimplement this and always check the return values because the request could be\ndenied or canceled. You can also request and check for multiple permissions at\nonce--the following sample only checks for a single permission. \n\n### Kotlin\n\n```kotlin\n fun onRequestPermissionsResult(\n requestCode: Int,\n permissions: Array,\n grantResults: IntArray\n ) {\n if (requestCode == REQUEST_LOCATION_PERMISSION_CODE) {\n if (grantResults.singleOrNull() == PackageManager.PERMISSION_GRANTED) {\n // We can now safely use the API we requested access to\n val locationResult: Task = LocationServices\n .getFusedLocationProviderClient(this /* Context */)\n .lastLocation // Request the last known location.\n } else {\n // Permission was denied or request was cancelled\n }\n }\n }\n```\n\n### Java\n\n```java\n public void onRequestPermissionsResult(int requestCode,\n String[] permissions,\n int[] grantResults) {\n if (requestCode == REQUEST_LOCATION_PERMISSION_CODE) {\n if(grantResults.length == 1\n && grantResults[0] == PackageManager.PERMISSION_GRANTED) {\n // We can now safely use the API we requested access to\n Task locationResult = LocationServices\n .getFusedLocationProviderClient(this /** Context */)\n .getLastLocation(); // Request the last known location.\n } else {\n // Permission was denied or request was cancelled\n }\n }\n }\n```\n\n### Show the permission rationale\n\nIf the permissions your app requests are necessary for the core features of the\napp and the user has previously denied the permission request, your app should\ndisplay an additional explanation before requesting the permission again. Users\nare more likely to grant permissions when they understand the why the permission\nis needed and the immediate benefit for them.\n\nIn this case, before the calling `requestPermissions`, you should call\n[`shouldShowRequestPermissionRationale`](https://developer.android.com/reference/androidx/core/app/ActivityCompat#shouldShowRequestPermissionRationale(android.app.Activity,java.lang.String)). If it returns\ntrue, you should create some UI to display additional context for the\npermission.\n\nFor example, your code might look like this: \n\n### Kotlin\n\n```kotlin\n private const val REQUEST_LOCATION_PERMISSION_CODE = 2\n if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)\n != PackageManager.PERMISSION_GRANTED) {\n // Check Permissions Now\n if ActivityCompat.shouldShowRequestPermissionRationale(\n this,\n Manifest.permission.ACCESS_FINE_LOCATION\n ) {\n // Display UI and wait for user interaction\n } else {\n ActivityCompat.requestPermissions(\n this,\n arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),\n REQUEST_LOCATION_PERMISSION_CODE)\n }\n } else {\n // Permission has already been granted, continue as usual\n val locationResult: Task = LocationServices\n .getFusedLocationProviderClient(this /* Context */)\n .lastLocation\n }\n```\n\n### Java\n\n```java\n if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)\n != PackageManager.PERMISSION_GRANTED) {\n // Check Permissions Now\n private static final int REQUEST_LOCATION_PERMISSION_CODE = 2;\n if (ActivityCompat.shouldShowRequestPermissionRationale(this,\n Manifest.permission.ACCESS_FINE_LOCATION)) {\n // Display UI and wait for user interaction\n } else {\n ActivityCompat.requestPermissions(\n this, new String[]{Manifest.permission.LOCATION_FINE},\n REQUEST_LOCATION_PERMISSION_CODE);\n }\n } else {\n // permission has been granted, continue as usual\n Task locationResult = LocationServices\n .getFusedLocationProviderClient(this /** Context */)\n .getLastLocation();\n }\n```\n\nGoogle Play services API calls will automatically display either a dialog (if\nthe client is instantiated with an `Activity`) or system tray notification (if\nthe client is instantiated with a `Context`) that the user can tap to start the\npermissions resolution intent. Calls will be enqueued and retried once the\npermission is granted."]]