Android Message Center

This tutorial will cover how to build a custom Message Center. Before continuing, read Android: Message Center to see if the provided Message Center is suitable for your application.

Message Center is provided out-of-the-box as of the release of SDK 7.0, and supports some basic theming options. This tutorial is for more advanced implementations. If you are looking for an out-of-the-box solution, see Out-of-the-Box Message Center.

Message Listing

The easiest way to display the Message Center message listing is to use MessageListFragment :

MessageListFragment messageListFragmnet = new MessageListFragment();
getSupportFragmentManager()
        .beginTransaction()
        .add(R.id.message_list_container, messageFragment)
        .commit();

To customize the item layout, create a new fragment that extends the MessageListFragment and override MessageListFragment.createMessageViewAdapter :

public class CustomMessageListFragment extends MessageListFragment {

    @NonNull
    @Override
    protected MessageViewAdapter createMessageViewAdapter() {

        return new MessageViewAdapter(getContext(), R.layout.custom_item_view) {
            @Override
            protected void bindView(View view, RichPushMessage message, int position) {
                // bind the message to the custom view inflated from R.layout.custom_item_view
            }
        };

    }
}

By default, whenever a message item is clicked it will attempt to display an activity that can display the message. To override the behavior, add a AdapterView.OnItemClickListener to the list view:

public class CustomMessageListFragment extends MessageListFragment {

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        getAbsListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                // Handle item clicks
                UAirship.shared().getInbox().startMessageActivity(getMessage(position).getMessageId());
            }
        });
    }
}

The fragments layout can also be customized, make sure the inflated layout contains a AbsListView with id android.R.id.list:

public class CustomMessageListFragment extends MessageListFragment {

        /**
         * Subclasses can override to replace with their own layout.  If doing so, the
         * returned view hierarchy <em>must</em> have an AbsListView (GridView or ListView) whose id
         * is {@code android.R.id.list}, and can optionally empty list TextView view with id {@code andorid.R.id.empty}.
         */
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.custom_message_list_fragment, container, false);

            // When inflating a custom view, the adapter will automatically be set on the list view.

            return view;
        }
}

Once the message listing has been customized, show the fragment in an activity by either defining the fragment in a layout or performing a fragment transaction. Make sure to add the com.urbanairship.VIEW_RICH_PUSH_INBOX intent action as an intent filter to the activity so it will be displayed instead of the default Message Center:

<activity android:name=".CustomMessageCenter">
    <intent-filter>
        <action android:name="com.urbanairship.VIEW_RICH_PUSH_INBOX" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

Displaying a Message

The SDK provides MessageFragment that can be used to display a RichPushMessage in any activity:

MessageFragment messageFragment = MessageFragment.newInstance(messageId);
getSupportFragmentManager()
        .beginTransaction()
        .add(android.R.id.content, messageFragment)
        .commit();

To override the default Message Activity, create a new Activity that can handle the com.urbanairship.VIEW_RICH_PUSH_MESSAGE intent action:

public class CustomMessageActivity extends FragmentActivity {

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

        String messageId = null;

        // Handle the "com.urbanairship.VIEW_RICH_PUSH_MESSAGE" intent action with the message
        // ID encoded in the intent's data in the form of "message:<MESSAGE_ID>
        if (getIntent() != null && getIntent().getData() != null
             && RichPushInbox.VIEW_MESSAGE_INTENT_ACTION.equals(getIntent().getAction())) {
            messageId = getIntent().getData().getSchemeSpecificPart();
        }

        RichPushMessage message = UAirship.shared().getInbox().getMessage(messageId);
        if (message == null) {
            // Message is no longer available
            finish();
            return;
        }

        if (savedInstanceState == null) {
            MessageFragment messageFragment = MessageFragment.newInstance(messageId);
            getSupportFragmentManager()
                    .beginTransaction()
                    .add(android.R.id.content, messageFragment)
                    .commit();
        }

        setTitle(message.getTitle());
    }
}

In the AndroidManifest.xml:

<activity name=".CustomMessageActivity">
    <intent-filter>
        <action android:name="com.urbanairship.VIEW_RICH_PUSH_MESSAGE" />
        <data android:scheme="message"/>
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

Library Components

Below are a few basic definitions of the classes used for interacting with the Message Center. For more details, please see the Urban Airship Library Reference

RichPushInbox

The RichPushInbox is the main access point for fetching and accessing messages. The inbox provides methods to delete messages, mark messages as read and unread, and is automatically updated with Urban Airship.

The inbox can be accessed directly from UAirship :

RichPushInbox inbox = UAirship.shared().getInbox();

To start an activity that displays the Message Center call showInboxActivity:

UAirship.shared().getInbox().showInboxActivity();

To force a message list update:

UAirship.shared().getInbox().fetchMessages();

To force a message list update with a callback:

UAirship.shared().getInbox().fetchMessages(new RichPushInbox.FetchMessagesCallback() {
        @Override
        public void onFinished(boolean success) {
            // message request complete
        }
});

Listening for updates

To listen for inbox updates, add the RichPushInbox.Listener and onInboxUpdated() will be called when the inbox is updated:

private RichPushInbox.Listener inboxListener = new RichPushInbox.Listener() {
    @Override
    public void onInboxUpdated() {
        // inbox messages updated
    }
};

Then add the listener:

UAirship.shared().getInbox().addListener(inboxListener);

The listener can be removed with:

UAirship.shared().getInbox().removeListener(inboxListener);

RichPushMessage

Each RichPushMessage contains information about a user’s message such as sent date, title, read/unread status, extras and the URL of the message’s content.

To get the RichPushMessage with the corresponding message ID:

RichPushMessage message = UAirship.shared().getInbox().getMessage(messageId);

Marking the message read/unread:

// mark it read
message.markRead();

// mark it unread
message.markUnread();

Marking messages read/unread in bulk:

// mark messages read
UAirship.shared().getInbox().markMessagesRead(messageIds);

// mark messages unread
UAirship.shared().getInbox().markMessagesUnread(messageIds);

Deleting the message:

// delete it
message.delete();

Deleting messages in bulk:

// delete messages using the inbox and a set of message IDs
UAirship.shared().getInbox().deleteMessages(messageIds);

To get the message’s extras:

// get the message's extras in a bundle
message.getExtras();

// get the value associated with the given key in the message's extras bundle
message.getExtras().getString("a_specified_key");

UAWebView

The UAWebView is an extended WebView that is configured to display the content of a RichPushMessage .

To the load the web view with the message:

UAWebView webView = new UAWebView(UAirship.getApplicationContext());
webView.loadRichPushMessage(message);

The UAWebViewClient is required to allow running Urban Airship Actions through JavaScript and handling user authorization for rich messages.

To extend UAWebViewClient :

webView.setWebViewClient(new UAWebViewClient() {
        @Override
        public void onPageFinished(WebView view, String url) {
            // Make sure to call through to the super's implementation
            // or the JavaScript native bridge will not be fully loaded
            super.onPageFinished(view, url);
        }
});