Summary of special android user Notification usage-Notification source code analysis

Source: Internet
Author: User

Summary of special android user Notification usage-Notification source code analysis

Android phones that have been used all the time, with so many apps, will also encounter interesting notifications. Here we will summarize two types of notifications and Icon numbers, some will be studied later. Also, I want to promote it. I just created a Q group named 544645972. If you are interested, I will add it and grow together.

Dynamic Change

After setting the setOngoing attribute of a notification to true, notification can stay in the system notification bar until cancel or the application exits. So sometimes you need to dynamically change the notification according to the scenario in real time. Here we take the timer function as an example. We need to update the notification every 1 s. The specific effect is as follows:
  
The Code is also very simple:

<CODE class="hljs java">private Timer timer;private TimerTask task;...if (timer != null)    return;timer = new Timer("time");task = new TimerTask() {    @Override    public void run() {        showDynamicNotification();    }};timer.scheduleAtFixedRate(task, 0, 1000);private void showDynamicNotification() {    L.i("show dynamic notification");    mBuilder = new NotificationCompat.Builder(NotificationActivity.this);    RemoteViews view = new RemoteViews(getPackageName(), R.layout.layout_notification);    view.setTextViewText(R.id.tv_number, parseDate());    view.setImageViewResource(R.id.iv_icon, R.mipmap.ic_launcher);    Intent intent = new Intent(NOTIFY_ACTION);    PendingIntent pendingIntent = PendingIntent.getBroadcast(NotificationActivity.this,            1000, intent, PendingIntent.FLAG_UPDATE_CURRENT);    mBuilder.setSmallIcon(R.mipmap.ic_launcher)            .setContentIntent(pendingIntent)            .setTicker("you got a new message")            .setOngoing(true)            .setContent(view);    notification = mBuilder.build();    notificationManager.notify(NOTIFY_ID2, notification);}private String parseDate() {    SimpleDateFormat format = new SimpleDateFormat("yyyy hh:mm:ss", Locale.getDefault());    return format.format(System.currentTimeMillis());}</CODE>

Note that Notification. Builder is introduced in Android 3.0 (API 11). To be compatible with earlier versions, we generally use icationicationcompat. Builder provided by the Support V4 package to build Notification. To dynamically update a notification, you must use icationicationmanager. notify () id parameter, which must be unique in the application (if not unique, in some 4. the pendingIntent cannot respond to the issue on x's mobile phone, similar to the case on the red mi mobile phone). to update a notification with a specific id, you only need to create a new notification, and trigger a notification with the same id as the previous one. If the previous notification is still visible, the system updates the notification based on the content of the new notification object. On the contrary, if the previous notification has been cleared, the system creates a new notification.
In this example, the fully-customized remoteViews are used. The update mechanism of remoteViews is different from that of general views. There are a lot of online materials. If you are interested, you can take a closer look. Another one is PendingIntent, which will not be described in detail. Here we will briefly list the functions of the four flags of PendingIntent.

FLAG_CANCEL_CURRENT: If the built PendingIntent already exists, cancel the previous one and re-build one. FLAG_NO_CREATE: if the previous PendingIntent does not exist, it will no longer be built. FLAG_ONE_SHOT: indicates that the PendingIntent built here can only be used once. FLAG_UPDATE_CURRENT: If the built PendingIntent already exists, replace it.

 

Big view

Notification has two visual styles: Standard view and Big view ). Standard views are common in Android, but for large views, only versions of Android4.1 + are supported, such as emails, music and other software will use the extended notification bar of this large view style. The system provides the setStyle () function to set the large view mode. Generally, there are three modes to choose from:

Icationicationcompat. BigPictureStyle: A 256dp height bitmap icationicationcompat. BigTextStyle is displayed in the details section, and a large text block is displayed in the details section. NotificationCompat. InboxStyle: displays a line of text in the details section. After version 21, a Notification. MediaStyle is added, which can be similar
  
The effect is basically similar to the interface of some mainstream media players. I will not introduce it here. I will provide a document: controllingMedia
If you do not use the preceding Styles, you can customize the layout completely. For example:
  
Here I will take a simple implementation as an example. The effect is as follows:
  
Code:

 

