最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android中微信搶紅包插件原理解析及開(kāi)發(fā)思路

 更新時(shí)間:2016年02月14日 13:44:17   作者:尼古拉斯_趙四  
本文給大家介紹Android中微信搶紅包插件原理解析及開(kāi)發(fā)思路,對(duì)微信搶紅包插件原理相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧

一、前言

自從去年中微信添加搶紅包的功能,微信的電商之旅算是正式開(kāi)始正式火爆起來(lái)。但是作為Android開(kāi)發(fā)者來(lái)說(shuō),我們?cè)趽尲t包的同時(shí)意識(shí)到了很多問(wèn)題,就是手動(dòng)去搶紅包的速度慢了,當(dāng)然這些有很多原因?qū)е铝恕;蛟S是網(wǎng)絡(luò)的原因,而且這個(gè)也是最大的原因。但是其他的不可忽略的因素也是要考慮到進(jìn)去的,比如在手機(jī)充電鎖屏的時(shí)候,我們并不知道有人已經(jīng)開(kāi)始發(fā)紅包了,那么這時(shí)候也是讓我們喪失了一大批紅包的原因。那么關(guān)于網(wǎng)絡(luò)的問(wèn)題,我們開(kāi)發(fā)者可能用相關(guān)技術(shù)無(wú)法解決(當(dāng)然在Google和Facebook看來(lái)的話,他們的理想是能夠在任何地方都能連接互聯(lián)網(wǎng),當(dāng)然在偏遠(yuǎn)的農(nóng)村也是,不過(guò)我們期待他們有一天能夠普及開(kāi)來(lái)。到時(shí)候才是真正的互聯(lián)網(wǎng))。扯得有點(diǎn)遠(yuǎn)了。我們回歸到正題,今天我們來(lái)看看使用技術(shù)來(lái)解決其他非網(wǎng)絡(luò)問(wèn)題。在充電鎖屏的時(shí)候也可以自動(dòng)幫我們搶紅包。而且你要知道,機(jī)器搶紅包的準(zhǔn)確率是100%的,這個(gè)也許就是人和機(jī)器的區(qū)別。那么保證搶得準(zhǔn)確率是100%的話,那就依賴于我們高效準(zhǔn)確的算法實(shí)現(xiàn)了。下面就來(lái)看看原理實(shí)現(xiàn)。

當(dāng)去年我看到搶紅包那么火爆的時(shí)候,當(dāng)時(shí)作為一個(gè)開(kāi)發(fā)者心里是多么渴望開(kāi)發(fā)一個(gè)插件出來(lái),可是當(dāng)時(shí)我們能想到的就是使用:

adb shell monkey

命令去模擬點(diǎn)擊屏幕,但是那種方式有一個(gè)問(wèn)題就是是無(wú)頭緒的盲目點(diǎn)擊,所以幾乎會(huì)出現(xiàn)誤點(diǎn),點(diǎn)擊成功率極其低下。所以當(dāng)時(shí)就沒(méi)有想到其他方法了,因?yàn)樽罱隽擞嘘P(guān)輔助功能相關(guān)的工作的時(shí)候,那么就發(fā)現(xiàn)這個(gè)功能可以用于搶紅包。

其實(shí)現(xiàn)在我們可以去各大市場(chǎng)搜索一下看到,有很多搶紅包的插件了。當(dāng)然我們并不是用于商業(yè)化,這里只是來(lái)解析一下原理。我們會(huì)發(fā)現(xiàn)那些插件都有一個(gè)共同的特點(diǎn)是:第一步都是引導(dǎo)用戶去開(kāi)啟輔助功能。

二、原理解析

關(guān)于輔助功能(AccessibilityService),如果又不了解的同學(xué)可以去Google一下,這個(gè)功能其實(shí)很有用的,但是他的出現(xiàn)的出發(fā)點(diǎn)是給那些肢體上有障礙的人使用的,比如手指不健全的用戶,怎么才能滑動(dòng)屏幕,然后打開(kāi)一個(gè)應(yīng)用呢?那么輔助功能就是干這些事,他的功能其實(shí)就是可以概括兩句話:

第一、尋找到我們想要的View節(jié)點(diǎn)

第二、然后模擬點(diǎn)擊,實(shí)現(xiàn)特定功能

我們知道Android中的View體系是一個(gè)樹(shù)形結(jié)構(gòu),那么每一個(gè)View就是一個(gè)節(jié)點(diǎn)。所以我們可以查找到指定的節(jié)點(diǎn),那么我們?cè)撊绾尾檎业轿覀兿胍墓?jié)點(diǎn)呢?這里我們先看一下輔助功能(AccessibilityService)的用法

第一步、我們需要集成AccessibilityService類

我們需要自定一個(gè)Service然后繼承AccessibilityService,當(dāng)然還需要在AndroidManifest.xml中聲明這個(gè)服務(wù):

第二步、聲明權(quán)限和配置

這個(gè)服務(wù)需要注明一個(gè)權(quán)限:

android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" 

當(dāng)然還要一個(gè)meta-data的聲明,這個(gè)聲明是對(duì)這個(gè)AccessibilityService的配置。我們看一下配置文件內(nèi)容:

<?xml version="1.0" encoding="utf-8"?> 
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" 
android:accessibilityEventTypes="typeNotificationStateChanged|typeWindowStateChanged" 
android:accessibilityFeedbackType="feedbackGeneric" 
android:accessibilityFlags="flagDefault" 
android:canRetrieveWindowContent="true" 
android:description="@string/desc" 
android:notificationTimeout="100" 
android:packageNames="com.tencent.mm" /> 

這里我們看到有很多選項(xiàng),我們看一下常用的幾個(gè)屬性:

1、android:accessibilityEventTypes="typeAllMask"
看屬性名也差不多可以明白,這個(gè)是用來(lái)設(shè)置響應(yīng)事件的類型,typeAllMask當(dāng)然就是響應(yīng)所有類型的事件了。當(dāng)然還有單擊、長(zhǎng)按、滑動(dòng)等。

2、android:accessibilityFeedbackType="feedbackSpoken"

設(shè)置回饋給用戶的方式,有語(yǔ)音播出和振動(dòng)。可以配置一些TTS引擎,讓它實(shí)現(xiàn)發(fā)音。

3、android:notificationTimeout="100"

響應(yīng)時(shí)間的設(shè)置就不用多說(shuō)了

4、android:packageNames="com.example.android.apis"

可以指定響應(yīng)某個(gè)應(yīng)用的事件,這里因?yàn)橐憫?yīng)所有應(yīng)用的事件,所以不填,默認(rèn)就是響應(yīng)所有應(yīng)用的事件。比如我們寫一個(gè)微信搶紅包的輔助程序,就可以在這里填寫微信的包名,便可以監(jiān)聽(tīng)微信產(chǎn)生的事件了。

注意:

1、我們這些配置信息除了在xml中定義,同樣也可以在代碼中定義,我們一般都是在onServiceConnected()方法里進(jìn)行

@Override 
protected void onServiceConnected() { 
AccessibilityServiceInfo info = getServiceInfo(); 
info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK; 
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN; 
info.notificationTimeout = 100; 
setServiceInfo(info); 
info.packageNames = new String[]{"xxx.xxx.xxx", "yyy.yyy.yyy","...."}; 
setServiceInfo(info); 
super.onServiceConnected(); 
}

2、這里我們一般都會(huì)在這里寫上我們需要監(jiān)聽(tīng)的應(yīng)用的包名,但是有時(shí)候我們需要監(jiān)聽(tīng)多個(gè)應(yīng)用,那么這時(shí)候我們?cè)撛趺崔k呢?

這時(shí)候我們可以這么做:

第一種:我們?cè)诖a中注冊(cè)多個(gè)應(yīng)用的包名,從而可以監(jiān)聽(tīng)多個(gè)應(yīng)用

@Override 
protected void onServiceConnected() { 
AccessibilityServiceInfo info = getServiceInfo(); 
//這里可以設(shè)置多個(gè)包名,監(jiān)聽(tīng)多個(gè)應(yīng)用 
info.packageNames = new String[]{"xxx.xxx.xxx", "yyy.yyy.yyy","...."}; 
setServiceInfo(info); 
super.onServiceConnected(); 
}

第二種:我們?cè)趏nAccessibilityEvent事件監(jiān)聽(tīng)的方法中做包名的過(guò)濾(這種方式最常用)

@Override 
public void onAccessibilityEvent(AccessibilityEvent event) { 
String pkgName = event.getPackageName().toString(); 
if("xxx.xxx.xxx".equals(pkgName)){ 
}else if("yyy.yyy.yyy".equals(pkgName)){ 
}else if("....".equals(pkgName)){ 
} 
}

第三步、在onAccessibilityEvent方法中監(jiān)聽(tīng)指定的事件

比如我們需要監(jiān)聽(tīng)有通知欄消息的事件:

@Override 
public void onAccessibilityEvent(AccessibilityEvent event) { 
int eventType = event.getEventType(); 
switch (eventType) { 
case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED: 
//....... 
} 
}

這個(gè)事件類型很多的,我們可以查看AccessibilityEvent類的源碼:

@Deprecated 
public static final int MAX_TEXT_LENGTH = 500; 
/** 
* Represents the event of clicking on a {@link android.view.View} like 
* {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. 
*/ 
public static final int TYPE_VIEW_CLICKED = 0x00000001; 
/** 
* Represents the event of long clicking on a {@link android.view.View} like 
* {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. 
*/ 
public static final int TYPE_VIEW_LONG_CLICKED = 0x00000002; 
/** 
* Represents the event of selecting an item usually in the context of an 
* {@link android.widget.AdapterView}. 
*/ 
public static final int TYPE_VIEW_SELECTED = 0x00000004; 
/** 
* Represents the event of setting input focus of a {@link android.view.View}. 
*/ 
public static final int TYPE_VIEW_FOCUSED = 0x00000008; 
/** 
* Represents the event of changing the text of an {@link android.widget.EditText}. 
*/ 
public static final int TYPE_VIEW_TEXT_CHANGED = 0x00000010; 

/** 
* Represents the event of opening a {@link android.widget.PopupWindow}, 
* {@link android.view.Menu}, {@link android.app.Dialog}, etc. 
*/ 
public static final int TYPE_WINDOW_STATE_CHANGED = 0x00000020; 
/** 
* Represents the event showing a {@link android.app.Notification}. 
*/ 
public static final int TYPE_NOTIFICATION_STATE_CHANGED = 0x00000040; 

/** 
* Represents the event of a hover enter over a {@link android.view.View}. 
*/ 
public static final int TYPE_VIEW_HOVER_ENTER = 0x00000080; 
/** 
* Represents the event of a hover exit over a {@link android.view.View}. 
*/ 
public static final int TYPE_VIEW_HOVER_EXIT = 0x00000100; 
/** 
* Represents the event of starting a touch exploration gesture. 
*/ 
public static final int TYPE_TOUCH_EXPLORATION_GESTURE_START = 0x00000200; 

/** 
* Represents the event of ending a touch exploration gesture. 
*/ 
public static final int TYPE_TOUCH_EXPLORATION_GESTURE_END = 0x00000400; 
/** 
* Represents the event of changing the content of a window and more 
* specifically the sub-tree rooted at the event's source. 
*/ 
public static final int TYPE_WINDOW_CONTENT_CHANGED = 0x00000800; 

/** 
* Represents the event of scrolling a view. 
*/ 
public static final int TYPE_VIEW_SCROLLED = 0x00001000; 
/** 
* Represents the event of changing the selection in an {@link android.widget.EditText}. 
*/ 
public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 0x00002000; 

/** 
* Represents the event of an application making an announcement. 
*/ 
public static final int TYPE_ANNOUNCEMENT = 0x00004000; 

/** 
* Represents the event of gaining accessibility focus. 
*/ 
public static final int TYPE_VIEW_ACCESSIBILITY_FOCUSED = 0x00008000; 
/** 
* Represents the event of clearing accessibility focus. 
*/ 
public static final int TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 0x00010000; 

/** 
* Represents the event of traversing the text of a view at a given movement granularity. 
*/ 
public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 0x00020000; 
/** 
* Represents the event of beginning gesture detection. 
*/ 
public static final int TYPE_GESTURE_DETECTION_START = 0x00040000; 
/** 
* Represents the event of ending gesture detection. 
*/ 
public static final int TYPE_GESTURE_DETECTION_END = 0x00080000; 
/** 
* Represents the event of the user starting to touch the screen. 
*/ 
public static final int TYPE_TOUCH_INTERACTION_START = 0x00100000; 
/** 
* Represents the event of the user ending to touch the screen. 
*/ 
public static final int TYPE_TOUCH_INTERACTION_END = 0x00200000; 
/** 
* Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event: 
* The type of change is not defined. 
*/ 
public static final int CONTENT_CHANGE_TYPE_UNDEFINED = 0x00000000; 

/** 
* Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event: 
* A node in the subtree rooted at the source node was added or removed. 
*/ 
public static final int CONTENT_CHANGE_TYPE_SUBTREE = 0x00000001; 

/** 
* Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event: 
* The node's text changed. 
*/ 
public static final int CONTENT_CHANGE_TYPE_TEXT = 0x00000002; 
/** 
* Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event: 
* The node's content description changed. 
*/ 
public static final int CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION = 0x00000004; 

這里有很多事件,這些事件我們通過(guò)名字就可以看出來(lái)有很多我們可能都知道,比如當(dāng)窗口發(fā)生變化的時(shí)候,當(dāng)某個(gè)View被點(diǎn)擊了,被滾動(dòng)了等消息都是可以知道的。那么我們有了這些事件我們就可以做我們的事情了,因?yàn)槲覀冎朗录|發(fā)了。

第四步、查找到我們想要處理的節(jié)點(diǎn)View

這里系統(tǒng)提供了兩個(gè)方法讓我們來(lái)進(jìn)行查找想要的節(jié)點(diǎn)View

第一種是通過(guò)節(jié)點(diǎn)View的Text內(nèi)容來(lái)查找

findAccessibilityNodeInfosByText("查找內(nèi)容")

這種方式查找,就是像TextView,Button等View有文本內(nèi)容的,可以使用這種方式快速的找到。

第二種是通過(guò)節(jié)點(diǎn)View在xml布局中的id名稱

findAccessibilityNodeInfosByViewId("@id/xxx")

這個(gè)一般很難知道,但是我們?cè)诓檎蚁到y(tǒng)控件的時(shí)候還是可以做的,因?yàn)橄到y(tǒng)的控件的id是可以知道的,而且是統(tǒng)一的。
(關(guān)于這兩個(gè)方法我們?cè)趯懢W(wǎng)頁(yè)爬蟲(chóng)程序的時(shí)候可能知道,在html中通過(guò)tag/name/id等信息可以找到一個(gè)節(jié)點(diǎn),原理都類似)

第五步、模擬點(diǎn)擊指定事件

我們找到我們想要的View節(jié)點(diǎn),調(diào)用方法模擬事件:

performAction(AccessibilityNodeInfo.ACTION_CLICK)

調(diào)用這個(gè)方法即可,當(dāng)然這里的參數(shù)就是指定事件的名稱,這個(gè)和AccessibilityEvent中監(jiān)聽(tīng)的那些事件是一一對(duì)應(yīng)的,這里是模擬點(diǎn)擊事件,我們當(dāng)然可以模擬View的滾動(dòng)事件,長(zhǎng)按事件等。

三、實(shí)戰(zhàn)案例:微信搶紅包插件

上面我們就介紹了一個(gè)輔助功能開(kāi)發(fā)的具體步驟,那么下面就通過(guò)一個(gè)簡(jiǎn)單的例子,來(lái)實(shí)戰(zhàn)一下

例子:微信自動(dòng)搶紅包插件

首先我們來(lái)看一下微信搶紅包的流程:

第一步、我們?cè)谕ㄖ獧跁?huì)接收到一個(gè)微信紅包的消息

我們監(jiān)聽(tīng)通知欄事件:

AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED

然后查看通知欄的消息中是否有:[微信紅包] 的文本內(nèi)容

是的話,就走進(jìn)入第二步

第二步、我們模擬打開(kāi)通知欄

打開(kāi)微信如下圖:

我們查找包含有:領(lǐng)取紅包 的文本內(nèi)容的節(jié)點(diǎn)View,然后模擬點(diǎn)擊,進(jìn)入第三步:

第三步、我們點(diǎn)擊領(lǐng)取紅包

'如下圖:

這里我們?cè)诓檎野校翰鸺t包 的文本內(nèi)容的節(jié)點(diǎn)View,然后模擬點(diǎn)擊


下面我們來(lái)看一下代碼中的具體實(shí)現(xiàn):

package krelve.demo.rob; 
import java.util.List; 
import android.accessibilityservice.AccessibilityService; 
import android.accessibilityservice.AccessibilityServiceInfo; 
import android.annotation.SuppressLint; 
import android.app.Notification; 
import android.app.PendingIntent; 
import android.app.PendingIntent.CanceledException; 
import android.util.Log; 
import android.view.accessibility.AccessibilityEvent; 
import android.view.accessibility.AccessibilityNodeInfo; 
public class RobMoney extends AccessibilityService { 
@Override 
public void onAccessibilityEvent(AccessibilityEvent event) { 
int eventType = event.getEventType(); 
switch (eventType) { 
//第一步:監(jiān)聽(tīng)通知欄消息 
case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED: 
List<CharSequence> texts = event.getText(); 
if (!texts.isEmpty()) { 
for (CharSequence text : texts) { 
String content = text.toString(); 
Log.i("demo", "text:"+content); 
if (content.contains("[微信紅包]")) { 
//模擬打開(kāi)通知欄消息 
if (event.getParcelableData() != null 
&& 
event.getParcelableData() instanceof Notification) { 
Notification notification = (Notification) event.getParcelableData(); 
PendingIntent pendingIntent = notification.contentIntent; 
try { 
pendingIntent.send(); 
} catch (CanceledException e) { 
e.printStackTrace(); 
} 
} 
} 
} 
} 
break; 
//第二步:監(jiān)聽(tīng)是否進(jìn)入微信紅包消息界面 
case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: 
String className = event.getClassName().toString(); 
if (className.equals("com.tencent.mm.ui.LauncherUI")) { 
//開(kāi)始搶紅包 
getPacket(); 
} else if (className.equals("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI")) { 
//開(kāi)始打開(kāi)紅包 
openPacket(); 
} 
break; 
} 
} 
/** 
* 查找到 
*/ 
@SuppressLint("NewApi") 
private void openPacket() { 
AccessibilityNodeInfo nodeInfo = getRootInActiveWindow(); 
if (nodeInfo != null) { 
List<AccessibilityNodeInfo> list = nodeInfo 
.findAccessibilityNodeInfosByText("搶紅包"); 
for (AccessibilityNodeInfo n : list) { 
n.performAction(AccessibilityNodeInfo.ACTION_CLICK); 
} 
} 
} 
@SuppressLint("NewApi") 
private void getPacket() { 
AccessibilityNodeInfo rootNode = getRootInActiveWindow(); 
recycle(rootNode); 
} 
/** 
* 打印一個(gè)節(jié)點(diǎn)的結(jié)構(gòu) 
* @param info 
*/ 
@SuppressLint("NewApi") 
public void recycle(AccessibilityNodeInfo info) { 
if (info.getChildCount() == 0) { 
if(info.getText() != null){ 
if("領(lǐng)取紅包".equals(info.getText().toString())){ 
//這里有一個(gè)問(wèn)題需要注意,就是需要找到一個(gè)可以點(diǎn)擊的View 
Log.i("demo", "Click"+",isClick:"+info.isClickable()); 
info.performAction(AccessibilityNodeInfo.ACTION_CLICK); 
AccessibilityNodeInfo parent = info.getParent(); 
while(parent != null){ 
Log.i("demo", "parent isClick:"+parent.isClickable()); 
if(parent.isClickable()){ 
parent.performAction(AccessibilityNodeInfo.ACTION_CLICK); 
break; 
} 
parent = parent.getParent(); 
} 
} 
} 
} else { 
for (int i = 0; i < info.getChildCount(); i++) { 
if(info.getChild(i)!=null){ 
recycle(info.getChild(i)); 
} 
} 
} 
} 
@Override 
public void onInterrupt() { 
} 
}

代碼沒(méi)什么好說(shuō)的了,按照我們之前說(shuō)的三個(gè)步驟來(lái)就可以了,但是這里需要注意點(diǎn)細(xì)節(jié)上的問(wèn)題:

1、我們?cè)诒O(jiān)聽(tīng)到通知欄的消息的時(shí)候,調(diào)用如下代碼來(lái)進(jìn)行通知欄的消息點(diǎn)擊

if (content.contains("[微信紅包]")) { 
//模擬打開(kāi)通知欄消息 
if (event.getParcelableData() != null 
&& 
event.getParcelableData() instanceof Notification) { 
Notification notification = (Notification) event.getParcelableData(); 
PendingIntent pendingIntent = notification.contentIntent; 
try { 
pendingIntent.send(); 
} catch (CanceledException e) { 
e.printStackTrace(); 
} 
} 
}

2、我們?cè)谀M點(diǎn)擊通知欄消息之后,還是需要監(jiān)聽(tīng):AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED 這個(gè)事件,這個(gè)事件我們以后會(huì)經(jīng)常用到,這個(gè)事件就是在窗口發(fā)生改變的時(shí)候發(fā)出來(lái)的事件,很常用的,比如我們可以通過(guò)這個(gè)事件來(lái)監(jiān)聽(tīng)TopActivity,然后得到包名,這也是一個(gè)實(shí)現(xiàn)應(yīng)用鎖的一個(gè)原理。

3、我們?cè)诓檎翌I(lǐng)取紅包的時(shí)候,模擬點(diǎn)擊的時(shí)候做了一個(gè)工作,就是從“領(lǐng)取紅包”文本的控件View網(wǎng)上查找,查找到一個(gè)可以點(diǎn)擊的View出來(lái),然后模擬點(diǎn)擊

if(info.getText() != null){ 
if("領(lǐng)取紅包".equals(info.getText().toString())){ 
//這里有一個(gè)問(wèn)題需要注意,就是需要找到一個(gè)可以點(diǎn)擊的View 
Log.i("demo", "Click"+",isClick:"+info.isClickable()); 
info.performAction(AccessibilityNodeInfo.ACTION_CLICK); 
AccessibilityNodeInfo parent = info.getParent(); 
while(parent != null){ 
Log.i("demo", "parent isClick:"+parent.isClickable()); 
if(parent.isClickable()){ 
parent.performAction(AccessibilityNodeInfo.ACTION_CLICK); 
break; 
} 
parent = parent.getParent(); 
} 
} 
} 

這里為什么這么做,其實(shí)原理很簡(jiǎn)單,因?yàn)槲覀儾恢牢⑿潘慕缑娌季?,也不知道他?duì)哪個(gè)View進(jìn)行了setOnClickListener。我們可以寫一個(gè)例子,performAction方法只對(duì)調(diào)用了setOnClickListener方法的View模擬點(diǎn)擊才有效,其實(shí)看View的源碼也是可以看出來(lái)的.這里就不多解釋了。所以我們就需要得到一個(gè)View節(jié)點(diǎn)之后,從下往上找,直到找到一個(gè)可以click的View為止。

技術(shù)延展:

我們其實(shí)還可以使用DDMS工具里的Dump View Hierarchy For UI Automator 去分析微信UI結(jié)構(gòu),這個(gè)方法也是我后面才發(fā)現(xiàn)的,比上面的代碼更有效,如下圖:



這里我們可以看到View的詳細(xì)布局,還有每個(gè)View的屬性,還有很重要的信息resource-id,這個(gè)就是我們?cè)趚ml中定義的id,這個(gè)id我們也可以使用前面說(shuō)到的findAccessibilityNodeInfosByViewId("@id/xxx")來(lái)查找控件了
這個(gè)也算是學(xué)習(xí)了,學(xué)會(huì)使用DDMS來(lái)分析View結(jié)構(gòu)。

四、延展

關(guān)于微信搶紅包的原理解析上面已經(jīng)做了分析了,但是要想做到極致,這里還有很多問(wèn)題的,比如我們還需要過(guò)濾一些已經(jīng)領(lǐng)取過(guò)的紅包,這樣的話效率也是很高的。這個(gè)都是算法精確的問(wèn)題了,我想在這里說(shuō)的是,我們不僅可以用輔助功能來(lái)實(shí)現(xiàn)搶紅包,還可以實(shí)現(xiàn)很多功能,比如

1、靜默安裝

對(duì)于這兩個(gè)要求,我們或許很難得到,那么現(xiàn)在如果有了輔助功能,我們就好做了:

我們可以監(jiān)聽(tīng)系統(tǒng)的這個(gè)安裝界面,然后得到安裝節(jié)點(diǎn)View,然后模擬點(diǎn)擊即可,卸載也是同樣的原理

2、強(qiáng)制停止應(yīng)用

我們知道Android中停止應(yīng)用有很多方法,kill進(jìn)程,stopService,但是這些方法,有一些應(yīng)用它們都是有對(duì)策的,那么我們之前用到的強(qiáng)制停止的方法是獲取root權(quán)限調(diào)用系統(tǒng)的forceStop的api來(lái)停止,但是前提還是有root。那么現(xiàn)在如果我們有了輔助功能的話,我們可以這么做:

我們可以監(jiān)聽(tīng)系統(tǒng)的應(yīng)用詳情頁(yè)面,然后找到:結(jié)束運(yùn)行的節(jié)點(diǎn)View,然后模擬點(diǎn)擊即可

當(dāng)然上面我就說(shuō)了兩個(gè)簡(jiǎn)單的例子,還有很多輔助功能都是可以做的。他的好處就是不需要root權(quán)限。但是他也是需要用戶授權(quán)的:

如果用戶沒(méi)有授權(quán)的話,那么所有的工作都沒(méi)辦法開(kāi)始了,所以說(shuō)這個(gè)方法也不是萬(wàn)能的。當(dāng)然說(shuō)句題外話:有了輔助功能的話,他的危險(xiǎn)性比root之后的危險(xiǎn)性更大,比如我們上面的搶紅包插件,其實(shí)我們稍作修改,就可以獲取微信通訊錄信息,微信支付的密碼。這些事都是可以做的,所以說(shuō),我們?cè)谧鳛橛脩舻臅r(shí)候,進(jìn)行授權(quán)的時(shí)候還是需要三思而后行。

五、總結(jié)

關(guān)于輔助功能,之前沒(méi)有太多的接觸,是在一次工作中用到了這個(gè)功能,就去學(xué)習(xí)了一下,作為自己的興趣,就延展了學(xué)習(xí)了如何寫一個(gè)微信搶紅包的插件,同時(shí)可以考慮了使用輔助功能能夠做我們之前需要root做的事情。當(dāng)然輔助功能是google對(duì)于肢體上有障礙的人開(kāi)發(fā)出來(lái)的一個(gè)功能,我們開(kāi)發(fā)者或許使用這個(gè)功能,可以做一下產(chǎn)品的拓展功能,當(dāng)然這些是google沒(méi)有想到的事情,但是這個(gè)至少是我們開(kāi)發(fā)者在以后的開(kāi)發(fā)道路上的一個(gè)解決問(wèn)題的一個(gè)辦法和途徑,謹(jǐn)記此功能!

相關(guān)文章

  • Android中Glide獲取緩存大小并清除緩存圖片

    Android中Glide獲取緩存大小并清除緩存圖片

    這篇文章主要介紹了Android中Glide獲取緩存大小并清除緩存圖片,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • OpenGL ES渲染管線概述(一)

    OpenGL ES渲染管線概述(一)

    這篇文章主要為大家詳細(xì)介紹了OpenGL ES渲染管線的簡(jiǎn)單概述,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • Android開(kāi)發(fā)使用json實(shí)現(xiàn)服務(wù)器與客戶端數(shù)據(jù)的交互功能示例

    Android開(kāi)發(fā)使用json實(shí)現(xiàn)服務(wù)器與客戶端數(shù)據(jù)的交互功能示例

    這篇文章主要介紹了Android開(kāi)發(fā)使用json實(shí)現(xiàn)服務(wù)器與客戶端數(shù)據(jù)的交互功能,結(jié)合具體實(shí)例形式分析了Android使用json格式數(shù)據(jù)在服務(wù)器與客戶端傳遞實(shí)現(xiàn)數(shù)據(jù)庫(kù)查詢功能的步驟與相關(guān)操作技巧,需要的朋友可以參考下
    2017-10-10
  • android的GC內(nèi)存泄露問(wèn)題

    android的GC內(nèi)存泄露問(wèn)題

    本篇文章主要介紹了android GC內(nèi)存泄露問(wèn)題,具有一定的參考價(jià)值,有需要的可以了解一下。
    2016-11-11
  • Android開(kāi)關(guān)控件Switch的使用案例

    Android開(kāi)關(guān)控件Switch的使用案例

    今天小編就為大家分享一篇關(guān)于Android開(kāi)關(guān)控件Switch的使用案例,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-03-03
  • android WebView組件使用總結(jié)

    android WebView組件使用總結(jié)

    瀏覽器控件是每個(gè)開(kāi)發(fā)環(huán)境都具備的,這為馬甲神功提供了用武之地,windows的有webbrowser,android和ios都有webview;本篇主要介紹android的webview之強(qiáng)大,感興趣的朋友可以研究下
    2012-12-12
  • Android使用Jetpack WindowManager開(kāi)發(fā)可折疊設(shè)備(過(guò)程分享)

    Android使用Jetpack WindowManager開(kāi)發(fā)可折疊設(shè)備(過(guò)程分享)

    這篇文章主要介紹了Android使用Jetpack WindowManager開(kāi)發(fā)可折疊設(shè)備,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2023-11-11
  • Android中使用BitmapShader類來(lái)制作各種圖片的圓角

    Android中使用BitmapShader類來(lái)制作各種圖片的圓角

    這篇文章主要介紹了Android中使用BitmapShader類來(lái)制作各種圖片的圓角的方法,文中隨教程講解帶出的例子可以輕松控制圖片圓形的變換,很好很強(qiáng)大,需要的朋友可以參考下
    2016-04-04
  • Android小知識(shí)之OkHttp的2種請(qǐng)求方式詳解

    Android小知識(shí)之OkHttp的2種請(qǐng)求方式詳解

    OkHttp可以說(shuō)是如今最為流行的網(wǎng)絡(luò)請(qǐng)求框架之一,下面這篇文章主要給大家介紹了關(guān)于Android小知識(shí)之OkHttp的2種請(qǐng)求方式的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2018-10-10
  • Android從相冊(cè)選擇圖片剪切和上傳

    Android從相冊(cè)選擇圖片剪切和上傳

    這篇文章主要為大家詳細(xì)介紹了Android從相冊(cè)選擇一個(gè)圖片剪切、上傳的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-02-02

最新評(píng)論

吴忠市| 托克托县| 宁德市| 阜新| 无棣县| 女性| 徐水县| 施甸县| 襄垣县| 永宁县| 新平| 花莲市| 和田县| 阜新市| 阿瓦提县| 华容县| 富锦市| 金昌市| 新乡县| 陵川县| 福清市| 双城市| 望城县| 东丽区| 滨海县| 靖西县| 奈曼旗| 简阳市| 夏津县| 高州市| 承德县| 玉山县| 崇仁县| 通州市| 淮安市| 民勤县| 大邑县| 苍梧县| 石门县| 志丹县| 赫章县|