Java 在更高版本的Android上,通知删除意图被破坏

Java 在更高版本的Android上,通知删除意图被破坏,java,android,android-intent,android-notifications,android-pendingintent,Java,Android,Android Intent,Android Notifications,Android Pendingintent,在我们的应用程序OneBusAway Android()中,当用户取消某个特定提醒通知时,我们需要得到通知,因此我们不会为同一事件发布另一个提醒通知(他们的巴士到达的时间) 我们通过监听应用程序中的Intent来实现这一点,该应用程序使用通知注册为deleteentent。当用户解除通知时(通过刷卡或点击通知窗口中的清除按钮),我们的应用程序应该会收到该意图 通过测试,在以下版本的Android中,我们的应用程序似乎从未接收到DeleteIntent(和): 安卓4.4.3 安卓4.4.4

在我们的应用程序OneBusAway Android()中,当用户取消某个特定提醒通知时,我们需要得到通知,因此我们不会为同一事件发布另一个提醒通知(他们的巴士到达的时间)

我们通过监听应用程序中的
Intent
来实现这一点,该应用程序使用
通知注册为
deleteentent
。当用户解除通知时(通过刷卡或点击通知窗口中的清除按钮),我们的应用程序应该会收到该
意图

通过测试,在以下版本的Android中,我们的应用程序似乎从未接收到DeleteIntent(和):

  • 安卓4.4.3
  • 安卓4.4.4
但是,完全相同的代码在以下情况下起作用(即,应用程序收到注册为DeleteIntent的意图):

  • 安卓2.3.3
  • 安卓2.3.6
  • 安卓4.1.1
  • 安卓4.1.2
我看了以下关于DeleteIntent的帖子,上面列出的解决方案都不适用于Android 4.4.3和4.4.4:

当前工作主分支使用服务侦听意图。然而,基于上面的一些帖子,我确实调整了一些代码,使之更符合使用广播接收器来监听意图的工作示例

使用BroadcastReceiver的代码位于以下Github分支中:

下面是我当前版本的摘录(仍然适用于Android 4.1.2及更低版本,但不适用于4.4.3或4.4.4),以及指向Github源代码的链接:


创建通知

标题和其他动态通知信息将在几行之后设置(如果通知未被删除,则稍后重置):

包含操作的常量:

public static final String ACTION_CANCEL =
        "com.joulespersecond.seattlebusbot.action.CANCEL";
报警接收器

AndroidManifest

remement\u MIME\u TYPE
application/vnd.com.joulespersecond.seattlebusbot.remement

用于使用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>

对于这个问题

编辑

我还在一个小型Github项目“DeleteIntentDemo”中复制了这个问题:

本项目的自述文件中有复制说明

编辑2

这似乎是由于Android在
Notification.setLateStevenInfo()
中的一个bug造成的-我在这里报告了它:

有关解决方法,请参见@commonware的答案

编辑3

修复此问题的我的AOSP修补程序现已合并,因此此问题不会出现在Android未来版本的旧版应用程序中:


但是,在上面的AOSP线程中强调,不应再使用
通知。setLatestEventInfo()
-而是使用
通知.Builder
创建新通知。

您一定有不同的问题,因为我能够在几个4.3和4.4模拟器中接收deleteintent

我想测试你的“简单”项目,但它使用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);
-覆盖
onNewIntent
以在取消通知时显示toast或记录消息:

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

要取消通知,请轻扫或按清除按钮。它无法在上面运行,因为autocancel不被视为一个明确的用户操作,因此无法传递删除意图。

在示例项目中,如果删除以下行,则删除意图将在运行4.4.4的Nexus 4上运行:

setLatestInfo(getActivity(), notification, routeId);

我怀疑此调用正在清除您的
deleteIntent
。作为
setLatestInfo()
处理的一部分,可以将
deleteIntent
重新应用到
通知中。

您是否尝试过明确的
Intent
?除非这些操作是第三方应该调用的某些公共SDK的一部分,否则您不应该在
AlarmReceiver
上使用
。我无法用显式的
Intent
--
setdeleteentent()
重现您的问题,它在运行4.4.4的Nexus 4上运行良好。
Intent deleteentent=new Intent(mContext,AlarmReceiver.class)是一个明确的意图,对吗?这种设计中的一些在我参与该项目之前就已经存在,但我相信其想法是(最终)允许外部应用程序安排/取消交通警报,并从内部代码触发相同的操作。我试图删除AlarmReceiver上的
s,但这并没有改变任何东西。@Commonware在我回答的底部,我在Github上添加了一个小样本项目,它再现了这个问题-。任何反馈都将不胜感激。如果您能提供正确工作的示例,这也会有所帮助。这是autocancel错误还是其他错误?手动删除通知时是否激发了意图?@SeanBarbeau:“当前使用的是明确的意图,对吗?”--是的,对不起,我关注的是
。你说得对!如果我在演示项目中删除该行,它也可以在我的Galaxy S3上使用4.4.4。查看Android源代码中的
Notification.setLatestEventInfo()
(),它看起来像是
Notification.Builder()
在内部用于用新值覆盖当前通知,但当前的
deleteIntent
从未被复制-因此这本质上是一个bug。奇怪的是,由于取消了
通知。setLateStevenInfo()
在原始pr中没有任何效果
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();
<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>
    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
    public void onNewIntent(Intent intent){
        Toast.makeText(this, "Notification deleted!", Toast.LENGTH_LONG).show();
    }
setLatestInfo(getActivity(), notification, routeId);