SDK

Remote Notifications

In this page you'll learn how notifications are handled in your app and what all the options at your disposal to create a great messaging experience for your users.

If you are using the default re.notifica.push.gcm.DefaultIntentReceiver you will not have any control in how messages are handled. If you've followed our recommendation and have implemented your own Intent Receiver, you will have a way of intercepting and customize the way messages are displayed in your app.

Notificare library accepts several types of interactive and actionable notifications that will be handled for you without any extra development. If you are going to prevent this default behaviour, please note that you will have to either handle all the functionality yourself (metrics logging, presenting UI or collect replies) or if you don't, you understand that some features will not work as advertised.

Receiving Notifications

Starting in Android 8 (a.k.a Oreo), in order for your app to display notifications, you need to create channels. Without a channel, notifications will never appear in the notification manager. Simply add the following line in your Application class:

public class MyBaseApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        ..more code

        //Launch Notificare system
        Notificare.shared().launch(this);

        //After launch you can create a channel
        //For Android Oreo add this line
        Notificare.shared().createDefaultChannel();

        ...more code
    }

    ...more code

}

That is enough to make notifications work in Android 8. Every notification will appear in the default channel "Push Notifications". You can change the name and the description of the default channel by adding these values in your /app/res/strings.xml file:

<string name="notificare_default_channel_name">Push Notifications</string>
<string name="notificare_default_channel_description">This channel shows push notifications</string>

You can also create channels yourself in the app. If you want a channel that your app created to be the default channel, invoke the following method:

Notificare.shared().setDefaultChannel(myChannel.getId());

If you are using our Loyalty add-on and you want all the relevance and update notifications to be in a separated channel, you can set as follows:

Notificare.shared().setPassbookChannel(myPassbookChannel.getId());

Once you're receiving notifications in your app, we can dive deeper and fully understand how they are handled. In most cases, developers will not need to take any action in order to display notifications. In your own Intent Receiver you will most likely implement a method like this one:

@Override
public void onNotificationReceived(String alert, String notificationId, String inboxItemId,
    Bundle extras) {

    //Handle UI updates in your own app, like presenting a badge
    Log.d(TAG, " received with extra Notification" + extras.getString("mykey"));
    super.onNotificationReceived(alert, notificationId, inboxItemId, extras);
}

But there might be situations where you will want to intercept an incoming notification in the method above and handle some UI updates in your app like showing a badge or similar functionality, without interfering with the fact that our library will display the message in the notification drawer, log the events for open notifications or any other default behaviour.

There will be also cases, where apps offer users the possibility to silence notifications completely, like a switch in a settings view that enables and disables notifications. You could achieve this by registering or unregistering devices but another way of achieving it would be to intercept an incoming notification and according to the user preferences, show it or not. Here's an example of how you could achieve something like that:

public class MyIntentReceiver extends DefaultIntentReceiver {

    ...more code

    @Override
    protected void generateNotification(String intentAction, int icon, @Nullable NotificareNotification notification, @Nullable String inboxItemId, Bundle extras, Bitmap picture, Bitmap largeIcon) {

        boolean canShowNotification = false;

        if (MyUserPrefsClass.getNotificationsEnabled()) {
            canShowNotification = true;
        }

        if (canShowNotification) {
            super.generateNotification(intentAction, icon, notification, inboxItemId, extras, picture, largeIcon);
        }

    }

    ...more code
}

This would allow you to keep a device active but in certain circumstances show or not the notification.

Another example of cases where you will need to intercept interactions in a notification is when users engage with actionable notifications. Extending the content of a notification with actionable buttons that can quickly collect the input a user are one of the things marketers love about Notificare, because of that you might need at some point to acknowledge when those actions are clicked. When you implement your own Intent Receiver these actions can be easily be intercepted by simply overriding the following method:

public class MyIntentReceiver extends DefaultIntentReceiver {

    ...more code

    @Override
    public void onActionReceived(Uri target) {
        Log.d(TAG, "Custom action was received: " + target.toString());
        super.onActionReceived(target);
    }

    ...more code

}

In modern apps, this is a great way of creating interactions between notifications and your own app content, allowing you to send messages that can eventually drive the user to open content hidden deeper in your app.

