안 드 로 이 드 위 챗 자동 보너스 뺏 기

본 고 는 위 챗 이 자동 으로 보 너 스 를 빼 앗 는 실현 방법 을 소개 하 는데 주로 다음 과 같은 몇 가지 기능 을 실현 한다.
      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오픈 시간 이 길 면 시스템 이 꺼 지기 도 한다.
종결 어
이상 은 본 고의 모든 내용 이 니 여러분 의 학습 과 업무 에 도움 이 되 기 를 바 랍 니 다.

좋은 웹페이지 즐겨찾기