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 に答える