Android輔助功能原理與基本使用詳解-AccessibilityService

来源:http://www.cnblogs.com/popfisher/archive/2017/08/30/7455754.html
-Advertisement-
Play Games

輔助功能(AccessibilityService)其實是一個Android系統提供給的一種服務,本身是繼承Service類的。這個服務提供了增強的用戶界面,旨在幫助殘障人士或者可能暫時無法與設備充分交互的人們。從開發者的角度看,其實就是提供兩種功能:查找界面元素,實現模擬點擊。實現一個輔助功能服務... ...


輔助功能原理與基本使用詳解

本文主要介紹輔助功能的使用

  1. 輔助功能基本原理
  2. 輔助功能基本配置和框架搭建
  3. 輔助功能實戰解析

一、輔助功能基本原理

  輔助功能(AccessibilityService)其實是一個Android系統提供給的一種服務,本身是繼承Service類的。這個服務提供了增強的用戶界面,旨在幫助殘障人士或者可能暫時無法與設備充分交互的人們。

  從開發者的角度看,其實就是提供兩種功能:查找界面元素,實現模擬點擊。實現一個輔助功能服務要求繼承AccessibilityService類並實現它的抽象方法。自定義一個服務類AccessibilitySampleService(這個命名可以隨意),繼承系統的AccessibilityService並覆寫onAccessibilityEvent和onInterrupt方法。編寫好服務類之後,在系統配置文件(AndroidManifest.xml)中註冊服務。完成前面兩個步驟就完成了基本發輔助功能服務註冊與配置,具體的功能實現需要在onAccessibilityEvent中完成,根據onAccessibilityEvent回調方法傳遞過來的AccessibilityEvent對象可以對事件進行過濾,結合AccessibilitySampleService本身提供的查找節點與模擬點擊相關的介面即可實現許可權節點的查找與點擊。

二、輔助功能基本配置和框架搭建

創建自定義輔助功能服務類

import android.accessibilityservice.AccessibilityService;
import android.view.accessibility.AccessibilityEvent;

import com.accessibility.utils.AccessibilityLog;
public class AccessibilitySampleService extends AccessibilityService {

    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();
    }

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        // 此方法是在主線程中回調過來的,所以消息是阻塞執行的
        // 獲取包名
        String pkgName = event.getPackageName().toString();
        int eventType = event.getEventType();
        // AccessibilityOperator封裝了輔助功能的界面查找與模擬點擊事件等操作
        AccessibilityOperator.getInstance().updateEvent(this, event);
        AccessibilityLog.printLog("eventType: " + eventType + " pkgName: " + pkgName);
        switch (eventType) {
            case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
                break;
        }
    }

    @Override
    public void onInterrupt() {

    }
}

註冊輔助功能服務

// 註冊輔助功能服務
<service android:name=".AccessibilitySampleService"
    android:label="@string/accessibility_tip"
    android:exported="true"
    android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
    android:process=":BackgroundService">
    <intent-filter>
        <action android:name="android.accessibilityservice.AccessibilityService" />
    </intent-filter>
    // 通過xml文件完成輔助功能相關配置,也可以在onServiceConnected中動態配置
    <meta-data
        android:name="android.accessibilityservice"
        android:resource="@xml/accessibility_config"/>
</service>

上面android:label="@string/accessibility_tip"是配置此輔助功能服務在系統輔助功能頁面裡面顯示的名字

accessibility_config文件內容如下:

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeAllMask"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:canRetrieveWindowContent="true"
    android:description="@string/accessibility_desc"
    android:notificationTimeout="100" />

跳轉到系統輔助功能頁面,開啟輔助功能服務

  完成上面配置之後,輔助功能服務就註冊成功了,在系統輔助功能頁面就能找到這個服務,但是預設是關閉的,也就是說,這個服務要開始為我們服務,還需要去系統界面開啟那個開關。下麵是跳轉到輔助功能頁面的代碼,跳轉過去之後,手動點擊開關按鈕。開關打開之後,這個輔助功能服務就開始工作了,系統開始回調onAccessibilityEvent方法。我們可以在onAccessibilityEvent方法中處理查找節點與點擊操作。

public class OpenAccessibilitySettingHelper {
    private static final String ACTION = "action";
    private static final String ACTION_START_ACCESSIBILITY_SETTING = "action_start_accessibility_setting";

    public static void jumpToSettingPage(Context context) {
        try {
            Intent intent = new Intent(context,  AccessibilityOpenHelperActivity.class);
            intent.putExtra(ACTION, ACTION_START_ACCESSIBILITY_SETTING);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent);
        } catch (Exception ignore) {}
    }
}

