Disallowed call from unknown not

2019-07-11  本文已影响0人  CZKGO

问题:

java.lang.SecurityException: Disallowed call from unknown notification listener: android.service.notification.INotificationListener$Stub$Proxy@130eeac class android.service.notification.INotificationListener$Stub$Proxy
        at android.os.Parcel.createException(Parcel.java:1950)
        at android.os.Parcel.readException(Parcel.java:1918)
        at android.os.Parcel.readException(Parcel.java:1868)
        at android.app.INotificationManager$Stub$Proxy.cancelNotificationsFromListener(INotificationManager.java:2381)
        at android.service.notification.NotificationListenerService.cancelNotification(NotificationListenerService.java:590)
        at com.app.service.MyNotificationListenerService.deleteNotification(MyNotificationListenerService.java:190)
        at com.app.service.MyNotificationListenerService$1.run(MyNotificationListenerService.java:304)
        at com.neat.async.TaskQueue.run(TaskQueue.java:41)
     Caused by: android.os.RemoteException: Remote stack trace:
        at com.android.server.notification.ManagedServices.checkServiceTokenLocked(ManagedServices.java:601)
        at com.android.server.notification.NotificationManagerService$11.cancelNotificationsFromListener(NotificationManagerService.java:2844)
        at android.app.INotificationManager$Stub.onTransact(INotificationManager.java:665)
        at android.os.Binder.execTransact(Binder.java:752)

原因:

        调用cancelNotification方法时,如果NotificationListenerService断开连接,就会产生该bug,NotificationListenerService会在授权成功时连接,授权关闭时断开连接,但也会因为一些其他原因导致连接断开,如下:

NotificationListenerService不能监听到通知,研究了一天不知道是什么原因? - 知乎

分析:

         根据堆栈信息,在ManagedServices类的checkServiceTokenLocked方法中找到了该bug的出处,如下:

public ManagedServiceInfo checkServiceTokenLocked(IInterface service) {
    checkNotNull(service);
    final IBinder token = service.asBinder();
    final int N = mServices.size();
    for (int i=0; i<N; i++) {
        final ManagedServiceInfo info = mServices.get(i);
        if (info.service.asBinder() == token) return info;
    }
    throw new SecurityException("Disallowed call from unknown " + getCaption() + ": "
            + service);
}

         可以看到,当传进来的参数IInterface不在mServices列表里时,就会产生该bug,在ManagedServices类的mServices属性前有如下注释:

// contains connections to all connected services, including app services
// and system services
protected final ArrayList<ManagedServiceInfo> mServices = new ArrayList<ManagedServiceInfo>();

解决方案:

         有上文可知,属性mServices包括所有已连接的服务,所以,我们可以在继承NotificationListenerService的服务中重写onListenerConnected和onListenerDisconnected两个方法,并用一个bool值listenerConnected来标记该服务连接状态,如下:

private boolean listenerConnected;
@Override
public void onListenerConnected() {
    super.onListenerConnected();
    listenerConnected = true;
}

@Override
public void onListenerDisconnected() {
    super.onListenerDisconnected();
    listenerConnected = false;
}

         然后再调用cancelNotification前先判断连接状态:

if (listenerConnected) {
    if (Build.VERSION.SDK_INT >= 21) {
        cancelNotification(key);
    } else {
        cancelNotification(packageName, tag, id);
    }
}
上一篇 下一篇

猜你喜欢

热点阅读