Android:輔助功能之自動(dòng)搶紅包

hi大家好遗锣。
新年又來(lái)了货裹,微信群里又是各種紅包橫飛。作為技術(shù)人員的我們卻大可不必?fù)?dān)心一不小心精偿,手速慢了點(diǎn)弧圆,又錯(cuò)過(guò)了幾十萬(wàn)。我們可以通過(guò)安卓的輔助功能來(lái)實(shí)現(xiàn)自己的微信自動(dòng)搶紅包笔咽,安全又快捷搔预。

輔助服務(wù)

我們?cè)?設(shè)置->無(wú)障礙 中,就可以看到手機(jī)中所有的輔助服務(wù)了叶组。輔助功能通常是針對(duì)一些視力聽(tīng)力等有障礙導(dǎo)致使用手機(jī)有障礙的人群拯田,做一些語(yǔ)言提醒等幫助他們更好地使用手機(jī)。
因?yàn)檩o助功能可以得到系統(tǒng)級(jí)別的事件和服務(wù)甩十,第三方應(yīng)用的輔助功能都需要手動(dòng)開(kāi)啟船庇。我們常用的綠色守護(hù),冰箱等應(yīng)用都是利用輔助服務(wù)實(shí)現(xiàn)的侣监。

image

我們先來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的輔助服務(wù)吧鸭轮。

1,繼承AccessibilityService類橄霉。AccessibilityService類一共有四個(gè)可以重寫的方法窃爷。

TestService類

public class TestService extends AccessibilityService {
    /**
     *  必須重寫的方法:此方法用了接受系統(tǒng)發(fā)來(lái)的event。在你注冊(cè)的event發(fā)生是被調(diào)用姓蜂。在整個(gè)生命周期會(huì)被調(diào)用多次按厘。
     */
    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
    }

   /**
     *  必須重寫的方法:系統(tǒng)要中斷此service返回的響應(yīng)時(shí)會(huì)調(diào)用。在整個(gè)生命周期會(huì)被調(diào)用多次钱慢。
     */
    @Override
    public void onInterrupt() {
    }

     /**
     *  當(dāng)系統(tǒng)連接上你的服務(wù)時(shí)被調(diào)用
     */
    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();
    }


    /**
     *  在系統(tǒng)要關(guān)閉此service時(shí)調(diào)用刻剥。
     */
    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }
}

2,給你的輔助服務(wù)寫一個(gè)配置文件滩字。
res/xml/text_server_config.xml

<accessibility-service
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeAllMask"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagDefault"
    android:canRetrieveWindowContent="true"
    android:description="@string/accessibility_description"
    android:notificationTimeout="10" />

看屬性的名字應(yīng)該比較容易猜測(cè)到不同是屬性是用來(lái)干嘛的造虏。

accessibilityEventTypes:響應(yīng)那種類型的事件

accessibilityFeedbackType:用什么方式反饋給用戶

notificationTimeout:響應(yīng)時(shí)間

packageNames:指定響應(yīng)哪個(gè)應(yīng)用的事件御吞。如果不填則是響應(yīng)所有的應(yīng)用事件(如果以后寫搶紅包的輔助功能,可以只寫微信的包名)

description:輔助服務(wù)的描述信息漓藕。

3陶珠,在manifest中注冊(cè)服務(wù)。

        <service
            android:name=".TestService"
            //輔助功能的名稱
            android:label="@string/test_service_label"
            //此處必須聲明一次權(quán)限
            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
            <intent-filter>
                <action android:name="android.accessibilityservice.AccessibilityService" />
            </intent-filter>
            <meta-data
            //對(duì)享钞,我就是上面寫好的配置文件
                android:name="android.accessibilityservice"
                android:resource="@xml/text_service_config" />
        </service>

4揍诽,最后,回到服務(wù)的類栗竖,TestService暑脆。在onAccessibilityEvent(AccessibilityEvent event)方法中,我們可以接收到系統(tǒng)發(fā)過(guò)來(lái)的事件狐肢。當(dāng)然取決于我們?cè)谂渲梦募羞x擇了我們要監(jiān)聽(tīng)哪些種類添吗,哪些應(yīng)用的事件了。

 public void onAccessibilityEvent(AccessibilityEvent event) {
    //得到事件的包名份名。如果注冊(cè)了多個(gè)應(yīng)用的事件碟联,可以在此做一個(gè)判斷。
    String packageName = event.getPackageName().toString();
    
    //得到對(duì)應(yīng)的事件類型僵腺,這里有很多很多種的事件類型鲤孵,具體可以自行翻閱AccessibilityEvent類中的定義。
    int eventType = event.getEventType();
    
    //得到根的view節(jié)點(diǎn)辰如∑占啵可以當(dāng)做當(dāng)前acitivity的視圖看成是樹(shù)狀結(jié)構(gòu)的(實(shí)際上也是~。~)琉兜,而我們現(xiàn)在就得到了它的根節(jié)點(diǎn)鹰椒。
    AccessibilityNodeInfo root = getRootInActiveWindow();
    
    //我們可以得到此節(jié)點(diǎn)的文字
    String rootText = root.getText().toString();
    //得到此節(jié)點(diǎn)的class
    String rootClass = root.getClass().toString();
    //得到子節(jié)點(diǎn)的和子節(jié)點(diǎn)總數(shù)
    root.getChild(root.getChildCount()-1);
 }
 

到這里,我們可以通過(guò)無(wú)數(shù)次遍歷呕童,找到視圖上自己想要的那個(gè)控件了漆际。當(dāng)然,還有更加簡(jiǎn)單的方法夺饲。

    //這兩個(gè)方法如果找不到的話奸汇,都會(huì)報(bào)錯(cuò)。所以請(qǐng)做好對(duì)應(yīng)的處理往声。
    root.findAccessibilityNodeInfosByText("根據(jù)文本內(nèi)容查找節(jié)點(diǎn)");
    root.findAccessibilityNodeInfosByViewId("根據(jù)id查找節(jié)點(diǎn)擂找,當(dāng)然實(shí)際上很難知道id是多少~、~");

最后我們可以對(duì)控件做一些操作,比如

    //點(diǎn)擊操作
    root.performAction(AccessibilityNodeInfo.ACTION_CLICK);

    //滑動(dòng)操作
    root.performAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);

好浩销,對(duì)于輔助服務(wù)的基礎(chǔ)知識(shí)我們學(xué)到這里已經(jīng)差不多了贯涎,如果跟著我寫了一個(gè)demo的童鞋們,可以運(yùn)行一下慢洋,在設(shè)置->無(wú)障礙中把自己的輔助功能打開(kāi)試試塘雳。把玩一下陆盘。


下面可以進(jìn)入搶紅包的開(kāi)發(fā)。

搶紅包

我們先回顧一下手動(dòng)搶紅包的過(guò)程败明。
假設(shè)小新某天在用手機(jī)刷微博隘马。叮叮,聽(tīng)到提示聲妻顶,通知欄上顯示:“小明\n [微信紅包]恭喜發(fā)財(cái)酸员,大吉大利”。
小新光速點(diǎn)了一下微信通知讳嘱,手機(jī)自動(dòng)跳轉(zhuǎn)到了對(duì)應(yīng)的微信聊天頁(yè)面幔嗦,聊天界面里正是一條橙色底色,配上紅包圖片的信息:“恭喜發(fā)財(cái)沥潭,大吉大利\n領(lǐng)取紅包\n微信紅包”邀泉。
腦子還沒(méi)反應(yīng)過(guò)來(lái),手指已經(jīng)自動(dòng)點(diǎn)到這條信息上叛氨,這是有一個(gè)正在加載的提示框一閃而過(guò)呼渣,然后就是正中一個(gè)大大的紅包棘伴,中間是金黃色的“開(kāi)”字寞埠。
不用想了,開(kāi)焊夸!看著開(kāi)字轉(zhuǎn)啊轉(zhuǎn)仁连,心急如焚。最后屏幕一閃阱穗,跳到了紅包詳情頁(yè)面饭冬,心頭大石落地,詳情頁(yè)面寫在“0.01分錢”揪阶。小新也心滿意足地回去看微博了昌抠。

我們的自動(dòng)搶紅包就是要自動(dòng)幫我們完成這么一個(gè)流程:
1,獲取通知欄的信息鲁僚,判斷是否紅包炊苫。
2,如果屏幕關(guān)著的冰沙,先打開(kāi)屏幕侨艾。
3,點(diǎn)擊通知拓挥,進(jìn)入聊天界面
4唠梨,點(diǎn)擊紅包信息
5,點(diǎn)擊紅包中的“開(kāi)”
6侥啤,返回主界面当叭,安安靜靜了無(wú)痕跡茬故。

先上github的地址我是地址;大家可以直接去看代碼科展。代碼很簡(jiǎn)單均牢。無(wú)非就是遍歷找控件。

1, 得到通知欄信息
通知欄事件

AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED

可以通過(guò)event.getText()方法得到通知欄的文字才睹。然后在與“[微信紅包]”做對(duì)比徘跪,判斷是否微信紅包。

2琅攘,
打開(kāi)屏幕垮庐。如果是有屏幕鎖的那我就沒(méi)辦法了哎坞琴,哨查,知道的童鞋請(qǐng)賜教。

  /**
     * 解鎖
     */
    private void wakeAndUnlock() {
        //獲取電源管理器對(duì)象
        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);

        //獲取PowerManager.WakeLock對(duì)象剧辐,后面的參數(shù)|表示同時(shí)傳入兩個(gè)值寒亥,最后的是調(diào)試用的Tag
        PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "bright");

        //點(diǎn)亮屏幕
        wl.acquire(1000);

        //得到鍵盤鎖管理器對(duì)象
        KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
        kl = km.newKeyguardLock("unLock");

        //解鎖
        kl.disableKeyguard();
    }

記得釋放鍵盤管理器

 kl.reenableKeyguard();

3,通過(guò)通知欄進(jìn)入微信聊天界面荧关。

//打開(kāi)微信聊天頁(yè)面
    private void openWeichaPage(AccessibilityEvent event) {
        if (event.getParcelableData() != null && event.getParcelableData() instanceof Notification) {
            //得到通知的對(duì)象
            Notification notification = (Notification) event.getParcelableData();

            //得到通知欄的信息
//            String content = notification.tickerText.toString();
//            String name = content.substring(0, content.indexOf(":"));
//            String scontent = content.substring(content.indexOf(":"), content.length());
//            Log.d("mylog", "------openWeichaPage  name: " + name + " content: " + scontent);


            //打開(kāi)通知欄的intent溉奕,即打開(kāi)對(duì)應(yīng)的聊天界面
            PendingIntent pendingIntent = notification.contentIntent;
            try {
                pendingIntent.send();
            } catch (PendingIntent.CanceledException e) {
                e.printStackTrace();
            }
        }
    }

4,我們需要監(jiān)聽(tīng)頁(yè)面的變化加自己定義變量來(lái)判斷是否跳轉(zhuǎn)到了微信聊天頁(yè)面。

頁(yè)面跳轉(zhuǎn)的事件是:

 AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED

微信聊天頁(yè)面的classname:

com.tencent.mm.ui.LauncherUI

判斷的方法:

    String className = event.getClassName().toString();
    
    //是否微信聊天頁(yè)面的類
    if (className.equals(LAUCHER)) {
       findStuff();
    }

然后就是做遍歷忍啤,大體思路是調(diào)用getChild(i)找到聊天頁(yè)面中的紅包加勤。可以先通過(guò)getClassName()比較是否“android.widget.TextView”同波,然后通過(guò)getText()匹配文本內(nèi)容鳄梅。

具體方法不表。大家可以自己寫寫未檩,不想寫可以看GitHub上我寫的代碼戴尸。

5,和上面的方法一直冤狡,判斷窗口跳轉(zhuǎn)孙蒙,加遍歷找到“開(kāi)”字,對(duì)筒溃,開(kāi) 也是一個(gè)TextView马篮。

6,至此就大功告成怜奖,可以返回桌面了浑测。

 /**
     * 回到系統(tǒng)桌面
     */
    private void back2Home() {
        Intent home = new Intent(Intent.ACTION_MAIN);

        home.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        home.addCategory(Intent.CATEGORY_HOME);

        startActivity(home);
    }

我們的搶紅包之旅到這里就告一段落了,結(jié)束的是一次艱苦的擼代碼的時(shí)光,開(kāi)啟的是千千萬(wàn)萬(wàn)次自動(dòng)搶紅包的快感迁央。

最后掷匠,祝大家新年 大 吉 吧!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末岖圈,一起剝皮案震驚了整個(gè)濱河市讹语,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蜂科,老刑警劉巖顽决,帶你破解...
    沈念sama閱讀 211,348評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異导匣,居然都是意外死亡才菠,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門贡定,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)赋访,“玉大人,你說(shuō)我怎么就攤上這事缓待◎镜ⅲ” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 156,936評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么戏阅? 我笑而不...
    開(kāi)封第一講書人閱讀 56,427評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮燃辖,結(jié)果婚禮上锯玛,老公的妹妹穿的比我還像新娘。我一直安慰自己踢涌,他們只是感情好通孽,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著睁壁,像睡著了一般背苦。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上潘明,一...
    開(kāi)封第一講書人閱讀 49,785評(píng)論 1 290
  • 那天行剂,我揣著相機(jī)與錄音,去河邊找鬼钳降。 笑死厚宰,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播铲觉,決...
    沈念sama閱讀 38,931評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼澈蝙,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了撵幽?” 一聲冷哼從身側(cè)響起灯荧,我...
    開(kāi)封第一講書人閱讀 37,696評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎盐杂,沒(méi)想到半個(gè)月后逗载,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,141評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡链烈,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評(píng)論 2 327
  • 正文 我和宋清朗相戀三年撕贞,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片测垛。...
    茶點(diǎn)故事閱讀 38,625評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡捏膨,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出食侮,到底是詐尸還是另有隱情号涯,我是刑警寧澤,帶...
    沈念sama閱讀 34,291評(píng)論 4 329
  • 正文 年R本政府宣布锯七,位于F島的核電站链快,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏眉尸。R本人自食惡果不足惜域蜗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望噪猾。 院中可真熱鬧霉祸,春花似錦、人聲如沸袱蜡。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)坪蚁。三九已至奔穿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間敏晤,已是汗流浹背贱田。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留嘴脾,地道東北人男摧。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親彩倚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子筹我,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 閱讀原文:http://www.reibang.com/p/5a44b6eaba20 快到年底了,又到了拼手速搶...
    Tyhj閱讀 10,776評(píng)論 7 16
  • 輔助功能(AccessibilityService)是一個(gè)Android系統(tǒng)提供的一種服務(wù)帆离,繼承自Service類...
    宛丘之上兮閱讀 7,995評(píng)論 5 10
  • 微信紅包自打出世以來(lái)就極其受歡迎,搶紅包插件可謂紅極一時(shí).今天,我們重新談?wù)創(chuàng)尲t包插件的哪些事兒.本質(zhì)上,搶紅包插...
    于加澤閱讀 1,853評(píng)論 0 6
  • 被命運(yùn)欺負(fù)過(guò)的人對(duì)生活的要求總不會(huì)很高蔬蕊。三奶奶平時(shí)穿的破破爛爛,身上總是臟臟的哥谷,走到鄰居身邊也是經(jīng)常遭白...
    麥田_0102閱讀 1,245評(píng)論 12 69
  • “活著”的人和“不自殺”的人 一 “活著”與“不自殺”所指并非行為岸夯,而是代表兩種精神意志。小說(shuō)《活著》展現(xiàn)了這兩種...
    梵高的椅子閱讀 209評(píng)論 0 0