📜 ⬆️ ⬇️

Android Notifications. Alerts via the Status Bar

Good afternoon, habrovchane. I have been developing for Android for a long time and I would like to tell the community about the right approach to creating notifications.

image

On Habré there is already an article on notifications in the status bar for android . It covers the basics of displaying the standard and configurable layout in the status bar.
')
Below, in addition to the previously described, we will consider adding a progress bar, event handling by clicking on notifications, various options for notification states. Consider added recently in the Compatibility library Notification.Builder. And also we will talk about recommendations on UI ( design guidlines ), which Google recommends to follow when creating notifications.


Guidlines
How to advise Android developers in the official guideline
When to show notifications:



When not to show notifications:

  1. You do not need to show notifications for non-important time-sensitive events. For example, news from social networks.
  2. No need to show what is already displayed in the application's UI.
  3. It is not necessary to display the course of low-level operations, such as referring to the database.
  4. If the application quickly corrects the error itself, then you do not need to show this error at all, let alone the notification.
  5. Do not show notifications about services that the user cannot control.
  6. A bad approach is to create a large number of notifications in order to remind the user about the application, constantly displaying its icon and name.


Good practice:

  1. By clicking on the notification, the user should open the corresponding application screen. In some cases, it is enough that a click on a notification is simply removed.
  2. Specifying the time of the event in the notification is also a good approach.
  3. It is recommended to add similar events to one notification, and not to display its own for each event.
  4. Always remove from the status bar notifications that the user has already read and performed the appropriate actions.
  5. Show a small preview of the notification when it is created in the collapsed status bar image
  6. Allow the user to turn off notifications in the application settings.
  7. Use icons that indicate the ownership of a notification to a specific application. Icons do monochrome. To do this, we recommend using a special online editor.
  8. If the event requires a direct user response, use dialogs instead of notifications.


Architecture:

As a utility that is responsible for notifications, I use singleton in my applications, which can be accessed from any application class, I just need to have a link to context .

It always stores links to all notifications created during the application that are still displayed in the status bar.

And to assign a unique id to a new notification, a simple mechanism is used to refer to a private integer field, which is incremented by one each time.
public class NotificationUtils {

private static final String TAG = NotificationUtils. class .getSimpleName();

private static NotificationUtils instance;

private static Context context;
private NotificationManager manager; // ,
private int lastId = 0; // ,
private HashMap<Integer, Notification> notifications; // -


// Singleton
private NotificationUtils(Context context){
this .context = context;
manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notifications = new HashMap<Integer, Notification>();
}

/**
*
*/

public static NotificationUtils getInstance(Context context){
if(instance== null ){
instance = new NotificationUtils(context);
} else{
instance.context = context;
}
return instance;
}

* This source code was highlighted with Source Code Highlighter .


Create a notification using NotificationCompat.Builder:
In order to use the classes included in the library of support for previous versions (Compatibility library) , you need to add a library to the project from the folder / extras/android/support/v4/android-support-v4.jar
If the project is aimed at Android 3.0 and above, then you do not need to add anything enough to refer to Notification.Builder

public int createInfoNotification( String message){
Intent notificationIntent = new Intent(context, HomeActivity. class ); // HomeActivity
NotificationCompat.Builder nb = new NotificationCompat.Builder(context)
//NotificationCompat.Builder nb = new NotificationBuilder(context) // Android > 3.0
.setSmallIcon(R.drawable.ic_action_picture) //
.setAutoCancel( true ) //
.setTicker(message) //, -
.setContentText(message) //
.setContentIntent(PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT))
.setWhen(System.currentTimeMillis()) //
.setContentTitle( "AppName" ) //
.setDefaults(Notification.DEFAULT_ALL); // ,

Notification notification = nb.getNotification(); //
manager.notify(lastId, notification); // .
notifications.put(lastId, notification); // id
return lastId++;
}


* This source code was highlighted with Source Code Highlighter .


Creating a custom display notification (Custom layout):

/**
*
* @param fileName - , .
*/
public int createDownloadNotification( String fileName){
String text = context.getString(R. string .notification_downloading).concat( " " ).concat(fileName); //
RemoteViews contentView = createProgressNotification(text, context.getString(R. string .notification_downloading)); //View
contentView.setImageViewResource(R.id.notification_download_layout_image, R.drawable.ic_stat_example); //
return lastId++; // id,
}

