發布應用市場的 Android 平臺搶紅包工具《紅包精靈》開源啦
關鍵Service代碼:
實現原理
1.1 狀態說明
private static final String WECHAT_OPEN_CH = "拆紅包";
private static final String WECHAT_VIEW_SELF_CH = "查看紅包";
private static final String WECHAT_VIEW_OTHERS_CH = "領取紅包";
private static final String WECHAT_NOTIFICATION_TIP = "[微信紅包]";
1.2 根據階段選擇不同的入口
在每次窗體狀態發生變化后,根據當前所在的階段選擇入口。
/* 如果戳開但還未領取 */
if (mNeedUnpack && (mUnpackNodeList != null)) {
Log.d(TAG, "事件----> start performAction 戳開但還未領取");
int size = mUnpackNodeList.size();
if (size > 0) {
AccessibilityNodeInfo cellNode = mUnpackNodeList.get(size - 1);
cellNode.performAction(AccessibilityNodeInfo.ACTION_CLICK);
mNeedUnpack = false;
}
Log.d(TAG, "事件----> end performAction 戳開但還未領取");
}
- 屏幕內容檢測和自動化點擊的實現
/** 打開通知欄消息*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void openNotify(AccessibilityEvent event) {
if(event.getParcelableData() == null || !(event.getParcelableData() instanceof Notification)) {
return;
}
//將微信的通知欄消息打開
Notification notification = (Notification) event.getParcelableData();
PendingIntent pendingIntent = notification.contentIntent;
Log.d(TAG, "事件----> 打開通知欄消息 " + event);
try {
pendingIntent.send();
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
}
和其他插件一樣,這里使用的是Android API提供的AccessibilityService。這個類位于android.accessibilityservice包內,開啟服務后就會自動做一些操作 像現在360的自動安裝apk,也是開啟了此服務。
AccessibilityService 服務在后臺運行,等待系統在發生 AccessibilityEvent 事件時回調。這些事件指的是用戶界面上發生的狀態變化, 比如焦點變更、按鈕按下等等。服務可以請求“查詢當前窗口中內容”的能力。 開發輔助服務需要繼承該類并實現其抽象方法。
2.1 配置AccessibilityService
在這個例子中,我們需要監聽的事件是當紅包來或者滑動屏幕時引起的屏幕內容變化,和點開紅包時窗體狀態的變化,因此我們只需要在配置XML的accessibility-service標簽中加入一條
android:accessibilityEventTypes="typeWindowStateChanged|typeWindowContentChanged" 或在onAccessibilityEvent回調函數中對事件進行一次類型判斷
final int eventType = event.getEventType(); if (eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED || eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) { // ... } 除此之外,由于我們只監聽微信,還需要指定微信的包名
android:packageNames="com.tencent.mm" 為了獲取窗口內容,我們還需要指定
android:canRetrieveWindowContent="true" 其他配置請看代碼。
2.2 獲取紅包所在的節點
首先,我們要獲取當前屏幕的根節點,下面兩種方式效果是相同的:
/* 聊天會話窗口,遍歷節點匹配“領取紅包”和"查看紅包" */
List<AccessibilityNodeInfo> nodes1 = this.findAccessibilityNodeInfosByTexts(
this.rootNodeInfo,
new String[]{
WECHAT_VIEW_OTHERS_CH, WECHAT_VIEW_SELF_CH });
if (!nodes1.isEmpty()) {
String nodeId = Integer.toHexString(System.identityHashCode(this.rootNodeInfo));
if (!nodeId.equals(lastFetchedHongbaoId)) {
mLuckyMoneyReceived = true;
mReceiveNodeList = nodes1;
}
return;
}
2.3 紅包標識符
/**
* 將節點對象的id和紅包上的內容合并
* 用于表示一個唯一的紅包
*
* @param node 任意對象
* @return 紅包標識字符串
*/
private String getHongbaoText(AccessibilityNodeInfo node) {
/* 獲取紅包上的文本 */
String content;
try {
AccessibilityNodeInfo i = node.getParent().getChild(0);
content = i.getText().toString();
} catch (NullPointerException npe) {
return null;
}
Log.d(TAG, "事件----> start getHongbaoText() " + content);
return content;
}