DeleteIntent notification broken in later versions of Android

In our OneBusAway Android app ( open source on Github ), we need to receive notifications when a user rejects a reminder notification, so we donโ€™t send another reminder for the same event (how long their bus takes).

We do this by listening to the Intent in our application registered as DeleteIntent using Notification . When the user rejects the notification (either by unscrewing it or by clicking the clear button in the notification window), our application should receive this Intent .

From testing, it seems that with the current version on Google Play (and the current main branch on Github ), DeleteIntent is never accepted in our application in the following versions of Android:

  • Android 4.4.3
  • Android 4.4.4

However, the same DOES code works (i.e., the Intent registered as DeleteIntent received by the application):

  • Android 2.3.3
  • Android 2.3.6
  • Android 4.1.1
  • Android 4.1.2

I looked at the following SO posts regarding DeleteIntent and none of these solutions work in Android 4.4.3 and 4.4.4:

The current working branch of the wizard uses the Service to listen to Intent. However, based on some of the posts above, I made some of the code to fit the working examples that BroadcastReceiver uses to listen to Intent.

Code using BroadcastReceiver is in the following Github branch:

https://github.com/CUTR-at-USF/onebusaway-android/tree/issue104-RepeatingReminders

Below are the snippets for my current version (which still works on Android 4.1.2 and lower, but not 4.4.3 or 4.4.4), as well as links to the Github source:


Create Notification

