안 드 로 이 드 위 챗 자동 보너스 뺏 기
1.화면 에 나타 난 보 너 스 를 자동 으로 뜯 기
2.데스크 톱 또는 채 팅 목록 에 있 을 때 보너스 정 보 를 받 으 면 자동 으로 채 팅 창 에 들 어가 보너스 뜯 기
3.로그 기능,보너스 쟁탈 의 상세 로 그 를 기록
실현 원리
1.Accessibility Service 보조 서 비 스 를 이용 하여 스크린 내용 을 모니터링 하고 보 너 스 를 자동 으로 뜯 는 목적 을 실현 한다.
2.ActiveAndroid 데이터 베 이 스 를 이용 하여 보너스 로 그 를 간단하게 기록 합 니 다.
3.preference 를 이용 하여 모니터링 옵션 기록 실현
최종 인터페이스
보너스 쟁탈 핵심 코드
AccessibilityService 설정
android:accessibilityEventTypes
감청 회 조 를 촉발 하 는 이벤트 유형 을 설정 합 니 다.android:packageNames
감청 애플 리 케 이 션 을 설치 하고 여기 서 감청 하 는 것 은 위 챗 이 므 로 위 챗 의 가방 이름com.tencent.mm
을 기입 합 니 다.
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeNotificationStateChanged|typeWindowStateChanged|typeWindowContentChanged"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagDefault"
android:canRetrieveWindowContent="true"
android:description="@string/accessibility_description"
android:notificationTimeout="100"
android:packageNames="com.tencent.mm"
android:settingsActivity="com.oden.annotations.app.activity.ManActivity" />
AndroidManifest.xml 에서 설명:
<service
android:name=".app.service.HongbaoService_"
android:enabled="true"
android:exported="true"
android:label="@string/app_name"
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_config" />
</service>
보너스 실현 코드수신 시스템 에서 보 내 온
AccessibilityEvent
private static final String GET_RED_PACKET = " ";
private static final String CHECK_RED_PACKET = " ";
private static final String RED_PACKET_PICKED = " , ";
private static final String RED_PACKET_PICKED2 = " ";
private static final String RED_PACKET_PICKED_DETAIL = " ";
private static final String RED_PACKET_SAVE = " ";
private static final String RED_PACKET_NOTIFICATION = "[ ]";
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
L.d("RECEIVE EVENT!");
if (watchedFlags == null) return;
/* */
if (!mMutex) {
if (watchedFlags.get("pref_watch_notification") && watchNotifications(event)) return;
if (watchedFlags.get("pref_watch_list") && watchList(event)) return;
}
if (!watchedFlags.get("pref_watch_chat")) return;
this.rootNodeInfo = event.getSource();
if (rootNodeInfo == null) return;
mReceiveNode = null;
mUnpackNode = null;
checkNodeInfo();
/* */
if (mLuckyMoneyReceived && !mLuckyMoneyPicked && (mReceiveNode != null)) {
mMutex = true;
AccessibilityNodeInfo cellNode = mReceiveNode;
cellNode.getParent().performAction(AccessibilityNodeInfo.ACTION_CLICK);
mLuckyMoneyReceived = false;
mLuckyMoneyPicked = true;
L.d(" !");
}
/* */
if (mNeedUnpack && (mUnpackNode != null)) {
AccessibilityNodeInfo cellNode = mUnpackNode;
cellNode.performAction(AccessibilityNodeInfo.ACTION_CLICK);
mNeedUnpack = false;
L.d(" !");
}
if (mNeedBack) {
performGlobalAction(GLOBAL_ACTION_BACK);
mMutex = false;
mNeedBack = false;
L.d(" !");
//
if (isGetMoney) {
T.showShort(this, " : " + gotMoney + " !");
totalMoney = totalMoney + gotMoney;
totalSuccessNum++;
myPrefs.totalMoney().put(totalMoney);
myPrefs.successNum().put(totalSuccessNum);
L.d("totalMoney: " + totalMoney);
L.d("totalSuccessNum: " + totalSuccessNum);
saveToLog(hongbaoInfo);
isGetMoney = false;
}
}
}
감청 이벤트 의 노드 정 보 를 검사 합 니 다.
private void checkNodeInfo() {
L.d("checkNodeInfo!");
if (this.rootNodeInfo == null) return;
/* , “ ” " " */
List<AccessibilityNodeInfo> nodes1 = this.findAccessibilityNodeInfosByTexts(this.rootNodeInfo, new String[]{
GET_RED_PACKET, CHECK_RED_PACKET});
if (!nodes1.isEmpty()) {
L.d("!nodes1.isEmpty()");
AccessibilityNodeInfo targetNode = nodes1.get(nodes1.size() - 1);
if ("android.widget.LinearLayout".equals(targetNode.getParent().getClassName()))//
{
if (this.signature.generateSignature(targetNode)) {
mLuckyMoneyReceived = true;
mReceiveNode = targetNode;
L.d("signature:" + this.signature.toString());
}
} else {
L.d("this is text");
}
return;
}
List<AccessibilityNodeInfo> nodes2 = this.findAccessibilityNodeInfosByTexts(this.rootNodeInfo, new String[]{
" "});
if (!nodes2.isEmpty()) {
L.d("node2 != null");
for (AccessibilityNodeInfo nodeInfo : nodes2) {
if (nodeInfo.getClassName().equals("android.widget.Button"))
nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
} else {
/* , , “ ” */
AccessibilityNodeInfo node2 = (this.rootNodeInfo.getChildCount() > 3) ? this.rootNodeInfo.getChild(3) : null;
if (node2 != null && node2.getClassName().equals("android.widget.Button")) {
mUnpackNode = node2;
mNeedUnpack = true;
isToGetMoney = true;
L.d("find red packet!");
return;
}
}
/* , , “ ” “ ” */
if (mLuckyMoneyPicked) {
List<AccessibilityNodeInfo> nodes3 = this.findAccessibilityNodeInfosByTexts(this.rootNodeInfo, new String[]{
RED_PACKET_PICKED, RED_PACKET_SAVE, RED_PACKET_PICKED2, RED_PACKET_PICKED_DETAIL});
if (!nodes3.isEmpty()) {
L.d("!nodes3.isEmpty()");
if (rootNodeInfo.getChildCount() > 1) {
L.d("RED_PACKET_PICKED!");
} else {
L.d("nodes3.get(0).toString(): " + nodes3.get(0).getText().toString());
if (!nodes3.get(0).getText().toString().equals(RED_PACKET_PICKED_DETAIL)) {
AccessibilityNodeInfo targetNode = nodes3.get(nodes3.size() - 1);
hongbaoInfo.getInfo(targetNode);
if (isToGetMoney) {
isGetMoney = true;
isToGetMoney = false;
gotMoney = hongbaoInfo.getMoney();
L.d("gotMoney: " + gotMoney);
}
L.d("RED_PACKET_SAVE!");
L.d("hongbaoInfo: " + hongbaoInfo.toString());
} else {
L.d("this packet is myself!");
}
}
mNeedBack = true;
mLuckyMoneyPicked = false;
}
}
}
주로'보너스 수령'등 핵심 문자 정보 검 사 를 통 해 새 보너스 가 있 는 지 여 부 를 판단 한다.보 너 스 를 받 았 을 때'
android.widget.LinearLayout
'여 부 를 판단 하고 채 팅 메시지 의 문자 방 해 를 차단 합 니 다.보 너 스 를 뜯 을 때 위 챗 버 전이 다 를 수 있 기 때문에 두 가지 판단 을 동시에 하여 일부 버 전 을 호 환 할 수 있 습 니 다.
보 너 스 를 다 뜯 으 면 자동 으로 돌아 가 야 합 니 다.다음 과 같은 몇 가지 상황 이 있 습 니 다.빼 앗 았 고 손 이 느 리 며 이 보 너 스 는 자신 이 보 낸 보너스 입 니 다.
다음은 채 팅 목록 을 감청 하 는 코드 입 니 다.
private boolean watchList(AccessibilityEvent event) {
// Not a message
if (event.getEventType() != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED || event.getSource() == null)
return false;
List<AccessibilityNodeInfo> nodes = event.getSource().findAccessibilityNodeInfosByText(RED_PACKET_NOTIFICATION);
if (!nodes.isEmpty()) {
AccessibilityNodeInfo nodeToClick = nodes.get(0);
CharSequence contentDescription = nodeToClick.getContentDescription();
if (contentDescription != null && !lastContentDescription.equals(contentDescription)) {
nodeToClick.performAction(AccessibilityNodeInfo.ACTION_CLICK);
lastContentDescription = contentDescription.toString();
return true;
}
}
return false;
}
다음은 알림 정 보 를 감청 하 는 코드 입 니 다.
private boolean watchNotifications(AccessibilityEvent event) {
// Not a notification
if (event.getEventType() != AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED)
return false;
// Not a hongbao
String tip = event.getText().toString();
if (!tip.contains(RED_PACKET_NOTIFICATION)) return true;
Parcelable parcelable = event.getParcelableData();
if (parcelable instanceof Notification) {
Notification notification = (Notification) parcelable;
try {
notification.contentIntent.send();
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
}
return true;
}
보너스 정보 획득 및 로그 저장노드 의 서브 정 보 를 얻 고 보너스 발송 자 와 빼 앗 은 금액,보너스 시간 등 정 보 를 얻 으 며 간단 한 양식 을 만들어 이 정 보 를 각각 기록 합 니 다.
@Table(name = "HongbaoInfos")
public class HongbaoInfo extends Model {
private int month;
private int day;
private int hour;
private int min;
private int sec;
@Column(name = "sender")
public String sender;
@Column(name = "money")
public String money;
@Column(name = "time")
public String time;
public void getInfo(AccessibilityNodeInfo node) {
AccessibilityNodeInfo hongbaoNode = node.getParent();
sender = hongbaoNode.getChild(0).getText().toString();
money = hongbaoNode.getChild(2).getText().toString();
time = getStringTime();
}
private String getStringTime() {
Calendar c = Calendar.getInstance();
month = c.get(Calendar.MONTH) + 1;
day = c.get(Calendar.DAY_OF_MONTH);
hour = c.get(Calendar.HOUR_OF_DAY);
min = c.get(Calendar.MINUTE);
sec = c.get(Calendar.SECOND);
return month+" "+day+" "+hour+":"+min+":"+sec;
}
@Override
public String toString() {
return "HongbaoInfo [sender=" + sender + ", money=" + money + ", time=" + time + "]";
}
public static List<HongbaoInfo> getAll() {
return new Select()
.from(HongbaoInfo.class)
.orderBy("Id ASC")
.execute();
}
public static void deleteALL() {
new Delete().from(HongbaoInfo.class).execute();
}
public float getMoney() {
return Float.parseFloat(money);
}
public String getSender() {
return sender;
}
public String getTime() {
return time;
}
}
기억 장치 동작:
private void saveToLog(HongbaoInfo hongbaoInfo) {
if (watchedFlags.get("pref_etc_log")) {
HongbaoInfo hongbaoInfo1 = new HongbaoInfo();
hongbaoInfo1 = hongbaoInfo;
hongbaoInfo1.save();
} else {
L.d("log closed!");
}
}
총결산주요 코드 는 여기까지 기본적으로 끝 났 습 니 다.현재 위 챗 최신 판 에서 ok 을 테스트 하고 다음 과 같은 몇 가지 문제 가 존재 합 니 다.
1.같은 사람 이 연속 으로 보 낸 것 은 자동 으로 뺏 을 수 없습니다.중복 클릭 을 방지 하기 위해 필 터 를 했 기 때문에 같은 사람의 보 너 스 를 뺏 은 후에 다시 클릭 하지 않 습 니 다.
2.
AccessibilityService
오픈 시간 이 길 면 시스템 이 꺼 지기 도 한다.종결 어
이상 은 본 고의 모든 내용 이 니 여러분 의 학습 과 업무 에 도움 이 되 기 를 바 랍 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin의 기초 - 2부지난 글에서는 Kotlin이 무엇인지, Kotlin의 특징, Kotlin에서 변수 및 데이터 유형을 선언하는 방법과 같은 Kotlin의 기본 개념에 대해 배웠습니다. 유형 변환은 데이터 변수의 한 유형을 다른 데이터...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.