diff options
author | Quddus Chong <quddusc@google.com> | 2015-05-26 14:21:05 -0700 |
---|---|---|
committer | Joe Fernandez <joefernandez@google.com> | 2015-08-16 21:21:41 -0700 |
commit | 28f2ba8e30d774859b38e91a3f1ab91e31a69caf (patch) | |
tree | c7b12d9f2f7d4281c0ce0926cea4628913625e2b /docs/html/google/auth | |
parent | 85429c0d9476502afdcc66c0379fde632d8e5863 (diff) | |
download | frameworks_base-28f2ba8e30d774859b38e91a3f1ab91e31a69caf.zip frameworks_base-28f2ba8e30d774859b38e91a3f1ab91e31a69caf.tar.gz frameworks_base-28f2ba8e30d774859b38e91a3f1ab91e31a69caf.tar.bz2 |
docs: Remove Google Play Services pages under Develop > Google Services.
Cherry-pick from Change-Id: I392075b58bebc5556f306c2d20987811efe90b13
Change-Id: I17ad018a0875b653c0706fd9bbe5f637760cdfbc
Diffstat (limited to 'docs/html/google/auth')
-rw-r--r-- | docs/html/google/auth/api-client.jd | 654 | ||||
-rw-r--r-- | docs/html/google/auth/http-auth.jd | 558 |
2 files changed, 0 insertions, 1212 deletions
diff --git a/docs/html/google/auth/api-client.jd b/docs/html/google/auth/api-client.jd deleted file mode 100644 index 8f926f5..0000000 --- a/docs/html/google/auth/api-client.jd +++ /dev/null @@ -1,654 +0,0 @@ -page.title=Accessing Google APIs -page.tags="oauth 2.0","GoogleAuthUtil" - -trainingnavtop=true -startpage=true - -@jd:body - -<div id="qv-wrapper"> - <div id="qv"> - -<h2>In this document</h2> -<ol> - <li><a href="#Starting">Start a Connection</a> - <ol> - <li><a href="#HandlingFailures">Handle connection failures</a></li> - <li><a href="#MaintainingState">Maintain state while resolving an error</a></li> - <li><a href="#WearableApi">Access the Wearable API</a></li> - </ol> - </li> - <li><a href="#Communicating">Communicate with Google Services</a> - <ol> - <li><a href="#Async">Using asynchronous calls</a></li> - <li><a href="#Sync">Using synchronous calls</a></li> - </ol> - </li> -</ol> -</div> -</div> - - -<p>When you want to make a connection to one of the Google APIs provided in the Google Play services -library (such as Google+, Games, or Drive), you need to create an instance of <a -href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code -GoogleApiClient}</a> ("Google API Client"). The Google API Client provides a common entry point to all -the Google Play services and manages the network connection between the user's device and each -Google service.</p> - -<div class="sidebox" style="clear:right;width:190px"> -<h2>Connecting to REST APIs</h2> -<p>If the Google API you want to use is not included in the Google Play services library, you can -connect using the appropriate REST API, but you must obtain an OAuth 2.0 token. For more -information, read <a href="{@docRoot}google/auth/http-auth.html">Authorizing with Google -for REST APIs</a>.</p> -</div> - -<p>This guide shows how you can use Google API Client to:</p> -<ul> -<li>Connect to one or more Google Play services asynchronously and handle failures.</li> -<li>Perform synchronous and asynchronous API calls to any of the Google Play services.</li> -</ul> - -<p class="note"> -<strong>Note:</strong> If you have an existing app that connects to Google Play services with a -subclass of {@code GooglePlayServicesClient}, you should migrate to <a -href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code -GoogleApiClient}</a> as soon as possible.</p> - - -<img src="{@docRoot}images/google/GoogleApiClient@2x.png" width="464px" alt="" /> -<p class="img-caption"> -<strong>Figure 1.</strong> An illustration showing how the Google API Client provides an -interface for connecting and making calls to any of the available Google Play services such as -Google Play Games and Google Drive.</p> - - - -<p>To get started, you must first install the Google Play services library (revision 15 or higher) for -your Android SDK. If you haven't done so already, follow the instructions in <a -href="{@docRoot}google/play-services/setup.html">Set Up Google -Play Services SDK</a>.</p> - - - - -<h2 id="Starting">Start a Connection</h2> - -<p>Once your project is linked to the Google Play services library, create an instance of <a -href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code -GoogleApiClient}</a> using the <a -href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.Builder.html">{@code -GoogleApiClient.Builder}</a> APIs in your activity's {@link -android.app.Activity#onCreate onCreate()} method. The <a -href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.Builder.html">{@code -GoogleApiClient.Builder}</a> class -provides methods that allow you to specify the Google APIs you want to use and your desired OAuth -2.0 scopes. For example, here's a <a -href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code -GoogleApiClient}</a> instance that connects with the Google -Drive service:</p> -<pre> -GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this) - .addApi(Drive.API) - .addScope(Drive.SCOPE_FILE) - .build(); -</pre> - -<p>You can add multiple APIs and multiple scopes to the same <a -href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code -GoogleApiClient}</a> by appending -additional calls to -<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.Builder.html#addApi(com.google.android.gms.common.api.Api<? extends com.google.android.gms.common.api.Api.ApiOptions.NotRequiredOptions>)" ->{@code addApi()}</a> and -<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.Builder.html#addScope(com.google.android.gms.common.api.Scope)" ->{@code addScope()}</a>.</p> - -<p class="caution"> -<strong>Important:</strong> If you are adding multiple APIs to a -<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html"><code>GoogleApiClient</code></a>, -you may run into client connection errors on devices that do not have the -<a href="https://play.google.com/store/apps/details?id=com.google.android.wearable.app&hl=en">Android -Wear app</a> installed. To avoid connection errors, call the -<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.Builder.html#addApiIfAvailable(com.google.android.gms.common.api.Api<? extends com.google.android.gms.common.api.Api.ApiOptions.NotRequiredOptions>, com.google.android.gms.common.api.Scope...)">{@code addApiIfAvailable()}</a> -method and pass in the <a -href="{@docRoot}reference/com/google/android/gms/wearable/Wearable.html">{@code -Wearable}</a> API to indicate that your client should gracefully handle the missing API. -For more information, see <a -href="{@docRoot}google/auth/api-client.html#WearableApi">Access the Wearable API</a>.</p> - -<p>Before you can begin a connection by calling <a -href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html#connect()" ->{@code connect()}</a> on the <a -href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code -GoogleApiClient}</a>, you must specify an implementation for the callback interfaces, <a -href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html" ->{@code ConnectionCallbacks}</a> and <a -href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.OnConnectionFailedListener.html" ->{@code OnConnectionFailedListener}</a>. These interfaces receive callbacks in -response to the asynchronous <a -href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html#connect()" ->{@code connect()}</a> method when the connection to Google Play services -succeeds, fails, or becomes suspended.</p> - -<p>For example, here's an activity that implements the callback interfaces and adds them to the Google -API Client:</p> - -<pre> -import com.google.android.gms.common.api.GoogleApiClient; -import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks; -import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener; -import gms.drive.*; -import android.support.v4.app.FragmentActivity; - -public class MyActivity extends FragmentActivity - implements ConnectionCallbacks, OnConnectionFailedListener { - private GoogleApiClient mGoogleApiClient; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - // Create a GoogleApiClient instance - mGoogleApiClient = new GoogleApiClient.Builder(this) - .addApi(Drive.API) - .addScope(Drive.SCOPE_FILE) - .addConnectionCallbacks(this) - .addOnConnectionFailedListener(this) - .build(); - ... - } - - @Override - public void onConnected(Bundle connectionHint) { - // Connected to Google Play services! - // The good stuff goes here. - } - - @Override - public void onConnectionSuspended(int cause) { - // The connection has been interrupted. - // Disable any UI components that depend on Google APIs - // until onConnected() is called. - } - - @Override - public void onConnectionFailed(ConnectionResult result) { - // This callback is important for handling errors that - // may occur while attempting to connect with Google. - // - // More about this in the next section. - ... - } -} -</pre> - -<p>With the callback interfaces defined, you're ready to call <a -href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html#connect()" ->{@code connect()}</a>. To gracefully manage -the lifecycle of the connection, you should call <a -href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html#connect()" ->{@code connect()}</a> during the activity's {@link -android.app.Activity#onStart onStart()} (unless you want to connect later), then call <a -href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html#disconnect()" ->{@code disconnect()}</a> during the {@link android.app.Activity#onStop onStop()} method. For example:</p> -<pre> - @Override - protected void onStart() { - super.onStart(); - if (!mResolvingError) { // more about this later - mGoogleApiClient.connect(); - } - } - - @Override - protected void onStop() { - mGoogleApiClient.disconnect(); - super.onStop(); - } -</pre> - -<p>However, if you run this code, there's a good chance it will fail and your app will receive a call -to <a -href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.OnConnectionFailedListener.html#onConnectionFailed(com.google.android.gms.common.ConnectionResult)" ->{@code onConnectionFailed()}</a> with the <a -href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html#SIGN_IN_REQUIRED" ->{@code SIGN_IN_REQUIRED}</a> error because the user account -has not been specified. The next section shows how to handle this error and others.</p> - - -<h3 id="HandlingFailures">Handle connection failures</h3> - -<p>When you receive a call to the -<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.OnConnectionFailedListener.html#onConnectionFailed(com.google.android.gms.common.ConnectionResult)"> -{@code onConnectionFailed()}</a> callback, you should call <a -href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html#hasResolution()" ->{@code hasResolution()}</a> on the provided <a -href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html" ->{@code ConnectionResult}</a> object. If it returns true, you can -request the user take immediate action to resolve the error by calling <a -href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html#startResolutionForResult(android.app.Activity, int)">{@code startResolutionForResult()}</a> on the <a -href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html" ->{@code ConnectionResult}</a> object. The <a -href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html#startResolutionForResult(android.app.Activity, int)" ->{@code startResolutionForResult()}</a> behaves the same as {@link -android.app.Activity#startActivityForResult startActivityForResult()} and launches the -appropriate activity for the user -to resolve the error (such as an activity to select an account).</p> - -<p>If <a -href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html#hasResolution()" ->{@code hasResolution()}</a> returns false, you should instead call <a -href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesUtil.html#getErrorDialog(int, android.app.Activity, int)" ->{@code GooglePlayServicesUtil.getErrorDialog()}</a>, passing it the error code. This returns a {@link -android.app.Dialog} provided by Google Play services that's appropriate for the given error. The -dialog may simply provide a message explaining the error, but it may also provide an action to -launch an activity that can resolve the error (such as when the user needs to install a newer -version of Google Play services).</p> - -<p>For example, your -<a -href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.OnConnectionFailedListener.html#onConnectionFailed(com.google.android.gms.common.ConnectionResult)" ->{@code onConnectionFailed()}</a> callback method should now look like this:</p> - -<pre> -public class MyActivity extends FragmentActivity - implements ConnectionCallbacks, OnConnectionFailedListener { - - // Request code to use when launching the resolution activity - private static final int REQUEST_RESOLVE_ERROR = 1001; - // Unique tag for the error dialog fragment - private static final String DIALOG_ERROR = "dialog_error"; - // Bool to track whether the app is already resolving an error - private boolean mResolvingError = false; - - ... - - @Override - public void onConnectionFailed(ConnectionResult result) { - if (mResolvingError) { - // Already attempting to resolve an error. - return; - } else if (result.hasResolution()) { - try { - mResolvingError = true; - result.startResolutionForResult(this, REQUEST_RESOLVE_ERROR); - } catch (SendIntentException e) { - // There was an error with the resolution intent. Try again. - mGoogleApiClient.connect(); - } - } else { - // Show dialog using GooglePlayServicesUtil.getErrorDialog() - showErrorDialog(result.getErrorCode()); - mResolvingError = true; - } - } - - // The rest of this code is all about building the error dialog - - /* Creates a dialog for an error message */ - private void showErrorDialog(int errorCode) { - // Create a fragment for the error dialog - ErrorDialogFragment dialogFragment = new ErrorDialogFragment(); - // Pass the error that should be displayed - Bundle args = new Bundle(); - args.putInt(DIALOG_ERROR, errorCode); - dialogFragment.setArguments(args); - dialogFragment.show(getSupportFragmentManager(), "errordialog"); - } - - /* Called from ErrorDialogFragment when the dialog is dismissed. */ - public void onDialogDismissed() { - mResolvingError = false; - } - - /* A fragment to display an error dialog */ - public static class ErrorDialogFragment extends DialogFragment { - public ErrorDialogFragment() { } - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - // Get the error code and retrieve the appropriate dialog - int errorCode = this.getArguments().getInt(DIALOG_ERROR); - return GooglePlayServicesUtil.getErrorDialog(errorCode, - this.getActivity(), REQUEST_RESOLVE_ERROR); - } - - @Override - public void onDismiss(DialogInterface dialog) { - ((MainActivity)getActivity()).onDialogDismissed(); - } - } -} -</pre> - -<p>Once the user completes the resolution provided by <a -href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html#startResolutionForResult(android.app.Activity, int)" ->{@code startResolutionForResult()}</a> or <a -href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesUtil.html#getErrorDialog(int, android.app.Activity, int)" ->{@code GooglePlayServicesUtil.getErrorDialog()}</a>, your activity receives the {@link -android.app.Activity#onActivityResult onActivityResult()} callback with the {@link -android.app.Activity#RESULT_OK} -result code. You can then call <a -href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html#connect()" ->{@code connect()}</a> again. For example:</p> - -<pre> -@Override -protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (requestCode == REQUEST_RESOLVE_ERROR) { - mResolvingError = false; - if (resultCode == RESULT_OK) { - // Make sure the app is not already connected or attempting to connect - if (!mGoogleApiClient.isConnecting() && - !mGoogleApiClient.isConnected()) { - mGoogleApiClient.connect(); - } - } - } -} -</pre> - -<p>In the above code, you probably noticed the boolean, {@code mResolvingError}. This keeps track of -the app state while the user is resolving the error to avoid repetitive attempts to resolve the -same error. For instance, while the account picker dialog is showing to resolve the <a -href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html#SIGN_IN_REQUIRED" ->{@code SIGN_IN_REQUIRED}</a> error, the user may rotate the screen. This recreates your activity and causes -your {@link android.app.Activity#onStart onStart()} method to be called again, which then calls <a -href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html#connect()" ->{@code connect()}</a> again. This results in another call to <a -href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html#startResolutionForResult(android.app.Activity, int)" ->{@code startResolutionForResult()}</a>, which -creates another account picker dialog in front of the existing one.</p> - -<p>This boolean is effective only -if retained across activity instances, though. The next section explains further.</p> - - - -<h3 id="MaintainingState">Maintain state while resolving an error</h3> - -<p>To avoid executing the code in -<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.OnConnectionFailedListener.html#onConnectionFailed(com.google.android.gms.common.ConnectionResult)"> -{@code onConnectionFailed()}</a> while a previous attempt to resolve an -error is ongoing, you need to retain a boolean that tracks whether your app is already attempting -to resolve an error.</p> - -<p>As shown in the code above, you should set a boolean to {@code true} each time you call <a -href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html#startResolutionForResult(android.app.Activity, int)" ->{@code startResolutionForResult()}</a> or display the dialog from <a -href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesUtil.html#getErrorDialog(int, android.app.Activity, int)" ->{@code GooglePlayServicesUtil.getErrorDialog()}</a>. Then when you -receive {@link android.app.Activity#RESULT_OK} in the {@link android.app.Activity#onActivityResult -onActivityResult()} callback, set the boolean to {@code false}.</p> - -<p>To keep track of the boolean across activity restarts (such as when the user rotates the screen), -save the boolean in the activity's saved instance data using {@link -android.app.Activity#onSaveInstanceState onSaveInstanceState()}:</p> - -<pre> -private static final String STATE_RESOLVING_ERROR = "resolving_error"; - -@Override -protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - outState.putBoolean(STATE_RESOLVING_ERROR, mResolvingError); -} -</pre> - -<p>Then recover the saved state during {@link android.app.Activity#onCreate onCreate()}:</p> - -<pre> -@Override -protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ... - mResolvingError = savedInstanceState != null - && savedInstanceState.getBoolean(STATE_RESOLVING_ERROR, false); -} -</pre> - -<p>Now you're ready to safely run your app and connect to Google Play services. -How you can perform read and write requests to any of the Google Play services -using <a -href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code -GoogleApiClient}</a> is discussed in the next section.</p> - -<p>For more information about each services's APIs available once you're connected, -consult the corresponding documentation, such as for -<a href="{@docRoot}google/play-services/games.html">Google Play Games</a> or -<a href="{@docRoot}google/play-services/drive.html">Google Drive</a>. -</p> - - -<h3 id="WearableApi">Access the Wearable API</h3> - -<p>The Wearable API provides a communication channel for your handheld and wearable apps. The API -consists of a set of data objects that the system can send and synchronize over the wire and -listeners that notify your apps of important events with the data layer. The -<a href="{@docRoot}reference/com/google/android/gms/wearable/Wearable.html">{@code Wearable}</a> -API is available on devices running Android 4.3 (API level 18) or higher when a wearable device is -connected. The API is not available under the following conditions: -</p> - -<ul> -<li>Devices running Android 4.2 (API level 17) or earlier.</li> -<li><a href="https://play.google.com/store/apps/details?id=com.google.android.wearable.app&hl=en">Android -Wear companion app</a> is not installed on the device.</li> -<li>Android Wear device is not connected.</li> -</ul> - -<h4 id="OnlyWearableApi">Using only the Wearable API</h4> - -<p>If your app uses the -<a href="{@docRoot}reference/com/google/android/gms/wearable/Wearable.html">{@code Wearable}</a> -API but not other Google APIs, you can add this API by calling the -<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.Builder.html#addApi(com.google.android.gms.common.api.Api<? extends com.google.android.gms.common.api.Api.ApiOptions.NotRequiredOptions>)" ->{@code addApi()}</a> method. The following example shows how to add the -<a href="{@docRoot}reference/com/google/android/gms/wearable/Wearable.html">{@code Wearable}</a> -API to your <a -href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code -GoogleApiClient}</a> instance:</p> - -<pre> -GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this) - .addApi(Wearable.API) - .build(); -</pre> - -<p>In situations where the -<a href="{@docRoot}reference/com/google/android/gms/wearable/Wearable.html">{@code Wearable}</a> -API is not available, connection requests that include the <a -href="{@docRoot}reference/com/google/android/gms/wearable/Wearable.html">{@code -Wearable}</a> API fail with the <a -href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html#API_UNAVAILABLE"> -<code>API_UNAVAILABLE</code></a> error code.</p> - -<p> -The following example shows how to determine whether the -<a href="{@docRoot}reference/com/google/android/gms/wearable/Wearable.html">{@code Wearable}</a> -API is available: -</p> - -<pre> -// Connection failed listener method for a client that only -// requests access to the Wearable API -@Override -public void onConnectionFailed(ConnectionResult result) { - if (result.getErrorCode() == ConnectionResult.API_UNAVAILABLE) { - // The Wearable API is unavailable - } - ... -} -</pre> - - -<h4 id="WearableApiWithOthers">Using the Wearable API with other APIs</h4> - -<p> -If your app uses the -<a href="{@docRoot}reference/com/google/android/gms/wearable/Wearable.html">{@code Wearable}</a> -API in addition to other Google APIs, call the -<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.Builder.html#addApiIfAvailable(com.google.android.gms.common.api.Api<? extends com.google.android.gms.common.api.Api.ApiOptions.NotRequiredOptions>, com.google.android.gms.common.api.Scope...)">addApiIfAvailable()</a> -method and pass in the -<a href="{@docRoot}reference/com/google/android/gms/wearable/Wearable.html">{@code Wearable}</a> -API to indicate that your client should gracefully handle the missing API.</p> - -<p>The following example shows how to access the -<a href="{@docRoot}reference/com/google/android/gms/wearable/Wearable.html">{@code Wearable}</a> -API along with the -<a href="{@docRoot}reference/com/google/android/gms/drive/DriveApi.html">{@code Drive}</a> -API:</p> - -<pre> -// Create a GoogleApiClient instance -mGoogleApiClient = new GoogleApiClient.Builder(this) - .addApi(Drive.API) - .addApiIfAvailable(Wearable.API) - .addScope(Drive.SCOPE_FILE) - .addConnectionCallbacks(this) - .addOnConnectionFailedListener(this) - .build(); -</pre> - -<p>In the example above, the -<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code GoogleApiClient}</a> -can successfully connect with the Google Drive service without connecting to the -<a href="{@docRoot}reference/com/google/android/gms/wearable/Wearable.html">{@code Wearable}</a> -API if it is unavailable. After you connect your -<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code GoogleApiClient}</a> -instance, ensure that the -<a href="{@docRoot}reference/com/google/android/gms/wearable/Wearable.html">{@code Wearable}</a> -API is available before making the API calls: -</p> - -<pre> -mGoogleApiClient.hasConnectedApi(Wearable.API); -</pre> - - -<h2 id="Communicating">Communicate with Google Services</h2> - -<p>Once connected, your client can make read and write calls using the service-specific APIs for which -your app is authorized, as specified by the APIs and scopes you added to your <a -href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code -GoogleApiClient}</a> instance.</p> - -<p class="note"> -<strong>Note:</strong> Before making calls to specific Google services, you may first need to -register your app in the Google Developer Console. For specific instructions, refer to the -appropriate getting started guide for the API you're using, such as <a href= -"https://developers.google.com/drive/android/get-started">Google Drive</a> or <a href= -"https://developers.google.com/+/mobile/android/getting-started">Google+</a>.</p> - -<p>When you perform a read or write request using Google API Client, the immediate result is returned -as a <a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html">{@code -PendingResult}</a> object. This is an object representing the request, which hasn't yet -been delivered to the Google service.</p> - -<p>For example, here's a request to read a file from Google Drive that provides a -<a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html">{@code -PendingResult}</a> object:</p> - -<pre> -Query query = new Query.Builder() - .addFilter(Filters.eq(SearchableField.TITLE, filename)); -PendingResult result = Drive.DriveApi.query(mGoogleApiClient, query); -</pre> - -<p>Once you have the -<a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html">{@code -PendingResult}</a>, you can continue by making the request either asynchronous -or synchronous.</p> - - -<h3 id="Async">Using asynchronous calls</h3> - -<p>To make the request asynchronous, call <a -href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html#setResultCallback(com.google.android.gms.common.api.ResultCallback<R>)" ->{@code setResultCallback()}</a> on the -<a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html">{@code -PendingResult}</a> and -provide an implementation of the <a -href="{@docRoot}reference/com/google/android/gms/common/api/ResultCallback.html" ->{@code ResultCallback}</a> interface. For example, here's the request -executed asynchronously:</p> - -<pre> -private void loadFile(String filename) { - // Create a query for a specific filename in Drive. - Query query = new Query.Builder() - .addFilter(Filters.eq(SearchableField.TITLE, filename)) - .build(); - // Invoke the query asynchronously with a callback method - Drive.DriveApi.query(mGoogleApiClient, query) - .setResultCallback(new ResultCallback<DriveApi.MetadataBufferResult>() { - @Override - public void onResult(DriveApi.MetadataBufferResult result) { - // Success! Handle the query result. - ... - } - }); -} -</pre> - -<p>When your app receives a <a -href="{@docRoot}reference/com/google/android/gms/common/api/Result.html">{@code Result}</a> -object in the <a -href="{@docRoot}reference/com/google/android/gms/common/api/ResultCallback.html#onResult(R)" ->{@code onResult()}</a> callback, it is delivered as an instance of the -appropriate subclass as specified by the API you're using, such as <a -href="{@docRoot}reference/com/google/android/gms/drive/DriveApi.MetadataBufferResult.html" ->{@code DriveApi.MetadataBufferResult}</a>.</p> - - -<h3 id="Sync">Using synchronous calls</h3> - -<p>If you want your code to execute in a strictly defined order, perhaps because the result of one -call is needed as an argument to another, you can make your request synchronous by calling <a -href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html#await()" ->{@code await()}</a> on the -<a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html">{@code -PendingResult}</a>. This blocks the thread and returns the <a -href="{@docRoot}reference/com/google/android/gms/common/api/Result.html">{@code Result}</a> object -when the request completes, which is delivered as an instance of the -appropriate subclass as specified by the API you're using, such as <a -href="{@docRoot}reference/com/google/android/gms/drive/DriveApi.MetadataBufferResult.html" ->{@code DriveApi.MetadataBufferResult}</a>.</p> - -<p>Because calling <a -href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html#await()" ->{@code await()}</a> blocks the thread until the result arrives, it's important that you -never perform this call on the UI thread. So, if you want to perform synchronous requests to a -Google Play service, you should create a new thread, such as with {@link android.os.AsyncTask} in -which to perform the request. For example, here's how to perform the same file request to Google -Drive as a synchronous call:</p> - -<pre> -private void loadFile(String filename) { - new GetFileTask().execute(filename); -} - -private class GetFileTask extends AsyncTask<String, Void, Void> { - protected void doInBackground(String filename) { - Query query = new Query.Builder() - .addFilter(Filters.eq(SearchableField.TITLE, filename)) - .build(); - // Invoke the query synchronously - DriveApi.MetadataBufferResult result = - Drive.DriveApi.query(mGoogleApiClient, query).await(); - - // Continue doing other stuff synchronously - ... - } -} -</pre> - -<p class="note"> -<strong>Tip:</strong> You can also enqueue read requests while not connected to Google Play -services. For example, execute a method to read a file from Google Drive regardless of whether your -Google API Client is connected yet. Then once a connection is established, the read requests -execute and you'll receive the results. Any write requests, however, will generate an error if you -call them while your Google API Client is not connected.</p> - diff --git a/docs/html/google/auth/http-auth.jd b/docs/html/google/auth/http-auth.jd deleted file mode 100644 index 7d34d89..0000000 --- a/docs/html/google/auth/http-auth.jd +++ /dev/null @@ -1,558 +0,0 @@ -page.title=Authorizing with Google for REST APIs -page.tags="oauth 2.0","GoogleAuthUtil" - -trainingnavtop=true -startpage=true - -@jd:body - - -<div id="qv-wrapper"> - <div id="qv"> - -<h2>In this document</h2> -<ol> - <li><a href="#Register">Register Your App</a></li> - <li><a href="#AccountPicker">Invoke the Account Picker</a></li> - <li><a href="#AccountName">Retrieve the Account Name</a></li> - <li><a href="#ExtendAsyncTask">Extend AsyncTask to Get the Auth Token</a></li> - <li><a href="#HandleExceptions">Handle Exceptions</a></li> -</ol> -<h2>Try it out</h2> - -<div class="download-box"> -<a href="http://developer.android.com/shareables/training/GoogleAuth.zip" - class="button">Download the sample app</a> -<p class="filename">GoogleAuth.zip</p> -</div> - -</div> -</div> - -<p>When you want your Android app to access Google APIs using the user's Google account over -HTTP, the <a href= -"{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html">{@code GoogleAuthUtil}</a> -class and related APIs provide your users a secure and consistent experience for picking an -account and retrieving an OAuth 2.0 token for your app.</p> - -<p>You can then use that token in your HTTP-based communications with Google API services -that are not included in the <a href="{@docRoot}google/play-services/index.html">Google Play -services</a> library, such as the Blogger or Translate APIs.</p> - -<p class="note"><strong>Note:</strong> An OAuth 2.0 token using <a href= -"{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html">{@code GoogleAuthUtil}</a> -is required only for certain types of Google -APIs that you need to access over HTTP. If you're instead using the <a -href="{@docRoot}google/play-services/index.html">Google Play services library</a> to access Google -APIs such as <a href="{@docRoot}google/play-services/plus.html">Google+</a> or <a -href="{@docRoot}google/play-services/games.html">Play Games</a>, you don't need an OAuth 2.0 -token and you can instead access these services using the {@code GoogleApiClient}. For more -information, read <a href="{@docRoot}google/auth/api-client.html">Accessing Google Play -Services APIs</a>.</p> - -<p>To get started with <a href= -"{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html">{@code GoogleAuthUtil}</a> -for accessing Google's REST APIs, you must set up your Android app project with the Google Play -services library. Follow the procedures in <a href= -"{@docRoot}google/play-services/setup.html">Setup Google Play Services SDK</a>.</p> - - - - -<h2 id="Register">Register Your App</h2> - -<p>Before you can publish an app that retrieves an OAuth 2.0 token for Google REST APIs, -you must register your Android app with the Google Cloud Console by providing your app's -package name and the SHA1 fingerprint of the keystore with which you sign your release APK.</p> - -<p class="caution"><strong>Caution:</strong> While you are testing an APK that's <a -href="{@docRoot}tools/publishing/app-signing.html#debugmode">signed with a -debug key</a>, Google does not require that your app be registered in Google Cloud Console. However, -your app must be registered in Google Cloud Console in order to continue working once it is -<a href="{@docRoot}tools/publishing/app-signing.html#releasemode">signed -with a release key</a>.</p> - -<p>To register your Android app with Google Cloud Console:</p> - -<ol> -<li>Visit <a href="https://cloud.google.com/console" class="external-link" target="_blank" ->Google Cloud Console</a>. -<li>If you have an existing project to which you're adding an Android app, select the project. -Otherwise, click <strong>Create project</strong> at the top, enter your project name and ID, -then click <strong>Create</strong>. -<p class="note"><strong>Note:</strong> The name you provide for the project is the name that -appears to users in the Google Settings app in the list of <em>Connected apps</em>.</p> -<li>In the left-side navigation, select <strong>APIs & auth</strong>. -<li>Enable the API you'd like to use by setting the Status to <strong>ON</strong>. - -<li>In the left-side navigation, select <strong>Credentials</strong>. -<li>Click <strong>Create new client ID</strong> or <strong>Create new key</strong> -as appropriate for your app.</li> -<li>Complete the form that appears by filling in your Android app details. -<p>To get the SHA1 fingerprint for your app, run the following command in a terminal: -<pre class="no-pretty-print"> -keytool -exportcert -alias <keystore_alias> -keystore <keystore_path> -list -v -</pre> -<p>For example, you're using a debug-key with Eclipse, then the command looks like this:</p> -<pre class="no-pretty-print"> -keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore -list -v -</pre> -<p>Then the keystore password is "android".</p> -</li> -<li>Click <strong>Create</strong>. -</ol> - -<p>The Credentials page then provides the available credentials such as an OAuth 2.0 client ID and -an Android Key, but you don't need these to authorize your Android users. Simply registering your -app with the package name and SHA1 makes the Google services accessible by your app. - - -<p>To acquire the OAuth 2.0 token that will grant you access to Google APIs over HTTP, you need to -first identify the user's Google account with which you'll query the servers. For this task, the -Google Play services library provides a convenient account picker dialog you can invoke using -<a href="{@docRoot}reference/com/google/android/gms/common/AccountPicker.html">{@code -AccountPicker}</a>. The result delivered to your activity from the account picker is the account -name you'll use to request the OAuth 2.0 token in the next lesson.</p> - -<p class="note"><strong>Note:</strong> In order to use the APIs discussed here, you must -include the Google Play services library with your project. If you haven't set up your project -with the library yet, read the guide to <a -href="{@docRoot}google/play-services/setup.html">Setup Google Play Services SDK</a>.</p> - - - -<h2 id="AccountPicker">Invoke the Account Picker</h2> - -<p>To open the account picker dialog that's managed by the Google Play services library, call -{@link android.app.Activity#startActivityForResult startActivityForResult()} using an {@link -android.content.Intent} returned by <a href= -"{@docRoot}reference/com/google/android/gms/common/AccountPicker.html#newChooseAccountIntent(android.accounts.Account,%20java.util.ArrayList%3Candroid.accounts.Account%3E,%20java.lang.String[],%20boolean,%20java.lang.String,%20java.lang.String,%20java.lang.String[],%20android.os.Bundle)"> -{@code AccountPicker.newChooseAccountIntent}</a>.</p> - - -<p>For example:</p> -<pre> -static final int REQUEST_CODE_PICK_ACCOUNT = 1000; - -private void pickUserAccount() { - String[] accountTypes = new String[]{"com.google"}; - Intent intent = AccountPicker.newChooseAccountIntent(null, null, - accountTypes, false, null, null, null, null); - startActivityForResult(intent, REQUEST_CODE_PICK_ACCOUNT); -} -</pre> - -<p>When this code executes, a dialog appears for the user to pick an account. When the user -selects the account, your activity receives the result in the {@link -android.app.Activity#onActivityResult onActivityResult()} callback.</p> - -<p>Most apps should pass the <a href= -"{@docRoot}reference/com/google/android/gms/common/AccountPicker.html#newChooseAccountIntent(android.accounts.Account,%20java.util.ArrayList%3Candroid.accounts.Account%3E,%20java.lang.String[],%20boolean,%20java.lang.String,%20java.lang.String,%20java.lang.String[],%20android.os.Bundle)"> -{@code newChooseAccountIntent()}</a> method the same arguments shown in the above example, -which indicate that:</p> - - -<ul> -<li>There is no currently selected account.</li> -<li>There is no restricted list of accounts.</li> -<li>The dialog should list only accounts from the "com.google" domain.</li> -<li>Don't prompt the user to pick an account if there's only one available account (just use that -one). However, even if only one account currently exists, the dialog may include an option for the -user to add a new account.</li> -<li>There is no custom title for the dialog.</li> -<li>There is no specific auth token type required.</li> -<li>There are no restrictions based on account features.</li> -<li>There are no authenticator-specific options.</li> -</ul> - -<p>For more details about these arguments, see the <a href= -"{@docRoot}reference/com/google/android/gms/common/AccountPicker.html#newChooseAccountIntent(android.accounts.Account,%20java.util.ArrayList%3Candroid.accounts.Account%3E,%20java.lang.String[],%20boolean,%20java.lang.String,%20java.lang.String,%20java.lang.String[],%20android.os.Bundle)"> -{@code newChooseAccountIntent()}</a> method documentation.</p> - - - - -<h2 id="AccountName">Retrieve the Account Name</h2> - -<p>Once the user selects an account, your activity receives a call to its -{@link android.app.Activity#onActivityResult onActivityResult()} method. The received -{@link android.content.Intent} includes an extra for -{@link android.accounts.AccountManager#KEY_ACCOUNT_NAME}, specifying the account name -(an email address) you must use to acquire the OAuth 2.0 token.</p> - -<p>Here's an example implementation of the callback {@link android.app.Activity#onActivityResult -onActivityResult()} that receives the selected account:</p> - -<pre> -String mEmail; // Received from <a href= -"{@docRoot}reference/com/google/android/gms/common/AccountPicker.html#newChooseAccountIntent(android.accounts.Account,%20java.util.ArrayList%3Candroid.accounts.Account%3E,%20java.lang.String[],%20boolean,%20java.lang.String,%20java.lang.String,%20java.lang.String[],%20android.os.Bundle)" ->{@code newChooseAccountIntent()}</a>; passed to <a href= -"{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context,%20java.lang.String,%20java.lang.String)">{@code getToken()}</a> - -@Override -protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (requestCode == REQUEST_CODE_PICK_ACCOUNT) { - // Receiving a result from the AccountPicker - if (resultCode == RESULT_OK) { - mEmail = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME); - // With the account name acquired, go get the auth token - getUsername(); - } else if (resultCode == RESULT_CANCELED) { - // The account picker dialog closed without selecting an account. - // Notify users that they must pick an account to proceed. - Toast.makeText(this, R.string.pick_account, Toast.LENGTH_SHORT).show(); - } - } - // Later, more code will go here to handle the result from some exceptions... -} -</pre> - -<p>You can now pass the account name held by {@code mEmail} to <a href= -"{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context,%20java.lang.String,%20java.lang.String)"> -{@code GoogleAuthUtil.getToken()}</a> (which is what the {@code getUsername()} method -does), but because it performs network transactions, this method should not be called from the -UI thread. The next lesson shows how to create an {@link android.os.AsyncTask} to get the auth token -on a separate thread.</p> - - -<p>Once you have retrieved the account name for the user's Google account, you can call <a href= -"{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context,%20java.lang.String,%20java.lang.String)"> -{@code GoogleAuthUtil.getToken()}</a>, which returns the access token string required by Google API -services.</p> - - -<p>Calling this method is generally a straightforward procedure, but you must be -aware that:</p> -<ul> -<li>The <a href= -"{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context,%20java.lang.String,%20java.lang.String)"> -{@code GoogleAuthUtil.getToken()}</a> method requires a network connection, so your app must -acquire the {@link android.Manifest.permission#INTERNET} permission. You should also check whether -the device has a network connection at runtime by querying {@link android.net.NetworkInfo}, which -requires that your app also acquire the {@link android.Manifest.permission#ACCESS_NETWORK_STATE} -permissions—for more details, read <a href= -"{@docRoot}training/basics/network-ops/connecting.html">Connecting to the Network</a>.</li> -<li>Because the <a href= -"{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context,%20java.lang.String,%20java.lang.String)"> -{@code GoogleAuthUtil.getToken()}</a> method performs a synchronous network transaction, you should -always perform this call from a worker thread to avoid blocking your app's UI thread.</li> -<li>As is true when performing any network transaction, you should be prepared to handle -exceptions that may occur. There are also specific exceptions that -<a href= -"{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context,%20java.lang.String,%20java.lang.String)"> -{@code GoogleAuthUtil.getToken()}</a> may throw, defined as <a href= -"{@docRoot}reference/com/google/android/gms/auth/GoogleAuthException.html">{@code -GoogleAuthException}</a> objects.</li> -</ul> - -<p>This lesson shows how you can gracefully handle these concerns by performing authentication in -an {@link android.os.AsyncTask} and providing users with the appropriate information and available -actions during known exceptions.</p> - -<p class="note"><strong>Note:</strong> The code shown in this lesson, using <a href= -"{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context,%20java.lang.String,%20java.lang.String)">{@code GoogleAuthUtil.getToken()}</a>, -is appropriate when you will be requesting the OAuth token from an {@link android.app.Activity}. -However, if you need to request the OAuth token from a {@link android.app.Service}, then you -should instead use <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>. This method works the same as <a href= -"{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context,%20java.lang.String,%20java.lang.String)">{@code GoogleAuthUtil.getToken()}</a>, but if an error occurs, it -also creates an appropriate -<a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">notification</a> -that allows the user can recover from the error. -The sample available for download above includes code showing how to use this method instead.</p> - - -<h2 id="ExtendAsyncTask">Extend AsyncTask to Get the Auth Token</h2> - -<p>The {@link android.os.AsyncTask} class provides a simple way to create a worker thread for jobs -that should not run on your UI thread. This lesson focuses on how to create such a thread -to get your auth token; for a more complete discussion about {@link android.os.AsyncTask}, -read <a href="{@docRoot}training/articles/perf-anr.html">Keeping Your -App Responsive</a> and the {@link android.os.AsyncTask} class reference.</p> - - -<p>The {@link android.os.AsyncTask#doInBackground doInBackground()} method in your {@link -android.os.AsyncTask} class is where you should call the <a href= -"{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context,%20java.lang.String,%20java.lang.String)"> -{@code GoogleAuthUtil.getToken()}</a> method. You can also use it to catch some of the generic -exceptions that may occur during your network transactions.</p> - -<p>For example, here's part of an {@link android.os.AsyncTask} subclass that calls <a href= -"{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context,%20java.lang.String,%20java.lang.String)"> -{@code GoogleAuthUtil.getToken()}</a>:</p> - -<pre> -public class GetUsernameTask extends AsyncTask<Void, Void, Void>{ - Activity mActivity; - String mScope; - String mEmail; - - GetUsernameTask(Activity activity, String name, String scope) { - this.mActivity = activity; - this.mScope = scope; - this.mEmail = name; - } - - /** - * Executes the asynchronous job. This runs when you call execute() - * on the AsyncTask instance. - */ - @Override - protected Void doInBackground(Void... params) { - try { - String token = fetchToken(); - if (token != null) { - // <b>Insert the good stuff here.</b> - // Use the token to access the user's Google data. - ... - } - } catch (IOException e) { - // The fetchToken() method handles Google-specific exceptions, - // so this indicates something went wrong at a higher level. - // TIP: Check for network connectivity before starting the AsyncTask. - ... - } - return null; - } - - /** - * Gets an authentication token from Google and handles any - * GoogleAuthException that may occur. - */ - protected String fetchToken() throws IOException { - try { - <b>return GoogleAuthUtil.getToken(mActivity, mEmail, mScope);</b> - } catch (UserRecoverableAuthException userRecoverableException) { - // GooglePlayServices.apk is either old, disabled, or not present - // so we need to show the user some UI in the activity to recover. - mActivity.handleException(userRecoverableException); - } catch (GoogleAuthException fatalException) { - // Some other type of unrecoverable exception has occurred. - // Report and log the error as appropriate for your app. - ... - } - return null; - } - ... -} -</pre> - -<p>In order to call <a href= -"{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context,%20java.lang.String,%20java.lang.String)"> -{@code GoogleAuthUtil.getToken()}</a>, you must provide the app {@link android.content.Context}, -the account name retrieved from the account picker, and the scope for your auth -token request. The above sample code (and the attached sample) defines these -arguments with class members that the host activity passes to the {@link android.os.AsyncTask} class constructor. For more information about setting the scope, see -the <a href="#SpecifyingScopes">Specifying Scopes</a> section below. </p> - -<p class="note"><strong>Note:</strong> -As shown by the {@code fetchToken()} method above, you must handle -special exceptions that may occur during the <a href= -"{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context,%20java.lang.String,%20java.lang.String)"> -{@code GoogleAuthUtil.getToken()}</a> method. The next section shows how you should -respond to these exceptions.</p> - -<p>Once you have an {@link android.os.AsyncTask} subclass defined, -you can instantiate and execute an instance after you get the user's -account name from the account picker. -For example, back in the {@link android.app.Activity} class you can do something like this:</p> - -<pre> -String mEmail; // Received from <a href= -"{@docRoot}reference/com/google/android/gms/common/AccountPicker.html#newChooseAccountIntent(android.accounts.Account,%20java.util.ArrayList%3Candroid.accounts.Account%3E,%20java.lang.String[],%20boolean,%20java.lang.String,%20java.lang.String,%20java.lang.String[],%20android.os.Bundle)" ->{@code newChooseAccountIntent()}</a>; passed to <a href= -"{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context,%20java.lang.String,%20java.lang.String)">{@code getToken()}</a> -private static final String SCOPE = - "oauth2:https://www.googleapis.com/auth/userinfo.profile"; - -/** - * Attempts to retrieve the username. - * If the account is not yet known, invoke the picker. Once the account is known, - * start an instance of the AsyncTask to get the auth token and do work with it. - */ -private void getUsername() { - if (mEmail == null) { - pickUserAccount(); - } else { - if (isDeviceOnline()) { - <b>new GetUsernameTask(HelloActivity.this, mEmail, SCOPE).execute();</b> - } else { - Toast.makeText(this, R.string.not_online, Toast.LENGTH_LONG).show(); - } - } -} -</pre> - -<p>The {@code pickUserAccount()} method is shown in the first lesson, <a -href="{@docRoot}training/auth-google/picking-account.html">Picking the User's Account</a>. - -<p>For information about how to check whether the device is currently online (as performed by -the {@code isDeviceOnline()} method above), see the attached sample app or the -<a href= -"{@docRoot}training/basics/network-ops/connecting.html">Connecting to the Network</a> lesson.</p> - -<p>The only part left is how you should handle the exceptions that may occur when you call -<a href= -"{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context,%20java.lang.String,%20java.lang.String)"> -{@code GoogleAuthUtil.getToken()}</a>.</p> - -<h3 id="SpecifyingScopes">Specifying scopes</h3> -<p>The scope string is used to specify which Google services can be accessed by - an app using the requested auth token. An auth token can be associated with - multiple scopes.</p> -<p>When specifying the scopes in your auth token request, prefix the - scope string with {@code "oauth2:"} followed by a list of one or more OAuth scope - values. Use a space to separate each scope value in the list. To see a list of - valid OAuth scope values for Google services, browse - the <a href="https://developers.google.com/oauthplayground/" - class="external-link">OAuth 2.0 Playground</a>.</p> -<p class="note"><strong>Tip:</strong> Specify {@code "oauth2:<scope>"} - for a single scope. Specify - {@code "oauth2:<scope1> <scope2> <scopeN>"} for multiple - scopes (using a space to separate each scope).</p> -<p>For example, to access the Google Books API, the scope is - {@code "oauth2:https://www.googleapis.com/auth/books"}. To add an additional - scope, say for Google+ login, your code might look like this:</p> -<pre> -private final static String BOOKS_API_SCOPE - = "https://www.googleapis.com/auth/books"; -private fina; static String GPLUS_SCOPE - = "https://www.googleapis.com/auth/plus.login"; -private final static String mScopes - = "oauth2:" + BOOKS_API_SCOPE + " " + GPLUS_SCOPE; -String token = GoogleAuthUtil.getToken(mActivity, mEmail, mScopes); -</pre> - -<h2 id="HandleExceptions">Handle Exceptions</h2> - -<p>As shown in the <code>fetchToken()</code> method above, you must catch all occurrences of <a href= -"{@docRoot}reference/com/google/android/gms/auth/GoogleAuthException.html">{@code -GoogleAuthException}</a> when you call <a href= -"{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context,%20java.lang.String,%20java.lang.String)"> -{@code GoogleAuthUtil.getToken()}</a>.</p> - -<p>To provide users information and a proper solution to issues that may occur while acquiring the -auth token, it's important that you properly handle the following subclasses of <a href= -"{@docRoot}reference/com/google/android/gms/auth/GoogleAuthException.html">{@code -GoogleAuthException}</a>:</p> - - -<dl> -<dt><a href="{@docRoot}reference/com/google/android/gms/auth/UserRecoverableAuthException.html">{@code UserRecoverableAuthException}</a></dt> - <dd>This is an error that users can resolve through some verification. For example, users may - need to confirm that your app is allowed to access their Google data or they may need to re-enter - their account password. When you receive this exception, call <a href= -"{@docRoot}reference/com/google/android/gms/auth/UserRecoverableAuthException.html#getIntent()">{@code -getIntent()}</a> on the instance and pass the returned {@link android.content.Intent} to {@link -android.app.Activity#startActivityForResult startActivityForResult()} to give users the opportunity -to solve the problem, such as by logging in.</dd> - -<dt><a href="{@docRoot}reference/com/google/android/gms/auth/GooglePlayServicesAvailabilityException.html">{@code GooglePlayServicesAvailabilityException}</a></dt> - <dd>This is a specific type of <a - href="{@docRoot}reference/com/google/android/gms/auth/UserRecoverableAuthException.html">{@code - UserRecoverableAuthException}</a> indicating that the user's current version -of Google Play services is outdated. Although the recommendation above for -<a href="{@docRoot}reference/com/google/android/gms/auth/UserRecoverableAuthException.html">{@code - UserRecoverableAuthException}</a> also works for this exception, calling {@link -android.app.Activity#startActivityForResult startActivityForResult()} will immediately send users - to Google Play Store to install an update, which may be confusing. So you should instead call <a - href="{@docRoot}reference/com/google/android/gms/auth/GooglePlayServicesAvailabilityException.html#getConnectionStatusCode()"> -{@code getConnectionStatusCode()}</a> and pass the result to <a href= -"{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesUtil.html#getErrorDialog(int,%20android.app.Activity,%20int,%20android.content.DialogInterface.OnCancelListener)"> -{@code GooglePlayServicesUtil.getErrorDialog()}</a>. This returns a {@link android.app.Dialog} -that includes an appropriate message and a button to take users to Google Play Store so they -can install an update.</dd> -</dl> - -<p>For example, the <code>fetchToken()</code> method in the above sample code catches any -occurrence of <a -href="{@docRoot}reference/com/google/android/gms/auth/UserRecoverableAuthException.html">{@code -UserRecoverableAuthException}</a> and passes it back to the activity with a method called -{@code handleException()}. Here's what that method in the activity may look like:</p> - - -<pre> -static final int REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR = 1001; - -/** - * This method is a hook for background threads and async tasks that need to - * provide the user a response UI when an exception occurs. - */ -public void handleException(final Exception e) { - // Because this call comes from the AsyncTask, we must ensure that the following - // code instead executes on the UI thread. - runOnUiThread(new Runnable() { - @Override - public void run() { - if (e instanceof GooglePlayServicesAvailabilityException) { - // The Google Play services APK is old, disabled, or not present. - // Show a dialog created by Google Play services that allows - // the user to update the APK - int statusCode = ((GooglePlayServicesAvailabilityException)e) - .getConnectionStatusCode(); - Dialog dialog = GooglePlayServicesUtil.getErrorDialog(statusCode, - HelloActivity.this, - REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR); - dialog.show(); - } else if (e instanceof UserRecoverableAuthException) { - // Unable to authenticate, such as when the user has not yet granted - // the app access to the account, but the user can fix this. - // Forward the user to an activity in Google Play services. - Intent intent = ((UserRecoverableAuthException)e).getIntent(); - startActivityForResult(intent, - REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR); - } - } - }); -} -</pre> - -<p>Notice that in both cases, the {@code REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR} -request code is passed with the request to handle the exception with a dialog or activity. -This way, when the user completes the appropriate action to resolve the exception, -your {@link android.app.Activity#onActivityResult onActivityResult()} method receives an -intent that includes this request code and you can try to acquire the auth -token again.</p> - - -<p>For example, the following code is a complete implementation of {@link -android.app.Activity#onActivityResult onActivityResult()} that handles results for -both the {@code REQUEST_CODE_PICK_ACCOUNT} action (shown in the previous lesson, <a -href="{@docRoot}training/auth-google/picking-account.html">Picking the User's Account</a>) -and the {@code REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR} action, which occurs after the user -completes one of the actions above to resolve an exception.</p> - - -<pre> -@Override -protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (requestCode == REQUEST_CODE_PICK_ACCOUNT) { - // Receiving a result from the AccountPicker - if (resultCode == RESULT_OK) { - mEmail = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME); - // With the account name acquired, go get the auth token - getUsername(); - } else if (resultCode == RESULT_CANCELED) { - // The account picker dialog closed without selecting an account. - // Notify users that they must pick an account to proceed. - Toast.makeText(this, R.string.pick_account, Toast.LENGTH_SHORT).show(); - } - } else if ((requestCode == REQUEST_CODE_RECOVER_FROM_AUTH_ERROR || - requestCode == REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR) - && resultCode == RESULT_OK) { - // Receiving a result that follows a GoogleAuthException, try auth again - getUsername(); - } -} -</pre> - -<p>For a complete set of code that acquires the OAuth token and queries a Google service -over HTTP (including how to use <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> when you need to acquire the token from -a {@link android.app.Service}), see the sample app available for download at the top -of this page.</p> - - - |