安卓使用無障礙服務監聽通知

需求

在開發微動手勢的時候,作了一個通知觸發的功能,就是在收到某個預設的通知的時候,自動觸發某個動做,所以須要監聽通知消息。android

方案

最開始想使用傳統的NotificationListenerService,可是這個微動手勢App剛好使用了安卓的無障礙服務, 也就是Accessibility Service, 翻這個文檔的時候竟然發現,無障礙服務裏能夠監聽通知事件,下表是無障礙服務能提供的事件類型:app

Event types
AccessibilityEvent#TYPE_VIEW_CLICKED
AccessibilityEvent#TYPE_VIEW_LONG_CLICKED
AccessibilityEvent#TYPE_VIEW_FOCUSED
AccessibilityEvent#TYPE_VIEW_SELECTED
AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED
AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED
AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED
AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START
AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END
AccessibilityEvent#TYPE_VIEW_HOVER_ENTER
AccessibilityEvent#TYPE_VIEW_HOVER_EXIT
AccessibilityEvent#TYPE_VIEW_SCROLLED
AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED
AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED
AccessibilityEvent#TYPE_ANNOUNCEMENT
AccessibilityEvent#TYPE_GESTURE_DETECTION_START
AccessibilityEvent#TYPE_GESTURE_DETECTION_END
AccessibilityEvent#TYPE_TOUCH_INTERACTION_START
AccessibilityEvent#TYPE_TOUCH_INTERACTION_END
AccessibilityEvent#TYPE_VIEW_ACCESSIBILITY_FOCUSED
AccessibilityEvent#TYPE_WINDOWS_CHANGED
AccessibilityEvent#TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED

類型好多啊,通知就是上圖中的黑體的事件,這樣省去了單獨的NotificationListenerService和額外的權限了,對這個App來講天然比較好。ide

實現

找到了方案,實現並不複雜。code

  1. 在AndroidManifest.xml註冊無障礙服務
<service
    android:name=".ServicePlus"
    android:label="@string/service_plus"
    android:stopWithTask="false"
    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/service_plus" />
</service>

上面的android:stopWithTask是個有意思的標誌,按照文檔的描述,應該是指這個服務不會隨前臺退出而退出,參考下面的一段話:xml

FLAG_STOP_WITH_TASK Added in API level 14

public static final int FLAG_STOP_WITH_TASK
Bit in flags: If set, the service will automatically be stopped by the system if the user removes a task that is rooted in one of the application's activities. Set from the R.attr.stopWithTask attribute.事件

Constant Value: 1 (0x00000001)ip

但在國內安卓環境下,我看應該是不起做用的。 ;)開發

  1. 使用xml對無障礙服務配置參數,就是上面的android:resource指向的xml:
<accessibility-service
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:accessibilityEventTypes="typeNotificationStateChanged"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:notificationTimeout="100"
    android:accessibilityFlags="flagRequestFilterKeyEvents"
    android:description="@string/service_plus_tip"
    tools:targetApi="n" />

其中的accessibilityEventTypes就指定了通知類型的事件。rem

  1. 能夠接收事件了,看下相應的代碼
public class ServiceBase extends AccessibilityService {

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        try {
            if(event.getEventType() == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) {
                Notification notif = (Notification) event.getParcelableData();
                if (notif != null) {
                    String title = notif.extras.getString(Notification.EXTRA_TITLE);
                    String text =  notif.extras.getString(Notification.EXTRA_TEXT);
                    // ...
                }
            }
        } catch(Exception e) {
            Log.e(Consts.LOG, "event", e);
        }
     }
}

這個代碼很好理解,不作什麼解釋了,Notification類還有不少獲取通知相關信息的方法,能夠參考Google文檔。文檔

總結

若是你開發的App用到了無障礙服務,監聽通知就有一個更簡單的方法。

相關文章
相關標籤/搜索