https://github.com/CUTR-at-USF/onebusaway-android/blob/issue104-RepeatingReminders/onebusaway-android/src/main/java/com/joulespersecond/seattlebusbot/tripservice/NotifierTask.java#L131

 private Notification createNotification(Uri alertUri) { //Log.d(TAG, "Creating notification for alert: " + alertUri); Intent deleteIntent = new Intent(mContext, AlarmReceiver.class); deleteIntent.setAction(TripService.ACTION_CANCEL); deleteIntent.setData(alertUri); return new NotificationCompat.Builder(mContext) .setSmallIcon(R.drawable.ic_stat_notification) .setDefaults(Notification.DEFAULT_ALL) .setOnlyAlertOnce(true) .setDeleteIntent(PendingIntent.getBroadcast(mContext, 0, deleteIntent, PendingIntent.FLAG_UPDATE_CURRENT)) .setAutoCancel(true) .build(); } 

The name and other information of the dynamic notification are set a few lines later (and reset later if the notification remains unmanageable):

 @SuppressWarnings("deprecation") private void setLatestInfo(Notification notification, String stopId, String routeId, long timeDiff) { final String title = mContext.getString(R.string.app_name); final PendingIntent intent = PendingIntent.getActivity(mContext, 0, new ArrivalsListActivity.Builder(mContext, stopId).getIntent(), PendingIntent.FLAG_UPDATE_CURRENT); notification.setLatestEventInfo(mContext, title, getNotifyText(routeId, timeDiff), intent); } 

TripService contains constants for the action:

 public static final String ACTION_CANCEL = "com.joulespersecond.seattlebusbot.action.CANCEL"; 

Alarmreceiver

https://github.com/CUTR-at-USF/onebusaway-android/blob/issue104-RepeatingReminders/onebusaway-android/src/main/java/com/joulespersecond/seattlebusbot/AlarmReceiver.java

 public class AlarmReceiver extends BroadcastReceiver { private static final String TAG = "AlarmReceiver"; @Override public void onReceive(Context context, Intent intent) { Log.d(TAG, "In onReceive with intent action " + intent.getAction()); ... } } 

AndroidManifest

https://github.com/CUTR-at-USF/onebusaway-android/blob/issue104-RepeatingReminders/onebusaway-android/src/main/AndroidManifest.xml

 <receiver android:name=".AlarmReceiver"> <!-- These action names must match the constants in TripService --> <intent-filter> <action android:name="com.joulespersecond.seattlebusbot.action.SCHEDULE" /> <action android:name="com.joulespersecond.seattlebusbot.action.POLL" /> <action android:name="com.joulespersecond.seattlebusbot.action.CANCEL" /> </intent-filter> </receiver> 

With the above, on Android 4.4.3 / 4.4.4, AlarmReceiver never sees the intent when the user rejects the notification.

I also tried to add a MIME type, as indicated in Custom Actions, using implicit intentions between applications , but this does not work on Android 4.4.3 / 4.4. 4:

 Intent deleteIntent = new Intent(mContext, AlarmReceiver.class); deleteIntent.setAction(TripService.ACTION_CANCEL); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { deleteIntent.setDataAndTypeAndNormalize(alertUri, TripService.REMINDER_MIME_TYPE); } else { deleteIntent.setDataAndType(alertUri, TripService.REMINDER_MIME_TYPE); } return new NotificationCompat.Builder(mContext) .setSmallIcon(R.drawable.ic_stat_notification) .setDefaults(Notification.DEFAULT_ALL) .setOnlyAlertOnce(true) .setDeleteIntent(PendingIntent.getBroadcast(mContext, 0, deleteIntent, 0)) //.setLights(0xFF00FF00, 1000, 1000) //.setVibrate(VIBRATE_PATTERN) .build(); 

REMINDER_MIME_TYPE is application/vnd.com.joulespersecond.seattlebusbot.reminder

Demonstrate using the MIME type:

 <receiver android:name=".AlarmReceiver"> <!-- These action names must match the constants in TripService --> <intent-filter> <action android:name="com.joulespersecond.seattlebusbot.action.SCHEDULE" /> <action android:name="com.joulespersecond.seattlebusbot.action.POLL" /> <action android:name="com.joulespersecond.seattlebusbot.action.CANCEL" /> <data android:mimeType="application/vnd.com.joulespersecond.seattlebusbot.reminder" /> </intent-filter> </receiver> 

I also tried not using the support library (i.e. using Notification.Builder instead of NotificationCompat.Builder ), but that didn't change anything.

Any ideas why this is not working on Android 4.4.3 / 4.4.4?

See the Github issue for this issue for more information.

EDIT

I also reproduced this problem in a small Github project "DeleteIntentDemo":

https://github.com/barbeau/DeleteIntentDemo

Instructions for reproducing are provided in the README for this project.

EDIT 2

This is due to an Android bug in Notification.setLatestEventInfo() - I reported it here: https://code.google.com/p/android/issues/detail?id=73720

Check out @CommonsWare's answer for a workaround.

EDIT 3

My AOSP patch to fix this problem is now merged, so this problem will not appear for legacy applications in future versions of Android: https://code.google.com/p/android/issues/detail?id=73720#c4

However, the AOSP stream above emphasizes that you no longer need to use Notification.setLatestEventInfo() - use Notification.Builder instead to create a new notification.

+6
source share
2 answers

In your example project, if you delete the following line, deleteIntent works on Nexus 4, running 4.4.4:

 setLatestInfo(getActivity(), notification, routeId); 

I suspect this call destroys your deleteIntent . You may need to reapply deleteIntent to Notification as part of your setLatestInfo() processing.

+4
source

You should have another problem, because I can get deleteintent in several emulators 4.3 and 4.4.

I wanted to test your โ€œsimpleโ€ project, but it uses Android Studio, so I made my own simpler test.

Steps to play:

-Create an action and set the launch mode to singleInstance in the manifest.

- In the button or menu item handler, run the notification:

  Intent deleteIntent = new Intent(this, MainActivity.class); Notification notification = new NotificationCompat.Builder(this) .setSmallIcon(android.R.drawable.ic_dialog_alert) .setOnlyAlertOnce(true) .setContentTitle("Notification delete intent test") .setContentText("Please dismiss this notification by swipping or deleting it. A Toast will be shown if the deletion intent works.") .setDeleteIntent(PendingIntent.getActivity(this, 0, deleteIntent, 0)) .setAutoCancel(true) .build(); NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); nm.notify((int)System.currentTimeMillis(), notification); 

-Override onNewIntent to show a toast or record a message when the notification is canceled:

  @Override public void onNewIntent(Intent intent){ Toast.makeText(this, "Notification deleted!", Toast.LENGTH_LONG).show(); } 

To reject a notification, swipe the screen or press the clear button. He will not work on it, because autorun is not considered an explicit user action, and therefore, the intention to delete will not.

+1
source

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


All Articles