【移動應(yīng)用開發(fā)技術(shù)】Android輔助功如何實現(xiàn)自動搶紅包_第1頁
【移動應(yīng)用開發(fā)技術(shù)】Android輔助功如何實現(xiàn)自動搶紅包_第2頁
【移動應(yīng)用開發(fā)技術(shù)】Android輔助功如何實現(xiàn)自動搶紅包_第3頁
【移動應(yīng)用開發(fā)技術(shù)】Android輔助功如何實現(xiàn)自動搶紅包_第4頁
【移動應(yīng)用開發(fā)技術(shù)】Android輔助功如何實現(xiàn)自動搶紅包_第5頁
已閱讀5頁,還剩23頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)

文檔簡介

【移動應(yīng)用開發(fā)技術(shù)】Android輔助功如何實現(xiàn)自動搶紅包

一、描述二、效果圖/upload/information/20200623/125/125800.gif/upload/information/20200623/125/125801.gif三、AccessibilityService使用public

class

MyService

extends

AccessibilityService

{

@Override

public

void

onAccessibilityEvent(AccessibilityEvent

event)

{

}

@Override

public

void

onInterrupt()

{

}

}//具體屬性的說明在第5點有說明

<?xml

version="1.0"

encoding="utf-8"?>

<accessibility-service

xmlns:android="/apk/res/android"

android:description="@string/accessibility_service_description"

android:accessibilityEventTypes="typeAllMask"

android:accessibilityFeedbackType="feedbackGeneric"

android:notificationTimeout="100"

android:accessibilityFlags="flagDefault"

android:canRetrieveWindowContent="true"

android:packageNames="top.cokernut.sample"

android:settingsActivity="com.example.android.accessibility.ServiceSettingsActivity"

/><service

android:name=".MyService"

android:label="輔助功能"

android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">

<intent-filter>

<action

android:name="android.accessibilityservice.AccessibilityService"

/>

</intent-filter>

<meta-data

android:name="android.accessibilityservice"

android:resource="@xml/accessibility_service_info"

/>

</service>

<uses-permission

android:name="android.permission.BIND_ACCESSIBILITY_SERVICE"

/>//是否可以檢索整個層級下的內(nèi)容

android:canRetrieveWindowContent="true"級下的信息

//事件通知觸發(fā)點,比如窗口打開,滑動,焦點變化,長按等。

android:accessibilityEventTypes="typeAllMask"

#TYPES_ALL_MASK:所有類型

#TYPE_VIEW_CLICKED

:單擊

#TYPE_VIEW_LONG_CLICKED

:長按

#TYPE_VIEW_SELECTED

:選中

#TYPE_VIEW_FOCUSED

:獲取焦點

#TYPE_VIEW_TEXT_CHANGED

:文字改變

#TYPE_WINDOW_STATE_CHANGED

:窗口狀態(tài)改變

//表示反饋方式,比如是語音播放,還是震動

android:accessibilityFeedbackType="feedbackGeneric"

//接受事件的時間間隔,通常將其設(shè)置為100即可.

android:notificationTimeout="100"

//表示該服務(wù)是用來單獨監(jiān)聽哪個應(yīng)用的產(chǎn)生的事件,其他的都會過濾,如果不填就是對所有的應(yīng)用進行監(jiān)聽,填入包名即可。

android:packageNames="top.cokernut.sample"

//在代碼中我們就可以通過node節(jié)點來getViewIdResourceName()獲取對應(yīng)的節(jié)點的id

android:accessibilityFlags="flagDefault"public

class

BaseAccessibilityService

extends

AccessibilityService

{

private

AccessibilityManager

mAccessibilityManager;

private

Context

mContext;

private

static

BaseAccessibilityService

mInstance;

public

void

init(Context

context)

{

mContext

=

context.getApplicationContext();

mAccessibilityManager

=

(AccessibilityManager)

mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);

}

public

static

BaseAccessibilityService

getInstance()

{

if

(mInstance

==

null)

{

mInstance

=

new

BaseAccessibilityService();

}

return

mInstance;

}

/**

*

Check當(dāng)前輔助服務(wù)是否啟用

*

*

@param

serviceName

serviceName

*

@return

是否啟用

*/

private

boolean

checkAccessibilityEnabled(String

serviceName)

{

List<AccessibilityServiceInfo>

accessibilityServices

=

mAccessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_GENERIC);

