SDK

Customizations

In this page we'll dive deeper into several aspects of our Android library that can be customized to match your needs.

Setting keys in code

Instead of relying on the applicationKey and applicationSecret in notificareconfig.properties, it is possible to set these in code.

1
2
Notificare.shared().setApplicationKey("APP_KEY");
Notificare.shared().setApplicationSecret("APP_SECRET");

These methods should be called before calling Notificare.shared().launch() to make sure the correct keys are used. If you set keys programmatically and have a google-services.json (mandatory) you can safely delete the notificareconfig.properties.

Notification LED Settings

You can send along the preferred color and blinking time of the notification light (only works on selected device models) per notification form the Notificare REST API or the Dashboard. However, you can also set a default color for your app. If neither are set, it defaults to white colored blinking for 500 ms on and 1500 ms off.

1
2
3
Notificare.shared().setDefaultLightsColor("red");
Notificare.shared().setDefaultLightsOn(1000);
Notificare.shared().setDefaultLightsOff(2000);

Allow JavaScript in HTML and Web Page notifications

By default the Notificare SDK does not allow JavaScript in WebViews (HTML or URL type) as a basic security measure. If you are sure you can trust the source of the URLs you push to users, you might want to enable.

1
Notificare.shared().setAllowJavaScript(true);

Notifications UI

Changing user interface in the Android is intrinsically decided by your app's styles. Basically Notificare will just use the styles you provide in your app, for the several elements used throughout our UI. We recommend these changes are done in your /res/values folders like shown below:

Android styles 684ae34016

Action Labels

Labels used for Action Buttons in both the Notification Manager as well as Notification Dialogs can be localized by adding them as strings resources, where the name is equal to the label. To protect collision of resource names, they can be prefixed with a string. The prefix must then be set by calling Notificare.shared().setLocalizedActionLabelPrefix().

Settings Activity

