前言
在手機(jī)的更多設(shè)置或者高級(jí)設(shè)置中,我們會(huì)發(fā)現(xiàn)有個(gè)無障礙的功能,很多人不知道這個(gè)功能具體是干嘛的,包括我們開發(fā)也很少接觸這部分功能,以至于對(duì)這塊不甚了解。前段時(shí)間在同事的安利下去了解了下這部分功能。在這里和大家淺談下自己對(duì)這個(gè)功能的理解和部分運(yùn)用。這邊打算從 “是什么,為什么,怎么用,好不好”幾個(gè)方面來說
提綱
是什么(應(yīng)用場景,定義,作用)
為什么(原理及源碼解析)
怎么用(如何開發(fā)無障礙服務(wù))
怎么防(防止無障礙服務(wù)外掛的一些做法)
是什么(定位及作用)
為了更好的介紹輔助功能服務(wù),這里先看下應(yīng)用場景
輔助功能服務(wù)一般用于操作自動(dòng)化和輔助操作
應(yīng)用場景
●?操作自動(dòng)化,通過輔助功能服務(wù)來代替用戶執(zhí)行連續(xù)性的操作,重復(fù)性的操作,或者特殊場景的操作(例如自動(dòng)搶紅包,自動(dòng)點(diǎn)贊,自動(dòng)回復(fù),自動(dòng)搜索更優(yōu)惠商品)
WechatHelper? ?https://github.com/coder-pig/WechatHelper
●?輔助操作,幫助無法和設(shè)備完全交互的用戶(例如患有視力問題或正在忙而無法操作手機(jī)的用戶)執(zhí)行操作(例如talkback(視力低弱輔助),隨選聽讀,語音操作)
官方定義(AccessibilityService)
無障礙服務(wù)是一種應(yīng)用程序,給有殘疾的用戶或暫時(shí)無法與設(shè)備完全交互的用戶提供了更好的無障礙用戶交互功能。比如駕駛、照顧小孩或者在吵鬧的派對(duì)上可能需要額外或者替代的交互反饋。
Android提供標(biāo)準(zhǔn)的輔助功能服務(wù),包括TalkBack,開發(fā)人員可以創(chuàng)建和分發(fā)自己的服務(wù)。
引入及發(fā)展
在Android 4.0以前,Accessibility功能單一,僅能過單向獲取窗口信息(獲取輸入框內(nèi)容);
在Android 4.0及以后,Accessibility增加了與窗口元素的雙向交互,可以操作窗口元素(點(diǎn)擊按鈕)。
在Android 4.0之前,無障礙服務(wù)事件在提供有關(guān)用戶選擇的用戶界面控件的信息時(shí),只提供了有限的上下文信息。在許多情況下,缺少的上下文信息可能對(duì)理解所選控件的含義至關(guān)重要。
Android 4.0通過基于視圖層次結(jié)構(gòu)組合可訪問性事件,顯著擴(kuò)展了輔助功能服務(wù)可以獲得的有關(guān)用戶界面交互的信息量。
輔助功能服務(wù)可以代表用戶執(zhí)行操作,包括更改輸入焦點(diǎn)和選擇(激活)用戶界面元素。在Android
4.1(API級(jí)別16)中,操作范圍已擴(kuò)展為包括滾動(dòng)列表和與文本字段交互。
輔助功能服務(wù)的作用
因?yàn)闊o障礙服務(wù)具有強(qiáng)大的界面監(jiān)聽能力和替代用戶操作的能力,谷歌建議輔助功能服務(wù)僅應(yīng)用于幫助殘障用戶使用Android設(shè)備和應(yīng)用。
在我們開發(fā)者看來,無障礙服務(wù)顯然能做的更多,例如微信搶紅包應(yīng)用,自動(dòng)點(diǎn)贊,自動(dòng)回復(fù)等
android 輔助功能google官方示例?https://github.com/googlesamples/android-BasicAccessibility
為什么(原理及源碼解析)
Q:為什么輔助功能可以監(jiān)聽用戶的操作,界面變化,并根據(jù)需要進(jìn)行反饋
A:輔助功能通過在后臺(tái)中運(yùn)行無障礙服務(wù),通過AccessibilityEvent接收指定事件的回調(diào),這樣的事件表示用戶在界面中的一些狀態(tài)轉(zhuǎn)換,例如:焦點(diǎn)改變了,一個(gè)按鈕被點(diǎn)擊,等等。
簡單的說無障礙就是一個(gè)后臺(tái)監(jiān)控服務(wù),當(dāng)你監(jiān)控的內(nèi)容發(fā)生改變時(shí),就會(huì)調(diào)用后臺(tái)服務(wù)的回調(diào)方法
從具體實(shí)例入手看原理:程序內(nèi)部的后臺(tái)服務(wù)——?內(nèi)部的跨進(jìn)程通信 AM & AMS
拿一個(gè)具體的例子來看,這是一個(gè)搶紅包的外掛,把WeChat稱作Target
APP,就是被監(jiān)控的APP,當(dāng)跳出來一個(gè)紅包,觸發(fā)了一個(gè)AccessibilityEvent,system_server中的AccessibilityManagerService將AccessibilityEvent分發(fā)給有AccessibilityService的APP,稱為Accessibility
APP,這個(gè)AccessibilityService受到這個(gè)AccessibilityEvent后,會(huì)找到這個(gè)頁面的Open
Button,模擬點(diǎn)擊。
而在程序內(nèi)部,這個(gè)過程其實(shí)就是三個(gè)類之間的交互 AccessibilityManager(AM):發(fā)送AccessibilityEventAccessibilityManagerService(AMS):分發(fā)事件AccessibilityService(AS):進(jìn)行回應(yīng)?
看到AccessibilityManagerService這樣的起名,就很容易聯(lián)想到,這是一個(gè)Binder通信的過程,AM通過IAccessibilityManager(AMS的本地Binder)與AMS跨進(jìn)程通信。AMS通過IAccessibilityManagerClient(AM的本地Binder)與AM通信。
AM是與AMS進(jìn)行通信
AM是什么時(shí)候與AMS進(jìn)行通信的,查看源碼可以知道,AM的設(shè)計(jì)其實(shí)是一個(gè)單例模式,每個(gè)app進(jìn)程都會(huì)有一個(gè)AM,而AM在構(gòu)建的時(shí)候,即getInstance的時(shí)候,就會(huì)調(diào)用tryConnectToServiceLocked()的方法,連接AMS,得到AMS的代理后,把自己的代理也設(shè)置給AMS,這樣AM就可以和AMS進(jìn)行通信了
AS和AMS聯(lián)系的時(shí)機(jī)
那么AS又是什么時(shí)候和AMS有聯(lián)系的呢,這又是一個(gè)跨進(jìn)程binder通信的過程。
無障礙服務(wù)是很強(qiáng)大的服務(wù),需要我們進(jìn)到設(shè)置中開啟這個(gè)服務(wù)。綁定Service。
這里我們結(jié)合時(shí)序圖進(jìn)行說明。
Settings->Accessibility->enable(enableAccessibilityServiceLocked())
Settings->Accessibility->disable(disableAccessibilityServiceLocked())
Some RegisterBroadcastReceivers (registerBroadcastReceivers())
當(dāng)用戶在設(shè)置->無障礙里面選擇了開啟或關(guān)閉一個(gè)輔助功能,會(huì)導(dǎo)致一些系統(tǒng)狀態(tài)會(huì)變化;Accessibility APP的安裝狀態(tài)會(huì)以BroadcastReceivers的方式會(huì)通知狀態(tài)改變;還有其他的一些狀態(tài)改變。這些變化最終會(huì)調(diào)用到AMS的onUserStateChangedLocked()方法。
RegisterBroadcastReceivers? 很多情況簡單列為這四種,安裝app,更新app。強(qiáng)制關(guān)閉app,刪除app。
onUserStateChangedLocked方法中,有比較多的方法調(diào)用,都是一些特定狀態(tài)的更新,但我們這次只用關(guān)注updateServicesLocked這個(gè)方法,是處理無障礙服務(wù)綁定的
updateServicesLocked這個(gè)方法涉及到多個(gè)AMS類內(nèi)部的集合,遍歷如上圖左邊所見
這個(gè)方法會(huì)遍歷ams中的mInstalledServices,看名字可以知道是已經(jīng)安裝的無障礙服務(wù)列表。
然后根據(jù)enableServices,判斷是否已經(jīng)啟用,如果啟用則通過mComponentNameToServiceMap判斷是否為空,為空就會(huì)new一個(gè)AccessibilityServiceConnection, 調(diào)用其bindlock方法,綁定
未啟用就通過mComponentNameToServiceMap判斷是否為空,不為空就調(diào)用其unbindLocked(),解綁
接下來的過程其實(shí)就是跨進(jìn)程的Binder通信。AS會(huì)通過onBind(Intent intent)這個(gè)函數(shù)返回一個(gè)IAccessibilityServiceClientWrapper對(duì)象給AccessibilityServiceConnection,這個(gè)對(duì)象就是AS的本地Binder,AccessibilityServiceConnection通過這個(gè)本地Binder去和AS通信。
然后AccessibilityServiceConnection會(huì)在onServiceConnected中調(diào)用方法,把自己的代理傳到AS中。
監(jiān)聽無障礙服務(wù)事件(觸發(fā) 分發(fā) 回調(diào))
講完服務(wù)是什么時(shí)候綁定的,怎么建立通信的。接下來說下怎么監(jiān)聽事件的,AccessibilityEvent 是從哪里傳遞出來的
這里分為觸發(fā) 分發(fā) 回調(diào)三個(gè)部分
先說觸發(fā),以點(diǎn)擊為例
首先需要知道View都有接入 AccessibilityEventSource接口 分有兩個(gè)方法。用于發(fā)送無障礙事件。
回歸到圖的部分
●?View.java -- performClick() 被點(diǎn)擊調(diào)用
●?View.java -- sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); 發(fā)送類型為click的事件
●?View.java -- sendAccessibilityEventInternal() 創(chuàng)建了一個(gè)AM的實(shí)例(app單例),判斷是否enable狀態(tài),創(chuàng)建AM實(shí)例時(shí)會(huì)通過binder綁定遠(yuǎn)程AMS
●?View.java -- sendAccessibilityEventUnchecked(AccessibilityEvent) 這個(gè)Event方法是根據(jù)type調(diào)用AccessibilityEvent.obtain(type)創(chuàng)建的
●?View.java -- sendAccessibilityEventUncheckedInternal() 會(huì)調(diào)用onInitializeAccessibilityEvent()初始化一些event信息,比如className/packageName/source等,然后會(huì)調(diào)用getParent().requestSendAccessibilityEvent(this,event)將event分發(fā)給ParentView。requestSendAccessibilityEvent會(huì)不斷往上調(diào)用getParent().requestSendAccessibilityEvent(this,event),ViewRootImpl.requestSendAccessibilityEvent不管ParentView是哪一個(gè),最終會(huì)到View層次中的頂層,也就是ViewRootImpl
●?ViewRootImpl?-- requestSendAccessibilityEvent() 在這里就會(huì)調(diào)用AccessibilityManager.sendAccessibilityEvent(event);
●?AccessibilityManager -- sendAccessibilityEvent(event); 獲取遠(yuǎn)程的AMS 通過getServiceLocked()獲取本地Binder,然后通過service.sendAccessibilityEvent(dispatchedEvent, userId)去調(diào)用AMS的sendAccessibilityEvent方法。
然后是分發(fā),接著剛才的AccessibilityManagerService.java-- sendAccessibilityEvent()說
●?AccessibilityManagerService.java --sendAccessibilityEvent()
●?AccessibilityManagerService.java --notifyAccessibilityServicesDelayedLocked(),AMS會(huì)維護(hù)一個(gè)綁定AS的List(mBoundServices),List中每一個(gè)AccessibilityServiceConnection對(duì)應(yīng)一個(gè)綁定的AS,因此遍歷mBoundServices,獲取其中的serviceconection 然后去到AccessibilityServiceConnection的notifyAccessibilityEvent()函數(shù)。
●?AbstractAccessibilityServiceConnection.java-- notifyAccessibilityEvent()
●?AbstractAccessibilityServiceConnection.java-- notifyAccessibilityEventInternal()? ?在notifyAccessibilityEventInternal()中,listener是AS的本地Binder(IAccessibilityServiceClient類型),最終是回調(diào)到了AS的onAccessibilityEvent()。到這里Dispatch的部分就結(jié)束了。
剩下回調(diào),回調(diào)沒什么好說的,就是調(diào)用方法。
而onAccessibilityEvent()方法是繼承了AccessibilityService必須重寫的。
原理和源碼解析的結(jié)論
1.輔助功能通過在后臺(tái)中運(yùn)行無障礙服務(wù),通過AccessibilityEvent接收指定事件的回調(diào)
2.Accessibility服務(wù)框架類似于hook在Android View組件樹中的一套實(shí)現(xiàn),它并不是獨(dú)立的一套機(jī)制,而是”寄生”在View的顯示、事件分發(fā)的流程中。
●?功能實(shí)現(xiàn)依賴于ViewRootImpl, ViewGroup, View視圖層級(jí)管理的基本架構(gòu)。在視圖變化時(shí)發(fā)出事件、當(dāng)收到視圖操作請(qǐng)求時(shí)也能夠作出響應(yīng)。
●?system_server在實(shí)現(xiàn)該功能的過程中扮演著中間人的角色。當(dāng)被監(jiān)聽APP視圖變化時(shí),APP首先會(huì)發(fā)出事件到system_server,隨后再中轉(zhuǎn)到監(jiān)聽者APP端。當(dāng)監(jiān)聽者APP想要執(zhí)行視圖操作時(shí),也是首先在system_server中找到對(duì)應(yīng)的客戶端binder proxy,再調(diào)用相應(yīng)接口調(diào)用到被監(jiān)聽APP中。完成相關(guān)操作后,通過已經(jīng)獲取到的監(jiān)聽APP binder proxy句柄,直接binder call到對(duì)應(yīng)的監(jiān)聽客戶端。
3.無障礙權(quán)限十分重要,切記不可濫用,APP自身也需要有足夠的安全意識(shí),防止惡意應(yīng)用通過該服務(wù)獲取用戶隱私信息
怎么用(如何開發(fā)無障礙服務(wù))
剛剛說到,為什么輔助功能可以監(jiān)聽用戶的操作,界面變化,并根據(jù)需要進(jìn)行反饋,那怎么使用呢,我們繼續(xù)探究
一、創(chuàng)建服務(wù)類
繼承AccessibilityService 類,重寫onServiceConnected()方法、onAccessibilityEvent()方法和onInterrupt()方法
●?onServiceConnected (可選)系統(tǒng)成功綁定該服務(wù)時(shí)被觸發(fā),也就是當(dāng)你在設(shè)置中開啟相應(yīng)的服務(wù),系統(tǒng)成功的綁定了該服務(wù)時(shí)會(huì)觸發(fā),通常我們可以在這里做一些初始化操作
●?onUnbind(Intent intent) (可選)系統(tǒng)要關(guān)閉該服務(wù)是,將調(diào)用此方法。主要用來釋放資源。
●?onAccessibilityEvent(AccessibilityEvent event) 有關(guān)AccessibilityEvent事件的回調(diào)函數(shù),系統(tǒng)通過sendAccessibiliyEvent()不斷的發(fā)送AccessibilityEvent到此處
● onInterrupt 系統(tǒng)需要中斷AccessibilityService反饋時(shí),將調(diào)用此方法。AccessibilityService反饋包括服務(wù)發(fā)起的震動(dòng)、音頻等行為。
二、聲明服務(wù)
像其他Service服務(wù)一樣,需要在AndroidManifest.xml中聲明該服務(wù).除此之外,該服務(wù)還必須配置以下幾項(xiàng),否則都會(huì)使該服務(wù)沒有反應(yīng):
?●配置<intent-filter>,固定的action:android.accessibilityservice.AccessibilityService
?●聲明BIND_ACCESSIBILITY_SERVICE權(quán)限,以便系統(tǒng)能夠綁定該服務(wù)(4.0版本后要求)
?●android:label:在無障礙列表中顯示該服務(wù)的名字
三、配置服務(wù)參數(shù)
配置用來接受指定類型的事件,監(jiān)聽指定package,檢索窗口內(nèi)容,獲取事件類型的時(shí)間等等。其配置服務(wù)參數(shù)有兩種方法:
?● 方法一:安卓4.0之后可以通過meta-data標(biāo)簽指定xml文件進(jìn)行配置
accessibilityEventTypes:表示該服務(wù)對(duì)界面中的哪些變化感興趣,即哪些事件通知,比如窗口打開,滑動(dòng),焦點(diǎn)變化,長按等。具體的值可以在AccessibilityEvent類中查到,如typeAllMask表示接受所有的事件通知
accessibilityFeedbackType:表示反饋方式,比如是語音播放,還是震動(dòng)
canRetrieveWindowContent:表示該服務(wù)能否訪問活動(dòng)窗口中的內(nèi)容。也就是如果你希望在服務(wù)中獲取窗體內(nèi)容,則需要設(shè)置其值為true
description:對(duì)該無障礙功能的描述
notificationTimeout:接受事件的時(shí)間間隔,通常將其設(shè)置為100即可
packageNames:表示對(duì)該服務(wù)是用來監(jiān)聽哪個(gè)包的產(chǎn)生的事件
?● ?方法二:通過代碼動(dòng)態(tài)配置參數(shù)(setServiceInfo(AccessibilityServiceInfo))
AccessibilityServiceInfo類被用于配置AccessibilityService信息,該類中包含了大量用于配置的常量字段及用來xml屬性,常見的有:accessibilityEventTypes,canRequestFilterKeyEvents,packageNames等等
https://developer.android.google.cn/reference/android/accessibilityservice/AccessibilityServiceInfo
https://developer.android.google.cn/reference/android/view/accessibility/AccessibilityNodeInfo
https://developer.android.google.cn/reference/android/view/accessibility/AccessibilityWindowInfo
https://developer.android.google.cn/reference/android/view/accessibility/AccessibilityEvent
四、啟動(dòng)服務(wù)
在設(shè)置->輔助功能中便可以找到我們的服務(wù).該服務(wù)默認(rèn)處在關(guān)閉狀態(tài),需要手動(dòng)開啟.
也可以在app中跳轉(zhuǎn)到設(shè)置頁。
五、處理事件信息
onAccessibilityEvent(AccessibilityEvent event)是該服務(wù)的核心方法,其中參數(shù)event封裝來自界面相關(guān)事件的信息,比如我們可以獲得該事件的事件類型,進(jìn)而根據(jù)起類型選擇不同的處理方式:
常見種類如圖
六、獲取節(jié)點(diǎn)信息
獲取了界面窗口變化后,這個(gè)時(shí)候就要獲取控件的節(jié)點(diǎn)。整個(gè)窗口的節(jié)點(diǎn)本質(zhì)是個(gè)樹結(jié)構(gòu),通過以下操作節(jié)點(diǎn)信息
獲取窗口節(jié)點(diǎn)(根節(jié)點(diǎn))
AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
獲取指定子節(jié)點(diǎn)(控件節(jié)點(diǎn))
//通過文本找到對(duì)應(yīng)的節(jié)點(diǎn)集合
List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText(text);
//通過控件ID找到對(duì)應(yīng)的節(jié)點(diǎn)集合,如com.tencent.mm:id/gd
List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByViewId(clickId);
AccessibilityService 獲取View的Id
獲取id的一些方法
●?layoutInspector
●?Uiautomator viewer
隨緣,各種原因,成功率很低。截圖失敗或者超時(shí)
●?hierarchy view
相對(duì)可靠。
可以在命令行工具中,執(zhí)行如下命令 得到相關(guān)文件
adb shell uiautomator dump
執(zhí)行成功 系統(tǒng)會(huì)返回 UI hierchary dumped to: /mnt/sdcard/window_dump.xml
當(dāng)然 這個(gè)文件地址也是可以更改的。 adb shell uiautomator dump [file]
七、模擬節(jié)點(diǎn)點(diǎn)擊
當(dāng)我們獲取了節(jié)點(diǎn)信息之后,對(duì)控件節(jié)點(diǎn)進(jìn)行模擬點(diǎn)擊、長按等操作,AccessibilityNodeInfo類提供了performAction()方法讓我們執(zhí)行模擬操作,具體操作可看官方文檔介紹,這里列舉常用的操作
//模擬點(diǎn)擊
accessibilityNodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
//模擬長按
accessibilityNodeInfo.performAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
//模擬獲取焦點(diǎn)
accessibilityNodeInfo.performAction(AccessibilityNodeInfo.ACTION_FOCUS);
//模擬粘貼
accessibilityNodeInfo.performAction(AccessibilityNodeInfo.ACTION_PASTE);
八、示例及代碼——自動(dòng)安裝app
接下來用例子說明下怎么使用無障礙服務(wù)
平時(shí)我們點(diǎn)擊安裝包進(jìn)行安裝的時(shí)候,會(huì)彈出界面讓我們確認(rèn)。一般來說我們就是點(diǎn)擊下一步,安裝,然后安裝完成后點(diǎn)擊打開或者完成。
如果用無障礙服務(wù)的話,是可以在點(diǎn)擊安裝包的時(shí)候直接自動(dòng)幫忙點(diǎn)了下一步,安裝之類的。
具體做法就是在 onAccessibilityEvent()中,判斷是否安裝程序進(jìn)程,然后進(jìn)行下相應(yīng)的點(diǎn)擊動(dòng)作,代碼如右圖所示 這邊用的手機(jī)是小米,所以是小米的packgeInstaller的判斷。如果是的話,就開始執(zhí)行找控件點(diǎn)擊的邏輯
小作業(yè)試驗(yàn):完成自動(dòng)回復(fù)的功能
首先我們知道一般軟件,如微信接收信息時(shí)是有通知的,顯示在通知欄中,所以我們的事件監(jiān)聽需要監(jiān)聽通知欄變化
通知的點(diǎn)擊打開是可以進(jìn)入到相應(yīng)的聊天頁面的。
如果想在聊天頁面實(shí)現(xiàn)回復(fù),就是在輸入框中輸入文字,然后點(diǎn)擊發(fā)送就可以,剩下的回調(diào)由微信的程序完成
可以簡單實(shí)現(xiàn)下,如果真的想通過無障礙服務(wù)實(shí)現(xiàn)自動(dòng)回復(fù),邏輯會(huì)嚴(yán)謹(jǐn)很多,首先判斷依據(jù)需要跳轉(zhuǎn)聊天頁的依據(jù)就不會(huì)這么簡單。然后是場景也有多種區(qū)分,如后臺(tái),息屏,跳轉(zhuǎn)失敗,代理清除通知等
回復(fù)的邏輯也會(huì)復(fù)雜很多,接入半自動(dòng)回復(fù)機(jī)器人接口不用說,還有查找輸入框控件失敗,群聊,多條信息,是否需要執(zhí)行自動(dòng)回復(fù)的邏輯判斷等
怎么防(防止無障礙服務(wù)外掛的一些做法)
通過原理和源碼查看,我們知道了無障礙服務(wù)是內(nèi)嵌到整個(gè)android的view層類里的,但是還是有缺陷的
如通過Onclick實(shí)現(xiàn)的點(diǎn)擊事件,可以捕捉到,但通過onTouchEvent實(shí)現(xiàn)的的點(diǎn)擊事件,捕捉不到
如有獲取節(jié)點(diǎn)文字的方法,但沒有提供獲取圖片數(shù)據(jù)的方法,導(dǎo)致外掛搶票實(shí)現(xiàn)驗(yàn)證碼輸入不太可能。
那么我們可以怎么防御呢,有以下一些做法
AccessibilityManager有提供獲取安裝了的無障礙服務(wù)和開啟的無障礙的服務(wù)的方法。從而讓我們可以知道用戶有哪些無障礙服務(wù),及運(yùn)行的服務(wù)有哪些。幫助我們確定自動(dòng)點(diǎn)擊的外掛來源,從而在打開外掛后有一個(gè)警告
了解AccessibilityServices源碼之后,我們知道其內(nèi)部核心原理就是調(diào)用TextView的findViewsWithText方法。只要復(fù)寫這個(gè)方法,就可以屏蔽文案檢查
AccessibilityServices執(zhí)行點(diǎn)擊事件最終在調(diào)用View的mOnClickListener。可以利用onTouch代替onClick屏蔽服務(wù)調(diào)用點(diǎn)擊的動(dòng)作
某些微信紅包插件會(huì)監(jiān)控Notification的彈出,那么我們是否可以隨意發(fā)送這樣的Event出來,從而混干擾外掛插件的運(yùn)行邏輯。這種做法大部分情況比較雞肋,也看外掛同學(xué)的邏輯嚴(yán)不嚴(yán)謹(jǐn)
這個(gè)其實(shí)是繼第一種方式后的操作,在收集好已知外掛的信息后,設(shè)立黑名單,遍歷系統(tǒng)內(nèi)部所有已安裝的app,鑒別package name 和app name。執(zhí)行相應(yīng)處理
參考資料
?官方介紹
https://developer.android.com/guide/topics/ui/accessibility/services
?android 輔助功能google官方示例
https://github.com/googlesamples/android-BasicAccessibility
?WechatHelper 微信助手
https://github.com/coder-pig/WechatHelper
?AccessibilityService分析與防御
https://lizhaoxuan.github.io/2018/01/27/AccessibilityService%E5%88%86%E6%9E%90%E4%B8%8E%E9%98%B2%E5%BE%A1/