for

(AccessibilityServiceInfo

info

:

accessibilityServices)

{

if

(info.getId().equals(serviceName))

{

return

true;

}

}

return

false;

}

/**

*

前往開啟輔助服務(wù)界面

*/

public

void

goAccess()

{

Intent

intent

=

new

Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

mContext.startActivity(intent);

}

/**

*

模擬點擊事件

*

*

@param

nodeInfo

nodeInfo

*/

public

void

performViewClick(AccessibilityNodeInfo

nodeInfo)

{

if

(nodeInfo

==

null)

{

return;

}

while

(nodeInfo

!=

null)

{

if

(nodeInfo.isClickable())

{

nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);

break;

}

nodeInfo

=

nodeInfo.getParent();

}

}

/**

*

模擬返回操作

*/

public

void

performBackClick()

{

try

{

Thread.sleep(500);

}

catch

(InterruptedException

e)

{

e.printStackTrace();

}

performGlobalAction(GLOBAL_ACTION_BACK);

}

/**

*

模擬下滑操作

*/

public

void

performScrollBackward()

{

try

{

Thread.sleep(500);

}

catch

(InterruptedException

e)

{

e.printStackTrace();

}

performGlobalAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);

}

/**

*

模擬上滑操作

*/

public

void

performScrollForward()

{

try

{

Thread.sleep(500);

}

catch

(InterruptedException

e)

{

e.printStackTrace();

}

performGlobalAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);

}

/**

*

查找對應(yīng)文本的View

*

*

@param

text

text

*

@return

View

*/

public

AccessibilityNodeInfo

findViewByText(String

text)

{

return

findViewByText(text,

false);

}

/**

*

查找對應(yīng)文本的View

*

*

@param

text

text

*

@param

clickable

該View是否可以點擊

*

@return

View

*/

public

AccessibilityNodeInfo

findViewByText(String

text,

boolean

clickable)

{

AccessibilityNodeInfo

accessibilityNodeInfo

=

getRootInActiveWindow();

if

(accessibilityNodeInfo

==

null)

{

return

null;

}

List<AccessibilityNodeInfo>

nodeInfoList

=

accessibilityNodeInfo.findAccessibilityNodeInfosByText(text);

if

(nodeInfoList

!=

null

&&

!nodeInfoList.isEmpty())

{

for

(AccessibilityNodeInfo

nodeInfo

:

nodeInfoList)

{

if

(nodeInfo

!=

null

&&

(nodeInfo.isClickable()

==

clickable))

{

return

nodeInfo;

}

}

}

return

null;

}

/**

*

查找對應(yīng)ID的View

*

*

@param

id

id

*

@return

View

*/

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)

public

AccessibilityNodeInfo

findViewByID(String

id)

{

AccessibilityNodeInfo

accessibilityNodeInfo

=

getRootInActiveWindow();

if

(accessibilityNodeInfo

==

null)

{

return

null;

}

List<AccessibilityNodeInfo>

nodeInfoList

=

accessibilityNodeInfo.findAccessibilityNodeInfosByViewId(id);

if

(nodeInfoList

!=

null

&&

!nodeInfoList.isEmpty())

{

for

(AccessibilityNodeInfo

nodeInfo

:

nodeInfoList)

{

if

(nodeInfo

!=

null)

{

return

nodeInfo;

}

}

}

return

null;

}

public

void

clickTextViewByText(String

text)

{

AccessibilityNodeInfo

accessibilityNodeInfo

=

getRootInActiveWindow();

if

(accessibilityNodeInfo

==

null)

{

return;

}

List<AccessibilityNodeInfo>

nodeInfoList

=

accessibilityNodeInfo.findAccessibilityNodeInfosByText(text);

if

(nodeInfoList

!=

null

&&

!nodeInfoList.isEmpty())

{

for

(AccessibilityNodeInfo

nodeInfo

:

nodeInfoList)

{

if

(nodeInfo

!=

null)

{

performViewClick(nodeInfo);

break;

}

}

}

}

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)

public

void

clickTextViewByID(String

id)

{

AccessibilityNodeInfo

accessibilityNodeInfo

=

getRootInActiveWindow();

if

(accessibilityNodeInfo

==

null)

{

return;

}

List<AccessibilityNodeInfo>

nodeInfoList

=

accessibilityNodeInfo.findAccessibilityNodeInfosByViewId(id);

if

(nodeInfoList

!=

null

&&

!nodeInfoList.isEmpty())

{

for

(AccessibilityNodeInfo

nodeInfo

:

nodeInfoList)

{

if

(nodeInfo

!=

null)

{

performViewClick(nodeInfo);

break;

}

}

}

}

/**

*

模擬輸入

*

*

@param

nodeInfo

nodeInfo

*

@param

text

text

*/

public

void

inputText(AccessibilityNodeInfo

nodeInfo,

String

text)

{

if

(Build.VERSION.SDK_INT

>=

Build.VERSION_CODES.LOLLIPOP)

{

Bundle

arguments

=

new

Bundle();

arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,

text);

nodeInfo.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT,

arguments);

}

else

if

(Build.VERSION.SDK_INT

>=

Build.VERSION_CODES.JELLY_BEAN_MR2)

{

ClipboardManager

clipboard

=

(ClipboardManager)

getSystemService(Context.CLIPBOARD_SERVICE);

ClipData

clip

=

ClipData.newPlainText("label",

text);

clipboard.setPrimaryClip(clip);

nodeInfo.performAction(AccessibilityNodeInfo.ACTION_FOCUS);

nodeInfo.performAction(AccessibilityNodeInfo.ACTION_PASTE);

}

}

@Override

public

void

onAccessibilityEvent(AccessibilityEvent

event)

{

}

@Override

public

void

onInterrupt()

{

}

}四、QQ搶紅包/**

*

描述:QQ搶紅包服務(wù)

*

作者:卜俊文

*

郵箱:344176791@

*

日期:2017/11/6

上午9:25

*/

public

class

EnvelopeService

extends

BaseAccessibilityService