To be able to add tags to the Settings activity you can start by creating a new folder called xml (if you don't have one) under the folder res. Then add a xml file (eg.: preferences.xml) under xml with the following content:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
  <PreferenceCategory
	android:title="@string/pref_tags_title"
	android:key="pref_key_tags">
	<CheckBoxPreference
	  android:key="pref_key_tag_news"
	  android:summary="@string/pref_summary_tag_news"
	  android:title="@string/pref_title_tag_news"
	  android:defaultValue="false" />
	<CheckBoxPreference
	  android:key="pref_key_tag_updates"
	  android:summary="@string/pref_summary_tag_updates"
	  android:title="@string/pref_title_tag_updates"
	  android:defaultValue="true" />
  </PreferenceCategory>
</PreferenceScreen>

To keep resources organized, all the strings for the setting should reside under res/values/strings_preferences.xml. Inside that strings file add the keys used in the Settings view:

1
2
3
4
5
6
7
<resources>
	<string name="pref_tags_title">Notifications</string>
	<string name="pref_summary_tag_news">Receive the latest news</string>
	<string name="pref_title_tag_news">News</string>
	<string name="pref_summary_tag_updates">Receive information on updates</string>
	<string name="pref_title_tag_updates">Updates</string>
</resources>

By default, the activity contains a setting for location updates. The header, summary and title can be changed and localized too by adding the following strings to your resource file

1
2
3
<string name="pref_location_services_title">Location Services</string>
<string name="pref_summary_location_updates">Keep track of your location to receive only relevant information</string>
<string name="pref_title_location_updates">Location updates</string>

Customizing the IntentReceiver

If you've followed our recommendations, you've implemented your own Intent Receiver. This will offer you the possibility to customize how you handle notifications.

Handling the Extra property

There are use cases where you'll want to add extra sets of data to your notification. This is allowed via the dashboard and API and in order to handle that data you'll need to override the onNotificationReceived method:

1
2
3
4
5
6
7
8
9
public class MyIntentReceiver extends DefaultIntentReceiver {

//more code ...

@Override
public void onNotificationReceived(String alert, String notificationId, String inboxItemId, Bundle extras) {
  //Log.d(TAG, " received with extra Notification" + extras.getString("mykey"));
  super.onNotificationReceived(alert, notificationId, inboxItemId, extras);
}

This will give you the opportunity to intercept the incoming notification and retrieve the data you've included in your notification. Please note the you should call the super.onNotificationReceived method, that will make sure that Notificare library will still handle the notification for you.

If you do not call super.onNotificationReceived, which we do not recommend, then there are a few things you might want to take in consideration.

Events Logging

In order for all metrics to be collected correctly, please make sure you add the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
public void onNotificationOpened(String alert, String notificationId, Bundle extras) {

//more code ...

	Notificare.shared().getEventLogger().logOpenNotification(notificationId);
	Notificare.shared().getEventLogger().logOpenNotificationInfluenced(notificationId);
	if (inboxItemId != null) {
		Notificare.shared().getInboxManager().markItem(inboxItemId);
	}

  //more code ...
}

Handling Actions

Actions from the notification drawer come in as an intent extra. You can have them handled by the Notificare library in the background.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
NotificareAction action = extras.getParcelable(Notificare.INTENT_EXTRA_ACTION);
NotificareNotification notification = extras.getParcelable(Notificare.INTENT_EXTRA_NOTIFICATION);
if (action != null && notification != null) {
  try {
	Class<?> actionClass = Class.forName(action.getType());
	Constructor<?> ctor = actionClass.getConstructor(Activity.class, NotificareNotification.class, NotificareAction.class);
	NotificationAction actionHandler = (NotificationAction) ctor.newInstance(null, notification, action);
	actionHandler.handleAction(new NotificareCallback<NotificarePendingResult>() {
	  @Override
	  public void onSuccess(NotificarePendingResult result) {
		Log.d(TAG, "action handle successfully");
	  }

	  @Override
	  public void onError(NotificareError error) {
		Log.e(TAG, "error handling action", error);
	  }
	});
  } catch (Exception e) {
	Log.e(TAG, "error instantiating Action Handler", e);
  }
} else {

  // Display UI

}

Launching an Activity

Most likely if you are going to handle the notification yourself, you will want to launch an activity in your app. As an example, this is what the DefaultIntentReceiver does:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
if (action != null && notification != null) {
// Handle actions
} else {
	// Close the notification drawer
	Notificare.shared().getApplicationContext().sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
	Intent notificationIntent = new Intent()
	.setAction(Notificare.INTENT_ACTION_NOTIFICATION_OPENED)
	.putExtras(extras)
	.putExtra(Notificare.INTENT_EXTRA_DISPLAY_MESSAGE, Notificare.shared().getDisplayMessage())
	.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP)
	.setPackage(Notificare.shared().getApplicationContext().getPackageName());

	if (notificationIntent.resolveActivity(Notificare.shared().getApplicationContext().getPackageManager()) != null) {
	  // Notification handled by custom activity in package
	  Notificare.shared().getApplicationContext().startActivity(notificationIntent);
	} else {
	  // Start a task stack with NotificationActivity on top
	  notificationIntent.setClass(Notificare.shared().getApplicationContext(), Notificare.shared().getNotificationActivity());
	  TaskStackBuilder stackBuilder = TaskStackBuilder.create(Notificare.shared().getApplicationContext());
	  buildTaskStack(stackBuilder, notificationIntent, notification);
	  stackBuilder.startActivities();
	}
}

Cancel Notifications

One other thing you have to take in account when handling the notifications yourself is to make sure you clear notifications from the notification drawer whenever you read them. In your custom IntentReceiver, after presenting the notification, you can add the following:

1
2
3
4
5
6
7
8
9
10
11
@Override
public void onNotificationOpened(String alert, String notificationId, String inboxItemId, Bundle extras) {

//more code ...

	if (Notificare.shared().getAutoCancel()) {
		Notificare.shared().cancelNotification(notificationId);
	}

  //more code ...
}

Application Lifecycle

By default we will register both Open and Close events if your application's activities extend ActionBarBaseActivity. But in case this is not possible, you will have to handle it manually. This can be done using the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class YourActivity {

	//more code...

	@Override
	protected void onResume() {
		super.onResume();
		Notificare.shared().setForeground(true);
		Notificare.shared().getEventLogger().logStartSession();
	}

	@Override
	protected void onPause() {
		super.onPause();
		Notificare.shared().setForeground(false);
		Notificare.shared().getEventLogger().logEndSession();
	}

	//more code...
}

ProGuard

If you use ProGuard, rules for classes to keep are included with the AAR, so there is no need to manually add any rules for Notificare.

65k method limit exceeded

Notificare Android library is tested to work with MultiDex, both natively (Android 5 and above) as well as with the MultiDex support library.

Add the following to your app's build.gradle

1
2
3
4
5
6
7
defaultConfig {
	multiDexEnabled true
}

dependencies {
	compile 'com.android.support:multidex:1.0.1'
}

Then, override the attachBaseContext method in the Application class for your app.

1
2
3
4
5
@Override
protected void attachBaseContext(Context base) {
	super.attachBaseContext(base);
	MultiDex.install(this);
}

For more information on MultiDex and possible issues and workarounds, see Android Developer Documentation