Discussion on Android notification and authority mechanism

Source: Internet
Author: User

Recently, in order to do a small technical sharing in the Department, in-depth understanding of notification implementation principles, as well as the Android permissions mechanism. Here to make a record, the article may be longer, impatient words directly to see the outline of it.


Let's take a look at the following two pictures

Figure One:


See this figure may not understand, this and our notification have what relationship, I come to briefly introduce the background, this is happening in 15 NBA playoff season, the Rockets against the Mavericks, the Rockets to 3:1 lead, as long as win one can eliminate the opponent, At this time the official chief operating officer of the Rockets issued this official tweet. "A gun pointing at the calf's team, hem, just close your forehead, and it will be over." The tweet was forwarded and commented on by many people, and was sent to all fans and the media interested in the game. We imagine that you are a calf of the fans, lost the game after the mood is very poor, this time the mobile phone a shock, received this notification bar push, you will not have a strong feeling of contempt. A flurry of cyber-controversy on Twitter, not only calf fans, but also other neutral fans, said the Twitter irony was full, and already had a suspicion of insulting opponents. Of course, the notice bar indicates that I do not carry this pot, who will carry? The next day, the chief operating officer was expelled from the Rockets, claiming that the Twitter only had nothing to do with the Rockets ' personal opinion on behalf of the former operations officer.


Figure II:





Say the others, and then tell us about ourselves. March 5, the group is talking about this push, the intention is that our editor intends to push a break-up related to the song list, but the copy is not considered completely, let people misunderstand. Causing a lot of users to feel puzzled, we imagine that you are ready to have a dinner with the object of your recent contacts, before you go out to receive this message to wish us to break up, you feel very uncomfortable. Yes, on the micro-blog after a search on the discovery of a lot of users is this uncomfortable feeling. Of course, I didn't say I was going to fire the editor's squid with this contrast.



As if tricky is very far, say so much is actually want to explain one thing, the application notification is very important, the handling of the bad is likely to bring bad impression to the user, light spit groove, heavy is directly unloaded.

Okay, okay, let's get down to the list.

First, the use of notification

Ii. Source code Analysis of notification cross-process communication

Three, elegant design notice (7.0)

IV. Notification Permissions Issues

Five, Android's authority mechanism (6.0)

Vi. Summary



First, the use of notification

At the moment, we have the following three types of notifications used in our cool dogs.

1. Notification of the Message center

2. Download the song notification

3. Notifications initiated via Playbackservice

Here's a quick look at how notifications for these three scenarios are implemented.

The first is a normal notification style that is generated using the system layout


Notificationmanagercompat Manager = Notificationmanagercompat.from (this); Notificationcompat.builder Builder = new Notificationcompat.builder (this); Builder.setcontenttitle ()  [1]. Setlargeicon ()       [   2].setcontenttext (  ) [   3].setnumber (         ) [   4]. Setsmallicon ()          [5].setwhen (            )   [6].setcontentintent (Pendingintent); Manager.notify (tag, id, Builder.build ());


The second is a notification style that is generated using a custom layout

Notificationmanagercompat Manager = Notificationmanagercompat.from (this); Notificationcompat.builder Builder = new Notificationcompat.builder (this); Builder.setwhen (). Setsmallicon (). Setlargeicon (). Setcontentintent (pendingintent); Remoteviews RemoteView = new Remoteviews (getpackagename,  r.layout.custom); Remoteview.settextviewtext (R.id.tv_ Title,  "notice title"); Remoteview.setimageviewresource (R.id.iv_icon,  R.drawable.icon); Remoteview.setonclickpendingintent (R.id.iv_icon, pendingintent); Builder.setcontent (RemoteView); Manager.notify ( tag, id, Builder.build ());      Remoteviews does not support custom view and other complex view

The common denominator of these two points is that they are first initialized with Notificationmanagercompat, and Notificationcompat.builder, After a series of builder set the value through the manager.notify to send notifications, the difference is normal notification directly set the value of the interface element, and the custom notification is to construct a RemoteView custom layout, set it to the builder content. Custom Notifications There is a point to note that this custom layout of the TextView font size and color needs to be properly configured, otherwise it is easy to display in different systems and other app notifications, resulting in user notification bar because this is not beautiful, even very abrupt. Well, the official also has to provide us with such a solution:

Available before Android 5.0: Android:style/textappearance.statusbar.eventcontent.title    //Notification header style  android:style/ TextAppearance.StatusBar.EventContent             //notification content style  Android 5.0 and later:  android:style/ TextAppearance.Material.Notification.Title         //notification heading style  android:style/textappearance.material.notification                  //notification content style

Of course, this should be able to solve the majority of mobile phone notification text style problems, but there are some optimized or modified system, still incompatible with such a notification style, it is necessary to build () a default notification, and then to get the current system notification text and color way. In this way, we can look at how our code is implemented.

