Developer Console

Registration and Message Handling

1. Explore - Know your options 2. Choose - Find a solution 3. Fit - Update your code 4. Verify - Test your app 5. Push - Submit your app

On this page, learn how to register your app with Amazon Device Messaging (ADM) and handle incoming messages.

Get registration ID

Before receiving messages, your app must obtain a registration ID. The registration ID in ADM is similar to the device registration token in Firebase - it uniquely identifies the installation of your app on a particular device. In Firebase, you can call FirebaseMessaging.getInstance().getToken() to retrieve the device registration token. ADM has a similar method, getRegistrationId().

The following code shows how to use the methods in the com.amazon.device.messaging.ADM class to:

  • Create an instance of an ADM context
  • Initiate registration with ADM for this instance of your app
final ADM adm = new ADM(this);
if (adm.getRegistrationId() == null)
{
   // startRegister() is asynchronous; your app is notified via the
   // onRegistered() callback when the registration ID is available.
   adm.startRegister();
}

You should run this code each time your app starts, for example, by placing it within your onCreate() method. If your app is already registered, getRegistrationId() returns the registration ID for this instance of the app, and startRegister() isn't called. If this is the first startup of the app on a given device or if a previous registration failed, this code begins the registration process.

Implement registration and message handling

ADM has three classes that you must extend. Refer to the following table to understand the function of each. You can also review the ADM API reference.

Class Description
com.amazon.device.messaging.ADMMessageHandlerJobBase For handling messages on the latest Fire devices
com.amazon.device.messaging.ADMMessageHandlerBase For handling messages on older Fire devices
com.amazon.device.messaging.ADMMessageReceiver For forwarding messages to the appropriate message handling class

The broadcast receiver declared in your manifest both listens for intents and invokes your app when intents arrive. Your app communicates with the broadcast receiver via the following callback methods defined in the com.amazon.device.messaging.ADMMessageHandlerJobBase and com.amazon.device.messaging.ADMMessageHandlerBase classes:

Callback Method Description
onRegistered Called when the registration ID for the app instance is ready. Your app must transmit this registration ID to your server. Doing so enables your server to send messages to the app instance.
onUnregistered Called if your app instance becomes unregistered from ADM.
onRegistrationError Called if your app's ADM registration request fails for any reason, such as no Amazon user being signed in to the device.
onMessage Called when the ADM client delivers a message to your app instance. This is similar to the onMessageReceived callback in FCM, but rather than passing a RemoteMessage object, you pass an Intent object from which you extract the message content.

Your app must override these callbacks when you implement subclasses of com.amazon.device.messaging.ADMMessageHandlerJobBase, com.amazon.device.messaging.ADMMessageHandlerBase and com.amazon.device.messaging.ADMMessageReceiver, as shown in the following code examples:

  1. Check if the current device has been updated to support new ADM service.

     ADMLatestAvailable = false ;
     try{
         Class.forName( "com.amazon.device.messaging.ADMMessageHandlerJobBase" );
         ADMLatestAvailable = true ;
     }
     catch (ClassNotFoundException e)
     {
         // Handle the exception.
     }
    
  2. Create your receiver and service implementations.

     public class Receiver extends ADMMessageReceiver
     {   
         public Receiver()
         {   // This is needed for backward compatibility
            super(MyADMLegacyMessageHandler.class);
            // Where available, prefer using the new job based
            if (ADMLatestAvailable) {
                registerJobServiceClass(MyADMMessageHandler.class, <JOB_ID>)
            }
         }
         // Nothing else is required here; your broadcast receiver automatically
         // forwards intents to your service for processing.
     }
    
     public class MyADMMessageHandler extends ADMMessageHandlerJobBase
     {
    
         @Override
         protected void onRegistered(final Context context, final String newRegistrationId)
         {
             // You start the registration process by calling startRegister() in your Main
             // Activity. When the registration ID is ready, ADM calls onRegistered() on
             // your app. Transmit the passed-in registration ID to your server, so your
             // server can send messages to this app instance. onRegistered() is also
             // called if your registration ID is rotated or changed for any reason; your
             // app should pass the new registration ID to your server if this occurs.
             // Your server needs to be able to handle a registration ID up to 1536 characters
             // in length.
    
             // The following is an example of sending the registration ID to your
             // server via a header key/value pair over HTTP.
             URL url = new URL(YOUR_WEBSERVER_URL);
             HttpURLConnection con = (HttpURLConnection) url.openConnection();
             con.setDoInput(true);
             con.setUseCaches(false);
             con.setRequestMethod("POST");
             con.setRequestProperty("RegistrationId", newRegistrationId);
             con.getResponse();
         }
    
         @Override
         protected void onUnregistered(final Context context, final String registrationId)
         {
             // If your app is unregistered on this device, inform your server that
             // this app instance is no longer a valid target for messages.
         }
    
         @Override
         protected void onRegistrationError(final Context context, final String errorId)
         {
             // You should consider a registration error fatal. In response, your app may
             // degrade gracefully, or you may wish to notify the user that this part of
             // your app's functionality is not available.
         }
    
         @Override
         protected void onMessage(final Context context, final Intent intent)
         {
             // Extract the message content from the set of extras attached to
             // the com.amazon.device.messaging.intent.RECEIVE intent.
    
             // Create strings to access the message and timeStamp fields from the JSON data.
             final String msgKey = getString(R.string.json_data_msg_key);
             final String timeKey = getString(R.string.json_data_time_key);
    
             // Obtain the intent action that will be triggered in onMessage() callback.
             final String intentAction = getString(R.string.intent_msg_action);
    
             // Obtain the extras that were included in the intent.
             final Bundle extras = intent.getExtras();
    
             // Extract the message and time from the extras in the intent.
             // ADM makes no guarantees about delivery or the order of messages.
             // Due to varying network conditions, messages may be delivered more than once.
             // Your app must be able to handle instances of duplicate messages.
             final String msg = extras.getString(msgKey);
             final String time = extras.getString(timeKey);
         }
     }
    