RemoteViews smallView = new RemoteViews (getPackageName (), R. layout. layout_notification); smallView. setTextViewText (R. id. TV _number, parseDate (); smallView. setImageViewResource (R. id. iv_icon, R. mipmap. ic_launcher); mBuilder = new NotificationCompat. builder (icationicationactivity. this); mBuilder. setSmallIcon (R. mipmap. ic_launcher ). setNumber (int) (Math. random () * 1000) // No longer displayed in the status bar as of API 21 .. setTicker ("you got a new message "). setDefaults (Notification. DEFAULT_SOUND | Notification. DEFAULT_VIBRATE | Notification. DEFAULT_LIGHTS )//. setDeleteIntent (). setAutoCancel (true ). setWhen (0 ). setPriority (icationicationcompat. PRIORITY_LOW); intent = new Intent (yy_action); pendingIntent = PendingIntent. getBroadcast (icationicationactivity. this, 1000, intent, PendingIntent. FLAG_UPDATE_CURRENT); mBuilder. setContentIntent (pendingIntent); // After version 5.0, icationif if (Build. VERSION. SDK_INT> = Build. VERSION_CODES.LOLLIPOP) {mBuilder. setVisibility (icationicationcompat. VISIBILITY_PUBLIC);} notification = mBuilder. build (); notification. contentView = smallView; // if the system version is> = Android 4.1, set the RemoteViewsif (Build. VERSION. SDK_INT> = Build. VERSION_CODES.JELLY_BEAN) {RemoteViews view = new RemoteViews (getPackageName (), R. layout. layout_big_notification); view. setTextViewText (R. id. TV _name, "I'm name 1, I'm name 2, I'm name 3, I'm name 4, I'm name 5, I'm name 6, I'm name 7, I'm name"); view. setOnClickPendingIntent (R. id. btn_click_close, PendingIntent. getBroadcast (icationicationactivity. this, 1001, new Intent (CLICK_ACTION), PendingIntent. FLAG_UPDATE_CURRENT); // textview marquee property is useless for bigContentView notification. bigContentView = view;} icationicationmanager. Y (policy_id3, notification );

Xml layout:

<framelayout android:layout_height="150dp" android:layout_width="match_parent"></framelayout>
 

  Here are some points that need to be emphasized

The setTicker function has been Deprecated since version 21, but it has no effect. The setDeleteIntent function added after listening for notification deletion is released after version 11. If setAutoCancel is set to true, the function will become invalid. The setPriority function is used to set priority for notification. The above is a detailed introduction to the google documentation. After version 21, notification can be displayed on the screen lock page. This is also introduced in the google documentation. This experience is very deep for me and can be hidden for notifications such as text messages, however, for apps with no privacy, you can set it to public, saving users from unlocking and pulling down the notification bar. The custom big image mode also assigns the custom RemoteViews to the notification. bigContentView variable, and this function only takes effect after api16 (4.1. The height setting of the big image mode is somewhat strange. In the xml file above, the height setting of LinearLayout is invalid. You must set the FrameLayout layer and set the height of FrameLayout, it seems that the layoutParams of LinearLayout defining the outermost layer is invalid. In bigContentView, the marquee Effect of textview cannot be achieved, and the fact is strange. Using contentView alone, the marquee attribute of textview In the imported remoteViews is easy to use, but once bigContentView is set, the textview attribute in contentView is invalid. Pay attention to this when using contentView.

 

Floating notification

We should be looking at this effect a lot, but the implementation is also very simple:
  
Code:

RemoteViews headsUpView = new RemoteViews(getPackageName(), R.layout.layout_heads_up_notification);intent = new Intent(NOTIFY_ACTION);pendingIntent = PendingIntent.getBroadcast(NotificationActivity.this,        1000, intent, PendingIntent.FLAG_UPDATE_CURRENT);mBuilder = new NotificationCompat.Builder(NotificationActivity.this);mBuilder.setSmallIcon(R.mipmap.ic_launcher)        .setContentTitle("this is notification title test")        .setContentText("this is notification text test")        .setNumber((int) (Math.random() * 1000))        .setTicker("you got a new message")        //must set pendingintent for this notification, or will be crash        .setContentIntent(pendingIntent)        .setDefaults(Notification.DEFAULT_SOUND                | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS)        .setAutoCancel(true)        .setWhen(0);notification = mBuilder.build();if (Build.VERSION.SDK_INT >= 21) {    notification.priority = Notification.PRIORITY_MAX;    notification.headsUpContentView = headsUpView;}notificationManager.notify(NOTIFY_ID1, notification);


Notification FAQs

  1.When opening an activity through notification, it is necessary to save the user navigation. At this time, it is necessary to use the relevant content of the activity task, I have previously written a blog post about activity tasks: android deeply parses the launchMode startup mode, Intent Flag, and taskAffinity of the Activity. If you are interested, go and have a look. To enable click notification to open the specified activity, you need to set the relevant pendingIntent. There are two special cases to describe:

The first is to open the entire task stack of the activity. That is to say, the parent activity must be opened at the same time and arranged in the task stack in order. However, there is a problem here. Before opening the entire activity stack, it first clears the original activity task Stack, so there are only a few associated activities in the task stack, for example, I want to open the activity stack of A-> B-> C, but my original activity stack contains the activity stacks D and C, the system will directly close activity D and activity C in order, and then open activity A> activity B> activity C in order. The second is to open an activity directly in a separate task stack. In this case, two task stacks are generated. These two situations have been described in detail in the official google Documents:
   2.In my previous blog, I once introduced the problem that a notification icon turns into a white block: the status bar icon of android5.0 turns to white. This problem has been solved by myself in many domestic rom,  hammers and so on. However, rom, such as HTC and Samsung, still have such problems. Pay attention to them.
   3.Directly use

 

RemoteViews rvMain = new RemoteViews(context.getPackageName(), R.layout.notification_layout);//TODO rvMain...NotificationCompat.Builder builder = new NotificationCompat.Builder(context)                .setContent(rvMain);// TOOD ...

It is invalid. You need to use another method:

RemoteViews rvMain = new RemoteViews(context.getPackageName(), R.layout.notification_layout);//TODO rmMain...NotificationCompat.Builder builder = new NotificationCompat.Builder(context)                .setContent(rvMain);// TOOD ...Notification notification = builder.build();if(Build.VERSION.SDK_INT <= 10){    notification.contentView = rvMain;}

4.Operation events on the notification bar:

SetContentIntent (): setFullScreenIntent (): // TODO triggered when the user clicks the notification. setDeleteIntent () is called when the notification is displayed. It is triggered when the user clears the notification, you can click the Clear button or slide between the left and right to delete (of course, if it is a later version). 2.3 and below cannot handle operation events in the custom layout, in this way, we should not consider adding custom buttons.

 

Notification source code parsing

Analyze the source code and use icationicationmanager. notify as the portal for analysis:

INotificationManager service = getService();......service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,                    stripped, idOut, UserHandle.myUserId());

GetService () function:

static public INotificationManager getService(){    if (sService != null) {        return sService;    }    IBinder b = ServiceManager.getService("notification");    sService = INotificationManager.Stub.asInterface(b);    return sService;}

This function uses ServiceManager. getService ("notification") obtains the Binder object of inoicationicationmanager for cross-process communication. The obtained Binder object here is icationicationmanagerservice. The two classes involved here are described as follows: StatusBarManagerService and icationicationmanagerservice, both services are stored in frameworks/base/services/java/com/android/server/SystemServer. started in the java file:

class ServerThread extends Thread {    public void run() {  ......       StatusBarManagerService statusBar = null;       NotificationManagerService notification = null;  ......      statusBar = new StatusBarManagerService(context, wm);      ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar);  ......      notification = new NotificationManagerService(context, statusBar, lights);                         ServiceManager.addService(Context.NOTIFICATION_SERVICE, notification);  ......     }  }

