我有一个简单的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);
}
}
糟糕的是堆栈跟踪是没用的。出了什么问题?
答案 0 :(得分:7)
尽量不要自己启动服务。如果您在安全设置中启用了NotificationListenerService
,系统应自动绑定到它。
或者,检查崩溃日志以查看您的服务是否崩溃或其进程是否已被终止。我相信如果您的NotificaitonListerService死亡,系统将不会重新绑定,直到您重新启动手机或在安全设置中切换通知权限。
答案 1 :(得分: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));
}
如果已启用,我们会检查该服务是否为死亡:
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"));
当然,如果服务崩溃,最好还是检测为什么以及何时防止服务。