7

我有一个简单的NotificationListenerService实现来测试新的 4.3 API。该服务本身曾经工作。之后,我添加了在添加特定包的通知时发送广播。现在,只要我启动服务,它就会抛出一个DeadObjectException. 这是堆栈跟踪:

    E/NotificationService﹕ unable to notify listener (posted): android.service.notification.INotificationListener$Stub$Proxy@42c047a0
    android.os.DeadObjectException
    at android.os.BinderProxy.transact(Native Method)
    at android.service.notification.INotificationListener$Stub$Proxy.onNotificationPosted(INotificationListener.java:102)
    at com.android.server.NotificationManagerService$NotificationListenerInfo.notifyPostedIfUserMatch(NotificationManagerService.java:241)
    at com.android.server.NotificationManagerService$2.run(NotificationManagerService.java:814)
    at android.os.Handler.handleCallback(Handler.java:730)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:137)
    at com.android.server.ServerThread.run(SystemServer.java:1000)

这就是我启动服务的方式

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.action_start_service:
            startService(new Intent(this, ConnectService.class));
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

我可以验证服务是否启动,因为我在它的onCreate()onDestroy(). 如果需要,这里是处理通知发布的方式:

@Override
public void onNotificationPosted(StatusBarNotification sbn) {
    Log.i(TAG, sbn.getNotification().toString());
    if (sbn != null && sbn.getPackageName().equalsIgnoreCase(PKG)) {
        Intent intent = new Intent(ConnectService.NOTIFY);
        intent.putExtra("notification", sbn.getNotification().toString());
        bManager.sendBroadcast(intent);
    }
}

糟糕的是堆栈跟踪没有用。怎么了?

4

2 回答 2

7

尽量不要自己启动服务。如果您NotificationListenerService在安全设置中启用了,系统应该会自动绑定到它。

或者,检查您的崩溃日志以查看您的服务是否崩溃或其进程是否被终止。我相信有一个错误,如果您的 NotificaitonListerService 死亡,系统将不会重新绑定,直到您重新启动手机或在安全设置中切换通知权限。

于 2013-12-06T00:01:37.277 回答
6

由于我从 stackoverflow 的不同主题和我自己的测试中收集的信息,我想分享我的答案。如果您的 NotificationListenerService 失败(异常,如 IllegalStateException),系统将杀死它并且不再恢复它。您可以在 logcat 中看到:

592-592/? E/NotificationService﹕ unable to notify listener (posted): android.service.notification.INotificationListener$Stub$Proxy@4291d008 
android.os.DeadObjectException
....

如果用户转到安全、通知、禁用和启用您的应用程序,它仍然无法正常工作。为什么?因为只有当用户重新启动手机或用户重新启用选项通过您的应用程序时,它才会重新启动:

startActivity(new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"));

所以我们需要检查两件事,首先是否启用了该选项:

private boolean checkNotificationSetting() {

    ContentResolver contentResolver = getContentResolver();
    String enabledNotificationListeners = Settings.Secure.getString(contentResolver, "enabled_notification_listeners");
    String packageName = getPackageName();

    return !(enabledNotificationListeners == null || !enabledNotificationListeners.contains(packageName));
}

如果启用,我们检查服务是否为 Death:

private boolean isNLServiceCrashed() {
    ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    List<ActivityManager.RunningServiceInfo> runningServiceInfos = manager.getRunningServices(Integer.MAX_VALUE);

    if (runningServiceInfos != null) {
        for (ActivityManager.RunningServiceInfo service : runningServiceInfos) {

            //NotificationListener.class is the name of my class (the one that has to extend from NotificationListenerService)
            if (NotificationListener.class.getName().equals(service.service.getClassName())) {

                if (service.crashCount > 0) {
                    // in this situation we know that the notification listener service is not working for the app
                    return true;
                }
                return false;
            }
        }
    }
    return false;
}

这个service.crashCount是什么?文档说:

服务运行时服务进程崩溃的次数。

因此,如果它大于 0,则意味着它已经死亡。因此,在这两种情况下,我们都必须警告用户并提供使用我之前发布的意图重新启动服务的可能性:

startActivity(new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"));

当然,如果服务崩溃,最好检测原因以及何时阻止它。

于 2014-03-18T01:12:50.053 回答