I introduced SystemServer in my early blog. The sub-process of system_server was created by zygote through the forkSystemServer function. If you are interested, please refer to the android Startup Process for details. The above code calls the enqueuenotifwithtag method of icationicationmanagerservice. The enqueuenotifwithtag method calls the enqueuenotifinternal method. This method is the core. Let's analyze the important code:

Void enqueuenotifinternal (final String pkg, final String opPkg, final int callingUid, final int callingPid, final String tag, final int id, final Notification notification, int [] idOut, int incomingUserId) {... // ------ Here we will set a limit. In addition to system-level applications, the number of notifications of other applications will be limited, // ------ leakage caused by DOS attacks // Limit the number of notifications that any given package cannot the android // package or a registered Listener can enqueue. prevents DOS attacks and deals with leaks .... // ------ post to work handler for work mHandler. post (new Runnable () {@ Override public void run () {synchronized (mNotificationList) {// === Scoring ==/------ review parameter priority // 0. sanitize inputs notification. priority = clamp (notification. priority, Notification. PRIORITY_MIN, Notification. PRIORITY_MAX );..... // ------ initialize score // 1. initial Score: buckets of 10, around the app [-20 .. 20] final int score = notification. priority * NOTIFICATION_PRIORITY_MULTIPLIER; // ------ encapsulate the previously passed Notification into a StatusBarNotification object, then encapsulate // ------ and score into a icationicationrecord object, and then call the handlegroupednotiflocklocked/------ method, check whether the next operation can be skipped. Otherwise, the downloadManager will be processed separately. // 2. extract ranking signals from the notification data ..... // ------ mainly for statistics of notification In addition, add the encapsulated NotificationRecord object // ------ To The mNotificationList, and then sort it. If smallIcon is set for notification, // ------ call the yypostedlocked method of all NotificationListeners to notify a new notification. // ------ the input parameter is the StatusBarNotification object encapsulated above. // 3. Apply local rules... mRankingHelper. sort (mNotificationList); if (notification. getSmallIcon ()! = Null) {StatusBarNotification oldSbn = (old! = Null )? Old. sbn: null; mListeners. policypostedlocked (n, oldSbn);} else {......} // The notification status bar displays the notification buzzBeepBlinkLocked (r );}}});}

The notifyPostedLocked method will continue to post to the working handler, and call the notifyPosted method in the working handler. The notifyPosted method is very simple, and the icationicationlistenerservice class is also called through the Binder. This icationicationlistenerservice class is very practical, it can be inherited and used to listen to various actions of system notification: Android 4.4 KitKat icationmanagmanagerservice usage and Principle Analysis (1) _ usage details. After the notification is complete, the last asynchronous operation is to call the buzzBeepBlinkLocked () method to display the notification. This function is also very long, but has a clear responsibility to determine whether sound, vibration, and Flash are required, sound, vibration, and Flash:

private void buzzBeepBlinkLocked(NotificationRecord record) {    .....    // Should this notification make noise, vibe, or use the LED?    ......    // If we're not supposed to beep, vibrate, etc. then don't.    .....    if (disableEffects == null            && (!(record.isUpdate            && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 ))            && (record.getUserId() == UserHandle.USER_ALL ||            record.getUserId() == currentUser ||            mUserProfiles.isCurrentProfile(record.getUserId()))            && canInterrupt            && mSystemReady            && mAudioManager != null) {        if (DBG) Slog.v(TAG, "Interrupting!");        sendAccessibilityEvent(notification, record.sbn.getPackageName());        // sound        // should we use the default notification sound? (indicated either by        // DEFAULT_SOUND or because notification.sound is pointing at        // Settings.System.NOTIFICATION_SOUND)        .....        // vibrate        // Does the notification want to specify its own vibration?        ....    // light    ....    if (buzz || beep || blink) {        EventLogTags.writeNotificationAlert(record.getKey(),                buzz ? 1 : 0, beep ? 1 : 0, blink ? 1 : 0);        mHandler.post(mBuzzBeepBlinked);    }}

Finally, the mBuzzBeepBlinked post is sent to the working handler, And the mStatusBar is called. buzzBeepBlinked (), mStatusBar is the StatusBarManagerInternal object, this object is initialized in StatusBarManagerService, so the last call to StatusBarManagerService StatusBarManagerInternal's buzzBeepBlinked () method:

public void buzzBeepBlinked() {    if (mBar != null) {        try {            mBar.buzzBeepBlinked();        } catch (RemoteException ex) {        }    }}

 

Related Materials

Http://www.tutorialsface.com/2015/08/android-custom-notification-tutorial/
Http://developer.android.com/intl/zh-cn/guide/topics/ui/notifiers/notifications.html#Heads-up
Http://glgjing.github.io/blog/2015/11/18/android-kai-fa-zhi-notification-xiang-jie/
Http://www.codeceo.com/article/android-notification-4-types.html
Http://www.itnose.net/detail/6169442.html
Http://www.cnblogs.com/over140/p/4249503.html
Http://blog.csdn.net/loongggdroid/article/details/17616509/
Http://www.bkjia.com/kf/201408/327782.html
Http://blog.csdn.net/xxbs2003/article/details/19167331
Http://www.jianshu.com/p/4d76b2bc8784
Http://home.bdqn.cn/thread-42153-1-1.html

Icon number

  
Although this is the style on iOS, It is supported on some mobile phones, such as Samsung and HTC (m8t, 6.0).
Generally, HTC and Samsung can use the following functions to generate

public static void setBadge(Context context, int count) {    String launcherClassName = getLauncherClassName(context);    if (launcherClassName == null) {        return;    }    Intent intent = new Intent("android.intent.action.BADGE_COUNT_UPDATE");    intent.putExtra("badge_count", count);    intent.putExtra("badge_count_package_name", context.getPackageName());    intent.putExtra("badge_count_class_name", launcherClassName);    context.sendBroadcast(intent);}public static String getLauncherClassName(Context context) {    PackageManager pm = context.getPackageManager();    Intent intent = new Intent(Intent.ACTION_MAIN);    intent.addCategory(Intent.CATEGORY_LAUNCHER);    ListresolveInfos = pm.queryIntentActivities(intent, 0);    for (ResolveInfo resolveInfo : resolveInfos) {        String pkgName = resolveInfo.activityInfo.applicationInfo.packageName;        if (pkgName.equalsIgnoreCase(context.getPackageName())) {            String className = resolveInfo.activityInfo.name;            return className;        }    }    return null;}


 


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.