Android 에서 위 챗 보너스 쟁탈 조수 의 실현 에 대한 상세 한 설명

실현 원리
Accessibility Service 보조 서 비 스 를 이용 하여 모니터 내용,예 를 들 어 감청 상태 표시 줄 의 정보,스크린 점프 등 을 모니터링 함으로써 자동 으로 보 너 스 를 뜯 는 기능 을 실현 한다.Accessibility Service 보조 서비스 에 대해 서 는 자체 바 이 두 에서 더 많은 것 을 알 수 있 습 니 다. 
코드 기반:
1.먼저 RedPacketService 가 Accessibility Service 에서 계승 되 었 다 고 밝 혔 습 니 다.이 서비스 유형 은 두 가지 방법 으로 다시 써 야 합 니 다.다음 과 같 습 니 다.

/**
 * Created by cxk on 2017/2/3.
 *
 *       
 */

public class RedPacketService extends AccessibilityService {


  /**
   *        :            event。     event      。             。
   */
  @Override
  public void onAccessibilityEvent(AccessibilityEvent event) {

  }

  /**
   *        :      service         。             。
   */
  @Override
  public void onInterrupt() {
    Toast.makeText(this, "       -----", Toast.LENGTH_SHORT).show();
  }

  /**
   *      
   */
  @Override
  protected void onServiceConnected() {
    Toast.makeText(this, "       ", Toast.LENGTH_SHORT).show();
    super.onServiceConnected();
  }

  /**
   *      
   */
  @Override
  public boolean onUnbind(Intent intent) {
    Toast.makeText(this, "         ", Toast.LENGTH_SHORT).show();
    return super.onUnbind(intent);
  }
}

2.우리 의 RedPacketService 를 설정 합 니 다.이 설정 방법 은 코드 동적 설정(onServiceConnected 에서 설정)을 선택 할 수도 있 고 res/xml 에서.xml 파일 을 직접 새로 만 들 수도 있 습 니 다.xml 폴 더 없 이 새로 만 들 수도 있 습 니 다.여기 서 우 리 는 파일 을 redpacket 라 고 명명 합 니 다.service_config.xml,코드 는 다음 과 같 습 니 다.

<?xml version="1.0" encoding="utf-8"?>
<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/desc"
  android:notificationTimeout="100"
  android:packageNames="com.tencent.mm" />
accessibilityEventTypes:  
어떤 종류의 이벤트 에 응답 하 는 지 type:AllMask 는 모든 종류의 이벤트 에 응답 하 는 것 입 니 다.또한 클릭,길 게 누 르 기,미끄럼 등 도 있 습 니 다.
accessibilityFeedbackType: 
어떤 방식 으로 사용자 에 게 피드백 하고 음성 방송 과 진동 이 있 습 니까?발음 이 가능 하도록 TTS 엔진 을 설정 할 수 있 습 니 다.
packageNames:
어떤 이벤트 에 응답 할 지 지정 합 니 다.여기 서 우 리 는 보 너 스 를 빼 앗 는 조 수 를 쓰 고 위 챗 의 가방 이름 을 쓴다.com.tencent.mm.그러면 위 챗 에서 발생 한 사건 을 감청 할 수 있다.
notificationTimeout:
응답 시간
description:
보조 서비스의 설명 정보.
 3.service 는 4 대 구성 요소 중 하나 입 니 다.AndroidManifest 에서 설정 해 야 합 니 다.여기 가 조금 다 릅 니 다.

 <!--     -->
    <service
      android:name=".RedPacketService"
      android:enabled="true"
      android:exported="true"
      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/redpacket_service_config"></meta-data>
    </service>

