Getting started with Nearby Messages API on Android

Get started

This document explains how to start developing with the Nearby Messages API on Android. The Nearby Messages API is part of Google Play services.

Step 1: Get Google Play services

The Nearby Messages API is available on Android devices with Google Play services 7.8.0 or height. Ensure that you have the lastest client library for Google Play services  on your development host:

Step 2: Get a Google account

To use the Nearby Messages APIs, you need a Google account. If you already have an account, then you’re all set.

Step 3: Get an API key

Take these steps to activete the Google Nearby Messages API for Android for your project on the Google Develpers Console:

  • Visit Google Develpers Console the to create a new project, or select an existing project.
  • Activete the Nearby Messages API
  • Register the public certificate from app’s signed APK
  • Create an Android API key

This step is quite straightforward, I think you can do it. If you have never been do same task, you can get tutorials on Google search 😀

Step 4: Configure your project

You need add Google Play services to your project. Open build.gradle file and add the Google Play services client library as a dependency:

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

Then, configure your manifest with the API Key generated in the previous step:

<manifest  
  xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.google.sample.app">
  <application ...>
    <meta-data
      android:name="com.google.android.nearby.messages.API_KEY"
      android:value="API_KEY" />
    <activity>
      ...
    </activity>
  </application>
</manifest>  
Step 5: Connect to the Nearby Messages service

In your app, create a GoogleApiClient and add the Nearby Messages Api. The following snippet shows how to add the Nearby Messages API:

mGoogleApiClient = new GoogleApiClient.Builder(this) .addApi(Nearby.MESSAGES_API).addConnectionCallbacks(this).addOnConnectionFailedListener(this).build();  

Publish and Subscribe

Publish a message

To publish a message, call

Nearby.Messages.publish()  

passing your message byte array, as shown in the following snippet:

// Publish bytes to send message = new Message(yourByteArray);
Nearby.Messages.publish(mGoogleApiClient, message).setResultCallback(new ErrorCheckingCallback("publish()"));  

When calling Nearby.Messages.publish, you must implement a ResultCallback, and call setResultCallback() to handle any status codes resulting from the operation.

Subscribe to messages

To subscribe to and retrieve messages, create an instance of MessageListener, then call Nearby.Messages.subscribe(), as shown in the following snippet:

// Create an instance of MessageListener
messageListener = new MessageListener() {  
 @Override public void onFound(final Message message) {
  // Do something with message.getContent() 
 }
};
// Subscribe to receive messages 
Nearby.Messages.subscribe(mGoogleApiClient, messageListener).setResultCallback(new ErrorCheckingCallback("subscribe()"));  

When calling Nearby.Messages.subscribe, you must implement a ResultCallback, and call setResultCallback() to handle any status codes resulting from the operation.

Pub/Sub example

The following example app code demonstrates the entire publish-subscribe flow.

@Override protected void onStart() {
 super.onStart();
 if (!mGoogleApiClient.isConnected()) {
  mGoogleApiClient.connect();
 }
}
@Override protected void onStop() {
  if (mGoogleApiClient.isConnected()) {
   // Clean up when the user leaves the activity.
   Nearby.Messages.unpublish(mGoogleApiClient, mMessage).setResultCallback(new ErrorCheckingCallback("unpublish()"));
   Nearby.Messages.unsubscribe(mGoogleApiClient, mMessageListener).setResultCallback(new ErrorCheckingCallback("unsubscribe()"));
  }
  mGoogleApiClient.disconnect();
  super.onStop();
 }
 // GoogleApiClient connection callback.
