Tag Archives: Google client API

Google Play services and Firebase for Android will support API level 14 at minimum

Posted by Doug Stevenson, Developer Advocate

Version 10.0.0 of the Google Play services client libraries, as well as the Firebase client libraries for Android, will be the last version of these libraries that support Android API level 9 (Android 2.3, Gingerbread). The next scheduled release of these libraries, version 10.2.0, will increase the minimum supported API level from 9 to 14 (Android 4.0.1, Ice Cream Sandwich). This change will happen in early 2017.

Why are we discontinuing support for Gingerbread and Honeycomb in Google Play services?

The Gingerbread platform is almost six years old. Many Android developers have already discontinued support for Gingerbread in their apps. This helps them build better apps that make use of the newer capabilities of the Android platform. For us, the situation is the same. By making this change, we will be able to provide a more robust collection of tools for Android developers with greater speed.

What this means for your Android app that uses Google Play services or Firebase:

You may use version 10.0.0 of Google Play services and Firebase as you are currently. It will continue to work with Gingerbread devices as it has in the past.

When you choose to upgrade to the future version 10.2.0, and if your app minimally supports API level 14 or greater (typically specified as "minSdkVersion" in your build.gradle), you will not encounter any versioning problems. However, if your app supports lower than API level 14, you will encounter a problem at build time with an error that looks like this:

Error:Execution failed for task ':app:processDebugManifest'.
> Manifest merger failed : uses-sdk:minSdkVersion 9 cannot be smaller than version 14 declared in library [com.google.android.gms:play-services:10.2.0]
        Suggestion: use tools:overrideLibrary="com.google.android.gms:play_services" to force usage

Unfortunately, the stated suggestion will not help you successfully run your app on older devices. In order to use Google Play services 10.2.0 and later, you can choose one of the following options:

1. Target API level 14 as the minimum supported API level.

This is the recommended course of action. To discontinue support for API levels that will no longer receive Google Play services updates, simply increase the minSdkVersion value in your app's build.gradle to at least 14. If you update your app in this way and publish it to the Play Store, users of devices with less than that level of support will not be able to see or download the update. However, they will still be able to download and use the most recently published version of the app that does target their device.

A very small percentage of all Android devices are using API levels less than 14. You can read more about the current distribution of Android devices. We believe that many of these old devices are not actively being used.

If your app still has a significant number of users on older devices, you can use multiple APK support in Google Play to deliver an APK that uses Google Play services 10.0.0. This is described below.

2. Build multiple APKs to support devices with an API level less than 14.

Along with some configuration and code management, you can build multiple APKs that support different minimum API levels, with different versions of Google Play services. You can accomplish this with build variants in Gradle. First, define build flavors for legacy and newer versions of your app. For example, in your build.gradle, define two different product flavors, with two different compile dependencies for the components of Play Services you're using:

productFlavors {
    legacy {
        minSdkVersion 9
        versionCode 901  // Min API level 9, v01
    }
    current {
        minSdkVersion 14
        versionCode 1401  // Min API level 14, v01
    }
}

dependencies {
    legacyCompile 'com.google.android.gms:play-services:10.0.0'
    currentCompile 'com.google.android.gms:play-services:10.2.0'
}

In the above situation, there are two product flavors being built against two different versions of the Google Play services client libraries. This will work fine if only APIs are called that are available in the 10.0.0 library. If you need to call newer APIs made available with 10.2.0, you will have to create a compatibility library for the newer API calls so that they are only built into the version of the application that can use them:

  • Declare a Java interface that exposes the higher-level functionality you want to perform that is only available in current versions of Play services.
  • Build two Android libraries that implement that interface. The "current" implementation should call the newer APIs as desired. The "legacy" implementation should no-op or otherwise act as desired with older versions of Play services. The interface should be added to both libraries.
  • Conditionally compile each library into the app using "legacyCompile" and "currentCompile" dependencies.
  • In the app's code, call through to the compatibility library whenever newer Play APIs are required.

After building a release APK for each flavor, you then publish them both to the Play Store, and the device will update with the most appropriate version for that device. Read more about multiple APK support in the Play Store.

Announcing the People API

Posted by Laurence Moroney, Developer Advocate

We’re delighted to announce the availability of the People API. With it, you can retrieve data about an authenticated user’s connections from their Contacts. Previously, developers had to make multiple calls to the Google+ API for user profiles and the Contacts API for contacts. The new People API uses the newest protocols and technologies and will eventually replace the Contacts API which uses the GData protocol.

For example, if your user has contacts in her private contact list, a call to the API (if she provides consent to do so) will retrieve a list containing the contacts merged with any linked profiles. If the user grants the relevant scopes, the results are returned as a people.connections.list object. Each person object in this list will have a resourceName property, which can be used to get additional data about that person with a call to people.get.

The API is built on HTTP and JSON, so any standard HTTP client can send requests to it and parse the response. However, applications need to be authorized to access the APIs so you will need to create a project on the Google Developers Console in order to get the credentials you need to access the service. All the steps to do so are here. If you’re new to the Google APIs and/or the Developers Console, check out this first in a series of videos to help you get up-to-speed.

