草庐IT

java - 通知 DeleteIntent 在更高版本的 Android 上被破坏

coder 2023-12-03 原文

在我们的应用 OneBusAway Android (open-source on Github) 中,我们需要在用户关闭特定提醒通知时收到通知,因此我们不会为同一事件发布另一个提醒通知(他们的巴士到达还有多长时间)。

我们通过监听 Intent 来做到这一点。在我们的应用程序中,注册为 DeleteIntentNotification .当用户关闭通知时(通过滑动它,或点击通知窗口中的清除按钮),我们的应用程序应该收到 Intent .

从测试来看,似乎与 the current version on Google Play (和 current master branch on Github ),在以下 Android 版本中,我们的应用程序永远不会收到 DeleteIntent:

  • 安卓 4.4.3
  • 安卓 4.4.4

  • 但是,完全相同的代码 确实 工作(即,应用程序接收注册为 DeleteIntent 的 Intent):
  • 安卓2.3.3
  • 安卓 2.3.6
  • 安卓4.1.1
  • 安卓4.1.2

  • 我查看了以下处理 DeleteIntent 的 SO 帖子,列出的解决方案均不适用于 Android 4.4.3 和 4.4.4:
  • Notification Auto-Cancel does not call DeleteIntent
  • Android - DeleteIntent, how to use?
  • Notification deleteIntent does not work
  • 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 deleteIntent not working? What's wrong with my code?
  • Custom actions using implicit intents between applications

  • 当前工作的 master 分支使用一个 Service 来监听 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 源的链接:

    创建通知

    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 包含 Action 的常量:
    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());
            ...
        }
    }
    

    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>
    

    如上所述,在 Android 4.4.3/4.4.4 上,当用户关闭通知时,AlarmReceiver 永远不会看到 Intent。

    我还尝试添加一个 MIME 类型,如 Custom actions using implicit intents between applications 中指定的那样。 ,但这在 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_TYPEapplication/vnd.com.joulespersecond.seattlebusbot.reminder
    使用 MIME 类型的 list :
    <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 补丁现已合并,因此在 future 的 Android 版本中,旧版应用不会出现此问题:
    https://code.google.com/p/android/issues/detail?id=73720#c4

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

    最佳答案

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

    setLatestInfo(getActivity(), notification, routeId);
    

    我怀疑这个电话正在消灭你的deleteIntent .重新申请您的 deleteIntent 可能会起作用到Notification作为您的setLatestInfo() 的一部分加工。

    关于java - 通知 DeleteIntent 在更高版本的 Android 上被破坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24769228/

    有关java - 通知 DeleteIntent 在更高版本的 Android 上被破坏的更多相关文章

    1. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

      大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

    2. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

      我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

    3. java - 等价于 Java 中的 Ruby Hash - 2

      我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

    4. ruby-on-rails - 在 ruby​​ .gemspec 文件中,如何指定依赖项的多个版本? - 2

      我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这

    5. ruby - 当使用::指定模块时,为什么 Ruby 不在更高范围内查找类? - 2

      我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or

    6. ruby-on-rails - 如果我将 ruby​​ 版本 2.5.1 与 rails 版本 2.3.18 一起使用会怎样? - 2

      如果我使用ruby​​版本2.5.1和Rails版本2.3.18会怎样?我有基于rails2.3.18和ruby​​1.9.2p320构建的rails应用程序,我只想升级ruby的版本,而不是rails,这可能吗?我必须面对哪些挑战? 最佳答案 GitHub维护apublicfork它有针对旧Rails版本的分支,有各种变化,它们一直在运行。有一段时间,他们在较新的Ruby版本上运行较旧的Rails版本,而不是最初支持的版本,因此您可能会发现一些关于需要向后移植的有用提示。不过,他们现在已经有几年没有使用2.3了,所以充其量只能让更

    7. ruby-on-rails - 获取 inf-ruby 以使用 ruby​​ 版本管理器 (rvm) - 2

      我安装了ruby​​版本管理器,并将RVM安装的ruby​​实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby​​。有没有办法让emacs像shell一样尊重ruby​​的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el

    8. java - 从 JRuby 调用 Java 类的问题 - 2

      我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

    9. java - 我的模型类或其他类中应该有逻辑吗 - 2

      我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

    10. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

      什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

    随机推荐