在我们的应用程序OneBusAway Android(open-source on Github)中,我们需要在用户驳回特定提醒通知时收到通知,因此我们不会针对同一事件发布另一个提醒通知(他们的公共汽车到达多长时间) )。
我们通过在我们的应用中收听Intent
,并使用DeleteIntent
注册为Notification
来实现此目的。当用户取消通知时(通过轻扫通知或点击通知窗口中的清除按钮),我们的应用应该会收到Intent
。
从测试开始,似乎使用the current version on Google Play(以及current master branch on Github),我们的应用程序永远不会在以下Android版本中收到DeleteIntent:
然而,完全相同的代码 DOES 工作(即应用程序收到注册为DeleteIntent的Intent):
我查看了以下涉及DeleteIntent的SO帖子,并且列出的所有解决方案都不适用于Android 4.4.3和4.4.4:
当前工作的主分支使用服务来侦听Intent。但是,基于上面的一些帖子,我确实调整了一些代码,使其更符合使用BroadcastReceiver监听Intent的工作示例。
使用BroadcastReceiver的代码位于以下Github分支中:
https://github.com/CUTR-at-USF/onebusaway-android/tree/issue104-RepeatingReminders
以下是我当前版本的内容摘录(仍适用于Android 4.1.2及更低版本,但不适用于4.4.3或4.4.4),以及指向Github源代码的链接:
制作通知
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();
}
标题和其他动态通知信息会在几行之后设置(如果通知仍未确定,则稍后重置):
@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
包含操作的常量:
public static final String ACTION_CANCEL =
"com.joulespersecond.seattlebusbot.action.CANCEL";
AlarmReceiver
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
<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>
通过上述操作,在Android 4.4.3 / 4.4.4上,当用户解除通知时,AlarmReceiver永远不会看到Intent。
我还尝试添加Custom actions using implicit intents between applications中指定的MIME类型,但这在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
是application/vnd.com.joulespersecond.seattlebusbot.reminder
使用MIME类型的清单:
<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>
我还尝试使用支持库不(即使用Notification.Builder
代替NotificationCompat.Builder
),但这也没有改变任何内容。
为什么这不适用于Android 4.4.3 / 4.4.4?
此问题在Github issue中显示了更多信息。
修改
我还在一个小的Github项目“DeleteIntentDemo”中复制了这个问题:
https://github.com/barbeau/DeleteIntentDemo
重现的说明在此项目的自述文件中。
编辑2
这似乎是由于Notification.setLatestEventInfo()
中的Android中的错误 - 我在此处报告过:
https://code.google.com/p/android/issues/detail?id=73720
请参阅@ CommonsWare的解决方案答案。
编辑3
我的AOSP补丁修复此问题现已合并,因此在Android的未来版本中,旧版应用不会出现此问题: https://code.google.com/p/android/issues/detail?id=73720#c4
但是,在上述AOSP主题中强调一个人不应再使用Notification.setLatestEventInfo()
- 而是使用Notification.Builder
来创建新的通知。
答案 0 :(得分:4)
在您的示例项目中,如果您删除以下行,则deleteIntent
适用于运行4.4.4的Nexus 4:
setLatestInfo(getActivity(), notification, routeId);
我怀疑这个电话会消灭你的deleteIntent
。作为deleteIntent
处理的一部分,将Notification
重新应用于setLatestInfo()
可能会有效。
答案 1 :(得分:1)
您必须遇到其他问题,因为我能够在多个4.3和4.4模拟器中收到deleteintent。
我想测试你的简单&#34;项目,但它使用Android Studio,所以我做了我自己更简单的测试。
重现的步骤:
创建一个活动并在清单中将启动模式设置为singleInstance。
- 在按钮或菜单项的处理程序中,启动通知:
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
在通知取消时显示祝酒词或记录消息:
@Override
public void onNewIntent(Intent intent){
Toast.makeText(this, "Notification deleted!", Toast.LENGTH_LONG).show();
}
要解除通知,请滑动或按清除按钮。它无法按下它,因为autocancel不被视为显式用户操作,因此删除意图不会被传递。