应用程序崩溃后,通知侦听器服务无法运行

时间:2017-07-16 03:25:01

标签: android notifications crash reboot notification-listener

我的应用程序出现问题,我想报告此错误。

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

效果很好。

但NotificationListenerService类有我认为的问题。

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

有谁能解决这个问题?

请帮帮我。

错误很明显!!但要找到解决方案并不容易......

3 个答案:

答案 0 :(得分:8)

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

在您的服务类或其他服务/活动中,您可以将“组件难度”切换为收听通知​​

    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。 这将导致您的服务无法连接,并且永远不会在ListenerConnected上运行 保持Intent不变,大多数情况下你不需要编辑它。

答案 1 :(得分:0)

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

虽然看起来是一个糟糕而复杂的解决方案。

答案 2 :(得分:0)

我有同样的问题。这是我做过的一些事情,现在对我来说效果很好。

  1. 覆盖onStartCommand,调用super并返回START_STICKY;
  2. 覆盖onNotificationRemoved,调用super并添加祝酒词,以便您在android本身中知道每次滑动通知时服务尚未消失。
  3. 从省电列表中排除您的应用(设置->电池->省电排除)

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