摘要
在Android程序的開發(fā)維護(hù)過程中宋光,我們可能經(jīng)常需要知道自己所看到的界面處于哪一個Activity中勒极,相信大部分程序員的做法是“在基類里打Log”,很傳統(tǒng)沒毛病o(╯□╰)o....
前幾天茂浮,在應(yīng)用寶的應(yīng)用商店內(nèi)發(fā)現(xiàn)了一個很有意思的APP - 當(dāng)前Activity菌羽,可以顯示出當(dāng)前界面上顯示的 應(yīng)用包名 和 Activity類名。然后壮不,一直很好奇是如何實現(xiàn)的汗盘,最近抽時間研究了一下。
下面是研究成果:
開源項目CurrentActivity地址:
https://github.com/sinawangnan7/CurrentActivity
歡迎Star...(??????)??
正文
本文主要講述兩部分內(nèi)容:
1忆畅、CurrentActivity的使用場景
2衡未、CurrentActivity的實現(xiàn)思路
CurrentActivity的使用場景
1尸执、定位自己APP的頁面家凯,獲取類名稱
這應(yīng)該是我們經(jīng)常碰到的問題,測試人員經(jīng)常拿著出Bug的頁面詢問“開發(fā)人員”如失,如果這個頁面還不是“此開發(fā)人員”寫的绊诲,估計查起來就費勁了。此工具能幫助開發(fā)人員提高查找效率褪贵。
2掂之、分析其他APP命名及功能
可以查看其他APP的頁面路徑和命名抗俄,給自己開發(fā)做個參考(下面以微信和支付寶為例)。
(1) 微信
觀察上圖世舰,可以看到 微信 的Activity在命名時是以 "UI" 為后綴進(jìn)行標(biāo)識的动雹,類在分包時也放在了ui包目錄下。另外跟压,還有一個比較有意思的發(fā)現(xiàn)胰蝠,微信的“主界面”和“聊天界面”用的是同一個Activity。
(2) 支付寶
筆者公司開發(fā)的APP和支付寶APP類似震蒋,也是做 互聯(lián)網(wǎng)金融 的茸塞。所以,產(chǎn)品經(jīng)理在設(shè)計功能和流程時經(jīng)常會“參考”支付寶是如何實現(xiàn)的查剖,比如需要確定 哪些頁面用原生做钾虐,哪些需要用H5來做。但是笋庄,支付寶的原生和H5在使用體驗上很難感知出來(這里支付寶做得很贊)效扫,這時這個工具就可以派上用場了,支付寶展示H5的頁面用的是H5Activity直砂。
最近荡短,筆者需要做一個類似支付寶的支付鍵盤,一開始以為是純Dialog實現(xiàn)的哆键,最后發(fā)現(xiàn)實際上用Activity包了一層掘托。這其實也并不意外,第三方APP在吊起“支付寶支付”時籍嘹,用戶如果安裝了支付寶闪盔,吊起的也是這個FlyBirdWindowActivity。
CurrentActivity的實現(xiàn)思路
這個監(jiān)視活動的窗口是如何實現(xiàn)的辱士?
本文只講述 思路和核心代碼仪糖,完整代碼請參看GitHub開源項目:
CurrentActivity
實現(xiàn)這個監(jiān)視窗口需要解決兩個問題:
1、如何向界面頂部添加一個顯示窗口军浆?
2返敬、如何監(jiān)聽?wèi)?yīng)用切換、Activity切換头岔?
第一個問題很簡單塔拳,通過WindowManager添加一個TextView即可, 但是需要注意下懸浮窗權(quán)限問題,這個問題很多博客都給出了解決方案峡竣,筆者簡單說下靠抑,就不在贅述了。
筆者做了一個簡單的窗口視圖管理器:
創(chuàng)建窗口的核心代碼如下:
/**
* 添加窗口視圖
*/
private void addView() {
// 創(chuàng)建布局參數(shù)
mParams = new WindowManager.LayoutParams();
// 獲取窗口管理器
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
// 設(shè)置類型
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Android O 以上适掰,使用TYPE_APPLICATION_OVERLAY彈窗類型
mParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
// Android O 以下颂碧,使用TYPE_SYSTEM_ALERT彈窗類型
mParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
}
// 設(shè)置標(biāo)簽(FLAG_NOT_FOCUSABLE表示窗口不會獲取焦點荠列;FLAG_NOT_TOUCHABLE表示窗口不會接收Touch事件,即將Touch事件向下層分發(fā))
mParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
// 設(shè)置位圖模式 (PixelFormat.RGBA_8888可以使背景透明载城。不設(shè)置默認(rèn)PixelFormat.OPAQUE肌似,即不透明)
mParams.format = PixelFormat.RGBA_8888;
// 設(shè)置分布位置(距左對齊 + 距頂對齊)
mParams.gravity = Gravity.LEFT | Gravity.TOP;
// 設(shè)置布局寬/高為自適應(yīng)
mParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
mParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
// 添加TextView
mWindowManager.addView(mTextView, mParams);
// 記錄視圖已被添加、顯示
isAdded = true;
isShow = true;
}
提醒:
1.注意懸浮窗權(quán)限問題诉瓦,可參考 AndroidManifest.xml 中的權(quán)限聲明锈嫩。
2.適配Android 8.0,請使用TYPE_APPLICATION_OVERLAY彈窗類型垦搬。
第二個問題:如何監(jiān)聽?wèi)?yīng)用切換呼寸、Activity切換?筆者查了很長時間猴贰,最后發(fā)現(xiàn)了一個叫 AccessibilityService(輔助服務(wù))的東西对雪,了解完 AccessibilityService 感覺好像發(fā)現(xiàn)了新大陸,其實這個“輔助服務(wù)”使用最為出名的是“微信自動搶紅包插件”米绕。但是瑟捣,今天筆者只是簡單介紹下AccessibilityService(輔助服務(wù))的入門使用 - 監(jiān)聽窗口改變。
輔助服務(wù)創(chuàng)建步驟及使用流程
1.創(chuàng)建自定義AccessibilityService栅干,核心代碼如下:
/**
* @ClassName: MAccessibilityService
* @Description: 輔助服務(wù)
* @Author wangnan7
* @Date: 2018/4/1
*/
public class MAccessibilityService extends AccessibilityService {
......
/**
* 服務(wù)連接完成
*/
@Override
protected void onServiceConnected() {
// 添加窗口
mWindowViewContainer = WindowViewContainer.getInstance(this);
mWindowViewContainer.addWindowView();
......
}
......
/**
* 接收輔助服務(wù)事件
*/
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if (event == null) {
return;
}
switch (event.getEventType()) {
case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: // 窗口狀態(tài)改變
if (event.getPackageName() != null && event.getClassName() != null) {
// 更新窗口視圖
mWindowViewContainer.updateWindowView(event.getPackageName() + "\n" + event.getClassName());
}
break;
default:
break;
}
}
/**
* 服務(wù)中斷
*/
@Override
public void onInterrupt() {
}
/**
* 服務(wù)退出
*/
@Override
public void onDestroy() {
// 移除窗口迈套,銷毀視圖容器
mWindowViewContainer.destory();
......
}
}
整個功能的核心都在onAccessibilityEvent(AccessibilityEvent event)
這個方法中,如果開啟輔助服務(wù)碱鳞,只要服務(wù)不死桑李,進(jìn)程不掛,當(dāng)前窗口的每次改變我們都能監(jiān)聽到窿给。(如果你查看了完整代碼贵白,會看到筆者添加了一個Notification,把輔助服務(wù)提升為了前臺服務(wù)崩泡,這么做只是簡單的做下服務(wù)苯模活)
2.在AndroidManifest.xml文件中聲明該服務(wù), 核心代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.wangnan.currentactivity">
......
<application
......
<!-- 輔助服務(wù) -->
<service
android:name=".service.MAccessibilityService"
android:label="當(dāng)前Activity(輔助工具)"
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>
......
</application>
</manifest>
完整代碼:AndroidManifest.xml
詳細(xì)說下輔助服務(wù)的配置聲明:
1.android:name 用于指定服務(wù)名稱,前面加“.”表示書寫時省略掉了包名角撞。
2.android:lable 用于指定外部顯示的服務(wù)名稱呛伴。
3.android:permission 表明服務(wù)向系統(tǒng)請求那些權(quán)限
4.intent-filter 的 action 表明傳遞給該服務(wù)的哪些Intent需要過濾出來進(jìn)行處理
可能會有人疑問為什么要配置3和4,其實這是源碼文檔要求的谒所,是必須配置的热康,如下圖所示:
5.meta-data 元數(shù)據(jù),用于配置輔助服務(wù)的詳情信息
其實這一項在manifest文件中是可配可不配的百炬,只是文檔支持在manifest文件里進(jìn)行配置褐隆,如果不在這配置就需要到輔助服務(wù)的Java代碼里去配置了污它,源碼解釋如下:
接下來剖踊,看下筆者的元數(shù)據(jù)配置文件(android:resource="@xml/accessibility")
完整代碼:accessibility.xml
元數(shù)據(jù)配置文件說明庶弃,如下圖所示:
3.開啟輔助服務(wù)
開啟輔助服務(wù)不能用startService()
這種方式打開,因為使用輔助服務(wù)是有一定風(fēng)險的德澈,需要用戶主動授權(quán)(同意開啟)歇攻。
輔助服務(wù)打開流程:
安裝APP(含有輔助服務(wù)) -> 輔助功能 -> 服務(wù)(點擊需要開啟的服務(wù)) -> 開啟
以筆者的手機(jī)(360N5)和 CurrentActivity 為例,打開流程如下圖所示:
4.關(guān)閉輔助服務(wù)
輔助功能 -> 服務(wù)(點擊需要關(guān)閉的服務(wù)) -> 關(guān)閉
以筆者的手機(jī)(360N5)和 CurrentActivity 為例梆造,關(guān)閉流程如下圖所示:
CurrentActivity的詳細(xì)使用方法和源碼請參看Github:
其他
1.AccessibilityService位于在系統(tǒng)設(shè)置里缴守,有些手機(jī)翻譯成“輔助服務(wù)”,有些手機(jī)翻譯成“無障礙”镇辉。
2.AccessibilityService被用戶授權(quán)開啟后并不是一直甭潘耄活的,也有可能被系統(tǒng)銷毀忽肛。
題外話
輔助服務(wù)其實還有很多使用場景村砂。比如,從上圖筆者手機(jī)應(yīng)用列表里看到的云服務(wù)屹逛、360手機(jī)助手(下載自動安裝)础废、京東金融(手環(huán)社交軟件提醒)。另外罕模,還有我們經(jīng)常聽說的微信自動搶紅包评腺、微信自動回復(fù)...各位如果有興趣可以研究下。Good Luck~
最后的福利(2018年4月16號添加):
寫完這篇博客后淑掌,筆者又研究了下微信搶紅包原理蒿讥,寫了一個【微信自動搶紅包】插件,原理也是使用輔助服務(wù)抛腕,開源項目地址:
https://github.com/sinawangnan7/WXGiftMoney
歡迎Star...(??????)??