{

//鎖屏、解鎖相關(guān)

private

KeyguardManager.KeyguardLock

kl;

//喚醒屏幕相關(guān)

private

PowerManager.WakeLock

wl

=

null;

private

long

delayTime

=

0;//延遲搶的時間

/**

*

描述:所有事件響應(yīng)的時候會回調(diào)

*

作者:卜俊文

*

郵箱:344176791@

*

日期:2017/11/6

上午9:26

*/

@Override

public

void

onAccessibilityEvent(AccessibilityEvent

event)

{

//驗證搶紅包的開關(guān)

if

(!invalidEnable())

{

return;

}

//事件類型

int

eventType

=

event.getEventType();

//獲取包名

CharSequence

packageName

=

event.getPackageName();

if

(TextUtils.isEmpty(packageName))

{

return;

}

switch

(eventType)

{

//狀態(tài)欄變化

case

AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:

if

(QQConstant.QQ_PACKAGE_NAME.equals(packageName))

{

//處理狀態(tài)欄上QQ的消息,如果是紅包就跳轉(zhuǎn)過去

progressQQStatusBar(event);

}

break;

//窗口切換的時候回調(diào)

case

AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:

case

AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:

if

(QQConstant.QQ_PACKAGE_NAME.equals(packageName))

{

//處理正在QQ聊天窗口頁面,有其他群或者人有新的紅包提醒,跳轉(zhuǎn)過去。

progressNewMessage(event);

//處理聊天頁面的紅包

progressQQChat(event);

}

break;

}

}

/**

*

描述:處理新消息

*

作者:卜俊文

*

郵箱:344176791@

*

日期:2017/11/3

下午11:21

*/

private

void

progressNewMessage(AccessibilityEvent

event)

{

if

(event

==

null)

{

return;

}

AccessibilityNodeInfo

source

=

event.getSource();

if

(source

==

null)

{

return;

}

//根據(jù)event的source里的text,來判斷這個消息是否包含[QQ紅包]的字眼,有的話就跳轉(zhuǎn)過去

CharSequence

text

=

source.getText();

if

(!TextUtils.isEmpty(text)

&&

text.toString().contains(QQConstant.QQ_ENVELOPE_KEYWORD))

{

performViewClick(source);

}

}

/**

*

描述:驗證搶紅包是否開啟

*

作者:卜俊文

*

郵箱:344176791@

*

日期:2017/11/3

下午4:57

*/

private

boolean

invalidEnable()

{

return

SettingConfig.getInstance().getReEnable();

}

/**

*

描述:處理QQ狀態(tài)欄

*

作者:卜俊文

*

郵箱:344176791@

*

日期:2017/11/1

下午1:49

*/

public

void

progressQQStatusBar(AccessibilityEvent

event)

{

List<CharSequence>

text

=

event.getText();

//開始檢索界面上是否有QQ紅包的文本,并且他是通知欄的信息

if

(text

!=

null

&&

text.size()

>

0)

{

for

(CharSequence

charSequence

:

text)

{

if

(charSequence.toString().contains(QQConstant.QQ_ENVELOPE_KEYWORD))

{

//說明存在紅包彈窗,馬上進去

if

(event.getParcelableData()

!=

null

&&

event.getParcelableData()

instanceof

Notification)

{

Notification

notification

=

(Notification)

event.getParcelableData();

if

(notification

==

null)

{

return;

}

PendingIntent

pendingIntent

=

notification.contentIntent;

if

(pendingIntent

==

null)

{

return;

}

try

{

//要跳轉(zhuǎn)之前,先進行解鎖屏幕,然后再跳轉(zhuǎn),有可能你現(xiàn)在屏幕是鎖屏狀態(tài),先進行解鎖,然后打開頁面,有密碼的可能就不行了

wakeUpAndUnlock(MyApp.context);

//跳轉(zhuǎn)

pendingIntent.send();

}

catch

(PendingIntent.CanceledException

e)

{

e.printStackTrace();

}

}

}

}

}

}

/**

*

描述:處理QQ聊天紅包

*

作者:卜俊文

*

郵箱:344176791@

*

日期:2017/11/1

下午1:56

*/

public

void

progressQQChat(AccessibilityEvent

event)

{

if

(TextUtils.isEmpty(event.getClassName()))

{

return;

//如果當(dāng)前頁面是聊天頁面或者當(dāng)前的描述信息是"返回消息界面",就肯定是對話頁面

}

//驗證當(dāng)前事件是否符合查詢頁面上的紅包

if

(!invalidEnvelopeUi(event))

{

return;

}

//延遲點擊紅包,防止被檢測到開了搶紅包,不過感覺還是感覺會被檢測到,應(yīng)該有的效果吧...

try

{

Thread.sleep(delayTime);

}

catch

(InterruptedException

e)

{

e.printStackTrace();

}

//普通紅包,檢索點擊拆開的字眼。

List<AccessibilityNodeInfo>

envelope

=

findViewListByText(QQConstant.QQ_CLICK_TAKE_APART,

false);

//處理普通紅包

progressNormal(envelope);

//口令紅包,檢索口令紅包的字眼。

List<AccessibilityNodeInfo>

passwordList

=

findViewListByText(QQConstant.QQ_CLICK_PASSWORD_DIALOG,

false);

//處理口令紅包

progressPassword(passwordList);

}

/**

*

描述:驗證是否現(xiàn)在是在聊天頁面,可以進行搶紅包處理

*

作者:卜俊文

*

郵箱:344176791@

*

日期:2017/11/3

上午11:52

*

*

@param

event

*/

public

boolean

invalidEnvelopeUi(AccessibilityEvent

event)

{

//判斷類名是否是聊天頁面

if

(!QQConstant.QQ_IM_CHAT_ACTIVITY.equals(event.getClassName().toString()))

{

return

true;

}

//判斷頁面中的元素是否有點擊拆開的文本,有就返回可以進行查詢了

int

recordCount

=

event.getRecordCount();

if

(recordCount

>

0)

{

for

(int

i

=

0;

i

<

recordCount;

i++)

{

AccessibilityRecord

record

=

event.getRecord(i);

if

(record

==

null)

{

break;

}

List<CharSequence>

text

=

record.getText();

if

(text

!=

null

&&

text.size()

>

0

&&

text.contains(QQConstant.QQ_CLICK_TAKE_APART))

{

//如果文本中有點擊拆開的字眼,就返回可以進行查詢了

return

true;

}

}

}

return

false;

}

/**

*

回到系統(tǒng)桌面

*/

private

void

back2Home(int

time)

{

try

{

Thread.sleep(time);

}

catch

(InterruptedException

e)

{

e.printStackTrace();

}

Intent

home

=

new

Intent(Intent.ACTION_MAIN);

home.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

home.addCategory(Intent.CATEGORY_HOME);

startActivity(home);

}

/**

*

描述:處理普通紅包

*

作者:卜俊文

*

郵箱:344176791@

*

日期:2017/11/1

下午5:02

*/

public

void

progressNormal(List<AccessibilityNodeInfo>

passwordList)

{

if

(passwordList

!=

null

&&

passwordList.size()

>

0)

{

for

(AccessibilityNodeInfo

accessibilityNodeInfo

:

passwordList)

{

if

(accessibilityNodeInfo

!=

null

&&

!TextUtils.isEmpty(accessibilityNodeInfo.getText())

&&

QQConstant.QQ_CLICK_TAKE_APART.equals(accessibilityNodeInfo.getText().toString()))

{

//點擊拆開紅包

performViewClick(accessibilityNodeInfo);

//回復(fù)感謝信息,根據(jù)配置文件中配置的回復(fù)信息回復(fù)

String

reReplyMessage

=

SettingConfig.getInstance().getReReplyMessage();

if

(!TextUtils.isEmpty(reReplyMessage))

{

replyMessage(reReplyMessage);

}

}

}

//最后延遲事件觸發(fā)返回事件,關(guān)閉紅包頁面

performBackClick(1200);

}

}

/**

*

描述:處理口令紅包

*

作者:卜俊文

*

郵箱:344176791@

*

日期:2017/11/1

下午4:58

*

*

@param

passwordList

*/

public

void

progressPassword(List<AccessibilityNodeInfo>

passwordList)

{

if

(passwordList

!=

null

&&

passwordList.size()

>

0)

{

for

(AccessibilityNodeInfo

accessibilityNodeInfo

:

passwordList)

{

if

(accessibilityNodeInfo

!=

null

&&

!TextUtils.isEmpty(accessibilityNodeInfo.getText())

&&

QQConstant.QQ_CLICK_PASSWORD_DIALOG.equals(accessibilityNodeInfo.getText().toString()))

{

//如果口令紅包存在,就在輸入框中進行輸入,然后發(fā)送

AccessibilityNodeInfo

parent

=

accessibilityNodeInfo.getParent();

if

(parent

!=

null)

{

CharSequence

contentDescription

=

parent.getContentDescription();

if

(!TextUtils.isEmpty(contentDescription))

{

//1.

獲取口令

String

key

=

(String)

contentDescription;

if

(key.contains(",")

&&

key.contains("口令:"))

{

key

=

key.substring(key.indexOf("口令:")

+

3,

key.lastIndexOf(","));

}

Log.e("口令",

key);

//2.

填寫口令到編輯框上然后進行發(fā)送

replyMessage(key);

//返回,關(guān)閉紅包頁面

performBackClick(1200);

}

}

}

}

}

}

/**

*

喚醒屏幕并解鎖權(quán)限

*

<uses-permission

android:name="android.permission.WAKE_LOCK"

/>

*/

@SuppressLint("Wakelock")

@SuppressWarnings("deprecation")

public

void

wakeUpAndUnlock(Context

context)

{

//

點亮屏幕

wl.acquire();

//

釋放

wl.release();

//

解鎖

kl.disableKeyguard();

}

/**

*

描述:回復(fù)消息,無延遲

*

作者:卜俊文

*

郵箱:344176791@

*

日期:2017/11/3

下午5:10

*/

public

void

replyMessage(String

key)

{

replyMessage(key,

0);

}

/**

*

描述:回復(fù)消息

*

作者:卜俊文

*

郵箱:344176791@

*

日期:2017/11/3

下午5:10

*/

public

void

replyMessage(String

key,

int

time)

{

//延遲

if

(time

>

0)

{

try

{

Thread.sleep(time);

}

catch

(InterruptedException

e)

{

e.printStackTrace();

}

}

//獲取QQ聊天頁面輸入框

AccessibilityNodeInfo

chat_edit

=

findViewByID(QQConstant.QQ_CHAT_MESSAGE_INPUT);

if

(chat_edit

!=

null)

{

//把口令粘貼到輸入框中

pastaText(chat_edit,

MyApp.context,

key);

//獲取QQ聊天頁面發(fā)送消息按鈕

AccessibilityNodeInfo

sendMessage

=

findViewByID(QQConstant.QQ_CHAT_MESSAGE_SEND);

//然后就按下發(fā)送按鈕

if

(sendMessage

!=

null

&&

Button.class.getName().equals(sendMessage.getClassName()))

{

performViewClick(sendMessage);

}

}

}

@Override

public

void

onInterrupt()

{

}

@Override

protected

void

onService

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論