Public Systemnotification Getsystemtext () {msystemnotification = new systemnotification ();            try {notificationcompat.builder Builder = new Notificationcompat.builder (this);                   Builder.setcontenttitle ("Slnotification_title"). Setcontenttext ("Slnotification_text")            . Setsmallicon (R.drawable.comm_ic_notification). build ();            LinearLayout Group = new LinearLayout (this);            Remoteviews Tempview = Builder.getnotification (). Contentview;            ViewGroup event = (ViewGroup) tempview.apply (this, group);            Recursegroup (event);        Group.removeallviews ();            } catch (Exception e) {msystemnotification.titlecolor = Color.Black;            Msystemnotification.titlesize = 32;            Msystemnotification.contentcolor = Color.Black;        Msystemnotification.contentsize = 24;    } return msystemnotification; } Private Boolean Recursegroup (VieWgroup GP) {for (int i = 0; i < Gp.getchildcount (); i++) {View v = gp.getchildat (i);                if (v instanceof TextView) {final TextView text = (TextView) v;                Final String Sztext = Text.gettext (). toString (); if ("Slnotification_title". Equals (Sztext)) {Msystemnotification.titlecolor = Text.gettextcolors (). getd                    Efaultcolor ();                Msystemnotification.titlesize = Text.gettextsize ();//return true; } if ("Slnotification_text". Equals (Sztext)) {Msystemnotification.contentcolor = text.ge                    Ttextcolors (). Getdefaultcolor ();                Msystemnotification.contentsize = Text.gettextsize ();//return true;                }}//if (v instanceof ImageView) {//final ImageView image = (ImageView) v;// if (Image.getbackground (). Getconstantstate (). Equals (GetreSources (). Getdrawable (r.drawable.comm_ic_notification))) {//Msystemnotification.iconwidth = IMAGE.GETW            Idth ();//Msystemnotification.iconheight = Image.getheight ();//}//}            if (v instanceof viewgroup) {//If it is viewgroup traversal search recursegroup ((viewgroup) Gp.getchildat (i));    }} return false; }


As for how to send notifications, we will continue to analyze them later.


And the third kind of notice is special, is the notice that generates by SERVICE.STARTFORGROUND (notification) way.

When our cool dog starts, it generates a notification in the notification bar to control playback, which is generated when the Playbackdservice is started.

Notification Notification = new Notification (); Notification.icon = R.drawable.icon;notification.flags = Mflag; Notification.contentview = Mcontentview;notification.contentintent = Pendingintentmservice.startforeground (ID, notification);

The annotation for this method is: make this service run in the foreground, supplying the ongoing notification to being shown to the user and in T He state. By default services is background, meaning that if the system needs to kill them to reclaim more memory (such as to DISPL  Ay a large page in a Web browser), they can be killed without too much harm. Can set this flag if killing your service would being disruptive to the user, such as if your service is performing BACKG Round music playback, so the user would notice if their music stopped playing.

Ii. Source code Analysis of notification cross-process communication


How does our process pass the notification data to the system process? How does the system process get the resources of our process to draw the notification bar interface? The key is Remoteviews .

Well, we need to get a good look at how the Remoteviews works here, first, a flowchart.


Let me explain this picture, the system process where the local process and the system notification bar are located are transferred through binder. The notification internally itself has remoteviews variables when notification. When the builder executes the build () method, the data associated with the notification and the view operation are remoteviews through a series of addaction methods. When Notificationmanager actually executes notify (), the local process gets the binder object through GetService, and then generates an instance of Notificationmanagerservice. The service passes the data required for presentation notifications such as notification,pkgname,tag,id and so forth to the system process by calling the Enqueuenotificationwithtag () method. The system process loops through the Apply () method in the Remoteviews to get to the previous view operation and execute, and the system process to get the resources of the local process is through the context.createapplicationcontext () First get the same context as the local process, and then go through the GetResource (resource ID) to get the resources. This is a good way to explain how remoteviews communicates across processes. Here we have to follow up the remoteviews source code, to verify this process.
With that in mind, let's take a look at the collapse that has been in our collapsing tree for a while, and it's not a small amount.

The general meaning is that the system cannot create the notification, because the resource id0x7f021b02 cannot find the notification icon that needs to be displayed, it will not show the notice. And the way to get the resources, just now we talked about through Context.createapplicationcontext () to get the Context, the official explanation is: Return A new context object for the given Application name. This Context is the same as what the named application gets when it is launched, containing the same resources and class L Oader. Each call to this method returns a new instance of a Context object; Context objects is not gkfx, however they share common state (Resources, ClassLoader, etc) so the Context instance Itse LF is fairly lightweight. Then use context to getresource to get the resources, you can imagine, because this resource ID is in the previous build () operation has passed it to the system process, At this time if the local process overwrite upgrade after the replacement of the resource Mapping table, then the system process to execute getresource, with the old resource ID, of course, can not find resources. At present, the solution of our cool dog is to cure this part of the resource ID, so no matter how many new versions, the notification bar needs these resources are the same resource ID, how to take it will not be taken.

Understand the Remoteviews cross-process communication this piece, we will continue to follow up on the end of the notification.notify (), what happened to the specific process. There is still a picture,
This diagram clearly describes, the notification of the Notify method is how to trigger to the System Update Notification bar interface, source follow-up explanation. The main categories are the following NOTIFICATIONMANAGERNOTIFICATIONMANAGERSERVICENOTIFICATIONLISTENERSERVICEBASESTATUSBARPHONESTATUSBARSTATUSBARVIEWH Eadsupmanager
Three, elegant design notice
Here is a comparison of the notification interface, above the 7.0 system notification bar layout, below is 7.0 of the latest system notification bar layout. The specific change chart has been shown to be very clear. Of course, many handset makers are now experimenting with their own custom notification bar styles. This also allows us to make a custom notification when we encounter a lot of obstacles, it is obvious, because the factory chamber to draw the notification style, so our program to customize the notification, it is likely that the system style differs greatly, resulting in ugly phenomenon. Only when our notice itself is very special, do not need to follow the system's other notification style to show, it is more suitable for custom layout, the current cool dog download notification has such a problem.



Speaking of the interface layout I think of the first time I started to do a notice, a small problem encountered, here also talk about. Why the upper left corner of the SmallIcon can not see, is a group of gray it.

In fact, starting with Sdk21, Google requires that all application notification bar icons should be drawn using only alpha layers, not RGB layers. In layman's words, it's our notification bar icon that doesn't have color on it.

That's why I was curious to see the code in a cool dog before, but I don't know why.

if (Systemutils.getsdkint () >=) {    Setsmallicon (COM.KUGOU.COMMON.R.DRAWABLE.STAT_NOTIFY_MUSICPLAYER_FOR5) ;} else {    Setsmallicon (com.kugou.common.r.drawable.stat_notify_musicplayer);}

Let's take a look at what I think is a more elegant way to use notifications.

1. Notice in progress
2, monitoring the notification of the Purge event
3. Notification of different priority levels
4, the system suspended windows and lock screen notification
5. Notification of different style styles
6. Group Notice
7, can directly reply to the notice

In particular, the last two points are unique to the 7.0 Android system.

Https://material.io/guidelines/patterns/notifications.html#notifications-behavior

This website is Google launch design platform about the design of this piece of notice.

In this part we can take a look at the demo I wrote.


IV. Notification Permissions Issues

Speaking of the notification bar will have to mention the notification bar permissions issues, before our song single push function, product found I said that the amount of exposure is much larger than the number of clicks, from the technical what causes the user to receive the future does not click it.

Because the previous logic is that as long as the implementation of the Notify () method to consider the notification exposure, there is a problem with the design, because it is likely that the user has been the notification of our program has been banned.

So how do we know that our app notification permissions are banned? What if it is banned?

With these two questions, I began to consult the information.

1, API24 start system provides a ready-made method to get notification permissions

Notificationmanagercompat.from (This). Arenotificationenable ();

2, there is also a way to get through reflection

/** * Switch status to get notifications via reflection * @param context * @return */public static Boolean isnotificationenabled (context C        Ontext) {Appopsmanager mappops = (appopsmanager) context.getsystemservice (Context.app_ops_service);        ApplicationInfo appInfo = Context.getapplicationinfo ();        String pkg = Context.getapplicationcontext (). Getpackagename ();        int uid = APPINFO.UID; Class appopsclass = null;            /* Context.app_ops_manager */try {appopsclass = Class.forName (AppOpsManager.class.getName ());            Method Checkopnothrowmethod = Appopsclass.getmethod (Check_op_no_throw, Integer.type, Integer.type, String.class);            Field Oppostnotificationvalue = Appopsclass.getdeclaredfield (op_post_notification);            int value = (int) oppostnotificationvalue.get (integer.class);        return ((int) checkopnothrowmethod.invoke (mappops,value, uid, pkg) = = appopsmanager.mode_allowed); } catch (Exception e) {e.printstacktrace ();    } return true; }
The essence of this approach is to get the data in the file Appops.xml in the/data/system/directory through Appopsmanager and Appopsservice. This piece of the process we'll have a closer look at it later.

OK, now that we know the user's permission, if it is prohibited by the user, we have the following three processing methods

1, the most friendly way of course is to give users a pop-up window, why we need to inform the elaboration, and then guide the user to open permissions.

2, the most unfriendly way is to use the Appopsmanager.setmode () method to modify the user's permissions

3, through their own design of a suspended window to replace the system notification

The 2nd way, in practice, the discovery of execution will throw an exception, the following is the exception information

SecurityException Java.lang.SecurityException:uid 10835 does not having Android.permission.UPDATE_APP_OPS_STATS.

Non-system apps do not have permission to modify permissions. How to know if it is a system application, this is the UID. It seems that Google has blocked the road.

The 3rd way should be at present more common practice, product hope must show, that can only so mealy. Look directly at the Overlayutils in the project here. However, the suspension window also involves another suspended window of the permission, users need to open the line, so it seems to prefer the first let the user decide it.

Here's a note, I tested two phones.

Huawei: Open the notification, whether or not to open the Suspended window permission, can pop up the suspended window

Closed the notification, need to open the hover window permission to pop up the suspended window

Millet: Suspended window only controlled by the window, and whether to open the notification is not related


After saying the notice bar we look again, why I put the notification bar permission, the program's toast prompt also can not display.

Check the source and found that the toast is also used in the Notificationmanagerservice. After the toast executes the show () method, there is a piece of code that goes to Enqueuetoast

if (enable_blocked_toasts &&!notenotificationop (pkg, Binder.getcallinguid ())) {    if (!issystemtoast) {        slog.e (TAG, "suppressing toast from package" + pkg + "by user request.");        return;}    }
So, here is also the method of detecting notification permission Notenotificationop ().

Toast is also affected by the notification, but our program is everywhere toast, because the notification permission to cause the toast can not play a big impact. Let's look at alternatives, which are actually similar to the announcements. The first few will not say.

In fact, it is also used WindowManager suspended windows, but first through the system toast to the layout to use, so that the display effect and the system toast.


Five, Android's authority mechanism (6.0)

When it comes to Android's authority, I want to talk about a related issue that I encountered during my internship. Balabalabala

When the targetsdkversion value is less than 23 (that is, Android 6.0), the permissions are asked by the user when the program is installed and configured properly.
However, when the targetsdkversion value is 23 or more than 23, the permission is used when the user will be asked, if the code is not changed, directly using the use of dangerous permissions, the program will crash directly
Java.lang.SecurityException:Permission denial
At the moment the cool dog is 21, and for the time being it won't happen.
The authorities have provided a set of processes to interact with the permissions of the app and the user.

Should the targetsdkversion be promoted? The official said that when the user equipment and targersdkversion consistent, the program will improve efficiency, because there will be less processing a lot of compatibility issues, remains to be verified.

Let's take a look at the permission flow under 6.0.

The diagram on the left is the standard process, the right is the user action no longer prompt




Authentication (detection authority) This step, say. The appopsmanager that I mentioned before.



The Setting UI interacts with Appopsservice through Appopsmanager to provide the user with access to manage each app's operations.

Appopsservice specifically handles the user's settings, and the user's settings are stored in the/data/system/appops.xml file.
Appopsservice will also be injected into the various related system services for the inspection of permission operations.

The system services corresponding to each permission operation (such as locating the relevant location Service,audio related audio service, etc.) inject appopsservice judgment. If the user has made the corresponding settings, then these system services will be processed accordingly.
(for example, when the Locationmanagerserivce's location-related interface is implemented, it is determined whether the app that invokes the interface is set by the user to prohibit the operation, and if there is a setting, it will not continue to be targeted.) )


So what's this appops.xml file like?


In the OP tag
n the opcode that identifies the permission,
T represents a timestamp,
M identity permission value mode, there are three kinds
1.mode_allowed = 0;
2.mode_ignored = 1;
3.mode_errored = 2;

If there is no M-value, then the default value, each permission has a corresponding default value, in the Appopsmanager.sopdefaultmode array, this is an int array, the subscript represents opcode, the content represents the default permission value. Other properties can refer to the WriteState method one by one corresponding


Vi. Summary

First, the choice of the notice
1. Do not rely on the system version to display the same UI can use custom notifications (such as cool dog play notifications)
2. Need to use system notifications consistent with Android version UI (e.g. cool dog message notifications)
3. When you need to protect your service from system first kill, you can use SERVICE.STARTFOREGROUND (notification)
Second, do notice the extension of the time to consider as much as possible 7.0 of the notification bar characteristics (because these are the official design for the user-friendly experience)
Third, consider remoteviews when you need to use view across processes.
Iv. When the notification authority is blocked, consider the use of alternative solutions (suspended windows, etc.)
Five, establish a perfect authority inquiry mechanism (for targetsdkversion, improve efficiency and improve the user experience)



Discussion on Android notification and authority mechanism

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.