/**
* ProgressBar,
*
* @param text
* @param topMessage , -
* @return View .
*/
private RemoteViews createProgressNotification( String text, String topMessage) {
Notification notification = new Notification(R.drawable.ic_stat_example, topMessage, System.currentTimeMillis());
RemoteViews contentView = new RemoteViews(context.getPackageName(), R.layout.notification_download_layout);
contentView.setProgressBar(R.id.notification_download_layout_progressbar, 100, 0, false );
contentView.setTextViewText(R.id.notification_download_layout_title, text);

notification.contentView = contentView;
notification.flags = Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT | Notification.FLAG_ONLY_ALERT_ONCE;

Intent notificationIntent = new Intent(context, NotificationUtils. class );
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
notification.contentIntent = contentIntent;

manager.notify(lastId, notification);
notifications.put(lastId, notification);
return contentView;
}


notification_download_layout.xml:

<? xml version ="1.0" encoding ="utf-8" ? >
< LinearLayout xmlns:android ="http://schemas.android.com/apk/res/android"
android:layout_width ="fill_parent"
android:layout_height ="65sp"
android:padding ="10dp"
android:orientation ="vertical" >

< LinearLayout
android:layout_width ="fill_parent"
android:layout_height ="wrap_content"
android:orientation ="horizontal" >

< ImageView
android:id ="@+id/notification_download_layout_image"
android:layout_width ="wrap_content"
android:layout_height ="wrap_content"
android:src ="@drawable/ic_stat_example"
android:layout_gravity ="center_vertical" />

< TextView
android:id ="@+id/notification_download_layout_title"
style ="@style/NotificationTitle"
android:layout_width ="wrap_content"
android:layout_height ="wrap_content"
android:layout_alignParentTop ="true"
android:layout_marginLeft ="10dip"
android:singleLine ="true"
android:text ="notification_download_layout_title"
android:layout_gravity ="center_vertical" />
</ LinearLayout >

< ProgressBar
android:id ="@+id/notification_download_layout_progressbar"
style ="?android:attr/progressBarStyleHorizontal"
android:layout_width ="fill_parent"
android:layout_height ="wrap_content"
android:layout_marginTop ="4dp"
android:progress ="0" />

</ LinearLayout >


in Android 2.3 and higher (API> 10) a special resource was created in which the system theme indicates the colors of the text of the notifications. Because of this, in older versions you have to use a crutch:

In the file res / values ​​/ styles.xml we write:

<? xml version ="1.0" encoding ="utf-8" ? >
< resources >
< style name ="NotificationText" >
< item name ="android:textColor" > ?android:attr/textColorPrimary </ item >
</ style >
< style name ="NotificationTitle" >
< item name ="android:textColor" > ?android:attr/textColorPrimary </ item >
< item name ="android:textStyle" > bold </ item >
</ style >

</ resources >


And to support API> 10 Create a file res / values-v9 / styles.xml and enter:

<? xml version ="1.0" encoding ="utf-8" ? >
< resources >
< style name ="NotificationText" parent ="android:TextAppearance.StatusBar.EventContent" />
< style name ="NotificationTitle" parent ="android:TextAppearance.StatusBar.EventContent.Title" />
</ resources >


Now from the code of our application, we turn to the utility:

NotificationUtils n = NotificationUtils.getInstance(getActivity());
n.createInfoNotification( "info notification" );



Create notification with progress bar:

int pbId = NotificationUtils.getInstance(getActivity()).createDownloadNotification( "downloading video" );


And during the execution of a thread, we constantly update our progress by calling:

NotificationUtils.getInstance(getActivity()).updateProgress(pbId, YOUR_PROGRESS);


As a result, we obtain:
image

As you can see, the lower notification created by us with the help of the builder can be removed at any time. A notification with a progress bar is placed in the top block of notifications, in which the user cannot clear notifications.

And finally, a little trick:

If you do not want duplication of the same Activity in the stack - put in the manifest to the desired activity
android:launchMode="singleTop"

Source: https://habr.com/ru/post/140928/


All Articles