Authorizing and Using REST APIs

This guide tells you how to authorize with Google and use Google REST APIs when you want your app to access Google APIs with the user's Google account over HTTP. However, in some cases, there are other approaches that might make more sense for your app:

  • REST APIs are used by your server. If you only make REST API calls from a server that you manage and use to support your app, see Enable Server-Side API Access for instructions on how to authorize on your Android client.
  • Use Google APIs for Android. We provide Google APIs for Android for several Google products, and these are usually easier to use than REST APIs. We recommend that you use those APIs instead (for example, Google Fit, Games and Drive), and that you follow API-specific instructions for authentication.

Configure build dependencies

The first step is to configure build dependencies in your app's root-level build.gradle file. In this example, we are using the -auth API split in the Google Play services SDK to avoid loading the entire SDK into the app.

// Google Play services Auth split
compile 'com.google.android.gms:play-services-auth:10.2.1'
// Google Api Client library and Android extension
compile 'com.google.api-client:google-api-client:1.22.0'
compile 'com.google.api-client:google-api-client-android:1.22.0'
// Change to the API you want to access:
// Below is just an example for People REST API access
compile 'com.google.apis:google-api-services-people:v1-rev4-1.22.0'

Use the Google-Provided authorization UI for REST API access

You no longer need to spend time building an authorization UI to implement account selection, authorization and API access for Google APIs. Instead, you can save yourself time by giving users of your Android app a Google-provided authorization UI that handles all of this, by using the Auth.GoogleSignInApi method.

Specify scopes

To specify scopes, create a GoogleSignInOptions object with the new scopes that you want to request by calling GoogleSignInOptions.Builder.requestScopes. To see a list of valid OAuth scope values for Google services, see the OAuth 2.0 Playground.

When designing your app, you should request OAuth scope access incrementally. This means that you request access to only the scopes that your app needs in an appropriate context and at the time they are needed, so the user understands why these scopes are being requested.

For example, for a document scanning app, at initial sign-in time you should only request basic scopes by using GoogleSignInOption.DEFAULT_SIGN_IN. Then, prompt the user for Drive file access only when the user tries to save the document to Google Drive. Finally, request access to the user's contacts only when the user tries to send the doc to their contacts. This aligns with the runtime permissions model in Android Marshmallow and newer OS versions. By following these best practices when Requesting Additional Scopes, you help to foster user trust in your app, and increase the chances that they will choose to grant your app access to requested OAuth scopes.

The following example code shows how to use GoogleSignInOptions to select a user account and authorize specific scopes:

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.sign_in_button:
            authorizeContactsAccess();
            break;
        // ...
    }
}

private void authorizeContactsAccess() {
    GoogleSignInOptions gso =
        new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestEmail().
            .requestScopes(new Scope("https://www.googleapis.com/auth/contacts.readonly"))
            .build();

    mGoogleApiClient = new GoogleApiClient.Builder(this)
        .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
        .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
        .build();
    Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
    startActivityForResult(signInIntent, RC_AUTHORIZE_CONTACTS);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
    if (requestCode == RC_AUTHORIZE_CONTACTS) {
        GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
        if (result.isSuccess) {
            GoogleSignInAccount googleSignInAccount = result.getSignInAccount();
            mAuthorizedAccount = googleSignInAccount.getAccount();
            getContacts();
        }
    }
}

You can get an Android Account object as part of your Google Sign-In result, and you can later instantiate a GoogleAccountCredential object with it. When you use GoogleAccountCredential, the REST API client library code can handle underlying OAuth token retrieval on your behalf.

Use GoogleAccountCredential and the client library for REST API access

The following is an example of accessing the People REST API with the GoogleAccountCredential object.

private void getContacts(Account account) {
     GetContactsTask task = new GetContactsTask(mAuthorizedAccount);
     task.execute();
}

/** Global instance of the HTTP transport. */
private static HttpTransport HTTP_TRANSPORT = AndroidHttp.newCompatibleTransport();
/** Global instance of the JSON factory. */
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();

private class GetContactsTask extends AsyncTask<Void, Void, List<Person>> {

   Account mAccount;
   public GetContactsTask(Account account) {
       mAccount = account;
   }

   @Override
   protected List<Person> doInBackground(Void... params) {
       List<Person> result = null;
       try {
           GoogleAccountCredential credential =
               GoogleAccountCredential.usingOAuth2(
                   MainActivity.this,
                   Collections.singleton(
                       "https://www.googleapis.com/auth/contacts.readonly")
                );
           credential.setSelectedAccount(mAccount);
           People service = new People.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
               .setApplicationName("REST API sample")
               .build();
           ListConnectionsResponse connectionsResponse = service
               .people()
               .connections()
               .list("people/me")
               .execute();
           result = connectionsResponse.getConnections();
       } catch (UserRecoverableAuthIOException userRecoverableException) {
           // Explain to the user again why you need these OAuth permissions
           // And prompt the resolution to the user again:
           startActivityForResult(userRecoverableException.getIntent(),RC_REAUTHORIZE);
       } catch (IOException e) {
           // Other non-recoverable exceptions.
       }

       return result;
   }

   @Override
   protected void onCancelled() {
      ...
   }

   @Override
   protected void onPostExecute(List<Person> connections) {
      ...
   }
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
    if (requestCode == RC_AUTHORIZE_CONTACTS) {
        …
    } else if (requestCode == RC_REAUTHORIZE) {
        if (resultCode == RESULT_OK) {
            getContacts();
        }
    }
}

You can find the complete REST API sample code included in the Google Sign-In Quickstart on Github: RestApiActivity.java

Exception handling

If you already went through the authorization steps using Auth.GoogleSignInApi and it succeeded, UserRecoverableAuthIOException is usually not expected. However, a user might choose to revoke OAuth permission from your application even if they had authorized it previously. In those cases, UserRecoverableAuthIOExceptionwill be thrown in the code shown above. You can explain to the user again why you need the permission, prompt them for resolution, and retry.

To test out this revocation scenario, go to Settings -> Google -> Connected Apps and revoke access there. For Android Lollipop and earlier OS versions, go to Google Settings -> Connected Apps.