1page.title=Accessing Google APIs
2page.tags="oauth 2.0","GoogleAuthUtil"
3
4trainingnavtop=true
5startpage=true
6
7@jd:body
8
9<div id="qv-wrapper">
10  <div id="qv">
11
12<h2>In this document</h2>
13<ol>
14  <li><a href="#Starting">Start a Connection</a>
15    <ol>
16      <li><a href="#HandlingFailures">Handle connection failures</a></li>
17      <li><a href="#MaintainingState">Maintain state while resolving an error</a></li>
18      <li><a href="#WearableApi">Access the Wearable API</a></li>
19    </ol>
20  </li>
21  <li><a href="#Communicating">Communicate with Google Services</a>
22    <ol>
23      <li><a href="#Async">Using asynchronous calls</a></li>
24      <li><a href="#Sync">Using synchronous calls</a></li>
25    </ol>
26  </li>
27</ol>
28</div>
29</div>
30
31
32<p>When you want to make a connection to one of the Google APIs provided in the Google Play services
33library (such as Google+, Games, or Drive), you need to create an instance of <a
34href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code
35GoogleApiClient}</a> ("Google API Client"). The Google API Client provides a common entry point to all
36the Google Play services and manages the network connection between the user's device and each
37Google service.</p>
38
39<div class="sidebox" style="clear:right;width:190px">
40<h2>Connecting to REST APIs</h2>
41<p>If the Google API you want to use is not included in the Google Play services library, you can
42connect using the appropriate REST API, but you must obtain an OAuth 2.0 token. For more
43information, read <a href="{@docRoot}google/auth/http-auth.html">Authorizing with Google
44for REST APIs</a>.</p>
45</div>
46
47<p>This guide shows how you can use Google API Client to:</p>
48<ul>
49<li>Connect to one or more Google Play services asynchronously and handle failures.</li>
50<li>Perform synchronous and asynchronous API calls to any of the Google Play services.</li>
51</ul>
52
53<p class="note">
54<strong>Note:</strong> If you have an existing app that connects to Google Play services with a
55subclass of <a
56href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.html">{@code GooglePlayServicesClient}</a>, you should migrate to <a
57href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code
58GoogleApiClient}</a> as soon as possible.</p>
59
60
61<img src="{@docRoot}images/google/GoogleApiClient@2x.png" width="464px" alt="" />
62<p class="img-caption">
63<strong>Figure 1.</strong> An illustration showing how the Google API Client provides an
64interface for connecting and making calls to any of the available Google Play services such as
65Google Play Games and Google Drive.</p>
66
67
68
69<p>To get started, you must first install the Google Play services library (revision 15 or higher) for
70your Android SDK. If you haven't done so already, follow the instructions in <a
71href="{@docRoot}google/play-services/setup.html">Set Up Google
72Play Services SDK</a>.</p>
73
74
75
76
77<h2 id="Starting">Start a Connection</h2>
78
79<p>Once your project is linked to the Google Play services library, create an instance of <a
80href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code
81GoogleApiClient}</a> using the <a
82href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.Builder.html">{@code
83GoogleApiClient.Builder}</a> APIs in your activity's {@link
84android.app.Activity#onCreate onCreate()} method. The <a
85href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.Builder.html">{@code
86GoogleApiClient.Builder}</a> class
87provides methods that allow you to specify the Google APIs you want to use and your desired OAuth
882.0 scopes. For example, here's a <a
89href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code
90GoogleApiClient}</a> instance that connects with the Google
91Drive service:</p>
92<pre>
93GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this)
94    .addApi(Drive.API)
95    .addScope(Drive.SCOPE_FILE)
96    .build();
97</pre>
98
99<p>You can add multiple APIs and multiple scopes to the same <a
100href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code
101GoogleApiClient}</a> by appending
102additional calls to
103<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.Builder.html#addApi(com.google.android.gms.common.api.Api)"
104>{@code addApi()}</a> and
105<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.Builder.html#addScope(com.google.android.gms.common.api.Scope)"
106>{@code addScope()}</a>.</p>
107
108<p class="caution">
109<strong>Important:</strong> To avoid client connection errors on devices that do not have the
110<a href="https://play.google.com/store/apps/details?id=com.google.android.wearable.app&hl=en">Android
111Wear app</a> installed, use a separate <a
112href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code
113GoogleApiClient}</a> instance to access only the <a
114href="{@docRoot}reference/com/google/android/gms/wearable/Wearable.html">{@code
115Wearable}</a> API. For more information, see <a href="#WearableApi">Access the Wearable
116API</a>.</p>
117
118<p>Before you can begin a connection by calling <a
119href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html#connect()"
120>{@code connect()}</a> on the <a
121href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code
122GoogleApiClient}</a>, you must specify an implementation for the callback interfaces, <a
123href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html"
124>{@code ConnectionCallbacks}</a> and <a
125href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.OnConnectionFailedListener.html"
126>{@code OnConnectionFailedListener}</a>. These interfaces receive callbacks in
127response to the asynchronous <a
128href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html#connect()"
129>{@code connect()}</a> method when the connection to Google Play services
130succeeds, fails, or becomes suspended.</p>
131
132<p>For example, here's an activity that implements the callback interfaces and adds them to the Google
133API Client:</p>
134
135<pre>
136import gms.common.api.*;
137import gms.drive.*;
138import android.support.v4.app.FragmentActivity;
139
140public class MyActivity extends FragmentActivity
141        implements ConnectionCallbacks, OnConnectionFailedListener {
142    private GoogleApiClient mGoogleApiClient;
143
144    &#64;Override
145    protected void onCreate(Bundle savedInstanceState) {
146        super.onCreate(savedInstanceState);
147
148        // Create a GoogleApiClient instance
149        mGoogleApiClient = new GoogleApiClient.Builder(this)
150                .addApi(Drive.API)
151                .addScope(Drive.SCOPE_FILE)
152                .addConnectionCallbacks(this)
153                .addOnConnectionFailedListener(this)
154                .build();
155        ...
156    }
157
158    &#64;Override
159    public void onConnected(Bundle connectionHint) {
160        // Connected to Google Play services!
161        // The good stuff goes here.
162    }
163
164    &#64;Override
165    public void onConnectionSuspended(int cause) {
166        // The connection has been interrupted.
167        // Disable any UI components that depend on Google APIs
168        // until onConnected() is called.
169    }
170
171    &#64;Override
172    public void onConnectionFailed(ConnectionResult result) {
173        // This callback is important for handling errors that
174        // may occur while attempting to connect with Google.
175        //
176        // More about this in the next section.
177        ...
178    }
179}
180</pre>
181
182<p>With the callback interfaces defined, you're ready to call <a
183href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html#connect()"
184>{@code connect()}</a>. To gracefully manage
185the lifecycle of the connection, you should call <a
186href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html#connect()"
187>{@code connect()}</a> during the activity's {@link
188android.app.Activity#onStart onStart()} (unless you want to connect later), then call <a
189href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html#disconnect()"
190>{@code disconnect()}</a> during the {@link android.app.Activity#onStop onStop()} method. For example:</p>
191<pre>
192    &#64;Override
193    protected void onStart() {
194        super.onStart();
195        if (!mResolvingError) {  // more about this later
196            mGoogleApiClient.connect();
197        }
198    }
199
200    &#64;Override
201    protected void onStop() {
202        mGoogleApiClient.disconnect();
203        super.onStop();
204    }
205</pre>
206
207<p>However, if you run this code, there's a good chance it will fail and your app will receive a call
208to <a
209href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.OnConnectionFailedListener.html#onConnectionFailed(com.google.android.gms.common.ConnectionResult)"
210>{@code onConnectionFailed()}</a> with the <a
211href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html#SIGN_IN_REQUIRED"
212>{@code SIGN_IN_REQUIRED}</a> error because the user account
213has not been specified. The next section shows how to handle this error and others.</p>
214
215
216
217
218<h3 id="HandlingFailures">Handle connection failures</h3>
219
220<p>When you receive a call to the <a
221href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.OnConnectionFailedListener.html#onConnectionFailed(com.google.android.gms.common.ConnectionResult)"
222>{@code onConnectionFailed()}</a> callback, you should call <a
223href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html#hasResolution()"
224>{@code hasResolution()}</a> on the provided <a
225href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html"
226>{@code ConnectionResult}</a> object. If it returns true, you can
227request the user take immediate action to resolve the error by calling <a
228href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html#startResolutionForResult(android.app.Activity, int)">{@code startResolutionForResult()}</a> on the <a
229href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html"
230>{@code ConnectionResult}</a> object. The <a
231href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html#startResolutionForResult(android.app.Activity, int)"
232>{@code startResolutionForResult()}</a> behaves the same as {@link
233android.app.Activity#startActivityForResult startActivityForResult()} and launches the
234appropriate activity for the user
235to resolve the error (such as an activity to select an account).</p>
236
237<p>If <a
238href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html#hasResolution()"
239>{@code hasResolution()}</a> returns false, you should instead call <a
240href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesUtil.html#getErrorDialog(int, android.app.Activity, int)"
241>{@code GooglePlayServicesUtil.getErrorDialog()}</a>, passing it the error code. This returns a {@link
242android.app.Dialog} provided by Google Play services that's appropriate for the given error. The
243dialog may simply provide a message explaining the error, but it may also provide an action to
244launch an activity that can resolve the error (such as when the user needs to install a newer
245version of Google Play services).</p>
246
247<p>For example, your <a
248href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.OnConnectionFailedListener.html#onConnectionFailed(com.google.android.gms.common.ConnectionResult)"
249>{@code onConnectionFailed()}</a> callback method should now look like this:</p>
250
251<pre>
252public class MyActivity extends FragmentActivity
253        implements ConnectionCallbacks, OnConnectionFailedListener {
254
255    // Request code to use when launching the resolution activity
256    private static final int REQUEST_RESOLVE_ERROR = 1001;
257    // Unique tag for the error dialog fragment
258    private static final String DIALOG_ERROR = "dialog_error";
259    // Bool to track whether the app is already resolving an error
260    private boolean mResolvingError = false;
261
262    ...
263
264    &#64;Override
265    public void onConnectionFailed(ConnectionResult result) {
266        if (mResolvingError) {
267            // Already attempting to resolve an error.
268            return;
269        } else if (result.hasResolution()) {
270            try {
271                mResolvingError = true;
272                result.startResolutionForResult(this, REQUEST_RESOLVE_ERROR);
273            } catch (SendIntentException e) {
274                // There was an error with the resolution intent. Try again.
275                mGoogleApiClient.connect();
276            }
277        } else {
278            // Show dialog using GooglePlayServicesUtil.getErrorDialog()
279            showErrorDialog(result.getErrorCode());
280            mResolvingError = true;
281        }
282    }
283
284    // The rest of this code is all about building the error dialog
285
286    /* Creates a dialog for an error message */
287    private void showErrorDialog(int errorCode) {
288        // Create a fragment for the error dialog
289        ErrorDialogFragment dialogFragment = new ErrorDialogFragment();
290        // Pass the error that should be displayed
291        Bundle args = new Bundle();
292        args.putInt(DIALOG_ERROR, errorCode);
293        dialogFragment.setArguments(args);
294        dialogFragment.show(getSupportFragmentManager(), "errordialog");
295    }
296
297    /* Called from ErrorDialogFragment when the dialog is dismissed. */
298    public void onDialogDismissed() {
299        mResolvingError = false;
300    }
301
302    /* A fragment to display an error dialog */
303    public static class ErrorDialogFragment extends DialogFragment {
304        public ErrorDialogFragment() { }
305
306        &#64;Override
307        public Dialog onCreateDialog(Bundle savedInstanceState) {
308            // Get the error code and retrieve the appropriate dialog
309            int errorCode = this.getArguments().getInt(DIALOG_ERROR);
310            return GooglePlayServicesUtil.getErrorDialog(errorCode,
311                    this.getActivity(), REQUEST_RESOLVE_ERROR);
312        }
313
314        &#64;Override
315        public void onDismiss(DialogInterface dialog) {
316            ((MainActivity)getActivity()).onDialogDismissed();
317        }
318    }
319}
320</pre>
321
322<p>Once the user completes the resolution provided by <a
323href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html#startResolutionForResult(android.app.Activity, int)"
324>{@code startResolutionForResult()}</a> or <a
325href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesUtil.html#getErrorDialog(int, android.app.Activity, int)"
326>{@code GooglePlayServicesUtil.getErrorDialog()}</a>, your activity receives the {@link
327android.app.Activity#onActivityResult onActivityResult()} callback with the {@link
328android.app.Activity#RESULT_OK}
329result code. You can then call <a
330href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html#connect()"
331>{@code connect()}</a> again. For example:</p>
332
333<pre>
334&#64;Override
335protected void onActivityResult(int requestCode, int resultCode, Intent data) {
336    if (requestCode == REQUEST_RESOLVE_ERROR) {
337        mResolvingError = false;
338        if (resultCode == RESULT_OK) {
339            // Make sure the app is not already connected or attempting to connect
340            if (!mGoogleApiClient.isConnecting() &&
341                    !mGoogleApiClient.isConnected()) {
342                mGoogleApiClient.connect();
343            }
344        }
345    }
346}
347</pre>
348
349<p>In the above code, you probably noticed the boolean, {@code mResolvingError}. This keeps track of
350the app state while the user is resolving the error to avoid repetitive attempts to resolve the
351same error. For instance, while the account picker dialog is showing to resolve the <a
352href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html#SIGN_IN_REQUIRED"
353>{@code SIGN_IN_REQUIRED}</a> error, the user may rotate the screen. This recreates your activity and causes
354your {@link android.app.Activity#onStart onStart()} method to be called again, which then calls <a
355href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html#connect()"
356>{@code connect()}</a> again. This results in another call to <a
357href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html#startResolutionForResult(android.app.Activity, int)"
358>{@code startResolutionForResult()}</a>, which
359creates another account picker dialog in front of the existing one.</p>
360
361<p>This boolean is effective only
362if retained across activity instances, though. The next section explains further.</p>
363
364
365
366<h3 id="MaintainingState">Maintain state while resolving an error</h3>
367
368<p>To avoid executing the code in <a
369href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.OnConnectionFailedListener.html#onConnectionFailed(com.google.android.gms.common.ConnectionResult)"
370>{@code onConnectionFailed()}</a> while a previous attempt to resolve an
371error is ongoing, you need to retain a boolean that tracks whether your app is already attempting
372to resolve an error.</p>
373
374<p>As shown in the code above, you should set a boolean to {@code true} each time you call <a
375href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html#startResolutionForResult(android.app.Activity, int)"
376>{@code startResolutionForResult()}</a> or display the dialog from <a
377href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesUtil.html#getErrorDialog(int, android.app.Activity, int)"
378>{@code GooglePlayServicesUtil.getErrorDialog()}</a>. Then when you
379receive {@link android.app.Activity#RESULT_OK} in the {@link android.app.Activity#onActivityResult
380onActivityResult()} callback, set the boolean to {@code false}.</p>
381
382<p>To keep track of the boolean across activity restarts (such as when the user rotates the screen),
383save the boolean in the activity's saved instance data using {@link
384android.app.Activity#onSaveInstanceState onSaveInstanceState()}:</p>
385
386<pre>
387private static final String STATE_RESOLVING_ERROR = "resolving_error";
388
389&#64;Override
390protected void onSaveInstanceState(Bundle outState) {
391    super.onSaveInstanceState(outState);
392    outState.putBoolean(STATE_RESOLVING_ERROR, mResolvingError);
393}
394</pre>
395
396<p>Then recover the saved state during {@link android.app.Activity#onCreate onCreate()}:</p>
397
398<pre>
399&#64;Override
400protected void onCreate(Bundle savedInstanceState) {
401    super.onCreate(savedInstanceState);
402
403    ...
404    mResolvingError = savedInstanceState != null
405            && savedInstanceState.getBoolean(STATE_RESOLVING_ERROR, false);
406}
407</pre>
408
409<p>Now you're ready to safely run your app and connect to Google Play services.
410How you can perform read and write requests to any of the Google Play services
411using <a
412href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code
413GoogleApiClient}</a> is discussed in the next section.</p>
414
415<p>For more information about each services's APIs available once you're connected,
416consult the corresponding documentation, such as for
417<a href="{@docRoot}google/play-services/games.html">Google Play Games</a> or
418<a href="{@docRoot}google/play-services/drive.html">Google Drive</a>.
419</p>
420
421
422<h3 id="WearableApi">Access the Wearable API</h3>
423
424<p>On devices that do not have the <a
425href="https://play.google.com/store/apps/details?id=com.google.android.wearable.app&hl=en">Android
426Wear app</a> installed, connection requests that include the <a
427href="{@docRoot}reference/com/google/android/gms/wearable/Wearable.html">{@code
428Wearable}</a> API fail with the <a
429href="{@docRoot}reference/com/google/android/gms/common/ConnectionResult.html#API_UNAVAILABLE">
430<code>API_UNAVAILABLE</code></a> error code. If your app uses the <a
431href="{@docRoot}reference/com/google/android/gms/wearable/Wearable.html">{@code
432Wearable}</a> API in addition to other Google APIs, use a separate <a
433href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code
434GoogleApiClient}</a> instance to access the <a
435href="{@docRoot}reference/com/google/android/gms/wearable/Wearable.html">{@code
436Wearable}</a> API. This approach enables you to access other Google APIs on devices that are not
437paired with a wearable device.</p>
438
439<p>When you use a separate <a
440href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code
441GoogleApiClient}</a> instance to access only the Wearable API, you can determine
442whether the <a
443href="https://play.google.com/store/apps/details?id=com.google.android.wearable.app&hl=en">Android
444Wear app</a> is installed on the device:</p>
445
446<pre>
447// Connection failed listener method for a client that only
448// requests access to the Wearable API
449&#64;Override
450public void onConnectionFailed(ConnectionResult result) {
451    if (result.getErrorCode() == ConnectionResult.API_UNAVAILABLE) {
452        // The Android Wear app is not installed
453    }
454    ...
455}
456</pre>
457
458
459
460
461
462
463<h2 id="Communicating">Communicate with Google Services</h2>
464
465<p>Once connected, your client can make read and write calls using the service-specific APIs for which
466your app is authorized, as specified by the APIs and scopes you added to your <a
467href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">{@code
468GoogleApiClient}</a> instance.</p>
469
470<p class="note">
471<strong>Note:</strong> Before making calls to specific Google services, you may first need to
472register your app in the Google Developer Console. For specific instructions, refer to the
473appropriate getting started guide for the API you're using, such as <a href=
474"https://developers.google.com/drive/android/get-started">Google Drive</a> or <a href=
475"https://developers.google.com/+/mobile/android/getting-started">Google+</a>.</p>
476
477<p>When you perform a read or write request using Google API Client, the immediate result is returned
478as a <a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html">{@code
479PendingResult}</a> object. This is an object representing the request, which hasn't yet
480been delivered to the Google service.</p>
481
482<p>For example, here's a request to read a file from Google Drive that provides a
483<a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html">{@code
484PendingResult}</a> object:</p>
485
486<pre>
487Query query = new Query.Builder()
488        .addFilter(Filters.eq(SearchableField.TITLE, filename));
489PendingResult result = Drive.DriveApi.query(mGoogleApiClient, query);
490</pre>
491
492<p>Once you have the
493<a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html">{@code
494PendingResult}</a>, you can continue by making the request either asynchronous
495or synchronous.</p>
496
497
498<h3 id="Async">Using asynchronous calls</h3>
499
500<p>To make the request asynchronous, call <a
501href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html#setResultCallback(com.google.android.gms.common.api.ResultCallback<R>)"
502>{@code setResultCallback()}</a> on the
503<a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html">{@code
504PendingResult}</a> and
505provide an implementation of the <a
506href="{@docRoot}reference/com/google/android/gms/common/api/ResultCallback.html"
507>{@code ResultCallback}</a> interface. For example, here's the request
508executed asynchronously:</p>
509
510<pre>
511private void loadFile(String filename) {
512    // Create a query for a specific filename in Drive.
513    Query query = new Query.Builder()
514            .addFilter(Filters.eq(SearchableField.TITLE, filename))
515            .build();
516    // Invoke the query asynchronously with a callback method
517    Drive.DriveApi.query(mGoogleApiClient, query)
518            .setResultCallback(new ResultCallback&lt;DriveApi.MetadataBufferResult>() {
519        &#64;Override
520        public void onResult(DriveApi.MetadataBufferResult result) {
521            // Success! Handle the query result.
522            ...
523        }
524    });
525}
526</pre>
527
528<p>When your app receives a <a
529href="{@docRoot}reference/com/google/android/gms/common/api/Result.html">{@code Result}</a>
530object in the <a
531href="{@docRoot}reference/com/google/android/gms/common/api/ResultCallback.html#onResult(R)"
532>{@code onResult()}</a> callback, it is delivered as an instance of the
533appropriate subclass as specified by the API you're using, such as <a
534href="{@docRoot}reference/com/google/android/gms/drive/DriveApi.MetadataBufferResult.html"
535>{@code DriveApi.MetadataBufferResult}</a>.</p>
536
537
538<h3 id="Sync">Using synchronous calls</h3>
539
540<p>If you want your code to execute in a strictly defined order, perhaps because the result of one
541call is needed as an argument to another, you can make your request synchronous by calling <a
542href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html#await()"
543>{@code await()}</a> on the
544<a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html">{@code
545PendingResult}</a>. This blocks the thread and returns the <a
546href="{@docRoot}reference/com/google/android/gms/common/api/Result.html">{@code Result}</a> object
547when the request completes, which is delivered as an instance of the
548appropriate subclass as specified by the API you're using, such as <a
549href="{@docRoot}reference/com/google/android/gms/drive/DriveApi.MetadataBufferResult.html"
550>{@code DriveApi.MetadataBufferResult}</a>.</p>
551
552<p>Because calling <a
553href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html#await()"
554>{@code await()}</a> blocks the thread until the result arrives, it's important that you
555never perform this call on the UI thread. So, if you want to perform synchronous requests to a
556Google Play service, you should create a new thread, such as with {@link android.os.AsyncTask} in
557which to perform the request. For example, here's how to perform the same file request to Google
558Drive as a synchronous call:</p>
559
560<pre>
561private void loadFile(String filename) {
562    new GetFileTask().execute(filename);
563}
564
565private class GetFileTask extends AsyncTask&lt;String, Void, Void> {
566    protected void doInBackground(String filename) {
567        Query query = new Query.Builder()
568                .addFilter(Filters.eq(SearchableField.TITLE, filename))
569                .build();
570        // Invoke the query synchronously
571        DriveApi.MetadataBufferResult result =
572                Drive.DriveApi.query(mGoogleApiClient, query).await();
573
574        // Continue doing other stuff synchronously
575        ...
576    }
577}
578</pre>
579
580<p class="note">
581<strong>Tip:</strong> You can also enqueue read requests while not connected to Google Play
582services. For example, execute a method to read a file from Google Drive regardless of whether your
583Google API Client is connected yet. Then once a connection is established, the read requests
584execute and you'll receive the results. Any write requests, however, will generate an error if you
585call them while your Google API Client is not connected.</p>
586
587