Introduction to Google’s Awareness API

Awareness API Banner
Credits: Google API Docs

 A while ago, Google announced something really interesting called the Awareness API. According to Google Developers –  Android Awareness API bridges the physical world of users, and the digital world of Android to help you build more assistive and context-aware apps.

The last sentence can be a bit confusing. So here are some examples that will help you realise how powerful the Awareness API is:

Imagine you pass by a pharmacy and your phone reminds you that you have to buy medicines. Or as soon you enter your car, your phone automatically connects to the car’s Bluetooth and your navigation app opens up in driver mode.

Cool right? Awareness API makes this really easy.

Awareness API example

Credits: Google

What does the Awareness API mean for us?

The Awareness API unifies 7 location and context signals in a single API.

Context is at the heart of the Awareness API

Let’s take a quick look at the 7 context types offered by the Awareness API.

  1. TimeCurrent local time
  2. Location: Latitude and longitude
  3. PlacePlace, including place type
  4. Activity: Detected user activity (walking, running, biking)
  5. Beacons: Nearby beacons matching the specified namespace
  6. Headphones: Are headphones plugged in?
  7. Weather: Current weather conditions

 

Why use the Awareness API?

One API to Rule Them All

  • One API to rule them all
    You just need to add a single API and you are set. No headache of using tonnes of different APIs.
  • Battery and Data Friendly
    The API takes care of managing your battery life and data usage so that you can concentrate on features crucial to your app.
  • Better context data
    Raw signals are processed for improved quality. For example, advanced algorithms are used to determine the user’s activity with a high level of accuracy.

Set up

Awareness API is a part of Google Play Services and was introduced in v9.2. Let’s configure our project to use the Awareness API.

Create a project on Google Developer Console

Go to the APIs Library and search for Awareness API. Then click on it and Enable it.

Next, go to Credentials > Create Credentials > API Key > Android Key. Enter the name of your project and click create.

You will now be given an API key.  Copy it down somewhere.

Next, in your Android Studio project, add the following dependency in  app/build.gradle.

dependencies {
    ...
    compile 'com.google.android.gms:play-services-awareness:10.2.0'
}

Add the following code to the <application/> tag of your AndroidManifest.xml.

<meta-data
     android:name="com.google.android.awareness.API_KEY"
     android:value="YOUR_KEY" />
 <meta-data
     android:name="com.google.android.geo.API_KEY"
     android:value="YOUR_KEY" />
 <meta-data
     android:name="com.google.android.nearby.messages.API_KEY"
     android:value="YOUR_KEY" />

 

Remember to replace “YOUR_KEY” with the API Key you obtained.

That’s it! You are now ready to use the awesome Awareness API.


Fences and Snapshots

The Awareness API provides two distinct APIs:

  • Fences:
    Helps detect changes in user’s context, or when certain context conditions are met. For example, show a notification when the user reaches a certain location. Or even when the user starts walking or running.
  • Snapshot:
    Let’s your app request information related to the user’s current context. For example, what activity the user is currently engaged in.

In short, the Snapshot API helps you detect and identify changes in environment. Whereas the Fences API helps you react to those changes.

In this post, lets keep things simple and go through the Snapshots API alone. We’ll talk about the Fences API in the next post.

Snapshot API

Remember the 7 context types we discussed early? It’s time to dive into some code now.

1. Time

We can get the local time by using Android’s Time API. Hence there is no separate function for Time in the Awareness API. But since we are diving into code, here’s how you can get the locale time.

Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL);
Log.d(TAG, dateFormat.format(date));

2. Location

Get the user’s coordinates.

Since we are dealing with locations, we will need to make sure our app has Location permission.  Here is a quick recap on how to handle runtime permissions on Android Marshmallow and above.

Awareness.SnapshotApi
		.getLocation(googleApiClient)
       .setResultCallback(new ResultCallback<LocationResult>() {
           @Override
           public void onResult(@NonNull LocationResult locationResult) {
               if (!locationResult.getStatus().isSuccess()) {
                   Log.e(TAG, "Unable to get location");
                   return;
               }
               Location location = locationResult.getLocation();
               Log.i(TAG, "Latitude: " + location.getLatitude() );
               Log.i(TAG, "Longitude: " + location.getLongitude() );
           }
       });

The getLocation() method has a callback that returns a LocationResult object.

Then, we can use the LocationResult object to get the user’s latitude and longitude. For that, we use the methods getLatitude() and getLongitude().

3. Places

Get places around user’s location. The following example shows getting a list of possible places:

Awareness.SnapshotApi.getPlaces(mGoogleApiClient)
             .setResultCallback(new ResultCallback<PlacesResult>() {
                 @Override
                 public void onResult(@NonNull PlacesResult placesResult) {
                     if (!placesResult.getStatus().isSuccess()) {
                         Log.e(TAG, "Could not get places.");
                         return;
                     }
                     List<PlaceLikelihood> placeLikelihoodList = placesResult.getPlaceLikelihoods();
                     // Show the top 5 possible location results.
                     for (int i = 0; i < 5; i++) {
                         PlaceLikelihood p = placeLikelihoodList.get(i);
                         Log.i(TAG, p.getPlace().getName().toString() + ", likelihood: " + p.getLikelihood());
                     }
                 }
             });

