Android NotificationListenerService throws a DeadObjectException

I have a simple implementation of NotificationListenerService to test the new 4.3 API. The service itself worked. After that, I added broadcast sending when a notification about a specific package was added. Now, as soon as I started the service, he DeadObjectException . This is the stack trace:

  E/NotificationService﹕ unable to notify listener (posted): android.service.notification.INotificationListener$Stub$Proxy@42 c047a0 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) 

This is how I start the service

 @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); } } 

I can verify that the Service is starting because I am logging in to it onCreate() and onDestroy() . And here is how the notification posting is handled, if necessary:

 @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); } } 

The fact is that stack tracing is useless. What's wrong?

+6
source share
2 answers

Do not start the service yourself. If you enabled the NotificationListenerService parameter in the security settings, the system should automatically bind to it.

Also, check your crash logs to see if your service has been broken or its process has been killed. I believe that there is an error when your NotificaitonListerService dies, the system will not be restored until the phone is rebooted or the notification permission is switched in the security settings.

+6
source

I would like to share my answer because of the information that I have gathered from various topics in stackoverflow and my own tests. If your NotificationListenerService does not work (exception, for example IllegalStateException), the system will kill it and not restore it again. You can see that in logcat:

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

If the user goes to "Security", "Notifications", disables and enables your application, it still does not work. What for? Since it will only restart if the user reboots the phone, or if the user re-enables the BUT> option passing through your application using:

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

So, we need to check two things: first, if the option is enabled:

 private boolean checkNotificationSetting() { ContentResolver contentResolver = getContentResolver(); String enabledNotificationListeners = Settings.Secure.getString(contentResolver, "enabled_notification_listeners"); String packageName = getPackageName(); return !(enabledNotificationListeners == null || !enabledNotificationListeners.contains(packageName)); } 

If it is turned on, we check if the service is 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; } 

What is this service.crashCount ? The documentation reads:

The number of times the service process crashed while the service was running.

So, if it is more than 0, then this is death. Therefore, in both cases, we must warn the user and offer the ability to restart the service using the intention that I published earlier:

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

Of course, if the service crashes, it will be useful to determine why and when to prevent it.

+6
source

Source: https://habr.com/ru/post/953826/


All Articles