Discussion on Android notification and authority mechanism

Source: Internet
Author: User

Recently, in order to do a small technical sharing within the Department. In-depth understanding of the implementation of the notification principle. And the Android permissions mechanism. Make a note here. 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 picture may be not very clear, this and our notification have what relationship, I come to introduce the background. This happened during the 15 NBA playoffs, the Rockets against the Mavericks, the Rockets took the lead in 3:1, just to win another one will be able to eliminate opponents. At this time the official chief operating officer of the Rockets issued this official tweet.

"A gun pointing at the calf's line, hem, just need to close your forehead, and it will end immediately." The tweet was forwarded and commented on by a number of people, and it was sent to fans and the media who were all interested in the game.

Let's just imagine that you're a calf fan, and you were in a bad mood after losing the game. This time the mobile phone startled, received this notification bar push. Do you have a strong sense of contempt. There was a flurry of cyber controversy on Twitter that day. Not only calf fans, but other neutral fans have also said that the Twitter irony is full, and has been suspected 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 represents the former operator's personal opinion and the Rockets have no relation whatsoever.

Figure II:

Say the others, and then tell us about ourselves. On the day of March 5, the group was talking about the 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 very many users to feel baffled, let's just imagine. You are ready to have a dinner with your recent contacts, before you go out to receive this to wish us to break up notice. Are you feeling very uncomfortable? Yes, on the micro-blog after a search on the discovery of a very many users are such a feeling of discomfort. Of course, I didn't say I was going to fire the editor's squid with this control.

Seems tricky very far, say so much in fact is to explain one thing, application notification is a very important link, the bad treatment is very likely to bring bad impression to the user. The light is spit groove, heavy is the direct unloading.

Ok ok. Well, let me make a list of the issues.

First, the use of notification

Two, notification the source code analysis of the 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

Now, 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

watermark/2/text/ahr0cdovl2jsb2cuy3nkbi5uzxqvd3vob25ncwkwmdey/font/5a6l5l2t/fontsize/400/fill/i0jbqkfcma==/ Dissolve/70/gravity/center ">

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 ());

Another is a notification style that is generated using a layout of your own definition

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 its own definition of complex view such as view

The common denominator of these two points is that they initialize Notificationmanagercompat first. and Notificationcompat.builder, and then after a series of Builder set the value through the manager.notify to send notifications. The difference is that the normal notification sets the value of the interface element directly, and the self-defined notification constructs a RemoteView's own definition layout, which is set to the builder's content.

