239 lines
12 KiB
Plaintext
239 lines
12 KiB
Plaintext
page.title=Authorization
|
|
page.tags="AccountManager","oauth2"
|
|
@jd:body
|
|
|
|
<div id="qv-wrapper">
|
|
<div id="qv">
|
|
<h2>In this document</h2>
|
|
<ol>
|
|
<li><a href="#choose">Choosing an Account</a></li>
|
|
<li><a href="#obtain">Obtaining an Access Token</a></li>
|
|
<li><a href="#handle">Handling Exceptions</a></li>
|
|
<li><a href="#use">Using the Access Token</a></li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
|
|
<p>
|
|
Google Play services offers a standard authorization flow for all Google APIs and
|
|
all components of Google Play services. In addition, you can leverage the authorization
|
|
portion of the Google Play services SDK to gain authorization to services that are not yet supported
|
|
in the Google Play services platform by using the access token to manually make API
|
|
requests or using a client library provided by the service provider.
|
|
</p>
|
|
|
|
<p>For implementation details, see the sample in <code><android-sdk>/extras/google-play-services/samples/auth</code>,
|
|
which shows you how to carry out these basic steps for obtaining an access token.</p>
|
|
|
|
<h2 id="choose">Choosing an Account</h2>
|
|
<p>
|
|
Google Play services leverage existing accounts on an Android-powered device
|
|
to gain authorization to the services that you want to use. To obtain an access token,
|
|
a valid Google account is required and it must exist on the device. You can ask your users which
|
|
account they want to use by enumerating the Google accounts on the device or using the
|
|
built-in
|
|
<a href="{@docRoot}reference/com/google/android/gms/common/AccountPicker.html">{@code
|
|
AccountPicker}</a>
|
|
class to display a standard account picker view. You'll need the
|
|
{@link android.Manifest.permission#GET_ACCOUNTS}
|
|
permission set in your manifest file for both methods.
|
|
</p>
|
|
<p>
|
|
For example, here's how to gather all of the Google accounts on a device and return them
|
|
in an array. When obtaining an access token, only the email address of the account is
|
|
needed, so that is what the array stores:
|
|
</p>
|
|
|
|
<pre>
|
|
private String[] getAccountNames() {
|
|
mAccountManager = AccountManager.get(this);
|
|
Account[] accounts = mAccountManager.getAccountsByType(
|
|
GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE);
|
|
String[] names = new String[accounts.length];
|
|
for (int i = 0; i < names.length; i++) {
|
|
names[i] = accounts[i].name;
|
|
}
|
|
return names;
|
|
}
|
|
</pre>
|
|
<h2 id="obtain">Obtaining an Access Token</h2>
|
|
<p>
|
|
With an email address and the service scope you can now obtain an access token.
|
|
</p>
|
|
<p class="note"><strong>Note:</strong> Specify <code>"oauth2:<em>scope</em>"</code> for a single scope or
|
|
<code>"oauth2:<em>scope1</em> <em>scope2</em> <em>scope3</em>"</code> for multiple scopes.</p>
|
|
|
|
There are two general
|
|
ways to get a token:</p>
|
|
|
|
<ul>
|
|
<li>Call one of the two overloaded <a
|
|
href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context, java.lang.String, java.lang.String)"
|
|
>{@code GoogleAuthUtil.getToken()}</a> methods in a foreground activity where you can
|
|
display a dialog to the user to interactively handle authorization errors.</li>
|
|
<li>Call one of the three <a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getTokenWithNotification(android.content.Context, java.lang.String, java.lang.String, android.os.Bundle)"
|
|
>{@code getTokenWithNotification()}</a>
|
|
methods if you are trying to gain authorization in a background service or sync adapter so that a
|
|
notification is displayed if an error occurs.</a></li>
|
|
</ul>
|
|
|
|
<h3>Using getToken()</h3>
|
|
The following code snippet obtains an access token with an email address, the scope that you want to use for the service, and a {@link android.content.Context}:
|
|
|
|
<pre>
|
|
HelloActivity mActivity;
|
|
String mEmail;
|
|
String mScope;
|
|
String token;
|
|
|
|
...
|
|
try {
|
|
token = GoogleAuthUtil.getToken(mActivity, mEmail, mScope);
|
|
} catch {
|
|
...
|
|
}
|
|
</pre>
|
|
|
|
<p>Call this method off of the main UI thread since it executes network transactions. An easy way to do this
|
|
is in an {@link android.os.AsyncTask}.
|
|
The sample in the Google Play services SDK shows you how to wrap this call in an AsyncTask.
|
|
If authorization is successful, the token is returned. If not, the exceptions described in
|
|
<a href="#handle">Handling Exceptions</a>
|
|
are thrown that you can catch and handle appropriately.
|
|
</p>
|
|
|
|
<h3>Using getTokenWithNotification()</h3>
|
|
<p>If you are obtaining access tokens in a background service or sync adapter, there
|
|
are three overloaded
|
|
<a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getTokenWithNotification(android.content.Context, java.lang.String, java.lang.String, android.os.Bundle)"
|
|
>{@code getTokenWithNotification()}</a> methods
|
|
that you can use:</p>
|
|
<ul>
|
|
<li><a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getTokenWithNotification(android.content.Context, java.lang.String, java.lang.String, android.os.Bundle)"
|
|
>{@code getTokenWithNotification(Context context, String accountName, String scope, Bundle extras)}</a>:
|
|
For background services. Displays a notification to the user when authorization errors occur.</li>
|
|
<li><a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getTokenWithNotification(android.content.Context, java.lang.String, java.lang.String, android.os.Bundle, android.content.Intent)"
|
|
>{@code getTokenWithNotification(Context context, String accountName, String scope, Bundle extras, Intent callback)}</a>:
|
|
This method is for use in background services. It displays a notification to the user
|
|
when authorization errors occur. If a user clicks the notification and then authorizes the
|
|
app to access the account, the intent is broadcasted. When using this method:
|
|
<ul>
|
|
<li>Create a {@link android.content.BroadcastReceiver} that registers the intent and handles
|
|
it appropriately</li>
|
|
<li>In the app's manifest file, set the <a
|
|
href="{@docRoot}guide/topics/manifest/receiver-element.html#exported"><code>android:exported</code></a>
|
|
attribute to <code>true</code> for the broadcast receiver</li>
|
|
<li>Ensure that the intent is serializable using the {@link
|
|
android.content.Intent#toUri toUri(Intent.URI_INTENT_SCHEME)} and
|
|
{@link android.content.Intent#parseUri parseUri(intentUri, Intent.URI_INTENT_SCHEME)} methods.</li>
|
|
</ul>
|
|
<li><a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getTokenWithNotification(android.content.Context, java.lang.String, java.lang.String, android.os.Bundle, java.lang.String, android.os.Bundle)"
|
|
>{@code getTokenWithNotification(Context context, String accountName, String scope, Bundle extras, String authority, Bundle syncBundle)}</a>:
|
|
This method is for use in sync adapters. It displays a notification to the user when
|
|
errors occur. If a user clicks the notification and then authorizes the
|
|
app to access the account, the sync adapter retries syncing with the information
|
|
contained in the <code>syncBundle</code> parameter.</li>
|
|
</ul>
|
|
|
|
<p>See the sample in <code><android-sdk>/extras/google-play-services/samples/auth</code> for implementation details.</p>
|
|
|
|
|
|
|
|
|
|
<h2 id="handle">Handling Exceptions</h2>
|
|
<p>
|
|
When requesting an access token with
|
|
<a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context, java.lang.String, java.lang.String)"
|
|
>{@code GoogleAuthUtil.getToken()}</a>,
|
|
the following exceptions can be thrown:
|
|
</p>
|
|
<ul>
|
|
<li>
|
|
<a href="{@docRoot}reference/com/google/android/gms/auth/UserRecoverableAuthException.html"
|
|
>{@code UserRecoverableAuthException}</a>:
|
|
This exception is thrown when an error occurs that users can resolve, such as not yet granting access to their accounts or if they changed their password.
|
|
This exception class contains a {@link android.app.Activity#getIntent getIntent()}
|
|
method that you can call to obtain an intent that you can use with
|
|
{@link android.app.Activity#startActivityForResult startActivityForResult()}
|
|
to obtain the user's resolution. You will need to handle the
|
|
{@link android.app.Activity#onActivityResult onActivityResult()}
|
|
callback when this activity returns to take action based on the user's actions.
|
|
</li>
|
|
<li>
|
|
<a href="{@docRoot}reference/com/google/android/gms/auth/GooglePlayServicesAvailabilityException.html"
|
|
>{@code GooglePlayServicesAvailabilityException}</a>:
|
|
This exception is a special case of <a href="{@docRoot}reference/com/google/android/gms/auth/UserRecoverableAuthException.html"
|
|
>{@code UserRecoverableAuthException}</a>
|
|
and occurs when the actual Google Play services APK is not installed or unavailable.
|
|
This exception provides additional client support to
|
|
handle and fix this issue by providing an error code that describes the exact cause of the problem.
|
|
This exception also contains an intent that you can obtain and use to start
|
|
an activity to resolve the issue.
|
|
</li>
|
|
<li>
|
|
<a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthException.html">{@code
|
|
GoogleAuthException}</a>:
|
|
This exception is thrown when the authorization fails, such as when an invalid scope is
|
|
specified or if the email address used for authorization is actually not on the user's
|
|
device.
|
|
</li>
|
|
<li>
|
|
<a href="{@docRoot}reference/com/google/android/gms/auth/UserRecoverableNotifiedException.html"
|
|
>{@code UserRecoverableNotifiedException}</a>:
|
|
This exception is thrown when the authorization fails using one of the
|
|
<a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getTokenWithNotification(android.content.Context, java.lang.String, java.lang.String, android.os.Bundle)"
|
|
>{@code getTokenWithNotification()}</a> methods and if the error
|
|
is recoverable with a user action.
|
|
</li>
|
|
</ul>
|
|
<p>
|
|
For more information on how to handle these exceptions and code snippets, see the reference
|
|
documentation for the
|
|
<a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html">{@code
|
|
GoogleAuthUtil}</a> class.
|
|
</p>
|
|
|
|
|
|
|
|
|
|
<h2 id="use">Using the Access Token</h2>
|
|
<p>
|
|
Once you have successfully obtained a token, you can use it to access Google services.
|
|
Many Google services provide client libraries, so it is recommended that you use these when
|
|
possible, but you can make raw HTTP requests as well with the token. The following example
|
|
shows you how to do this and handle HTTP error and success responses accordingly:
|
|
</p>
|
|
|
|
<pre>
|
|
URL url = new URL("https://www.googleapis.com/oauth2/v1/userinfo?access_token="
|
|
+ token);
|
|
HttpURLConnection con = (HttpURLConnection) url.openConnection();
|
|
int serverCode = con.getResponseCode();
|
|
//successful query
|
|
if (serverCode == 200) {
|
|
InputStream is = con.getInputStream();
|
|
String name = getFirstName(readResponse(is));
|
|
mActivity.show("Hello " + name + "!");
|
|
is.close();
|
|
return;
|
|
//bad token, invalidate and get a new one
|
|
} else if (serverCode == 401) {
|
|
GoogleAuthUtil.invalidateToken(mActivity, token);
|
|
onError("Server auth error, please try again.", null);
|
|
Log.e(TAG, "Server auth error: " + readResponse(con.getErrorStream()));
|
|
return;
|
|
//unknown error, do something else
|
|
} else {
|
|
Log.e("Server returned the following error code: " + serverCode, null);
|
|
return;
|
|
}
|
|
</pre>
|
|
|
|
<p>
|
|
Notice that you must manually invalidate the token if the response from the server
|
|
signifies an authorization error (401). This could mean the access token
|
|
being used is invalid for the service's scope or the token may have expired. If this is the
|
|
case, obtain a new token using <a
|
|
href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context, java.lang.String, java.lang.String)"
|
|
>{@code GoogleAuthUtil.getToken()}</a>.
|
|
</p> |