下圖是小米手機開啟輔助功能的界面

三、輔助功能實戰解析

實現界面自動點擊操作,動畫有點模糊,將就看吧

界面節點查找與模擬點擊

  AccessibilityOperator封裝了輔助功能的界面查找與模擬點擊事件等操作,下麵介紹幾個關鍵的技術點。

界面節點查找操作

  AccessibilityNodeInfo提供兩種查找View節點的方法

1. 根據View的ID精確查找,但是要求SDK_INT >= 18才能用

 /**
 * 根據View的ID搜索符合條件的節點,精確搜索方式;
 * 這個只適用於自己寫的界面,因為ID可能重覆
 * api要求18及以上
 * @param viewId
 */
public List<AccessibilityNodeInfo> findNodesById(String viewId) {
    AccessibilityNodeInfo nodeInfo = getRootNodeInfo();
    if (nodeInfo != null) {
        if (Build.VERSION.SDK_INT >= 18) {
            return nodeInfo.findAccessibilityNodeInfosByViewId(viewId);
        }
    }
    return null;
}

2. 根據View的Text文本進行模糊查找

/**
 * 根據Text搜索所有符合條件的節點, 模糊搜索方式
 */
public List<AccessibilityNodeInfo> findNodesByText(String text) {
    AccessibilityNodeInfo nodeInfo = getRootNodeInfo();
    if (nodeInfo != null) {
       return nodeInfo.findAccessibilityNodeInfosByText(text);
    }
    return null;
}

模擬界面操作

1. 普通的View事件模擬(ACTION_CLICK)

private boolean performClick(List<AccessibilityNodeInfo> nodeInfos) {
    if (nodeInfos != null && !nodeInfos.isEmpty()) {
        AccessibilityNodeInfo node;
        for (int i = 0; i < nodeInfos.size(); i++) {
            node = nodeInfos.get(i);
            // 獲得點擊View的類型
            AccessibilityLog.printLog("View類型:" + node.getClassName());
            // 進行模擬點擊
            if (node.isEnabled()) {
                return node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
            }
        }
    }
    return false;
}

2. 全局事件模擬(返回鍵:AccessibilityService.GLOBAL_ACTION_BACK)

public boolean clickBackKey() {
    return performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
}

private boolean performGlobalAction(int action) {
    return mAccessibilityService.performGlobalAction(action);
}

源碼地址

https://github.com/PopFisher/AccessibilitySample


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 最近幾年隨著響應式佈局的發展,一次開發多次使用,自適應屏幕的響應式網站的需求越來越多。但是怎樣使得網站能自適應屏幕呢?這裡就需要提到一個css3裡面新增的技術了-media媒體查詢器。 那麼什麼是media媒體查詢器呢? Media媒體查詢器是CSS3新增的一個可以檢測打開網站的終端的屏幕解析度的技 ...
  • 以前我也是老搞不懂a++和++a的區別, 後來看了很多資料, 終於總結出來一條規律, 小白專用! 看完這個例子就懂了: 例1:$a = 8, 求 ++a + a++ - --a + a-- + ++a得多少? 舊值: 8 9 10 9 8 ++a + a++ - --a + a-- + ++a 新值 ...
  • 普及:瀏覽器的相容性問題,往往是個別瀏覽器(沒錯,就是那個與眾不同的瀏覽器)對於一些標準的定義不一致導致的。俗話說:沒有IE就沒有傷害。 貼士:內容都是自己總結的,不免會出現錯誤或者bug,歡迎更正和補充,本帖也會不斷更新。 Normalize.css 不同瀏覽器的預設樣式存在差異,可以使用 Nor ...
  • 最終效果圖: ...
  • ...
  • jYD是一個類似於jQuery的框架,包含常用的功能:如Dom操作,事件,樣式,表單和Ajax交互。 ...
  • 寫在前面 本文只是個人在熟悉 的一些個人筆記,因此我只根據我自己的情況來熟悉 ,所以很多 並沒有被列舉到,比如常規的 等等操作,這些 我認為只要你自己稍微看一下 "官網" 的介紹都可以知道怎麼用。本文所有的代碼請參看本人的 地址 "https://github.com/Rynxiao/immutab ...
  • 背景 最近在寫一個基於Android的IPC實現的一個小工具,主要實現的就是能夠在手機查看被監視程式的值的變化和日誌等。因為用了入侵的方式,所以需要被監視APK集成一個SDK。程式界面一覽: <! 工程結構以及SDK簡單示例: ! 大概還是一個半成品的樣子,後續會寫一些Root以後才有的功能。 遇到 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...