android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"  권한 신청
android:resource="@xml/redpacket_service_config"  방금 설정 파일 참조
핵심 코드:
우리 의 보너스 조수,핵심 사고방식 은 세 단계 로 나 뉜 다.
감청 알림 표시 줄 위 챗 메시지,[위 챗 보너스]메시지 가 뜨 면 아 날로 그 손가락 클릭 상태 표시 줄 이 위 챗 채 팅 창 으로 넘 어 갑 니 다→위 챗 채 팅 창 에서 보 너 스 를 찾 습 니 다.찾 으 면 아 날로 그 손가락 클릭 으로 열 립 니 다.팝 업 으로 보 너 스 를 엽 니 다→아 날로 그 손가락 으로 보 너 스 를 클릭 합 니 다""
1.알림 표시 줄 메 시 지 를 듣 고[위 챗 보너스]라 는 글자 가 있 는 지 확인 합 니 다.코드 는 다음 과 같 습 니 다.
 

  @Override
  public void onAccessibilityEvent(AccessibilityEvent event) {
    int eventType = event.getEventType();
    switch (eventType) {
      //      ,            ,     
      case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
        List<CharSequence> texts = event.getText();
        for (CharSequence text : texts) {
          String content = text.toString();
          if (!TextUtils.isEmpty(content)) {
            //      [    ]  
            if (content.contains("[    ]")) {
              //            
              openWeChatPage(event);
            }
          }
        }
        break;
     }
 }

   /**
   *            
   */
  private void openWeChatPage(AccessibilityEvent event) {
    //A instanceof B            A   B  ,           
    if (event.getParcelableData() != null && event.getParcelableData() instanceof Notification) {
      Notification notification = (Notification) event.getParcelableData();
      //         
      PendingIntent pendingIntent = notification.contentIntent;
      try {
        pendingIntent.send();
      } catch (PendingIntent.CanceledException e) {
        e.printStackTrace();
      }
    }
  }

2.현재 위 챗 채 팅 페이지 에 있 는 지 여 부 를 판단 합 니 다.그렇다면 현재 페이지 의 각 컨트롤 을 옮 겨 다 니 며 위 챗 보너스 가 들 어 있 거나 보 너 스 를 받 는 textview 컨트롤 을 찾 은 다음 에 한 층 한 층 그 를 찾 으 면 부모 레이아웃(그림 의 녹색 부분)을 클릭 하고''이 들 어 있 는 것 으로 전환 하 는 것 을 모 의 합 니 다.의 보너스 인터페이스,코드 는 다음 과 같 습 니 다:

 @Override
  public void onAccessibilityEvent(AccessibilityEvent event) {
    int eventType = event.getEventType();
    switch (eventType) {
      //             
      case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
        String className = event.getClassName().toString();
        //           
        if ("com.tencent.mm.ui.LauncherUI".equals(className)) {
          //            
          AccessibilityNodeInfo rootNode = getRootInActiveWindow();
          //     
          findRedPacket(rootNode);
        }
    }
  }
  /**
   *       
   */
  private void findRedPacket(AccessibilityNodeInfo rootNode) {
    if (rootNode != null) {
      //         
      for (int i = rootNode.getChildCount() - 1; i >= 0; i--) {
        AccessibilityNodeInfo node = rootNode.getChild(i);
        //  node        
        if (node == null) {
          continue;
        }
        CharSequence text = node.getText();
        if (text != null && text.toString().equals("    ")) {
          AccessibilityNodeInfo parent = node.getParent();
          //while  ,  "    "      ,          
          while (parent != null) {
            if (parent.isClickable()) {
              //    
              parent.performAction(AccessibilityNodeInfo.ACTION_CLICK);
              //isOpenRP            
              isOpenRP = true;
              break;
            }
            parent = parent.getParent();
          }
        }
        //                 ,      for  ,        
        if (isOpenRP) {
          break;
        } else {
          findRedPacket(node);
        }

      }
    }
  }

3.보너스 클릭 후 아 날로 그 손가락 으로""클릭이 를 통 해 보 너 스 를 오픈 하고 보 너 스 상세 화면 으로 이동 합 니 다.방법 은 절차 2 와 유사 합 니 다.

 @Override
  public void onAccessibilityEvent(AccessibilityEvent event) {
    int eventType = event.getEventType();
    switch (eventType) {
      //             
      case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
        String className = event.getClassName().toString();
     
        //       ‘ '       
        if ("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI".equals(className)) {
          AccessibilityNodeInfo rootNode = getRootInActiveWindow();
          //     
          openRedPacket(rootNode);
        }
        break;
    }
  }

  /**
   *       
   */
  private void openRedPacket(AccessibilityNodeInfo rootNode) {
    for (int i = 0; i < rootNode.getChildCount(); i++) {
      AccessibilityNodeInfo node = rootNode.getChild(i);
      if ("android.widget.Button".equals(node.getClassName())) {
        node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
      }
      openRedPacket(node);
    }
  }

상기 세 단 계 를 결합 하면 아래 는 전체 코드 이 고 주석 은 이미 명확 하 게 쓰 여 있 으 며 코드 를 직접 볼 수 있 습 니 다.

package com.cxk.redpacket;

import android.accessibilityservice.AccessibilityService;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.os.PowerManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Toast;

import java.util.List;

/**
 *    Service,  AccessibilityService
 */