public class MyADMLegacyMessageHandler extends ADMMessageHandlerBase
{

    @Override
    protected void onRegistered(final String newRegistrationId)
    {
        // You start the registration process by calling startRegister() in your Main
        // Activity. When the registration ID is ready, ADM calls onRegistered() on
        // your app. Transmit the passed-in registration ID to your server, so your
        // server can send messages to this app instance. onRegistered() is also
        // called if your registration ID is rotated or changed for any reason; your
        // app should pass the new registration ID to your server if this occurs.
        // Your server needs to be able to handle a registration ID up to 1536 characters
        // in length.

        // The following is an example of sending the registration ID to your
        // server via a header key/value pair over HTTP.
        URL url = new URL(YOUR_WEBSERVER_URL);
        HttpURLConnection con = (HttpURLConnection) url.openConnection();
        con.setDoInput(true);
        con.setUseCaches(false);
        con.setRequestMethod("POST");
        con.setRequestProperty("RegistrationId", newRegistrationId);
        con.getResponse();
    }

    @Override
    protected void onUnregistered(final String registrationId)
    {
        // If your app is unregistered on this device, inform your server that
        // this app instance is no longer a valid target for messages.
    }

    @Override
    protected void onRegistrationError(final String errorId)
    {
        // You should consider a registration error fatal. In response, your app may
        // degrade gracefully, or you may wish to notify the user that this part of
        // your app's functionality is not available.
    }

    @Override
    protected void onMessage(final Intent intent)
    {
        // Extract the message content from the set of extras attached to
        // the com.amazon.device.messaging.intent.RECEIVE intent.

        // Create strings to access the message and timeStamp fields from the JSON data.
        final String msgKey = getString(R.string.json_data_msg_key);
        final String timeKey = getString(R.string.json_data_time_key);

        // Obtain the intent action that will be triggered in onMessage() callback.
        final String intentAction = getString(R.string.intent_msg_action);

        // Obtain the extras that were included in the intent.
        final Bundle extras = intent.getExtras();

        // Extract the message and time from the extras in the intent.
        // ADM makes no guarantees about delivery or the order of messages.
        // Due to varying network conditions, messages may be delivered more than once.
        // Your app must be able to handle instances of duplicate messages.
        final String msg = extras.getString(msgKey);
        final String time = extras.getString(timeKey);
    }
}

Gracefully degrade if ADM is unavailable

In your manifest file, you declare whether your app can (android:required="false") or cannot (android:required="true") work without ADM. If you specify android:required="false", your app must degrade gracefully if ADM is unavailable.

Designing your app to accommodate the absence of ADM allows you to build a single APK that can be installed and run on devices that may or may not include ADM.

To modify your app to gracefully degrade:

  1. Use code similar to the following to check for ADM.

    ADMAvailable = false ;
    try
    {
        Class.forName( "com.amazon.device.messaging.ADM" );
        ADMAvailable = true ;
    }
    catch (ClassNotFoundException e)
    {
        // Handle the exception.
    }
    
  2. Add the following code to any of your code that requires the ADM library runtime.

    if (ADMAvailable)
    {
        // Your code that requires ADM goes here.
    }
    
  3. In your AndroidManifest.xml file, verify that the application element specifies:

    amazon:enable-feature android:name="com.amazon.device.messaging" android:required="false"
    

Server-side integration

Use the following guides to make sure your server is set up to work with ADM.

To send a message to a single device, you can use the Developer Console. For more details, see Verify.

Next steps

Go to the next step: Step 4: Verify - Test Your App.


Last updated: Mar 24, 2022