Home | History | Annotate | Download | only in play-services
      1 page.title=Authorization
      2 page.tags="AccountManager","oauth2"
      3 @jd:body
      4 
      5 <div id="qv-wrapper">
      6   <div id="qv">    
      7     <h2>In this document</h2>
      8     <ol>
      9     <li><a href="#choose">Choosing an Account</a></li>
     10     <li><a href="#obtain">Obtaining an Access Token</a></li>
     11     <li><a href="#handle">Handling Exceptions</a></li>
     12     <li><a href="#use">Using the Access Token</a></li>
     13     </ol>
     14   </div>
     15 </div>
     16 
     17 <p>
     18     Google Play services offers a standard authorization flow for all Google APIs and
     19     all components of Google Play services. In addition, you can leverage the authorization
     20     portion of the Google Play services SDK to gain authorization to services that are not yet supported 
     21     in the Google Play services platform by using the access token to manually make API
     22     requests or using a client library provided by the service provider.
     23 </p>
     24 
     25 <p>For implementation details, see the sample in <code>&lt;android-sdk&gt;/extras/google-play-services/samples/auth</code>,
     26 which shows you how to carry out these basic steps for obtaining an access token.</p>
     27 
     28 <h2 id="choose">Choosing an Account</h2>
     29 <p>
     30     Google Play services leverage existing accounts on an Android-powered device
     31     to gain authorization to the services that you want to use. To obtain an access token,
     32     a valid Google account is required and it must exist on the device. You can ask your users which
     33     account they want to use by enumerating the Google accounts on the device or using the
     34     built-in 
     35 <a href="{@docRoot}reference/com/google/android/gms/common/AccountPicker.html">{@code
     36 AccountPicker}</a>
     37     class to display a standard account picker view. You'll need the
     38     {@link android.Manifest.permission#GET_ACCOUNTS}
     39     permission set in your manifest file for both methods.
     40 </p>
     41 <p>
     42     For example, here's how to gather all of the Google accounts on a device and return them
     43     in an array. When obtaining an access token, only the email address of the account is 
     44     needed, so that is what the array stores:
     45 </p>
     46 
     47 <pre>
     48 private String[] getAccountNames() {
     49     mAccountManager = AccountManager.get(this);
     50     Account[] accounts = mAccountManager.getAccountsByType(
     51             GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE);
     52     String[] names = new String[accounts.length];
     53     for (int i = 0; i &lt; names.length; i++) {
     54         names[i] = accounts[i].name;
     55     }
     56     return names;
     57 }
     58 </pre>
     59 <h2 id="obtain">Obtaining an Access Token</h2>
     60 <p>
     61   With an email address and the service scope you can now obtain an access token.
     62 </p>
     63 <p class="note"><strong>Note:</strong> Specify <code>"oauth2:<em>scope</em>"</code> for a single scope or
     64   <code>"oauth2:<em>scope1</em> <em>scope2</em> <em>scope3</em>"</code> for multiple scopes.</p>
     65 
     66 There are two general
     67   ways to get a token:</p>
     68 
     69     <ul>
     70       <li>Call one of the two overloaded <a
     71       href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context, java.lang.String, java.lang.String)"
     72       >{@code GoogleAuthUtil.getToken()}</a> methods in a foreground activity where you can
     73         display a dialog to the user to interactively handle authorization errors.</li>
     74       <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)"
     75       >{@code getTokenWithNotification()}</a>
     76         methods if you are trying to gain authorization in a background service or sync adapter so that a
     77         notification is displayed if an error occurs.</a></li>
     78     </ul>
     79 
     80     <h3>Using getToken()</h3>
     81     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}:
     82 
     83 <pre>
     84 HelloActivity mActivity;
     85 String mEmail;
     86 String mScope;
     87 String token;
     88 
     89 ...
     90 try {
     91     token = GoogleAuthUtil.getToken(mActivity, mEmail, mScope);
     92 } catch {
     93     ...
     94 }
     95 </pre>
     96 
     97 <p>Call this method off of the main UI thread since it executes network transactions. An easy way to do this
     98   is in an {@link android.os.AsyncTask}.
     99   The sample in the Google Play services SDK shows you how to wrap this call in an AsyncTask.
    100   If authorization is successful, the token is returned. If not, the exceptions described in
    101 <a href="#handle">Handling Exceptions</a>
    102   are thrown that you can catch and handle appropriately.
    103 </p>
    104 
    105   <h3>Using getTokenWithNotification()</h3>
    106   <p>If you are obtaining access tokens in a background service or sync adapter, there
    107   are three overloaded
    108   <a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getTokenWithNotification(android.content.Context, java.lang.String, java.lang.String, android.os.Bundle)"
    109       >{@code getTokenWithNotification()}</a> methods
    110   that you can use:</p>
    111   <ul>
    112     <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)"
    113     >{@code getTokenWithNotification(Context context, String accountName, String scope, Bundle extras)}</a>:
    114     For background services. Displays a notification to the user when authorization errors occur.</li>
    115     <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)"
    116     >{@code getTokenWithNotification(Context context, String accountName, String scope, Bundle extras, Intent callback)}</a>:
    117     This method is for use in background services. It displays a notification to the user
    118     when authorization errors occur. If a user clicks the notification and then authorizes the
    119     app to access the account, the intent is broadcasted. When using this method:
    120     <ul>
    121      <li>Create a {@link android.content.BroadcastReceiver} that registers the intent and handles
    122 it appropriately</li>
    123      <li>In the app's manifest file, set the <a
    124      href="{@docRoot}guide/topics/manifest/receiver-element.html#exported"><code>android:exported</code></a>
    125      attribute to <code>true</code> for the broadcast receiver</li>
    126      <li>Ensure that the intent is serializable using the {@link
    127 android.content.Intent#toUri toUri(Intent.URI_INTENT_SCHEME)} and
    128     {@link android.content.Intent#parseUri parseUri(intentUri, Intent.URI_INTENT_SCHEME)} methods.</li>
    129    </ul>
    130     <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)"
    131     >{@code getTokenWithNotification(Context context, String accountName, String scope, Bundle extras, String authority, Bundle syncBundle)}</a>:
    132 This method is for use in sync adapters. It displays a notification to the user when
    133 errors occur. If a user clicks the notification and then authorizes the
    134 app to access the account, the sync adapter retries syncing with the information
    135     contained in the <code>syncBundle</code> parameter.</li>
    136   </ul>
    137   
    138    <p>See the sample in <code>&lt;android-sdk&gt;/extras/google-play-services/samples/auth</code> for implementation details.</p>
    139 
    140 
    141 
    142 
    143 <h2 id="handle">Handling Exceptions</h2>
    144 <p>
    145     When requesting an access token with
    146     <a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context, java.lang.String, java.lang.String)"
    147     >{@code GoogleAuthUtil.getToken()}</a>,
    148     the following exceptions can be thrown:
    149 </p>
    150 <ul>
    151     <li>
    152 <a href="{@docRoot}reference/com/google/android/gms/auth/UserRecoverableAuthException.html"
    153 >{@code UserRecoverableAuthException}</a>: 
    154         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.
    155         This exception class contains a {@link android.app.Activity#getIntent getIntent()} 
    156         method that you can call to obtain an intent that you can use with
    157 {@link android.app.Activity#startActivityForResult startActivityForResult()} 
    158         to obtain the user's resolution. You will need to handle the
    159 {@link android.app.Activity#onActivityResult onActivityResult()} 
    160         callback when this activity returns to take action based on the user's actions.
    161   </li>
    162   <li>
    163 <a href="{@docRoot}reference/com/google/android/gms/auth/GooglePlayServicesAvailabilityException.html"
    164 >{@code GooglePlayServicesAvailabilityException}</a>: 
    165         This exception is a special case of <a href="{@docRoot}reference/com/google/android/gms/auth/UserRecoverableAuthException.html"
    166         >{@code UserRecoverableAuthException}</a>
    167         and occurs when the actual Google Play services APK is not installed or unavailable.
    168         This exception provides additional client support to
    169         handle and fix this issue by providing an error code that describes the exact cause of the problem.
    170         This exception also contains an intent that you can obtain and use to start
    171         an activity to resolve the issue.
    172     </li>
    173     <li>
    174 <a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthException.html">{@code
    175 GoogleAuthException}</a>:
    176         This exception is thrown when the authorization fails, such as when an invalid scope is 
    177         specified or if the email address used for authorization is actually not on the user's 
    178         device.
    179     </li>
    180     <li>
    181 <a href="{@docRoot}reference/com/google/android/gms/auth/UserRecoverableNotifiedException.html"
    182 >{@code UserRecoverableNotifiedException}</a>:
    183         This exception is thrown when the authorization fails using one of the
    184 <a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getTokenWithNotification(android.content.Context, java.lang.String, java.lang.String, android.os.Bundle)"
    185       >{@code getTokenWithNotification()}</a> methods and if the error
    186         is recoverable with a user action.
    187     </li>
    188 </ul>
    189 <p>
    190     For more information on how to handle these exceptions and code snippets, see the reference 
    191     documentation for the 
    192 <a href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html">{@code
    193 GoogleAuthUtil}</a> class.
    194 </p>
    195 
    196 
    197 
    198 
    199 <h2 id="use">Using the Access Token</h2>
    200 <p>
    201     Once you have successfully obtained a token, you can use it to access Google services.
    202     Many Google services provide client libraries, so it is recommended that you use these when 
    203     possible, but you can make raw HTTP requests as well with the token. The following example 
    204     shows you how to do this and handle HTTP error and success responses accordingly:
    205 </p>
    206 
    207 <pre>
    208 URL url = new URL("https://www.googleapis.com/oauth2/v1/userinfo?access_token="
    209         + token);
    210 HttpURLConnection con = (HttpURLConnection) url.openConnection();
    211 int serverCode = con.getResponseCode();
    212 //successful query
    213 if (serverCode == 200) {
    214     InputStream is = con.getInputStream();
    215     String name = getFirstName(readResponse(is));
    216     mActivity.show("Hello " + name + "!");
    217     is.close();
    218     return;
    219 //bad token, invalidate and get a new one
    220 } else if (serverCode == 401) {
    221     GoogleAuthUtil.invalidateToken(mActivity, token);
    222     onError("Server auth error, please try again.", null);
    223     Log.e(TAG, "Server auth error: " + readResponse(con.getErrorStream()));
    224     return;
    225 //unknown error, do something else
    226 } else {
    227     Log.e("Server returned the following error code: " + serverCode, null);
    228     return;
    229 }
    230 </pre>
    231 
    232 <p>
    233     Notice that you must manually invalidate the token if the response from the server
    234     signifies an authorization error (401). This could mean the access token
    235     being used is invalid for the service's scope or the token may have expired. If this is the 
    236     case, obtain a new token using <a
    237 href="{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context, java.lang.String, java.lang.String)"
    238 >{@code GoogleAuthUtil.getToken()}</a>.
    239 </p>