In the previous entries, I have managed to display a notification and make it sticky. Now, since the app I'm developing is supposed to be visible mainly through this notification, I wanted to see if I can customise the actual content. Yes, I know there are options by default, like:
- Small and large notifications
- Add some buttons to perform actions
However, I wanted to see if I can, for example, add some icons and buttons like Sonos notification does:
It turns out that, with a bit of work and an OS Jelly Bean or better, anything is possible!
Preparation
Most for the NotificationBuilder code for custom notification is the same as the other ones:
NotificationCompat.Builder builder = new NotificationCompat.Builder(getContext())
// Set Icon
.setSmallIcon(R.drawable.ic_launcher)
// Set Ticker Message
.setTicker(getContext().getString(R.string.customnotificationticker))
// Dismiss Notification
.setAutoCancel(true)
// Set PendingIntent into Notification
.setContentIntent(pIntent);
Now, the builder is prepared to receive the custom layout. To make it compatible with devices pre-JellyBean, you need to do something like this:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
// build a complex notification, with buttons and such
//
builder = builder.setContent(getComplexNotificationView());
} else {
// Build a simpler notification, without buttons
//
builder = builder.setContentTitle(getTitle())
.setContentText(getText())
.setSmallIcon(android.R.drawable.ic_menu_gallery);
}
The custom content is set (as seen above) with builder.setContent(RemoteViews views). Now all we have to do is to build the remote view.
For the purpose of this exercise, custom layout is designed to have an image, a larger and a smaller text underneath, just like the default notification:
The RemoteViews creation code is:
private RemoteViews getComplexNotificationView() {
// Using RemoteViews to bind custom layouts into Notification
RemoteViews notificationView = new RemoteViews(
getContext().getPackageName(),
R.layout.activity_custom_notification
);
Once the view object is created, we can set the various components programmatically (e.g. content from an Intent):
// Locate and set the Image into customnotificationtext.xml ImageViews
notificationView.setImageViewResource(R.id.imagenotileft, R.drawable.ic_launcher);
// Locate and set the Text into customnotificationtext.xml TextViews
notificationView.setTextViewText(R.id.title, getTitle());
notificationView.setTextViewText(R.id.text, getText());
return notificationView;
}
Voila! the builder is now complete and we can show the notification as in the previous posts.
Code
Notification Layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
style="@android:style/TextAppearance.StatusBar.EventContent"
>
<ImageView
android:id="@+id/imagenotileft"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="8dp"
android:contentDescription="@string/app_name"
android:src="@drawable/ic_launcher" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentBottom="false"
android:layout_margin="8dp"
android:layout_toRightOf="@+id/imagenotileft"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/customnotificationtitle"
android:textStyle="bold"
/>
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/customnotificationtext"
/>
</LinearLayout>
</RelativeLayout>
buildNotification Method
For the lazy:
protected NotificationCompat.Builder buildNotification() {
// Open NotificationView.java Activity
PendingIntent pIntent = PendingIntent.getActivity(
getContext(),
NOTIFICATION_ID,
getIntent(),
PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(getContext())
// Set Icon
.setSmallIcon(R.drawable.ic_launcher)
// Set Ticker Message
.setTicker(getContext().getString(R.string.customnotificationticker))
// Dismiss Notification
.setAutoCancel(true)
// Set PendingIntent into Notification
.setContentIntent(pIntent);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
// build a complex notification, with buttons and such
//
builder = builder.setContent(getComplexNotificationView());
} else {
// Build a simpler notification, without buttons
//
builder = builder.setContentTitle(getTitle())
.setContentText(getText())
.setSmallIcon(android.R.drawable.ic_menu_gallery);
}
return builder;
}
getComplexNotificationView()
private RemoteViews getComplexNotificationView() {
// Using RemoteViews to bind custom layouts into Notification
RemoteViews notificationView = new RemoteViews(
getContext().getPackageName(),
R.layout.activity_custom_notification
);
// Locate and set the Image into customnotificationtext.xml ImageViews
notificationView.setImageViewResource(
R.id.imagenotileft,
R.drawable.ic_launcher);
// Locate and set the Text into customnotificationtext.xml TextViews
notificationView.setTextViewText(R.id.title, getTitle());
notificationView.setTextViewText(R.id.text, getText());
return notificationView;
}
HTH,
Member discussion: