日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

微信自动抢红包的实现(Demo已增加查看TopActivity功能)

發布時間:2024/1/1 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 微信自动抢红包的实现(Demo已增加查看TopActivity功能) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

?

先說說遇到的一些問題

去年寫過微信搶紅包插件的實現,但是今年春節的時候發現微信更新之后自己寫的插件竟然會停在開紅包的頁面無法繼續向下執行,debug之后發現問題是微信團隊把開紅包按鈕的文本內容現在改成了一張圖片,導致我使用findAccessibilityNodeInfosByText()找不到有效的子節點,也就無法實現模擬點擊去打開紅包。
于是乎我開始嘗試通過獲取指定控件的ID去實現,迅速打開IDE,使用Android Device Monitor查看開紅包按鈕的控件id,后面會附上使用方法,然后使用findAccessibilityNodeInfosByViewId()來獲取開紅包按鈕的節點,結果當然是可以的。
但是這就帶來了另一個問題:如果微信每次發版都修改這個按鈕的控件id,那我的插件也就只能每次都跟隨著修改代碼才能正常使用,事實也證明微信的確是每次發版都會修改此控件的id值。
針對這個問題我目前的做法是開一個ArrayList記錄微信開紅包button所使用過的id值,然后去遍歷id值通過findAccessibilityNodeInfosByViewId()獲取節點,當然用map存儲id值及其對應微信版本號用來做版本兼容會更好些,誰讓我懶呢,懶得去獲取微信版本號。當然,還有種暴力的方法,就是遍歷開紅包頁面的節點樹并模擬點擊其下的每一個能點擊的button,因為其實界面里能點擊的就只有關閉按鈕和開紅包按鈕,但關閉按鈕其實是個imageView而不是button。
坑總是一個接一個,在最近的微信版本更新后,我發現不僅僅是控件id會發生改變,就連某些activity的名稱都被修改了,以及聊天頁面對消息推送的處理方式也變了,適配的代碼我已經更新到github。
以后微信紅包如果還有其他修改,我會把適配后的代碼直接更新到github的demo,所以下方的代碼片不一定是最新的,感興趣的同學可以上github去star一下,demo地址。當然適配過程中遇到的問題我還是會記錄在這里。

核心代碼片如下:

搶紅包:

if ("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI".equals(event.getClassName())) {//當前在紅包待開頁面,去拆紅包getLuckyMoney(); } else if ("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI".equals(event.getClassName())) {//拆完紅包后看詳細紀錄的界面openNext("查看我的紅包記錄"); } else if ("com.tencent.mm.ui.LauncherUI".equals(event.getClassName())) {//在聊天界面,去點中紅包openLuckyEnvelope(); }

自動加人:

if (eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED && event.getClassName().equals("com.tencent.mm.ui.LauncherUI")) {//記錄打招呼人數置零i = 0;//當前在微信聊天頁就點開發現openNext("發現");//然后跳轉到附近的人openDelay(1000, "附近的人"); } else if (event.getClassName().equals("com.tencent.mm.plugin.nearby.ui.NearbyFriendsUI") && eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {prepos = 0;//當前在附近的人界面就點選人打招呼AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText("米以內");Log.d("name", "附近的人列表人數: " + list.size());if (i < (list.size() * page)) {list.get(i % list.size()).performAction(AccessibilityNodeInfo.ACTION_CLICK);list.get(i % list.size()).getParent().performAction(AccessibilityNodeInfo.ACTION_CLICK);} else if (i == list.size() * page) {//本頁已全部打招呼,所以下滑列表加載下一頁,每次下滑的距離是一屏for (int i = 0; i < nodeInfo.getChild(0).getChildCount(); i++) {if (nodeInfo.getChild(0).getChild(i).getClassName().equals("android.widget.ListView")) {AccessibilityNodeInfo node_lsv = nodeInfo.getChild(0).getChild(i);node_lsv.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);page++;new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(1000);} catch (InterruptedException mE) {mE.printStackTrace();}AccessibilityNodeInfo nodeInfo_ = getRootInActiveWindow();List<AccessibilityNodeInfo> list_ = nodeInfo_.findAccessibilityNodeInfosByText("米以內");Log.d("name", "列表人數: " + list_.size());//滑動之后,上一頁的最后一個item為當前的第一個item,所以從第二個開始打招呼list_.get(1).performAction(AccessibilityNodeInfo.ACTION_CLICK);list_.get(1).getParent().performAction(AccessibilityNodeInfo.ACTION_CLICK);}}).start();}}} } else if (event.getClassName().equals("com.tencent.mm.plugin.profile.ui.ContactInfoUI") && eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {if (prepos == 1) {//從打招呼界面跳轉來的,則點擊返回到附近的人頁面performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);i++;} else if (prepos == 0) {//從附近的人跳轉來的,則點擊打招呼按鈕AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();if (nodeInfo == null) {Log.w(TAG, "rootWindow為空");return;}List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText("打招呼");if (list.size() > 0) {list.get(list.size() - 1).performAction(AccessibilityNodeInfo.ACTION_CLICK);list.get(list.size() - 1).getParent().performAction(AccessibilityNodeInfo.ACTION_CLICK);} else {//如果遇到已加為好友的則界面的“打招呼”變為“發消息",所以直接返回上一個界面并記錄打招呼人數+1performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);i++;}} } else if (event.getClassName().equals("com.tencent.mm.ui.contact.SayHiEditUI") && eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {//當前在打招呼頁面prepos = 1;//輸入打招呼的內容并發送inputHello(hello);openNext("發送"); }

打開通知欄消息:

private void openNotification(AccessibilityEvent event) {if (event.getParcelableData() == null || !(event.getParcelableData() instanceof Notification)) {return;}//將通知欄消息打開Notification notification = (Notification) event.getParcelableData();PendingIntent pendingIntent = notification.contentIntent;try {pendingIntent.send();} catch (PendingIntent.CanceledException e) {e.printStackTrace();} }

點擊匹配的nodeInfo @param str text關鍵字:

private void openNext(String str) {AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();if (nodeInfo == null) {Log.w(TAG, "rootWindow為空");Toast.makeText(this, "rootWindow為空", Toast.LENGTH_SHORT).show();return;}List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText(str);Log.d("name", "匹配個數: " + list.size());if (list.size() > 0) {list.get(list.size() - 1).performAction(AccessibilityNodeInfo.ACTION_CLICK);list.get(list.size() - 1).getParent().performAction(AccessibilityNodeInfo.ACTION_CLICK);} else {Toast.makeText(this, "找不到有效的節點", Toast.LENGTH_SHORT).show();} }

自動輸入打招呼內容:

private void inputHello(String hello) {AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();//找到當前獲取焦點的viewAccessibilityNodeInfo target = nodeInfo.findFocus(AccessibilityNodeInfo.FOCUS_INPUT);if (target == null) {Log.d(TAG, "inputHello: null");return;}ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);ClipData clip = ClipData.newPlainText("label", hello);clipboard.setPrimaryClip(clip);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {target.performAction(AccessibilityNodeInfo.ACTION_PASTE);} }

關于如何獲取app頁面中控件的id:

在Android Studio中開啟Android Device Monitor,選擇設備后點擊Dump View Hierarchy for UI Automator即可查看

?

?

配置使用AccessibilityService:

在manifest中的配置:

<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" /> <serviceandroid:enabled="true"android:exported="true"android:label="@string/app_name"android:name=".AutoService"android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"><intent-filter><action android:name="android.accessibilityservice.AccessibilityService"/></intent-filter><meta-dataandroid:name="android.accessibilityservice"android:resource="@xml/envelope_service_config"/> </service>

meta-data中的xml資源文件:

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"android:accessibilityEventTypes="typeNotificationStateChanged|typeWindowStateChanged|typeWindowContentChanged"android:accessibilityFeedbackType="feedbackGeneric"android:accessibilityFlags=""android:canRetrieveWindowContent="true"android:description="@string/app_name"android:notificationTimeout="100"android:packageNames="com.tencent.mm,com.huawei.android.launcher" />

其中packageName用于配置你想要監測的包名,如果多個則用逗號隔開
accessibilityEventTypes表示該服務可監測界面中哪些事件類型,如窗口打開,滑動等,具體值可查看api
accessibilityFeedbackType:表示反饋方式,比如是語音播放,還是震動
canRetrieveWindowContent:表示該服務能否訪問活動窗口中的內容
notificationTimeout:接受事件的時間間隔

當然,除了以meta-data的方式靜態配置,也可通過在服務啟動時的onServiceConnected()方法中調用setServiceInfo(AccessibilityServiceInfo)進行動態配置。

補充:

幾種常用accessibilityEventType事件類型:
TYPE_WINDOW_STATE_CHANGED: 窗口狀態改變事件類型,打開PopupWindow、dialog、menu等
TYPE_NOTIFICATION_STATE_CHANGED: 通知欄事件
TYPE_WINDOW_CONTENT_CHANGED: 窗口中內容改變
TYPE_VIEW_SCROLLED: 控件滑動事件
TYPE_WINDOWS_CHANGED: 顯示窗口改變
TYPE_VIEW_TEXT_CHANGED : editText控件的內容發生改變
TYPE_TOUCH_INTERACTION_START: 用戶開始觸摸屏幕
TYPE_TOUCH_INTERACTION_END: 用戶停止觸摸屏幕

其中TYPE_WINDOW_CONTENT_CHANGED 又可以細分為4個二級類型:
1.CONTENT_CHANGE_TYPE_SUBTREE: 節點發生增減
2.CONTENT_CHANGE_TYPE_TEXT: 節點文本發生改變
3.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION: 節點的內容描述發生改變,即控件的contentDescription屬性發生改變
4.CONTENT_CHANGE_TYPE_UNDEFINED: 未定義類型,即除上面三種之外的類型

接下來,或許你可以自己嘗試下使用AccessibilityService實現app的自動安裝/批量安裝,去學習吧,騷年!

轉載于:https://my.oschina.net/u/3729361/blog/1584214

總結

以上是生活随笔為你收集整理的微信自动抢红包的实现(Demo已增加查看TopActivity功能)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。