@Override public void onConnected(Bundle connectionHint) {
  Nearby.Messages.getPermissionStatus(mGoogleApiClient).setResultCallback(new ErrorCheckingCallback("getPermissionStatus", new Runnable() {
   @Override public void run() {
    publishAndSubscribe();
   }
  }));
 }
 // This is called in response to a button tap in the Nearby permission dialog.
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
 super.onActivityResult(requestCode, resultCode, data);
 if (requestCode == REQUEST_RESOLVE_ERROR) {
  mResolvingError = false;
  if (resultCode == RESULT_OK) {
   // Permission granted or error resolved successfully then we proceed 
   // with publish and subscribe.. 
   publishAndSubscribe();
  } else {
   // This may mean that user had rejected to grant nearby permission. 
   showToast("Failed to resolve error with code " + resultCode);
  }
 }
}
private void publishAndSubscribe() {  
 // We automatically subscribe to messages from nearby devices once 
 // GoogleApiClient is connected. If we arrive here more than once during 
 // an activity's lifetime, we may end up with multiple calls to 
 // subscribe(). Repeated subscriptions using the same MessageListener 
 // are ignored. 
 Nearby.Messages.publish(mGoogleApiClient, mMessage).setResultCallback(new ErrorCheckingCallback("publish()"));
 Nearby.Messages.subscribe(mGoogleApiClient, mMessageListener).setResultCallback(new ErrorCheckingCallback("subscribe()"));
} /** * A simple ResultCallback that displays a toast when errors occur. * It also displays the Nearby opt-in dialog when necessary. */
private class ErrorCheckingCallback implements ResultCallback < Status > {  
 private final String method;private final Runnable runOnSuccess;private ErrorCheckingCallback(String method) {
  this(method, null);
 }
 private ErrorCheckingCallback(String method, @Nullable Runnable runOnSuccess) {
  this.method = method;
  this.runOnSuccess = runOnSuccess;
 }
 @Override public void onResult(@NonNull Status status) {
  if (status.isSuccess()) {
   Log.i(TAG, method + " succeeded.");
   if (runOnSuccess != null) {
    runOnSuccess.run();
   }
  } else {
   // Currently, the only resolvable error is that the device is not opted 
   // in to Nearby. Starting the resolution displays an opt-in dialog. 
   if (status.hasResolution()) {
    if (!mResolvingError) {
     try {
      status.startResolutionForResult(MainActivity.this, REQUEST_RESOLVE_ERROR);
      mResolvingError = true;
     } catch (IntentSender.SendIntentException e) {
      showToastAndLog(Log.ERROR, method + " failed with exception: " + e);
     }
    } else {
     // This will be encountered on initial startup because we do 
     // both publish and subscribe together. So having a toast while 
     // resolving dialog is in progress is confusing, so just log it. 
     Log.i(TAG, method + " failed with status: " + status + " while resolving error.");
    }
   } else {
    showToastAndLog(Log.ERROR, method + " failed with : " + status + " resolving error: " + mResolvingError);
   }
  }
 }
}

Get Beacon Message

Your app can subscribe to Bluetooth Low Energy (BLE) beacons. When subscribing, your app will automatically receive any messages that you’ve attached to BLE beacons, in addition to any messages published by your app on other devices.

The following code snippet demonstrates subscribing to messages attached to BLE beacons.

MessageListener messageListener = new MessageListener() {  
 // Called each time a new message is discovered nearby.
 @Override public void onFound(Message message) {
   Log.i(TAG, "Found message: " + message);
  }
  // Called when a message is no longer nearby. 
 @Override public void onLost(Message message) {
  Log.i(TAG, "Lost message: " + message);
 }
};
// Subscribe to receive nearby messages created by this Developer Console project. 
// Use Strategy.BLE_ONLY because we are only interested in messages that we 
// attached to BLE beacons.
Nearby.Messages.subscribe(client, messageListener, Strategy.BLE_ONLY).setResultCallback(new ErrorCheckingCallback("subscribe()"));  

When calling Nearby.Messages.subscribe, you must implement a ResultCallback, and call setResultCallback() to handle any status codes resulting from the operation.

Notes:

  • To conserve batteru life, call Nearby.Messages.unsubscribe() in your Activity’s onStop() function.
  • To reduce latency, use the Strategy.BLE_ONLY option. This option is used when calling Nearby.Messages.subscribe(). When this option is set, Nearby Messages API won’t trigger WiFi scans or classic Bluetooth scans. This improves the latency for beacon detection since the system doesn’t cycle through all of the possition scan types.
  • To attach a message payload to a beacon, use the Proximity Beacon API.
Parsing beacon messages

Beacon attachments are blobs of arbitrary date that you can add to beacons. Each attachment consists of the following parts:

  • Namespace: A namespace identitier
  • Type: The date type
  • Data: The data value for the attachment

The following code snippet demonstrates getting the namespace, data and data type from a beacon message:

public void onFound(Message message) {  
 String nearbyMessageNamespace = message.getNamespace();
 String nearbyMessageType = message.getType();
 String nearbyMessageString = new String(message.getContent());
 Log.i(TAG, "Message string: " + nearbyMessageString);
 Log.i(TAG, "Message namespaced type: " + nearbyMessageNamespace + "/" + nearbyMessageType);
}