Define your own notifications. There is one thing that needs attention. This own definition of the layout of the TextView font size and color need to be properly configured, or very easy in different systems and other apps notification display way, resulting in user notification bar because this is not beautiful, even very abrupt. Well, the official also has to provide us with this 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, such a deal should be able to solve the majority of mobile phone notification text style problems, but there are some optimized or modified system. is still incompatible with this notification style, it is time to build () a default notification and then get the current system notification text and color.

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) {//is assumed to be viewgroup traversal search recursegroup ((viewgroup) Gp.getchildat (i));    }} return false; }

For details on how to implement the Send notification. We'll go back to the analysis later.

And the third kind of notice is more special. is a notification generated in Service.startforground (notification) mode.

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 of this method is this: make this service run in the foreground, supplying the ongoing notification to be shown to the user and in th is 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.

Two, notification the source code analysis of the 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 .

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

Let me explain this picture. The system processes where the local process and the system notification bar are located are transferred through binder. The internal notification itself has remoteviews variables. When notification. When the builder runs the build () method. The data related to the notice and the view operation are all through a series of addaction methods exist in Remoteviews. When Notificationmanager really runs 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, 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 run the system process to get the resources of the local process. is to get the same context as the local process by Context.createapplicationcontext () first. The resource is then fetched through the GetResource (resource ID).

This is a great way to explain how remoteviews communicates across processes.

Here we need to follow up the source code of Remoteviews to verify this process.
To figure this out. Let's take a look at the collapse that has been in our collapse tree before, and the amount is not small.

The general meaning is that the system can not create notification, because through the resource id0x7f021b02 can not find the need to show the notification icon, 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, can imagine, because this resource ID is in the previous build () operation has passed it to the system process, This is assuming that the local process overwrites the resource Mapping table after the upgrade, and then the system process runs getresource. With the old resource ID. Of course you can't find the resources. The solution to our cool dog right now is to solidify this part of the resource ID so that no matter how many new version numbers are issued, the resources required for the notification bar are the same resource IDs. It's not going to get any.

Understanding the Remoteviews cross-process communication this piece, we will continue to follow up on the Notification.notify (), what went through the detailed process. Here is still a picture,
This diagram clearly describes the description, the notification of the Notify method is how to trigger the System Update Notification bar interface, the source code follow-up commentary. Mainly the following classes NOTIFICATIONMANAGERNOTIFICATIONMANAGERSERVICENOTIFICATIONLISTENERSERVICEBASESTATUSBARPHONESTATUSBARSTATUSBARVIEWH Eadsupmanager
Three, elegant design notice
Here is a comparison chart of the notification interface. Above is the system notification bar layout before 7.0, the following is the latest system notification bar layout for 7.0.

The detailed change chart has been shown to be very clear. Of course, many mobile phone manufacturers are now experimenting with their own custom notification bar styles. This also allows us to encounter a lot of obstacles when we make our own definition notifications. Very clearly. Because the manufacturers will draw their own notification style, so our program to define their own notifications, it is very likely that the system and the style of the difference is very large, resulting in a very ugly phenomenon.

Only when our notice itself is very special, do not need to follow the system of other notification style to display, it is more suitable for their own definition of the layout, now cool dog Download notification has this problem.

Speaking of interface layout I remember when I first started to do the 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, from the beginning of Sdk21, Google asked. The notification bar icon for all applications should only be drawn with an alpha layer, not an RGB layer. In layman's words, it is our notification bar icon that does not bring color.

So that's why I was so curious to see this code in a cool dog, 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 of using 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.


This site is Google's launch of the design platform to inform this piece of design bar.

We can take a look at the demo I wrote in this section.

IV. Notification Permissions Issues

When it comes to the notification bar, you have to ask permission questions. Before our song single push function. Products found I said that the amount of exposure is much larger than the number of clicks, from the technical reasons for users to receive the future does not click it.

Since the previous logic is just to run the Notify () method to feel the notification exposure, there is a problem with the design, because it is very 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 the hypothesis is banned?

With these two questions. I started checking the information.

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

Notificationmanagercompat.from (This). Arenotificationenable ();

2, another way is to get through the 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 way is to get the data in the file Appops.xml in the/data/system/folder by Appopsmanager and Appopsservice.

This piece of the process we will be a detailed description of the narrative later.

OK, now that we know the user's permissions, assuming that the user is indeed forbidden, we have the following three ways to deal with

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

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

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

The 2nd way. In practice, the discovery run throws an exception, and 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 change permissions.

How to know if it is a system application. That's the UID.

It seems that Google has blocked the road.

The 3rd approach should be more common now. Products want to be sure to show. That would only be so mealy.

Look directly at the Overlayutils in the project here.

Just the suspension window and related to the right to have a suspended window, 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: Opened the notice, whether or not to open the Suspended window permission, can pop up the suspended window

Closed the notice, need to open the suspended window permission talent pop-up suspension window

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

After we have said the notification bar, we'll see why I've banned the notification bar. The program's toast hints are also not displayed.

After reviewing the source code, I found that Notificationmanagerservice was used in the toast.

After you run the Show () method on toast, there's a 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;}    }
I see. This also uses the method of Notenotificationop () to check the notification permissions.

Toasts are also affected by notification, but toast is everywhere in our program. Because the notification permission causes the toast to not have the influence quite big. Let's look at alternatives, which are actually similar to notifications. The first few will not say.

In fact, it is also used windowmanager suspension window. Just use the system toast first to get the layout, so the display effect is the same as 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 below 23 (that is, Android 6.0), the permission is asked by the user when the program is installed. and configured well.
However, when the targetsdkversion value is 23 or more than 23, the permission is used when the user will be asked, assuming that the code is not changed, directly use the use of critical permissions. The program will crash directly
Java.lang.SecurityException:Permission denial
Now that the cool dog is 21, there's no such thing as a temporary problem.
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 execution efficiency will improve, due to 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

watermark/2/text/ahr0cdovl2jsb2cuy3nkbi5uzxqvd3vob25ncwkwmdey/font/5a6l5l2t/fontsize/400/fill/i0jbqkfcma==/ Dissolve/70/gravity/center ">

Authentication (right to test) This step, say.

The appopsmanager that I mentioned before.

watermark/2/text/ahr0cdovl2jsb2cuy3nkbi5uzxqvd3vob25ncwkwmdey/font/5a6l5l2t/fontsize/400/fill/i0jbqkfcma==/ Dissolve/70/gravity/center ">

The Setting UI interacts with Appopsservice through Appopsmanager. To provide users with access to manage the operation of each app.

Appopsservice details 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 inference.

Assuming that the user has made the corresponding settings, then these system services will have to make corresponding processing.

For example Locationmanagerserivce the location-dependent interface at the time of implementation. There is an inference that the app that invokes the interface is set by the user to disallow the operation, assuming that the setting does not continue to locate. )

What's the Appops.xml file like? Let's take a look.

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;

Suppose there is no M-value. is the default value, each of these permissions has a corresponding default value. In the Appopsmanager.sopdefaultmode array, this is an int array, the subscript represents opcode, and the content represents the default permission value. Other properties can refer to WriteState method one by one corresponding

Vi. Summary

First, the choice of the notice
1. Do not rely on the system version number to display the same UI can use their own definition of notifications (such as cool dog play notifications)
2. Need to use system notifications consistent with Android version number UI (such as cool dog message notifications)
3. When you need to protect your service from system first kill, 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, when the need to step into the use of view can be considered remoteviews
Iv. When the notification authority is blocked, consider the use of alternative solutions (suspended windows, etc.)
Five, the establishment of a good authority inquiry mechanism (for targetsdkversion, improve efficiency and improve the user experience)

Discussion on Android notification and authority mechanism

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.