To prepare your app to handle deep links is not complicated and will allow you to handle not only Deep Link notification types, but also any link made from an web page. In order to indicate your app that you will handle a custom URL scheme you simply have to declare the following in the AndroidManifest.xml:

<activity android:name=".DeeplinkActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="com.mydomain" />
    </intent-filter>
</activity>

By simply providing a data entry in your activity Intent Filter element, any click in a link from a web page using com.mydomain://mydomain.com/product?id=1 as the href value, would simply trigger your app to open. But of course you will want to show something to the user based on that URL. That is also easily done by implementing the following in the activity you've declared to use a URL scheme:

public class DeeplinkActivity extends ActionBarBaseActivity{

    ...more code

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_deeplink);

        ...more code

        Uri data = getIntent().getData();
        if (data != null) {
            String path = data.getPath();
            //Open a view based on the path
        }

    }

    ...more code

}

Another common example where you will make use of deep links, would be to take proper action whenever users click in hypertext links in a Notificare's HTML or Web Page notification type. This is done by first declaring all the URL schemes that you want to handle in your AndroidManifest.xml:

<meta-data
    android:name="re.notifica.metadata.UrlSchemes"
    android:resource="@array/url_schemes" />

This entry will require you to create a /app/res/values/url_schemes.xml file with the following content:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="url_schemes">
        <item>com.mydomain</item>
        <item>com.mydomain2</item>
        <item>com.mydomain3</item>
    </string-array>
</resources>

Any click in a HTML or Web Page notification type, would be intercepted by our library and trigger the following method in your Intent Receiver:

public class MyIntentReceiver extends DefaultIntentReceiver {

    ...more code

    @Override
    public void onUrlClicked(Uri urlClicked, Bundle extras) {
        Log.i(TAG, "URL was clicked: " + urlClicked);
        NotificareNotification notification = extras.getParcelable(Notificare.INTENT_EXTRA_NOTIFICATION);
        if (notification != null) {
            Log.i(TAG, "URL was clicked for \"" + notification.getMessage() + "\"");
        }
    }

    ... more code
}

Inbox

With our library it's extremely easy to implement an in-app inbox. Implementing an inbox increases considerably the engagement rate of your notifications simply because messages will always be available inside your app. To activate the inbox functionality, please follow the instructions described here.

After activating this functionality you can start implementing your inbox in any activity or fragment of your app. The inbox is available via the Inbox Manager. To get all the items in the inbox you would basically invoke the following:

if (Notificare.shared().getInboxManager() != null) {
    for (NotificareInboxItem item : Notificare.shared().getInboxManager().getItems()) {
        inboxListAdapter.add(item);
    }
}

In the example above we assume that you will create a list adapter that will be populated by the Inbox Manager.

To retrieve the number of unread messages you can simply call the following method:

int unread = Notificare.shared().getInboxManager().getUnreadCount();

Assuming that your list adapter is assigned to a list view, to open an inbox item you would have to simply do something like this:

listView.setOnItemClickListener(new OnItemClickListener() {

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        NotificareInboxItem item = inboxListAdapter.getItem(position);
        Notificare.shared().getInboxManager().markItem(item);
        Notificare.shared().openNotification(InboxActivity.this, item.getNotification());
    }
});

To remove items from the inbox you would invoke the following method:

...more code

NotificareInboxItem msg = inboxListAdapter.getItem(position);

//Removes local item
Notificare.shared().getInboxManager().removeItem(msg);

//Removes remote item
Notificare.shared().deleteInboxItem(msg.getItemId(), new NotificareCallback<Boolean>() {
    @Override
    public void onSuccess(Boolean aBoolean) {
        //Inbox item removed
    }

    @Override
    public void onError(NotificareError notificareError) {
        //Failed to remove inbox item
    }
});

//Removes item from list adapter
inboxListAdapter.remove(msg);

...more code

To remove all items in the inbox you would do the following:

...more code

inboxListAdapter.clear();
if (Notificare.shared().getInboxManager() != null) {
    //Clears local inbox
    Notificare.shared().getInboxManager().clearInbox();
}

//Clears remote inbox
Notificare.shared().clearInbox(new NotificareCallback<Boolean>() {
    @Override
    public void onSuccess(Boolean aBoolean) {
        //Inbox is cleared
    }

    @Override
    public void onError(NotificareError notificareError) {
        //Failed to clear inbox
    }
});