To use the SnapshotAPI.getPlcaes() method, you must:

  1. Enable the Google Places API for Android in your Google Developers Console project.
  2. Add the android.permission.ACCESS_FINE_LOCATION permission to AndroidManifest.xml.

In case you are developing for Android Marshmallow and above, make sure to handle the runtime permission for location.

4. Activity

Get the activity the user is currently busy in by using the getDetectedActivity() method.

The getDetectedActivity() method requires  com.google.android.gms.permission.ACTIVITY_RECOGNITION permission.

Add this permission to  AndroidManifest.xml.

Awareness.SnapshotApi.getDetectedActivity(mGoogleApiClient)
        .setResultCallback(new ResultCallback<DetectedActivityResult>() {
            @Override
            public void onResult(@NonNull DetectedActivityResult detectedActivityResult) {
                if (!detectedActivityResult.getStatus().isSuccess()) {
                    Log.e(TAG, "Could not get the current activity.");
                    return;
                }
                ActivityRecognitionResult ar = detectedActivityResult.getActivityRecognitionResult();
                DetectedActivity probableActivity = ar.getMostProbableActivity();
                Log.i(TAG, probableActivity.toString());
            }
        });

DetectedActivityResult.getActivityRecognitionResult() returns an ActivityRecognitionResult. We can use the following functions to get various data related to the user’s activity

  • getMostProbableActivity() to get only the most probable activity
  • hasResult() to detect whether an Intent contains an ActivityRecognitionResult
  • getActivityConfidence() to return the confidence value for a given activity type.
  • getProbableActivities() to get a list of recent activities ranked by probability.

5. Weather

We can use SnapshotApi.getWeather() to get the weather conditions of the user’s current location.

The SnapshotApi.getWeather() method requires the  android.permission.ACCESS_FINE_LOCATION permission. Add this permission to AndroidManifest.xml.

Awareness.SnapshotApi.getWeather(mGoogleApiClient)
                .setResultCallback(new ResultCallback<WeatherResult>() {
                    @Override
                    public void onResult(@NonNull WeatherResult weatherResult) {
                        if (!weatherResult.getStatus().isSuccess()) {
                            Log.e(TAG, "Could not get weather.");
                            return;
                        }
                        Weather weather = weatherResult.getWeather();
                        Log.i(TAG, "Weather: " + weather);
                    }
                });

6. Headphone

We can use SnapshotApi.getHeadphoneState() to detect whether headphones are plugged into the device or not.

It returns a HeadphoneStateResult. We can then call HeadphoneStateResult.getHeadphoneState() to get the headphone status.

Awareness.SnapshotApi.getHeadphoneState(mGoogleApiClient)
                .setResultCallback(new ResultCallback<HeadphoneStateResult>() {
                    @Override
                    public void onResult(@NonNull HeadphoneStateResult headphoneStateResult) {
                        if (!headphoneStateResult.getStatus().isSuccess()) {
                            Log.e(TAG, "Could not get headphone state.");
                            return;
                        }
                        HeadphoneState headphoneState = headphoneStateResult.getHeadphoneState();
                        if (headphoneState.getState() == HeadphoneState.PLUGGED_IN) {
                            Log.i(TAG, "Headphones are plugged in.\n");
                        } else {
                            Log.i(TAG, "Headphones are NOT plugged in.\n");
                        }
                    }
                });

7. Beacons

We can use getBeaconState() to get information about nearby beacons.

To use the getBeaconState() method, we need to:

  1.  Add android.permission.ACCESS_FINE_LOCATION to AndroidManifest.xml.
  2. Activate the ‘Nearby Messages API’ for the Google Developers Console project.

We need to declare all the possible attachment’s namespaces and types in a TypeFilter.

private static final List BEACON_TYPE_FILTERS = Arrays.asList(
        BeaconState.TypeFilter.with(
                "my.beacon.namespace",
                "my-attachment-type"),
        BeaconState.TypeFilter.with(
                "my.other.namespace",
                "my-attachment-type"));

If your beacon’s attachment namespaceType is my-sample-project/mydata , my.beacon.namespace would be my-sample-project while my-attachment-type would be mydata.

Then, we can get the state of the beacon using the following code.

Awareness.SnapshotApi.getBeaconState(mGoogleApiClient, BEACON_TYPE_FILTERS)
                .setResultCallback(new ResultCallback<BeaconStateResult>() {
                    @Override
                    public void onResult(@NonNull BeaconStateResult beaconStateResult) {
                        if (!beaconStateResult.getStatus().isSuccess()) {
                            Log.e(TAG, "Could not get beacon state.");
                            return;
                        }
                        BeaconState beaconState = beaconStateResult.getBeaconState();
                        // Get info from the BeaconState.
                    }
                });

 


 Wrap up

In this post, we learnt about the Awareness API and its advantages. We also took a dive into the various context types provided by the Snapshots API. We even looked into some sample code to use each Context Type.

In the next post, we will learn about the Fences API while building a nice sample app.

So what are your thoughts on the Awareness API? Will you use it anytime soon? I would love to hear from you in the comments.

 

Header image credits: Google Awareness API

Subhrajyoti Sen

I am an Android developer and an active Mozillian. In my free time, I contribute to Open Source and watch lots of anime.

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *