AccessibilityService從入門到出軌html
AccessibilityService根據官方的介紹,是指開發者經過增長相似contentDescription的屬性,從而在不修改代碼的狀況下,讓殘障人士可以得到使用體驗的優化,你們能夠打開AccessibilityService來試一下,點擊區域,能夠有語音或者觸摸的提示,幫助殘障人士使用App。node
固然,如今AccessibilityService已經基本偏離了它設計的初衷,至少在國內是這樣,愈來愈多的App借用AccessibilityService來實現了一些其它功能,甚至是灰色產品。android
使用入門git
老規矩,官網鎮樓
https://developer.android.com...
https://developer.android.com...程序員
要使用AccessibilityService實際上很是簡單,通常來講,只須要如下三步便可。github
繼承系統AccessibilityServiceshell
public class MyAccessibility extends AccessibilityService {數據庫
private static final String TAG = "xys"; @Override public void onAccessibilityEvent(AccessibilityEvent event) { Log.d(TAG, "onAccessibilityEvent: " + event.toString()); } @Override public void onInterrupt() { }
}
其中有兩個必須實現的方法:onAccessibilityEvent和onInterrupt。瀏覽器
在onAccessibilityEvent中,咱們能夠接收所監聽的事件。不熟悉這些事件的話,只須要使用toString把這些信息打出來,本身多看幾個Log,就大概可以瞭解了。安全
新建配置文件
在資源目錄res下新建xml文件夾,新建accessibility.xml文件,寫入:
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask" android:accessibilityFeedbackType="feedbackSpoken" android:canRetrieveWindowContent="true" android:notificationTimeout="1000"/>
裏面有一些比較簡單的配置。
其中 description 爲 用戶容許應用的輔助功能的說明字符串,這裏沒有指定所要輔助的應用packageNames,當沒有指定時,默認輔助全部的應用,建議你們在使用時,指定須要監聽的包名(你能夠經過|來進行分隔),而不是全部的包名。typeAllMask是設置響應事件的類型,feedbackGeneric是設置回饋給用戶的方式,有語音播出和振動。
註冊
在AndroidMainifest中註冊:
<service
android:name=".MyAccessibility" 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/accessibility"/>
</service>
完成以上步驟後,一個AccessibilityService就可使用了,你要知道的是,AccessibilityService具備很高的系統權限,因此,系統不會讓App直接設置是否啓用,須要用戶進入設置-輔助功能中去手動啓用,這樣在必定程度上,保護了用戶數據的安全。
如何理解AccessibilityService
不少人可能對AccessibilityService瞭解的不是很深刻,因此認爲AccessibilityService是在調用一些系統服務來自動執行一些操做,實際上,這個理解不能算錯,固然也不全對,我以爲你能夠把AccessibilityService理解爲——『按鍵精靈』。相信不少開發者都玩過PC上的這款軟件,他的做用,就是將你一次操做的整個記錄,錄製下來,而後就能夠根據這個記錄,重複的執行這些操做,例如:先點擊某個輸入框,再輸入XXXX,再輸入驗證碼,最後點擊某按鈕,這些操做若是須要重複執行,那麼顯然是一套機械的步驟,那麼經過按鍵精靈,記錄下這些操做後,直接經過腳本就能夠完成這些操做。其實AccessibilityService跟這個是同樣的,咱們記錄的,實際上就是咱們的操做步驟,或者稱之爲『腳本』,那麼系統在監控整個手機的各類AccessibilityService事件時,就會根據咱們的邏輯來判斷該使用哪個腳本。
所以,咱們徹底能夠抽象出一個基類AccessibilityService,並抽象出一些腳本的事件,例如,根據Text查找對應的View、點擊某個View、滑動、返回等等,因此,我在這裏封裝了一個BaseAccessibilityService,這裏就不貼具體的代碼了,你們能夠參考個人Github:
https://github.com/xuyisheng/...
入門
不知道從何時開始,AccessibilityService忽然從一個殘障人士使用的輔助服務,一躍變成了各類App的黑科技,利用AccessibilityService來作的事情,也愈來愈偏離了AccessibilityService設計的初衷,各類安全問題也隨之暴露出來,Google的理想是好的,願天下都是安分守己的程序員。
免Root自動安裝
這個也許是能考證的最先利用AccessibilityService的使用場景了,最先在一些應用市場中出現,例如用戶一次下載了不少App,那麼每一個App下載完畢後都會彈出安裝界面,並且須要用戶手動去處理,確實體驗不太好,因此後來就出現了利用Root權限來靜默安裝App的功能,但如今普通用戶Root的需求愈來愈少,因此,AccessibilityService來實現免Root自動安裝的黑科技,才走上了桌面。
那麼按照咱們前面的思路,要實現自動安裝,實際上就是把手動安裝的步驟腳本化。通常來講,咱們要安裝一個App,會經過如下幾個步驟:
調用系統的安裝Intent
在安裝界面上尋找『安裝』、『下一步』這些操做按鈕
點擊『安裝』、『下一步』按鈕
完成安裝
那麼這些流程化的操做,咱們就徹底能夠經過腳原本實現,下面就是一些簡單的代碼實現。
調用系統安裝Intent:
public void autoInstall(View view) {
String apkPath = Environment.getExternalStorageDirectory() + "/test.apk"; Uri uri = Uri.fromFile(new File(apkPath)); Intent localIntent = new Intent(Intent.ACTION_VIEW); localIntent.setDataAndType(uri, "application/vnd.android.package-archive"); startActivity(localIntent);
}
監控安裝界面,並根據邏輯處理點擊:
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
super.onAccessibilityEvent(event); if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED && event.getPackageName().equals("com.android.packageinstaller")) { AccessibilityNodeInfo nodeInfo = findViewByText("安裝", true); if (nodeInfo != null) { performViewClick(nodeInfo); } }
}
代碼寫完才發現,看似很牛逼的自動安裝,其實不過十幾行代碼。惟一複雜的,就是抽象化這些流程了。
搶紅包
搶紅包應該是AccessibilityService火起來的最大因素。網上藉助AccessibilityService來實現的搶紅包插件也是數不勝數,又是一個看上去很牛逼的功能。那麼咱們再來分析下,你是怎麼搶紅包的。
加入你如今在桌面,怎麼知道有紅包了呢?哦,看通知欄,出現了『微信紅包』這幾個關鍵字,而後,你點擊這條通知進去,點擊紅包的那條消息,而後再點擊拆紅包的按鈕,返回,回到桌面。
這樣一看,搶紅包徹底是一個體力活啊,若是有個機器人能幫助我完成上面的動做,根本不用我搶啊,對的,這個機器人就是AccessibilityService,咱們一樣把搶紅包流程化。
獲取通知欄通知事件
點擊通知欄消息
找到紅包消息
點擊
點擊拆紅包
返回
這每一個步驟,也都不難啊,咱們的工具類中,全部的方法都實現了,惟一要作的,就是寫幾個ifelse把邏輯拼起來就好了,具體代碼就不貼了,畢竟是微信嚴打的一件事,你們適可而止就行了。
固然,這個Demo一樣能夠作的更完善一點,例如,增長WakeLock和Keyguard,實如今鎖屏狀況下的自動搶紅包等功能。
微信自動回覆
在瞭解了微信搶紅包的方式以後,再看看微信自動回覆,是否是就更是小菜一碟了?咱們只要把搶紅包的流程稍微改一下,就完成了整個功能的實現,不相信?
獲取通知欄通知事件
點擊通知欄消息
找到紅包消息 ——> 輸入自動回覆的消息
點擊 ——> 點擊發送
點擊拆紅包 ——> 不須要了
返回
是否是很是簡單?惟一一個有價值的代碼以下:
private void notifyWechat(AccessibilityEvent event) {
if (event.getParcelableData() != null && event.getParcelableData() instanceof Notification) { Notification notification = (Notification) event.getParcelableData(); String content = notification.tickerText.toString(); String[] msg = content.split(":"); name = msg[0].trim(); text = msg[1].trim(); PendingIntent pendingIntent = notification.contentIntent; try { pendingIntent.send(); } catch (PendingIntent.CanceledException e) { e.printStackTrace(); } }
}
一個簡單的Trick而已,借用notification.contentIntent來喚起Notification對應的App。
實際上,咱們能作的事情還有不少,當咱們拿到對應的聊天信息時,能夠經過聊天對象的篩選,來實現對『特別對象的監控』,例如你離開的時候,能夠設置給你的老婆自動回覆『親愛的我在忙呢,等等哈』,而對其它人自動回覆『滾,LZ忙』。再例如,能夠對聊天信息進行分詞、識別,從而實現對內容的精準回覆,固然,這裏還須要使用到一些第三方的語言分析軟解,這裏就不詳解了,總之,沒有想不到。
檢查微信好友
那麼再好比去年比較火的一個方法,經過拉好友進羣組來檢查是否還有好友關係。PC、Chrome上已經有不少軟件來作這個檢查了,其核心原理,都是經過拉羣組的方式來作。那麼在手機上,一樣能夠經過這種方式來實現,若是如今你還不知道該怎麼作,那麼後面的文章就沒有看的必要了……
進程清理
你們應該都用過馮老師的『綠色守護』,這個App的最基本無Root功能,就是經過在應用管理界面『結束進程』的方式來中止一個後臺運行的App,你們都知道天朝的App,基本都是全家桶,因此這種方式對釋放系統資源確實仍是有必定的幫助的,那麼咱們就來看看簡單的實現。
核心原理很是簡單,在應用詳情頁面,經過中止服務來禁止App服務。OK,那麼咱們要作的,實際上,就是下面的流程:
經過Intent打開對應App的管理詳情信息頁面
點擊中止運行
返回,處理下一個
流程要比搶紅包什麼的簡單多了,下面列出2個關鍵代碼,你們應用詳情界面:
public void cleanProcess(View view) {
for (String mPackage : mPackages) { Intent intent = new Intent(); intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", mPackage, null); intent.setData(uri); startActivity(intent); }
}
監控詳情頁面,進行中止操做:
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED && event.getPackageName().equals("com.android.settings")) { CharSequence className = event.getClassName(); if (className.equals("com.android.settings.applications.InstalledAppDetailsTop")) { AccessibilityNodeInfo info = findViewByText("強行中止"); if (info.isEnabled()) { performViewClick(info); } else { performBackClick(); } } if (className.equals("android.app.AlertDialog")) { clickTextViewByText("肯定"); performBackClick(); } }
}
這個App惟一的難點,應該就剩下怎麼把UI作的好看一點了。
另外,還有一個兼容性的問題,你們都懂的,國內各類第三方的ROM廠家,常常會修改一些系統的Activity,甚至不一樣系統版本同一個功能的Activity都有可能不同,因此,使用AccessibilityService的一個比較大的麻煩就是兼容性的處理,須要使用dumpsys和uiautomator這些工具來進行詳細的分析,這些工具的使用以及分析方法,在個人新書《Android羣英傳:神兵利器》中都有詳細的講解,想深刻了解的開發者能夠參考下。
判斷應用當前狀態
藉助AccessibilityService一樣能夠作一些比較有用的事情,例如監控App當前的狀態,例如前臺、後臺的切換,經過TYPE_WINDOW_STATE_CHANGED便可進行判斷,特別是在5.0以上,原先的getRunningTasks這個方法被升級到系統權限。
固然,AccessibilityService或多或少會存在一些性能問題,因此如今並不推薦使用這種方式來監控應用狀態,更多的是經過activitylifecyclecallbacks來實現對App狀態的跟蹤與監控。
出軌
其實一旦咱們瞭解了AccessibilityService的使用原理,那麼就很難作到不逾矩,畢竟這裏的誘惑太大了,當我寫到這裏時,甚至有種毛骨悚然的感受,因此這裏申明:
本文全部內容僅供學習、技術交流,由此產生的各類問題,均與本人無關。
防卸載
據我所知,已經有些App或者稱之爲惡意軟件實現了這樣的功能,這個功能難嗎,不難,估計都不超過20行代碼,但確實很噁心,特別是對一些普通、小白用戶,壓根都不知道AccessibilityService是什麼,莫名其妙你讓我啓用,寫的可能比較好看,什麼幫助你清理系統,優化資源,但實際上,在後面作一些見不得人的事情。
咱們來分析下如何實現,當用戶想要卸載你的App的時候,通常會來到設置界面,找到你的App而後選擇卸載,那麼若是咱們監控這個頁面,若是發現是本身的App,就直接退出,這樣不就沒法卸載了嗎?是的,代碼以下,沒幾行代碼:
private String mDefenseName = "微信";
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
super.onAccessibilityEvent(event); if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED && event.getPackageName().equals("com.android.settings")) { CharSequence className = event.getClassName(); if (className.equals("com.android.settings.SubSettings")) { AccessibilityNodeInfo nodeInfo = findViewByText("應用程序信息"); if (nodeInfo != null && findViewByText(mDefenseName) != null) { performBackClick(); } } }
}
那麼有人要說了,若是是用的一些第三方ROM,直接在桌面就能卸載呢?一樣的,只不過會稍微麻煩點,須要判斷的東西更多了,要處理的兼容性更復雜了而已。
這裏不得不說,雖然國內各類第三方ROM百花齊放、肆意妄爲,但這也給AccessibilityService形成了很大的兼容性處理難題,因此對一些惡意的使用AccessibilityService的App也造成了很大的限制。
瀏覽器劫持
實際上並不侷限於瀏覽器,各類App都能被劫持,由於AccessibilityService監控的是全局App,良心點的可能會指定包名進行監控。因此,咱們能夠監控任意一個App,例如瀏覽器,一旦打開,咱們就輸入指定的網址,或者是一打開一些App,就輸入一些查詢內容,這裏我以鄙司的滬江網校爲例,進入後直接進行搜索。
算了代碼仍是不貼了,徹底都是Copy前面的內容。
監控密碼框
呵呵呵,這個你還真是想多了,系統再天真也不會把這個權限開放給你,全部的設置爲password類型的EditText都是沒法被監控的,系統還算有點良心。
這裏我只列舉了一些很是簡單的Hack方式,但實際上,還有不少,例如經過拉取指定網站的內容後自動安裝App並模擬點擊等,固然,AccessibilityService也能夠用在自動化測試中,這徹底就是一把雙刃劍,是利是弊,徹底取決於使用他的人。
跳過用戶受權
通常來講,AccessibilityService是須要用戶手動操做受權才能夠執行的,可是,若是是在Root的狀況下,或者是在ADB鏈接PC的狀況下,甚至都不用用戶受權,就能夠完成AccessibilityService的受權操做。
Root的狀況就不說了,經過修改Setting的數據庫就能夠更改這個設置了,固然,有Root的狀況下,就根本不須要AccessibilityService了。
在沒有Root的狀況下,若是PC經過ADB發出指令,一樣是能夠自動完成受權的,這個能夠參考360的一篇文章:
http://www.freebuf.com/articl...
我這裏就很少說了,你們看看就懂了,並無太多的技術含量,應該算是系統的一個小的漏洞。
AccessibilityService通常分析步驟
前面咱們分析了那麼多AccessibilityService好的很差的使用方法,實際上,總結下就這麼幾步。
分析操做的流程,拆解成單步可實現的過程
經過UIAutomator和adb shell dumpsys來查看對應的UI控件ID、文本或者是具體的Activity
經過邏輯組合進行代碼編寫
調試、兼容性處理
經過上面的這些方式,基本就能夠實現一些固定流程的操做自動化了。關於AccessibilityService的工具類,我放到了Github上,雖然功能已經比較全了,但尚未通過不少的兼容性測試,同時,礙於時間和精力的關係,給出的Demo示例也很少,但願你們能夠多提PR,共同完善。
https://github.com/xuyisheng/...
歡迎你們關注個人微信公衆號:
Android羣英傳