Android监听设备的通知栏消息 - xiaoniudonghe2015/Android-Java-Code-Style GitHub Wiki

我们可能需要监听通知栏,来获取系统通知,然后去得到通知的相关信息.

NotificationListenerService的使用

NotificationListenerService 是在 Android 4.3 (API 18)时被加入的,作用就是用来监听通知栏消息。并且官方建议在 Android 4.3 及以上使用 NotificationListenerService 来监听通知栏消息,以此取代 AccessibilityService。

方案是:在 Android 4.3 以下(API < 18)使用 AccessibilityService 来读取新通知,在 Android 4.3 及以上(API >= 18)使用 NotificationListenerService 来满足需求。

首先创建一个 MyNotificationListenerService 继承 NotificationListenerService 。然后在 AndroidManifest.xml 中进行声明相关权限和 :

 <service android:name=".MyNotificationListenerService"
          android:label="@string/app_name"
          android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
          <intent-filter>
                <action android:name="android.service.notification.NotificationListenerService" />
          </intent-filter>
</service>

然后一般会重写下面这三个方法:

onNotificationPosted(StatusBarNotification sbn) :当有新通知到来时会回调;

onNotificationRemoved(StatusBarNotification sbn) :当有通知移除时会回调;

onListenerConnected:当 NotificationListenerService 是可用的并且和通知管理器连接成功时回调。

public class MyNotificationListenerService extends NotificationListenerService {
    @Override
    public void onNotificationPosted(StatusBarNotification sbn) {
        super.onNotificationPosted(sbn);
        //当有新通知到来时会回调;
        if (!BuildConfig.APPLICATION_ID.equals(sbn.getPackageName())) {
            return;
        }
        Notification notification = sbn.getNotification();
        if (notification == null) {
            return;
        }
    }

    @Override
    public void onNotificationRemoved(StatusBarNotification sbn) {
        super.onNotificationRemoved(sbn);
        //当有通知移除时会回调;
    }

    @Override
    public void onListenerConnected() {
        super.onListenerConnected();
        //是可用的并且和通知管理器连接成功时回调。
    }
}

检测通知监听服务是否被授权

public boolean isNotificationListenerEnabled(Context context) {
    Set<String> packageNames = NotificationManagerCompat.getEnabledListenerPackages(this);
    if (packageNames.contains(context.getPackageName())) {
        return true;
    }
    return false;
}

打开通知监听设置页面

public void openNotificationListenSettings() {
    try {
        Intent intent;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP_MR1) {
            intent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS);
        } else {
            intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
        }
        startActivity(intent);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

AccessibilityService的使用

AccessibilityService 支持的事件监听类型中有 TYPE_NOTIFICATION_STATE_CHANGED ,该事件类型就是用来监听通知栏消息状态改变的. 讲完了 NotificationListenerService 之后,按照前面说的那样,在 API < 18 的时候使用 AccessibilityService 。 同样,创建一个 MyAccessibilityService ,并且在 AndroidManifest.xml 中进行声明:

<service
            android:name=".MyAccessibilityService"
            android:label="@string/app_name"
            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
            <intent-filter>
                <action android:name="android.accessibilityservice.AccessibilityService" />
            </intent-filter>
            <meta-data
                android:name="android.accessibilityservice"
                android:resource="@xml/accessible_service_config" />
        </service>

声明之后,还要对 WeChatAccessibilityService 进行配置。需要在 res 目录下新建一个 xml 文件夹,在里面新建一个 accessible_service_config.xml 文件:

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
                       android:accessibilityEventTypes="typeNotificationStateChanged"
                       android:accessibilityFeedbackType="feedbackAllMask"
                       android:accessibilityFlags="flagIncludeNotImportantViews"
                       android:canRetrieveWindowContent="true"
                       android:description="@string/app_name"
                       android:notificationTimeout="100"
                       android:packageNames="com.mavericks.mynotificationlistenerservice"/>
public class MyAccessibilityService extends AccessibilityService {

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        if (Build.VERSION.SDK_INT < 18) {
            if (event != null) {
                Notification notification = (Notification) event.getParcelableData();
            }
        }
    }

    @Override
    public void onInterrupt() {

    }
} 
}

accessibilityEventTypes:表示该服务对界面中的哪些变化感兴趣,即哪些事件通知,比如窗口打开,滑动,焦点变化,长按等.具体的值可以在AccessibilityEvent类中查到,如typeAllMask表示接受所有的事件通知.

accessibilityFeedbackType:表示反馈方式,比如是语音播放,还是震动

canRetrieveWindowContent:表示该服务能否访问活动窗口中的内容.也就是如果你希望在服务中获取窗体内容的化,则需要设置其值为true.

notificationTimeout:接受事件的时间间隔,通常将其设置为100即可.

packageNames:表示对该服务是用来监听哪个包的产生的事件

另外,在Android 6.0之后,也就是api23之后,官方在NotificationManager中添加了这一方法getActiveNotifications(),我们可以使用NotificationManager直接调用该方法来获取通知状态

 NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
            StatusBarNotification[] nm = mgr.getActiveNotifications();
        }
⚠️ **GitHub.com Fallback** ⚠️