当前位置: 首页 > 知识库问答 >
问题:

在更高版本的Android系统上,通知被破坏

赫连睿
2023-03-14

在我们的应用程序OneBusAway Android(Github上的开源)中,当用户拒绝特定的提醒通知时,我们需要收到通知,因此我们不会为同一事件发布另一个提醒通知(他们的总线到达前多长时间)。

我们通过在我们的应用程序中侦听Intent来做到这一点,该Intent注册为DeleteIntent通知。当用户拒绝通知时(通过将其滑动或点击通知窗口中的清除按钮),我们的应用程序应该会收到该Intent

通过测试,在Google Play上的当前版本(以及Github上的当前主分支)下,我们的应用程序在以下Android版本中似乎从未收到DeleteIntent:

  • Android4.4.3
  • Android4.4.4

但是,完全相同的代码在以下情况下工作(即,应用程序接收到注册为DeleteIntent的Intent):

  • Android2.3.3

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

  • 通知自动取消不会调用DeleteIntent
  • Android-DeleteIntent,如何使用
  • 通知删除意图不起作用
  • https://stackoverflow.com/questions/24218626/how-to-detect-notification-cancel-event-in-android-not-deleteintent
  • https://stackoverflow.com/questions/22769523/why-my-deleteintent-is-not-working-on-my-notification
  • Android系统不工作?我的代码怎么了
  • 在应用程序之间使用隐式意图的自定义操作

当前工作的主分支使用服务来侦听Intent。但是,根据上面的一些帖子,我确实调整了一些代码,使其更符合使用BroadcastRecencer侦听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源代码的链接:

创建通知

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

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

@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";

报警接收器

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

Android清单

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>

如上所述,在Android 4.4.3/4.4.4上,当用户拒绝通知时,AlarmReceiver永远看不到意图。

我还尝试添加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();

提醒_MIME_TYPE应用程序/vnd。通用域名格式。焦耳秒。seattlebusbot。提醒

使用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),但这也没有改变任何事情。

知道为什么这在Android4.4.3/4.4.4上不起作用吗?

有关此问题的更多信息,请参阅Github问题。

编辑

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

https://github.com/barbeau/DeleteIntentDemo

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

编辑2

这似乎是由于Android系统在通知中出现了一个错误。setLateStevenInfo()-我在这里报告过:https://code.google.com/p/android/issues/detail?id=73720

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

编辑3

我的AOSP补丁修复了这个问题,现在已经被合并,所以这个问题不会出现在Android未来版本的遗留应用中:https://code.google.com/p/android/issues/detail?id=73720#c4

然而,在上面的AOSP线程中,强调了不应再使用通知。setLateStevenInfo()——使用通知。生成器创建新通知。

共有2个答案

厍浩广
2023-03-14

你一定有不同的问题,因为我能够在几个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以在通知取消时显示祝酒词或记录消息:

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

要取消通知,请轻扫或按清除按钮。按压它不起作用,因为自动取消不被视为显式用户操作,因此不会传递删除意图。

邹开畅
2023-03-14

在您的示例项目中,如果删除以下行,deleteIntent适用于运行4.4.4的Nexus 4:

setLatestInfo(getActivity(), notification, routeId);

我怀疑这个电话正在清除你的deleteIntent。作为setLatestInfo()处理的一部分,可以将deleteIntent重新应用到通知

 类似资料:
  • 这三个系统都为应用提供了向用户发送通知的API。 Electron允许开发人员使用HTML5 Notification API快速发送通知,并通过当前系统的自带通知API来显示。 注意: 由于这是一个HTML5 API,因此它仅在渲染器进程中可用 1 let myNotification = new Notification('测试标题', { 2 body: '测试通知' 3 }) 4 ​ 5

  • 最好的做法是什么,以通知所有的片断,在一些变化的后备栈? 我尝试使用和每个片段订阅事件,然后当发生更改时,主活动向所有订阅者发送post事件。 只有我取消订阅被破坏的片段。 我不喜欢这个解决方案,因为如果backbackback中有很多片段,它可能会同时占用大量的侦听器。 我的应用程序,有无限深入,从一个片段替换到另一个片段(并添加到backstack),您可以再次替换(并添加到backstack

  • 问题内容: 尝试获取SD卡ID时,我在服务onCreate()中遇到问题。使用src-external / android- core中android.os包的FileUtils类。 崩溃日志: 提前致谢! 问题答案: 是平台内部类,用注释。您不应该使用它。

  • 2020年,四大主流浏览器计划不再支持 TLS 1.0 和 1.1。这些旧版本容易受到攻击和利用,不再具备实用性。 通过与 Mozilla 的合作,在你使用的系统中至少有一个仅使用 TLS 1.0 或 1.1,你可以在下面找到它们。 一旦浏览器终止对这些旧协议的支持,该系统将无法建立HTTPS 连接。 现在请尽快启用或升级到 TLS 1.2 或 1.3,以防止中断、停机和用户不满的事件发生。 您的

  • 只能搜到一些早期的,官方文档似乎都没对应关系的表格之类的

  • 问题内容: 我有几个用Swift 2.2编写,用Xcode 7.3编译的应用程序,这些应用程序在App Store上实时运行。这些应用程序利用推送通知,并且在iOS 9.3和更早版本中可以正常运行。 但是,在已升级到iOS 10的设备上,我的应用程序未收到任何推送通知。仍在运行iOS 9的设备仍在接收通知。 考虑到可能是证书或权利问题,我尝试了以下操作:将我的一个应用程序升级到Swift 2.3,