public class RedPacketService extends AccessibilityService {
  /**
   *          +  。          LAUCHER-      ,LUCKEY_MONEY_RECEIVER-         
   */
  private String LAUCHER = "com.tencent.mm.ui.LauncherUI";
  private String LUCKEY_MONEY_DETAIL = "com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI";
  private String LUCKEY_MONEY_RECEIVER = "com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI";

  /**
   *             
   */
  private boolean isOpenRP;

  @Override
  public void onAccessibilityEvent(AccessibilityEvent event) {
    int eventType = event.getEventType();
    switch (eventType) {
      //      ,            ,     
      case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
        List<CharSequence> texts = event.getText();
        for (CharSequence text : texts) {
          String content = text.toString();
          if (!TextUtils.isEmpty(content)) {
            //      [    ]  
            if (content.contains("[    ]")) {
              //            
              openWeChatPage(event);

              isOpenRP=false;
            }
          }
        }
        break;
      //       
      case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
        String className = event.getClassName().toString();
        //           
        if (LAUCHER.equals(className)) {
          //            
          AccessibilityNodeInfo rootNode = getRootInActiveWindow();
          //     
          findRedPacket(rootNode);
        }

        //       ‘ '       
        if (LUCKEY_MONEY_RECEIVER.equals(className)) {
          AccessibilityNodeInfo rootNode = getRootInActiveWindow();
          //     
          openRedPacket(rootNode);
        }

        //               
        if(LUCKEY_MONEY_DETAIL.equals(className)){
          //    
          back2Home();
        }
        break;
    }
  }

  /**
   *       
   */
  private void openRedPacket(AccessibilityNodeInfo rootNode) {
    for (int i = 0; i < rootNode.getChildCount(); i++) {
      AccessibilityNodeInfo node = rootNode.getChild(i);
      if ("android.widget.Button".equals(node.getClassName())) {
        node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
      }
      openRedPacket(node);
    }
  }

  /**
   *       
   */
  private void findRedPacket(AccessibilityNodeInfo rootNode) {
    if (rootNode != null) {
      //         
      for (int i = rootNode.getChildCount() - 1; i >= 0; i--) {
        AccessibilityNodeInfo node = rootNode.getChild(i);
        //  node        
        if (node == null) {
          continue;
        }
        CharSequence text = node.getText();
        if (text != null && text.toString().equals("    ")) {
          AccessibilityNodeInfo parent = node.getParent();
          //while  ,  "    "      ,          
          while (parent != null) {
            if (parent.isClickable()) {
              //    
              parent.performAction(AccessibilityNodeInfo.ACTION_CLICK);
              //isOpenRP            
              isOpenRP = true;
              break;
            }
            parent = parent.getParent();
          }
        }
        //                 ,      for  ,        
        if (isOpenRP) {
          break;
        } else {
          findRedPacket(node);
        }

      }
    }
  }

  /**
   *            
   */
  private void openWeChatPage(AccessibilityEvent event) {
    //A instanceof B            A   B  ,           
    if (event.getParcelableData() != null && event.getParcelableData() instanceof Notification) {
      Notification notification = (Notification) event.getParcelableData();
      //         
      PendingIntent pendingIntent = notification.contentIntent;
      try {
        pendingIntent.send();
      } catch (PendingIntent.CanceledException e) {
        e.printStackTrace();
      }
    }
  }


  /**
   *     
   */
  @Override
  protected void onServiceConnected() {
    Toast.makeText(this, "       ", Toast.LENGTH_SHORT).show();
    super.onServiceConnected();
  }

  /**
   *        :      service         。             。
   */
  @Override
  public void onInterrupt() {
    Toast.makeText(this, "       -----", Toast.LENGTH_SHORT).show();
  }

  /**
   *     
   */
  @Override
  public boolean onUnbind(Intent intent) {
    Toast.makeText(this, "         ", Toast.LENGTH_SHORT).show();
    return super.onUnbind(intent);
  }

  /**
   *     
   */
  private void back2Home() {
    Intent home=new Intent(Intent.ACTION_MAIN);
    home.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    home.addCategory(Intent.CATEGORY_HOME);
    startActivity(home);
  }

}

사용 방법:
설정-보조 기능-무장 애-RedPacket 클릭 하여 오픈
알려 진 문제:
1.채 팅 리스트 또는 채 팅 창 에서 자동 으로 보너스 쟁탈 불가
2.스크린 을 끄 지 않 고 자동 으로 보 너 스 를 빼 앗 으 려 면 화면 을 끄 고 자동 으로 보 너 스 를 빼 앗 을 수 있 는 학생 이 바로 화면 코드 를 첫 번 째 단계 에 쓰 면 됩 니 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기