使用AccessibilityService實現微信自動搶紅包 問題在Z9max手機上無效 估計被修改過rom了
換了部手機還是沒效果
@Override public void onAccessibilityEvent(AccessibilityEvent event) { //不會被回調官方文檔介紹
http://www.android-doc.com/guide/topics/ui/accessibility/apps.html#focus-nav
http://www.android-doc.com/guide/topics/ui/accessibility/services.html#methods
http://www.android-doc.com/guide/topics/ui/accessibility/apps.html#focus-nav
最近要實現微信自動搶紅包的功能,使用AccessibilityService來開發,這裏主要寫一下邏輯以及注意點。
注意點
1、搜索關鍵字
我們實現某個功能比如點擊等需要找到對應的對象然後模擬點擊事件,所以首先就是怎麼樣找到對象,下面說三種方式:
(1)findAccessibilityNodeInfosByText通過文字來實現查找,返回的是List<AccessibilityNodeInfo>,所以需要通過for循環來具體判斷需要的關鍵字的對象
(2)findAccessibilityNodeInfosByViewId通過控件的id來查詢,返回的是List<AccessibilityNodeInfo>,雖然也是返回List但是一般只有一個,查找的準確性高,不過需要系統的版本API>=18
(3)搭配findAccessibilityNodeInfosByText來查找,在微信中使用uiautomatorviewer查看佈局,發現不同的手機相同的控件id是不一樣的,比如我們需要查詢獲取紅包的數量時,需要先查找'元',然後獲取其父控件,然後查找金額所在的位置,這個是不變的。
2、對於返回功能
一般我們領取紅包後進入紅包詳情界面,這時我們要返回到聊天界面使用uiautomatorviewer查看返回箭頭,查看其屬性他的clickable=false這樣的話我們就無法通過
accessibilityNodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);來實現點擊事件來實現返回的功能,不過查看AccessibilityService源碼裏面有對應的全局事件,下面說兩種實現返回功能的方法
(1)查找界面上對應的返回按鈕然後通過AccessibilityNodeInfo的
performAction(AccessibilityNodeInfo.ACTION_CLICK)實現點擊,不過在操作之前先判斷一下isCheckable()如果是false則無法實現其功能
(2)使用AccessibilityService的performGlobalAction的方法,介紹如下:
[java] view plain copy print?
/**
* Performs a global action. Such an action can be performed
* at any moment regardless of the current application or user
* location in that application. For example going back, going
* home, opening recents, etc.
*
* @param action The action to perform.
* @return Whether the action was successfully performed.
*
* @see #GLOBAL_ACTION_BACK
* @see #GLOBAL_ACTION_HOME
* @see #GLOBAL_ACTION_NOTIFICATIONS
* @see #GLOBAL_ACTION_RECENTS
*/
public final boolean performGlobalAction(int action) {
IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
if (connection != null) {
try {
return connection.performGlobalAction(action);
} catch (RemoteException re) {
Log.w(LOG_TAG, "Error while calling performGlobalAction", re);
}
}
return false;
}
所以要實現返回功能只需要調用performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);,當然如果想實現Home,通知,最近的應用換成對應的action就可以了
3、涉及微信界面的類
[java] view plain copy print?
/**
* 微信的包名
*/
static final String WECHAT_PACKAGENAME = "com.tencent.mm";
/**
* 拆紅包類
*/
static final String WECHAT_RECEIVER_CALSS = "com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI";
/**
* 紅包詳情類
*/
static final String WECHAT_DETAIL = "com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI";
/**
* 微信主界面或者是聊天界面
*/
static final String WECHAT_LAUNCHER = "com.tencent.mm.ui.LauncherUI";
這裏需要注意的是WECHAT_LAUNCHER,微信主界面以及聊天界面應該採用的FragmentActivity+Fragment這樣導致如果用戶進入到微信主界面則會調用AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED,導致再次進入微信聊天界面不會再調用AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED,而會調用AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,而AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED只要內容改變後都會調用,所以一般是使用AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED來作爲監測事件的,所以解決這個問題的方式就是加入判斷條件:
(1)觸發AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED這個事件搜索列表界面是否有"領取紅包"字樣,如果沒有則設置一個變量
(2)如果沒有觸發AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED而觸發了AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,則去判斷之前設置的變量綜合來判斷
4、增加紅包獲取量避免重複金額
在聊天界面的紅包雖然會有"領取紅包"的字樣,但是其實是已經拆過的,判斷的標識就是是否有"拆紅包",如果有拆紅包則計算對應詳情中的金額。
5、如何循環查詢所有的子控件
[java] view plain copy print?
/**
* @param info 當前節點
* @param matchFlag 需要匹配的文字
* @param type 操作的類型
*/
public void recycle(AccessibilityNodeInfo info, String matchFlag, int type) {
if (info != null) {
if (info.getChildCount() == 0) {
CharSequence desrc = info.getContentDescription();
switch (type) {
case ENVELOPE_RETURN://返回
if (desrc != null && matchFlag.equals(info.getContentDescription().toString().trim())) {
if (info.isCheckable()) {
info.performAction(AccessibilityNodeInfo.ACTION_CLICK);
} else {
performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
}
}
break;
}
} else {
int size = info.getChildCount();
for (int i = 0; i < size; i++) {
AccessibilityNodeInfo childInfo = info.getChild(i);
if (childInfo != null) {
Log.e(TAG, "index: " + i + " info" + childInfo.getClassName() + " : " + childInfo.getContentDescription()+" : "+info.getText());
recycle(childInfo, matchFlag, type);
}
}
}
}
}
網上關於搶紅包的源碼比較多,由於其他原因我們這裏的不會公佈,可以根據網上的源碼進行修改,能夠實現功能:
(1)截取通知欄中有[微信紅包]字樣的通知,然後跳到微信紅包界面
(2)進入羣聊界面會自動查詢當前界面所有"領取紅包",然後循環點擊查找增加紅包的概率
(3)準確的保存領取的紅包金額和日期
http://v.qq.com/page/e/w/u/e0180uzkswu.html
http://www.android-doc.com/guide/topics/ui/accessibility/services.html#methods