【问题标题】:Notification Listener Service does not work after app is crashed应用程序崩溃后通知侦听器服务不起作用
【发布时间】:2017-07-16 03:25:01
【问题描述】:

我的应用有问题,我想报告这个错误。

我开发了可以使用 NotificationListenerService 抓取通知的应用程序。

效果很好。

但是 NotificationListenerService 类有我认为的问题。

因为,如果应用崩溃了,应用根本无法抓取通知, 直到手机重启。

有谁能解决这个问题吗?

请帮帮我。

bug 很清楚!!但是找到解决方案并不容易......

【问题讨论】:

    标签: android notifications crash reboot notification-listener


    【解决方案1】:

    如果您已经拥有权限,那么:

    在您的服务类或其他服务/活动中,您可以切换“组件功能”以收听通知

        public void tryReconnectService() {
            toggleNotificationListenerService();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                ComponentName componentName =
                        new ComponentName(getApplicationContext(), NotificationReaderV2Service.class);
    
                //It say to Notification Manager RE-BIND your service to listen notifications again inmediatelly!
                requestRebind(componentName);
            }
        }
    
    /**
    * Try deactivate/activate your component service
    */
        private void toggleNotificationListenerService() {
            PackageManager pm = getPackageManager();
            pm.setComponentEnabledSetting(new ComponentName(this, NotificationReaderV2Service.class),
                    PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
            pm.setComponentEnabledSetting(new ComponentName(this, NotificationReaderV2Service.class),
                    PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
        }
    

    你的通知监听器,是一个服务,它可以被系统杀死,你可以将你的服务作为 FOREGROUND 来做,以大大降低系统杀死你的服务的概率。

    @Override
        public void onListenerConnected() {
            super.onListenerConnected();
            Log.d(TAG, "Service Reader Connected");
        Notification not = createNotification();
        NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        if (mNotificationManager != null) {
            mNotificationManager.notify(NOTIFICATION_ID, not);
        }
    
        startForeground(NOTIFICATION_ID, not);
    
        //Alarm to auto - send Intents to Service to reconnect, you can ommit next line.
        alarmIt();
    }
    

    如果你喜欢这样更“安全”,你可以对不友好的电池警报进行编程,请尝试使用不精确的警报,用户的电池会很高兴:

    private void alarmIt() {
        Log.d(TAG, "ALARM PROGRAMMATED at"+HotUtils.formatDate(new Date()));
        Calendar now = Calendar.getInstance();
        now.setTimeInMillis(System.currentTimeMillis());
        now.set(Calendar.MINUTE, now.get(Calendar.MINUTE) + 1);
    
        Intent intent = new Intent(this, NotificationReaderV2Service.class);
        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
        intent.setAction(REBIND_ACTION);
    
        PendingIntent pendingIntent = PendingIntent.getService(this, 0,
                intent, 0);
    
        AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    
        //The alarms that are repeated are inaccurate by default, use RTC_WAKE_UP at your convenience.
        //Alarm will fire every minute, CHANGE THIS iF DO YOU CAN, you can't use less than 1 minute to repeating alarms.
        manager.setRepeating(AlarmManager.RTC_WAKEUP, now.getTimeInMillis(), 1000 * 60 * 1, pendingIntent);
    }
    

    然后阅读 Intent 以重新连接服务绑定:

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "Notification service onStartCommandCalled");
        if (intent!=null && !HotUtils.isNullOrEmpty(intent.getAction()) && intent.getAction().equals(REBIND_ACTION)){
            Log.d(TAG, "TRYING REBIND SERVICE at "+HotUtils.formatDate(new Date()));
            tryReconnectService();//switch on/off component and rebind
        }
        //START_STICKY  to order the system to restart your service as soon as possible when it was killed.
        return START_STICKY;
    }
    

    请记住,执行所有这些步骤可以确保您的服务无论如何都会被系统终止,但此代码将重新启动服务并使其更难终止。

    也许,如果您想要更多确定性,您应该考虑将 PARTIAL_WAKE_LOCK 与您的服务一起使用并在一个进程中独立执行它(:remote)(也许这没用)

    我想添加一个经常出现的常见错误,切勿覆盖 onBind 和 onUnbind 方法或覆盖 INTENT ACTION。 这将导致您的服务无法连接并且永远不会运行 onListenerConnected 保持 Intent 原样,在大多数情况下您不需要对其进行编辑。

    【讨论】:

    • 结束了这个答案 issuetracker.google.com。这还能正常工作吗?
    • 我的服务运行了 37 天,并且在 Playstore 更新和类似事件中幸存下来。
    • 所以 requestRebind() 必须是 API24 或更高版本才能工作,对吧?那它没有办法在较低的 API 上工作吗?
    • 我已经在我流行的 AutoResponder 应用程序中对此进行了测试。这是我注意到的:最好不要使用 tryReconnectService() 方法,因为它会导致某些设备上出现不可预测的行为(在华为上,正在进行的通知总是出现和消失)而且我得到了很多(真的很多!)更多 ANR .也不要使用 AlarmManager,因为它会因为频繁的设备唤醒而导致 Google Play 上的不良行为。 startForeground 应该足够了。它可以防止 NotificationListener 停止:)
    • @Panther,你在哪里调用 startForeground?是在 AppNotificationListenerService 上吗?
    【解决方案2】:

    我看到的完全一样。我发现的唯一“解决方案”是让通知侦听器在单独的进程中运行。然后,如果应用程序的其余部分崩溃,它不会停止侦听器。因此,只有在特定通知侦听器服务崩溃时才需要重新启动。

    不过,这似乎是一个糟糕且过于复杂的解决方案。

    【讨论】:

      【解决方案3】:

      我遇到了同样的问题。以下是我做过的几件事,现在对我来说效果很好。

      1. 重写 onStartCommand,调用 super 并返回 START_STICKY;
      2. 覆盖 onNotificationRemoved,调用 super 并添加一个 toast,以便您在 android 本身中知道您的服务还没有在您滑动通知时死亡。
      3. 从省电列表中排除您的应用(设置-> 电池-> 省电排除)

      发布此消息,即使在主应用程序崩溃后,该服务也不会消失。我现在不需要重新启动来重新启动它。

      【讨论】:

        猜你喜欢
        • 2018-10-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-21
        • 2019-09-04
        • 2014-05-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多