Once you’re connected and authorized, you can then get the user’s connections like this (using the Google APIs Client Library for Java):


 ListConnectionsResponse response =   
     peopleService.people().connections().list("people/me").execute();  
 List<Person> connections = response.getConnections();  

Full documentation on the people.connections.list method is available here.

The list of connections will have details on all the user’s social connections if the required scopes have been granted. Contacts will only be returned if the user granted a contacts scope.

Each Person item will have a resource_name associated with it, so additional data for that person will be accessible via a simple call:

Person person = peopleService.people().get("resourceName").execute();

Details on this API call can be found here.

In addition to merging data from multiple sources and APIs into a single cohesive data source, the new People API also exposes additional data that was not possible to get before, such as private addresses, phone numbers, e-mails, and birthdays for a user who has given permission.

We hope that these new features and data along with simplified access to existing data inspires you to create the next generation of cool web and mobile apps that delight your users and those in their circles of influence. To learn more about the People API, check out the official documentation here.

API Updates for Sign-In with Google

Posted by Laurence Moroney

With the release of Google Play services 8.3, we’ve made a lot of improvements to Sign-In with Google. In the first blog post of this ongoing series, we discussed the user interface improvements. Today, we will look further into the changes to the API to make building apps that Sign-In with Google easier than ever before.

Changes to basic sign in flow

When building apps that sign in with Google, you’ll notice that there are a lot of changes to make your code easier to understand and maintain.

Prior to this release, if you built an app that used Sign-In with Google, you would build one that attempted to connect to a GoogleApiClient. At this point the user was presented with an account picker and/or a permissions dialog, both of which would trigger a connection failure. You would have to handle these connection failures in order to sign in. Once the GoogleApiClient connected, then the user was considered to be signed in and the permissions could be granted. The process is documented in a CodeLab here.

Now, your code can be greatly simplified.

The process of signing in and connecting the GoogleApiClient are handled separately. Signing in is achieved with a GoogleSignInOptions object, on which you specify the parameters of the sign in, such as scopes that you desire. Here’s a code example:

GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
        .requestEmail()
        .build();

Once you have a GoogleSignInOptions object, you can use it to configure the GoogleApiClient:

mGoogleApiClient = new GoogleApiClient.Builder(this)
        .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
        .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
        .build();

Here’s where your code will diverge greatly in the new API. Now, if you want to connect with a Google Account, instead of handling errors on the GoogleApiClient, you’ll instead use an intent that is initialized using the client.

Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);

Starting the intent will give you the account picker, and the scopes permission dialog if your GoogleSignInOptions requested anything other than basic scope. Once the user has finished interacting with the dialogs, an OnActivityResult callback will fire, and it will contain the requisite sign-in information.

@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_SIGN_IN) {
        GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
        handleSignInResult(result);
    }
}

You can learn more about this code in the Integrating Google Sign-In quickstart, or by looking at the sample code.

Silent Sign-In

To further reduce friction for users in a multi-device world, the API supports silent sign in. In this case, if your user has given authorization to the app on a different device, the details will follow their account, and they don’t need to re-give them on future devices that they sign into, unless they deauthorize. An existing sign-in is also cached and available synchronously on the current device is available.

Using it is as simple as calling the silentSignIn method on the API.

OptionalPendingResult opr = 
Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);

Then, you can check the isDone() method on the pending result -- and if it returns true, the user is signed in, and you can get their status from the PendingResult. If it isn’t then you have to wait for a callback with the SignInResult

if (pendingResult.isDone()) {
     doStuffWith(pendingResult.get());
 } else {
     // There's no immediate result ready, displays some progress indicator and waits for the
     // async callback.
     showProgressIndicator();
     pendingResult.setResultCallback(new ResultCallback() {
         @Override
         public void onResult(@NonNull GoogleSignInResult result) {
             updateButtonsAndStatusFromSignInResult(result);
             hideProgressIndicator();
         }
     });
 }

Customizing the Sign-In Button

When building apps that Sign-In with Google, we provide a SignInButton object that has the Google branding, and which looks like this:


You can customize this button with a number of properties and constants that are documented in the API here.

The branding guidelines are available here, and they include versions of the buttons in PNG, SVG, EPS and other formats in many resolutions, including all the different states of the button. These files may be used for localization of the button, and if you need to match the style of the button to your app, guidelines are provided.

This only deals with the Android side of your app. You’ll likely have a server back end, and you may want to use the credentials on that securely.

In the next blog post, we’ll discuss how to use Sign-In with Google in server-side scenarios, including how to securely pass your credentials to your own server, and how to use Google back-end services, such as Google Drive, with the permission and credentials from users.

New Client API Model in Google Play Services

gps

By Magnus Hyttsten, Google Developer Relations

Google Play services 4.2 has now been rolled out to the world, and it’s packed with much-anticipated features such as the brand new Cast API and the updated Drive API.

