輔助功能服務 1,創建服務類MyAccessibilityService繼承AccessibilityService。import android.accessibilityservice.AccessibilityService; public class MyAccessibilityService extends AccessibilityService { @Override public void onAccessibilityEvent(AccessibilityEvent event) { if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) { String packageName = event.getPackageName().toString(); String className = event.getClassName().toString(); Log.v(TAG, "包名:" + packageName + " 類名:" + className); } } @Override public void onInterrupt() { } } 2,創建服務的配置屬性文件res/xml/service_config.xml. <?xml version="1.0" encoding="utf-8"?> <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:accessibilityEventTypes="typeAllMask" android:accessibilityFeedbackType="feedbackVisual" android:canRetrieveWindowContent="true" android:accessibilityFlags="flagDefault" /> 3,清單文件(AndroidManifest.xml)中配置 <service android:name="com.example.server.MyAccessibilityService" 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_config" /> </service> 4,手動打開需要跳轉到輔助頁面。 // 跳轉到輔助功能頁面,用於開啟或關閉,服務。 public static void jump(Context context) { context.startActivity(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)); } 5,判斷當前應用的輔助功能服務是否開啟 public static String packageNameAndclassName = "com.example.server/com.example.server.MyAccessibilityService";//格式:包名/類名 public static boolean isAccessibilitySettingsOn(Context context, String packageNameAndclassName) { int accessibilityEnabled = 0; try { accessibilityEnabled = Settings.Secure.getInt(context.getContentResolver(), android.provider.Settings.Secure.ACCESSIBILITY_ENABLED); } catch (Settings.SettingNotFoundException e) { e.printStackTrace(); } if (accessibilityEnabled == 1) { String services = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); if (services != null) { return services.toLowerCase().contains(packageNameAndclassName.toLowerCase()); } } return false; } 6,代碼打開或關閉指定的服務。 public static String packageNameAndclassName = "com.example.server/com.example.server.MyAccessibilityService";//格式:包名/類名 // 需要權限 // <uses-permission android:name="android.permission.WRITE_SETTINGS" /> // <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> public static void openAccessibilitySettings(Context context, String packageNameAndclassName) { String accessibilityStr = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); if (accessibilityStr.toLowerCase().contains(packageNameAndclassName.toLowerCase())) { return; } if (TextUtils.isEmpty(accessibilityStr)) { accessibilityStr = packageNameAndclassName; } else { accessibilityStr = accessibilityStr + ":" + packageNameAndclassName; } Settings.Secure.putString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, accessibilityStr); Settings.Secure.putInt(context.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED, 1); } public static void closeAccessibilitySettings(Context context, String packageNameAndclassName) { String accessibilityAllString = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); if (!TextUtils.isEmpty(accessibilityAllString) && accessibilityAllString.toLowerCase().contains(packageNameAndclassName.toLowerCase())) { String retAccessibilitySeting = null; if (TextUtils.equals(accessibilityAllString.toLowerCase(), packageNameAndclassName.toLowerCase())) { retAccessibilitySeting = null; } else { int index = accessibilityAllString.toLowerCase().indexOf(packageNameAndclassName.toLowerCase()); if (index == 0) { retAccessibilitySeting = accessibilityAllString.substring(packageNameAndclassName.length() + 1); } else if (index + packageNameAndclassName.length() == accessibilityAllString.length()) { retAccessibilitySeting = accessibilityAllString.substring(0, index - 1); } else { retAccessibilitySeting = accessibilityAllString.substring(0, index - 1) + accessibilityAllString.substring(index + packageNameAndclassName.length()); } } Settings.Secure.putString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, retAccessibilitySeting); Settings.Secure.putInt(context.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED, TextUtils.isEmpty(retAccessibilitySeting) ? 0 : 1); } } 7,事件: 參考網址:https://developer.android.google.cn/reference/android/view/accessibility/AccessibilityEvent.html 事件: TYPE_VIEW_CLICKED//view點擊 getEventType() - The type of the event. getClassName() - The class name of the source. getPackageName() - The package name of the source. getSource() - The source info (for registered clients). getEventTime() - The event time. getText() - The text of the source's sub-tree. isEnabled() - Whether the source is enabled. isPassword() - Whether the source is password. isChecked() - Whether the source is checked. getContentDescription() - The content description of the source. getScrollX() - The offset of the source left edge in pixels (without descendants of AdapterView). getScrollY() - The offset of the source top edge in pixels (without descendants of AdapterView). getFromIndex() - The zero based index of the first visible item of the source, inclusive (for descendants of AdapterView). getToIndex() - The zero based index of the last visible item of the source, inclusive (for descendants of AdapterView). getItemCount() - The total items of the source (for descendants of AdapterView). TYPE_WINDOW_STATE_CHANGED//切換到新窗口。 getEventType() - The type of the event. getClassName() - The class name of the source. getPackageName() - The package name of the source. getSource() - The source info (for registered clients). getEventTime() - The event time. getText() - The text of the source's sub-tree. isEnabled() - Whether the source is enabled. TYPE_WINDOW_CONTENT_CHANGED getEventType() - The type of the event. getContentChangeTypes() - The type of content changes. getSource() - The source info (for registered clients). getClassName() - The class name of the source. getPackageName() - The package name of the source. getEventTime() - The event time. 跑龍套的事件: TYPE_WINDOWS_CHANGED TYPE_VIEW_LONG_CLICKED//長點。 TYPE_VIEW_SELECTED//選擇。 TYPE_VIEW_FOCUSED//獲取焦點。 TYPE_VIEW_TEXT_CHANGED TYPE_VIEW_TEXT_SELECTION_CHANGED TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY TYPE_VIEW_SCROLLED TYPE_NOTIFICATION_STATE_CHANGED TYPE_VIEW_HOVER_ENTER TYPE_VIEW_HOVER_EXIT TYPE_TOUCH_INTERACTION_START//觸摸交互開始。 getEventType() - The type of the event. TYPE_TOUCH_INTERACTION_END getEventType() - The type of the event. TYPE_TOUCH_EXPLORATION_GESTURE_START 1 1 TYPE_VIEW_CLICKED//view點擊 32 20 TYPE_WINDOW_STATE_CHANGED//一般用的窗口狀態監聽。 2048 800 TYPE_WINDOW_CONTENT_CHANGED//改變一個窗口的內容的事件 8 8 TYPE_VIEW_FOCUSED//view獲取焦點 64 40 TYPE_NOTIFICATION_STATE_CHANGED//通知狀態改變 4096 1000 TYPE_VIEW_SCROLLED//滾動view。