An analysis of invalid notification clicks for Android version 8.0 and above

Posted by Karlos94 on Sat, 27 Jul 2019 04:41:42 +0200

Copyright Statement: This is an original article by xing_star. Please indicate where it came from!

This article syncs from http://javaexception.com/archives/178

An analysis of invalid notification clicks for Android version 8.0 and above

Recently, in restructuring the chat service, there was an opportunity to refresh the previously written notification-related logic, hiding a deep bug that should have been left over for more than eight months.The reason was not identified until today, and it was suspected that it was a problem with your device. After writing demo, experimenting with it, we finally reached a conclusion.
Android 8.0 has changed a lot since notification related Api. When I took over the project, I didn't pay much attention to it. I thought there was no problem until today's test and verification, I found there were still problems. The problem is like clicking on the notification message of App notification bar, the notification bar is still there after clicking, and it hasn't beenResponse (the logic in the App business about the Click notification bar is not valid).From the point of code suspicion, I created a demo project, referring to Notification's usage, and made experiments to see the effect.

Experimental process

Here is a review of the process of doing the experiment yourself.

First, a demo project was created, code related to notifications was added, and a BroadcastReceiver was dynamically registered.

private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
 
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent == null || context == null) {
            return;
        }
        mNotificationManager.cancel(NOTIFICATION_ID_LIVE);
        String type = intent.getStringExtra(PUSH_TYPE);
        if (PUSH_TYPE_LINK.equals(type)) {
            mNumLinkes = 0;
        } else if (PUSH_TYPE_LIVE.equals(type)) {
            mNumLives = 0;
        }
        //Here we can recalculate
    }
};
private void registerHeadsetPlugReceiver() {
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(NOTIFICATION_CLICK_ACTION);
    intentFilter.addAction(NOTIFICATION_DELETED_ACTION);
    registerReceiver(mBroadcastReceiver, intentFilter);
}
private void sendLiveNotification() {
    Intent intent = new Intent(NOTIFICATION_CLICK_ACTION);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
        channel.setBypassDnd(true);    //Set Bypass-Free Mode
        channel.canBypassDnd();       //Detect whether to bypass interference-free mode
        channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);//Set this notification on the lock screen interface
        channel.setDescription("Test notification message content");
        channel.setLightColor(Color.GREEN);
        channel.setName("Test notification message name");
        channel.setShowBadge(true);
        channel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
        channel.enableVibration(true);
        mNotificationManager.createNotificationChannel(channel);
    }
 
    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID);
    String title = "Push test";
    mBuilder.setContentTitle(title);
    mBuilder.setTicker(title);
    mBuilder.setContentText("https://233.tv/over140");
    mBuilder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));
    mBuilder.setSmallIcon(R.mipmap.ic_launcher);
    mBuilder.setDefaults(Notification.DEFAULT_ALL);
    mBuilder.setWhen(System.currentTimeMillis());
    mBuilder.setContentIntent(PendingIntent.getBroadcast(this, NOTIFICATION_ID_LIVE, intent, 0));
    mBuilder.setDeleteIntent(PendingIntent.getBroadcast(this, NOTIFICATION_ID_LIVE, new Intent(NOTIFICATION_DELETED_ACTION).putExtra(PUSH_TYPE, PUSH_TYPE_LIVE), 0));
    mNotificationManager.notify(NOTIFICATION_ID_LIVE, mBuilder.build());
}

The test code for the first step is simple. When you call the sendLiveNotification() method in MainActivity, a notification bar appears. Then, you click on the notification bar to send a broadcast. We register this broadcast event in MainActivity and you will be able to receive it. It looks OK.Here's where the suspect is placed on the static registration, where BroadcastReceiver is registered in AndroidManifest.xml.

The next step is to modify the code, adjust the dynamically registered code to a CustomBroadcastReceiver, and register it in AndroidManifest.xml

<receiver
    android:name=".CustomBroadcastReceiver"
    android:enabled="true"
    android:exported="false">
    <intent-filter>
        <action android:name="me.star.notificationdemo2.click" />
        <action android:name="me.star.notificationdemo2.delete" />
    </intent-filter>
</receiver>
public class CustomBroadcastReceiver extends BroadcastReceiver {
    private int NOTIFICATION_ID_LIVE = 101;
    private String PUSH_TYPE_LIVE = "PUSH_TYPE_LIVE";
    private String PUSH_TYPE = "push_type";
    private String PUSH_TYPE_LINK = "PUSH_TYPE_LINK";
    private int mNumLinkes;
    private int mNumLives;
 
    @Override
    public void onReceive(Context context, Intent intent) {
        NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        if (intent == null || context == null) {
            return;
        }
        mNotificationManager.cancel(NOTIFICATION_ID_LIVE);
        String type = intent.getStringExtra(PUSH_TYPE);
        if (PUSH_TYPE_LINK.equals(type)) {
            mNumLinkes = 0;
        } else if (PUSH_TYPE_LIVE.equals(type)) {
            mNumLives = 0;
        }
    }
}

After adjusting, continue to validate your ideas.

Run the program, turn on debug mode, and find that after clicking on the notification bar, there is no intercept in CustomBroadcastReceiver. This confirms that the problem must be static registration, but in previous projects, some third-party broadcastReceiver was static registration, but ultimately the onReceiver method was implemented.That must be a problem with my posture.So google did a search and the keyword was that Android broadcastreceiver and roidmanifest Android 8.0 didn't run. The first article was what I wanted to find.After some reference, I find that the several statements mentioned are worth trying and have only been verified at present.

intent.setPackage(getPackageName());

Lower log output was also deliberately observed during data lookup

07-26 23:30:14.452 1637-1688/? W/BroadcastQueue: Background execution not allowed: receiving Intent { act=me.star.notificationdemo2.click flg=0x10 } to notification.star.me.notificationdemo2/.CustomBroadcastReceiver

Background execution is not allowed?Anyway, I can't understand anything, I didn't look closely at the related source code.Add intent.setPackage(getPackageName()); recompile

Then debug found out that the onReceiver code logic was executed this time, and finally found the problem. It took several hours to execute the code, but it was worth it.

 

Reference material

https://blog.csdn.net/u011386173/article/details/82889275

Demo Download

Links: https://pan.baidu.com/s/1Ac97_0kFxKavpQi6-YxB2w Password: niun (demo contains Git version control, you can switch commit, check dynamic registration, static registration code)

Topics: PHP Android xml Google git