In addition to these blockbuster announcements, we are also launching a slightly less visible but equally important new API — a new way to connect client APIs and manage API requests. As with the initial Drive API, these changes were available as a developer preview in earlier releases of Google Play services. We're now happy to graduate those APIs to fully supported and official.

In this post we'll take a look at the new Google Play services client APIs and what they mean for your apps — for details be sure to read Accessing Google Play services and the API reference documentation.

Connecting Client APIs

The client connection model has now been unified for all the APIs. As you may recall, you were previously required to use separate client classes for each API you wanted to use, for example: PlusClient, GamesClient, etc. Instead, you should now use GoogleApiClient, which allows you to connect to multiple APIs using a single call. This has great advantages such as:

  • Simplicity—The onConnected() method will be called once, and only when connectivity to all the client APIs you are using have been established. This means you do not have to intercept multiple callbacks, one for each API connected, which simplifies the code and state management.
  • Improved user experience—With this design, Google Play services knows about everything your app needs up front. All APIs, all scopes, the works. This means that we can take care of the user consents at once, creating a single consolidated user experience for all the APIs. No more sign-in mid-process terminations, partial state management, etc.

Below is an example of establishing a connection the Google+ and Drive APIs. To see the reference information for this new client connection model, you should check out the com.google.android.gms.common.api package.

@Override
protected void onCreate(Bundle b) {
    super.onCreate(b);

    // Builds single client object that connects to Drive and Google+
    mClient = new GoogleApiClient.Builder(this)
            .addApi(Drive.API)
            .addScope(Drive.SCOPE_FILE)
            .addApi(Plus.API, plusOptions)
            .addScope(Plus.SCOPE_PLUS_LOGIN)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();      
}

@Override
protected void onStart() {
    super.onStart();

    // Connect to Drive and Google+
    mClient.connect();
}

@Override
protected void onConnected(Bundle connectionHint) {
    // All clients are connected
    startRockAndRoll();
}

@Override
protected void onConnectionFailed(ConnectionResult result) {
    // At least one of the API client connect attempts failed
    // No client is connected
    ...
}

Enqueuing API Calls

Another new feature is enqueuing of API calls, which allows you to call read methods before the API clients are connected. This means you can issue these calls up front, for example in onStart/onResume, rather than having to wait and issue them in different callback methods. This is something which will greatly simplify code if your app requires data to be read when it is started. Here is an example of where a call like this can be placed:

@Override
protected void onStart() {
    super.onStart();
    mClient.connect();
}

@Override
protected void onResume() {
    super.onResume();

    // Enqueue operation.
    // This operation will be enqueued and issued once the API clients are connected.
    // Only API retrieval operations are allowed.
    // Asynchronous callback required to not lock the UI thread.
    Plus.PeopleApi.load(mClient, “me”, “you”, “that”).setResultCallback(this);
}

Supporting both Asynchronous and Synchronous Execution

With this release of Google Play services, you now have the option to specify if an API call should execute asynchronously (you will receive a callback once it is finished), or synchronously (the thread will block until the operation has completed). This is achieved by using the classes PendingResult, Result, and Status in the com.google.android.gms.common.api package.

In practice, this means that API operations will return an instance of PendingResult, and you can choose if you want the method to execute asynchronously using setResultCallback or synchronously using await. The following example demonstrates how to synchronously retrieve the metadata for a file and then clear any starred flag setting:

// Must be run in a background task and not on UI thread
new AsyncTask <DriveFile, Void, Void> {
    protected void doInBackground(DriveFile driveFile) {

        // Get the metadata synchronously
        MetaDataResult mdGetResult = driveFile.getMetadata(mClient).await();
        if (!mdGetResult.isSuccess()) {
            // Handle error
        }

        MetaData md = mdGetResult.getMetadata()
        // Perform operations based on metadata

        // Update the meta data, unconditionally clear the starred flag        
        MetaDataChangeSet mdCS = new MetadataChangeSet.Builder()
            .setStarred(false)
            .build();

        MetaDataResult mdUpdateResult =driveFile.updateMetaData(mClient,mdCS).await();
        if (!mdUpdateResult.isSuccess()) {
            // Handle error
        }

        … // continue doing other things synchronously
}).execute(fileName);

It should be stressed though that the old best practice rule — do not block the UI thread — is still in effect. This means that the execution of this sequence of API calls described above must be performed from a background thread, potentially by using AsyncTask as in the example above.

Moving your apps to the new client API

We believe these changes will make it easier for you to build with Google Play services in your apps. For those of you using the older clients, we recommend refactoring your code as soon as possible to take advantage of these features. Apps deployed using the old client APIs will continue to work since these changes do not break binary compatibility, but the old APIs are now deprecated and we'll be removing them over time.

That’s it for this time. Google Play services allows Google to provide you with new APIs and features faster than ever, and with the capabilities described in this post, you now have a generic way of using multiple client APIs and executing API calls. Make sure to check out the video below for a closer look at the new client APIs.

To learn more about Google Play services and the APIs available to you through it, visit the Google Services area of the Android Developers site. Details on the APIs are available in the API reference.

For information about getting started with Google Play services APIs, see Set Up Google Play Services SDK