以下:内容参考自乱七八糟哪都有的地方。 内容仅用于自我记录学习使用。该程序在QQ方面存在bug,不建议使用。关于辅助类的基础使用这里不再叙述。可以参考https://www.cnblogs.com/popfisher/p/7455754.html该内容
主要是通过AccessibilityService,即辅助Service实现的。可以通过AccessibilityService实现监控屏幕内容变化,模拟用户操作等功能。
下面是对AccessibilityService中常用的方法的介绍
disableSelf():禁用当前服务,也就是在服务可以通过该方法停止运行
findFoucs(int falg):查找拥有特定焦点类型的控件
getRootInActiveWindow():如果配置能够获取窗口内容,则会返回当前活动窗口的根结点
getSeviceInfo():获取当前服务的配置信息
onAccessibilityEvent(AccessibilityEvent event):有关AccessibilityEvent事件的回调函数,系统通过sendAccessibiliyEvent()不断的发送AccessibilityEvent到此处
performGlobalAction(int action):执行全局操作,比如返回,回到主页,打开最近等操作
setServiceInfo(AccessibilityServiceInfo info):设置当前服务的配置信息
getSystemService(String name):获取系统服务
onKeyEvent(KeyEvent event):如果允许服务监听按键操作,该方法是按键事件的回调,需要注意,这个过程发生了系统处理按键事件之前
onServiceConnected():系统成功绑定该服务时被触发,也就是当你在设置中开启相应的服务,系统成功的绑定了该服务时会触发,通常我们可以在这里做一些初始化操作
onInterrupt():服务中断时的回调
BaseAccessibilityService
基类Service,主要供QQ和微信Service继承使用。提供了一些基本方法。
package com.example.qxb_810.qianghongbaodemo.service;
import android.accessibilityservice.AccessibilityService;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.os.Build;
import android.os.PowerManager;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Button;
import com.example.qxb_810.qianghongbaodemo.common.EventTypes;
import com.example.qxb_810.qianghongbaodemo.listener.ScreenListener;
import java.util.List;
import static android.content.ContentValues.TAG;
/**
* @Data : 2018/12/13
* @Des : 辅助Service基类
*/
@TargetApi(Build.VERSION_CODES.N)
public class BaseAccessibilityService extends AccessibilityService {
//锁屏、解锁相关
protected KeyguardManager.KeyguardLock mKeyguardLock;
//唤醒屏幕相关
protected PowerManager.WakeLock mWakeLock = null;
protected String mEnvelopeKey = "";
protected AccessibilityNodeInfo mRootNodeInfo;
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
mRootNodeInfo = event.getSource();
if (mRootNodeInfo == null) return;
// 判断事件类型
switch (event.getEventType()) {
// 如果状态栏改变
case EventTypes.TYPE_NOTIFICATION_STATE_CHANGED:
progressStatusBar(event, mEnvelopeKey);
break;
case EventTypes.TYPE_WINDOW_STATE_CHANGED:
case EventTypes.TYPE_WINDOW_CONTENT_CHANGED: // window窗口内容或者状态改变的时候
Log.e(TAG, "事件类型 " + (event.getEventType() == 32 ? "TYPE_WINDOW_STATE_CHANGED" : "TYPE_WINDOW_CONTENT_CHANGED"));
// 处理其他聊天窗口的红包信息
progressOtherChat(event);
// 处理当前页面红包信息
progressCurrChat(event);
break;
}
}
/**
* 处理状态栏消息
* @param event
* @param envelopeKey 关键字
*/
protected void progressStatusBar(AccessibilityEvent event, String envelopeKey) {
List<CharSequence> text = event.getText();
if (text != null && !text.isEmpty()) {
text.stream().filter(t -> t.toString().contains(envelopeKey))
.forEach(t -> {
// 到达这一步说明存在红包,则跳转进去
if (event.getParcelableData() != null && event.getParcelableData() instanceof Notification) {
try {
Notification notification = (Notification) event.getParcelableData();
PendingIntent intent = notification.contentIntent;
// 这里需要处理一下解锁操作
//要跳转之前,先进行解锁屏幕,然后再跳转,有可能你现在屏幕是锁屏状态,先进行解锁,然后打开页面,有密码的可能就不行了
wakeUpAndUnlock(getApplicationContext());
intent.send();
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
}
});
}
}
/**
* 处理其他聊天页消息
*
* @param event
*/
protected void progressOtherChat(AccessibilityEvent event) {
}
/**
* 处理当前聊天页消息
*
* @param event
*/
protected void progressCurrChat(AccessibilityEvent event) {
}
/**
* 唤醒屏幕并解锁权限
*/
@SuppressLint("Wakelock")
@SuppressWarnings("deprecation")
protected void wakeUpAndUnlock(Context context) {
// 点亮屏幕
mWakeLock.acquire();
// 释放
mWakeLock.release();
// 解锁
mKeyguardLock.disableKeyguard();
}
/**
* 模拟返回操作
*/
protected void performBackClick() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
performGlobalAction(GLOBAL_ACTION_BACK);
}
/**
* 模拟返回操作
*/
protected void performBackClick(int time) {
try {
Thread.sleep(time);
} 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);
}
/**
* 查找对应ID
*
* @param id
* @return
*/
protected 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;
}
/**
* 模拟发送信息
*
* @param key
* @param time
*/
protected void replyMessage(String key, int time) {
//延迟
if (time > 0) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//获取QQ聊天页面输入框
AccessibilityNodeInfo chat_edit = findViewByID(EventTypes.QQ_CHAT_MESSAGE_INPUT);
if (chat_edit != null) {
//把口令粘贴到输入框中
pastaText(chat_edit, getApplicationContext(), key);
//获取QQ聊天页面发送消息按钮
AccessibilityNodeInfo sendMessage = findViewByID(EventTypes.QQ_CHAT_MESSAGE_SEND);
//然后就按下发送按钮
if (sendMessage != null && Button.class.getName().equals(sendMessage.getClassName())) {
performViewClick(sendMessage);
}
}
}
/**
* 粘贴口令到输入框
*
* @param nodeInfo
* @param context
* @param key
*/
protected void pastaText(AccessibilityNodeInfo nodeInfo, Context context, String key) {
//android>21 = 5.0时可以用ACTION_SET_TEXT
//android>18 3.0.1可以通过复制的手段,先确定焦点,再粘贴ACTION_PASTE
//使用剪切板
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
//获取焦点
nodeInfo.performAction(AccessibilityNodeInfo.ACTION_FOCUS);
//需要替换的key
clipboard.setPrimaryClip(ClipData.newPlainText("text", key));
//粘贴进入内容
nodeInfo.performAction(AccessibilityNodeInfo.ACTION_PASTE);
}
/**
* 模拟点击事件
*
* @param nodeInfo nodeInfo
*/
protected void performViewClick(AccessibilityNodeInfo nodeInfo) {
if (nodeInfo == null) {
return;
}
while (nodeInfo != null) {
if (nodeInfo.isClickable()) {
nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
break;
}
nodeInfo = nodeInfo.getParent();
}
}
@Override
public void onInterrupt() {
interrupt();
}
@Override
protected void onServiceConnected() {
super.onServiceConnected();
serviceConnected();
// 获取电源管理器对象
PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
// 获取PowerManager.WakeLock对象,后面的参数|表示同时传入两个值,最后的是调试用的Tag
mWakeLock = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "bright");
KeyguardManager km = (KeyguardManager) getApplicationContext().getSystemService(Context.KEYGUARD_SERVICE);
mKeyguardLock = km.newKeyguardLock("unLock");
//初始化屏幕的监听
ScreenListener screenListener = new ScreenListener(getApplicationContext());
screenListener.begin(new ScreenListener.ScreenStateListener() {
@Override
public void onScreenOn() {
Log.e("ScreenListener", "屏幕打开了");
}
@Override
public void onScreenOff() {
//在屏幕关闭的时候,进行锁屏,不执行的话,锁屏就失效了,因为要实现锁屏状态下也可以进行抢红包。
Log.e("ScreenListener", "屏幕关闭了");
if (mKeyguardLock != null) {
mKeyguardLock.disableKeyguard();
mKeyguardLock.reenableKeyguard();
}
}
@Override
public void onUserPresent() {
Log.e("ScreenListener", "解锁了");
}
});
}
/**
* 断开时操作
*/
protected void interrupt() {
}
/**
* 连接时操作
*/
protected void serviceConnected() {
}
}
QQAccessibilityService — QQ还有bug未解决,会重复点击以拆开红包并且不停。尝试用几种方式解决,最后因无法标识红包是否已拆开,所以目前仍未解决这个问题,所以建议不要使用。
另外,该程序不会点击“你已领取XXXX的红包/口令红包”提示之前的红包,虽然没什么卵用。
package com.example.qxb_810.qianghongbaodemo.service;
import android.annotation.TargetApi;
import android.graphics.Rect;
import android.os.Build;
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.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.stream.Collectors;
/**
* @Data : 2018/12/12
* @Des : QQ服务类基类
*/
@TargetApi(Build.VERSION_CODES.N)
public class QQAccessibilityService extends BaseAccessibilityService {
private static final String TAG = QQAccessibilityService.class.getSimpleName();
private static final int MAX_CACHE_TOLERANCE = 100; // 缓存最大的红包数量
private static final String ENVELOPE_NORMAL_KEY = "点击查看详情"; // 普通红包
private static final String ENVELOPE_PASSWORD_KEY = "口令红包"; // 口令红包
private static final String ENVELOPE_OPENED = "你领取了"; // 领取过后的红包
private Queue<String> mNodeIdQueue = new LinkedList<>(); // 存储已经领取的红包的id
private int mOpenedCount; // 已领取数量
protected boolean isBackStatus = false; // 是否是返回触发状态
private int mMaxTop = 0;
@Override
public void onCreate() {
super.onCreate();
mEnvelopeKey = "[QQ红包]";
}
/**
* 处理QQ当前窗口的红包信息
*
* @param event
*/
@Override
protected void progressCurrChat(AccessibilityEvent event) {
AccessibilityNodeInfo rootInActiveWindow = getRootInActiveWindow();
if (rootInActiveWindow == null) return;
// 返回状态不更新视图
if (isBackStatus) {
Log.e(TAG, "isBackStatus 状态 false");
isBackStatus = false;
return;
}
// 已领取的红包集
mMaxTop = 0;
List<AccessibilityNodeInfo> accessibilityNodeInfoList = rootInActiveWindow.findAccessibilityNodeInfosByText(ENVELOPE_OPENED);
accessibilityNodeInfoList.stream().filter(e -> e.getText() != null && (e.getText().toString().endsWith("的红包。") || e.getText().toString().endsWith("的口令红包。")))
.forEach(e -> {
Rect screenRect = new Rect();
e.getBoundsInScreen(screenRect);
mMaxTop = screenRect.top > mMaxTop ? screenRect.top : mMaxTop;
});
List<AccessibilityNodeInfo> envelopeTextList = findNodeInfosByTexts(rootInActiveWindow, new String[]{ENVELOPE_NORMAL_KEY, ENVELOPE_PASSWORD_KEY});
envelopeTextList.stream().forEach(t -> {
// 如果是口令红包
if (t.getText() != null && t.getText().toString().contains(ENVELOPE_PASSWORD_KEY)) {
progressPassword(t);
} else {
progressNormal(t);
}
});
}
/**
* 根据Text查找文本内容
*
* @param text
*/
private List<AccessibilityNodeInfo> findNodeInfosByTexts(AccessibilityNodeInfo rootInActiveWindow, String[] text) {
List<AccessibilityNodeInfo> envelopeTextList = new ArrayList<>();
Arrays.stream(text).forEach(t -> {
List<AccessibilityNodeInfo> accessibilityNodeInfosByText = rootInActiveWindow.findAccessibilityNodeInfosByText(t);
envelopeTextList.addAll(accessibilityNodeInfosByText.stream().filter(tt -> {
Rect rect = new Rect();
tt.getBoundsInScreen(rect);
return rect.top > mMaxTop;
}).collect(Collectors.toList()));
});
// 根据屏幕坐标排序
// Collections.sort(envelopeTextList, (o1, o2) -> {
// Rect o1ScreenRect = new Rect();
// o1.getBoundsInScreen(o1ScreenRect);
// Rect o2ScreenRect = new Rect();
// o2.getBoundsInScreen(o2ScreenRect);
// return o1ScreenRect.top - o2ScreenRect.top;
// });
return envelopeTextList;
}
/**
* 处理普通红包
*/
private void progressNormal(AccessibilityNodeInfo normaNodeInfo) {
performViewClick(normaNodeInfo);
performBackClick(1000);
isBackStatus = true;
Log.e(TAG, "progressNormal 状态 true");
}
/**
* 处理口令红包
*/
private void progressPassword(AccessibilityNodeInfo passwordNodeInfo) {
AccessibilityNodeInfo parent = passwordNodeInfo.getParent();
if (parent != null) {
CharSequence contentDescription = parent.getContentDescription();
if (!TextUtils.isEmpty(contentDescription)) {
// 获取口令
String key = contentDescription.toString();
if (key.contains(",") && key.contains("口令:")) {
key = key.substring(key.indexOf("口令:") + 3, key.lastIndexOf(","));
// 填写口令并发送
replyMessage(key, 0);
performBackClick(1000);
isBackStatus = true;
Log.e(TAG, "progressPassword 状态 true");
}
}
}
}
/**
* 处理其他聊天窗口的红包信息
*/
@Override
protected void progressOtherChat(AccessibilityEvent event) {
AccessibilityNodeInfo source = event.getSource();
if (source != null) {
//根据event的source里的text,来判断这个消息是否包含[QQ红包]的字眼,有的话就跳转过去
CharSequence text = source.getText();
if (!TextUtils.isEmpty(text) && text.toString().contains(mEnvelopeKey)) {
performViewClick(source);
}
}
}
@Override
protected void interrupt() {
Toast.makeText(this, "QQ抢红包服务已关闭", Toast.LENGTH_SHORT).show();
}
@Override
protected void serviceConnected() {
Toast.makeText(this, "QQ抢红包服务已开启", Toast.LENGTH_SHORT).show();
}
}
WXAccessibilityService 辅助Service — 与QQ流程相似, 比QQ多一个点击开的环节。
package com.example.qxb_810.qianghongbaodemo.service;
import android.annotation.TargetApi;
import android.os.Build;
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;
/**
* @Data : 2018/12/12
* @Des : QQ服务服务Service
*/
@TargetApi(Build.VERSION_CODES.N)
public class WXAccessibilityService extends BaseAccessibilityService {
private static final String TAG = WXAccessibilityService.class.getSimpleName();
private static final String ENVELOPE_STATUS_KEY = "[微信红包]"; // 状态栏提示红包
private static final String ENVELOPE_NORMAL_KEY = "领取红包"; // 未领取标志
@Override
public void onCreate() {
super.onCreate();
mEnvelopeKey = "[微信红包]";
}
/**
* 处理其他聊天窗口的红包信息
*/
@Override
protected void progressOtherChat(AccessibilityEvent event) {
AccessibilityNodeInfo source = event.getSource();
if (source != null) {
//根据event的source里的text,来判断这个消息是否包含[QQ红包]的字眼,有的话就跳转过去
CharSequence text = source.getText();
if (!TextUtils.isEmpty(text) && text.toString().contains(ENVELOPE_STATUS_KEY)) {
performViewClick(source);
}
}
}
/**
* 处理普通红包
*
* @param normalList
*/
private void progressNormal(List<AccessibilityNodeInfo> normalList) {
if (normalList != null && !normalList.isEmpty()) {
// 过滤点击
normalList.stream().forEach(t -> {
performViewClick(t);
Log.e(TAG, "红包控件的类名是 : " + t.getClassName().toString());
});
}
}
/**
* 处理QQ当前窗口的红包信息
*
* @param event
*/
@Override
protected void progressCurrChat(AccessibilityEvent event) {
AccessibilityNodeInfo rootInActiveWindow = getRootInActiveWindow();
if (rootInActiveWindow == null) return;
// 找到含有关键文本的控件
List<AccessibilityNodeInfo> envelopeNormalTextList = rootInActiveWindow.findAccessibilityNodeInfosByText(ENVELOPE_NORMAL_KEY); // 处理普通红包
progressNormal(envelopeNormalTextList);
progressDialog();
}
/**
* 处理红包弹窗后的红包领取
*/
private void progressDialog() {
AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
if (nodeInfo == null) {
return;
}
List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText("恭喜");
for (int i = list.size() - 1; i >= 0; i--) {
AccessibilityNodeInfo parent = list.get(i).getParent();
for (int j = 0; j < parent.getChildCount(); j++) {
AccessibilityNodeInfo child = parent.getChild(j);
if (child != null && child.isClickable()) {
child.performAction(AccessibilityNodeInfo.ACTION_CLICK);
performBackClick(1200);
break;
}
}
}
}
@Override
protected void interrupt(){
Toast.makeText(this, "微信抢红包服务已关闭", Toast.LENGTH_SHORT).show();
}
@Override
protected void serviceConnected() {
Toast.makeText(this, "微信抢红包服务已开启", Toast.LENGTH_SHORT).show();
}
}
接下来在res目录下建立xml文件夹并创建一下两个xml,用于配置两个Service。
envelope_service_config_qq.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- 关键是android:accessibilityEventTypes="typeAllMask", typeAllMask代表监听所有的事件,这边不写的话,AccessibilityService就接收不到 -->
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagRequestFilterKeyEvents"
android:canRetrieveWindowContent="true"
android:canRequestFilterKeyEvents="true"
android:description="@string/app_name"
android:notificationTimeout="100"
android:packageNames="com.tencent.mobileqq" />
envelope_service_config_wx.xml
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeWindowContentChanged|typeNotificationStateChanged|typeWindowStateChanged"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagRequestFilterKeyEvents"
android:canRetrieveWindowContent="true"
android:canRequestFilterKeyEvents="true"
android:description="@string/app_name"
android:notificationTimeout="100"
android:packageNames="com.tencent.mm" />
ScreenListener — 屏幕状态监听
package com.example.qxb_810.qianghongbaodemo.listener;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.PowerManager;
public class ScreenListener {
private Context mContext;
private ScreenBroadcastReceiver mScreenReceiver;
private ScreenStateListener mScreenStateListener;
public ScreenListener(Context context) {
mContext = context;
mScreenReceiver = new ScreenBroadcastReceiver();
}
/**
* screen状态广播接收者
*/
private class ScreenBroadcastReceiver extends BroadcastReceiver {
private String action = null;
@Override
public void onReceive(Context context, Intent intent) {
action = intent.getAction();
if (Intent.ACTION_SCREEN_ON.equals(action)) { // 开屏
mScreenStateListener.onScreenOn();
} else if (Intent.ACTION_SCREEN_OFF.equals(action)) { // 锁屏
mScreenStateListener.onScreenOff();
} else if (Intent.ACTION_USER_PRESENT.equals(action)) { // 解锁
mScreenStateListener.onUserPresent();
}
}
}
/**
* 开始监听screen状态
*
* @param listener
*/
public void begin(ScreenStateListener listener) {
mScreenStateListener = listener;
registerListener();
getScreenState();
}
/**
* 获取screen状态
*/
private void getScreenState() {
PowerManager manager = (PowerManager) mContext
.getSystemService(Context.POWER_SERVICE);
if (manager.isScreenOn()) {
if (mScreenStateListener != null) {
mScreenStateListener.onScreenOn();
}
} else {
if (mScreenStateListener != null) {
mScreenStateListener.onScreenOff();
}
}
}
/**
* 停止screen状态监听
*/
public void unregisterListener() {
mContext.unregisterReceiver(mScreenReceiver);
}
/**
* 启动screen状态广播接收器
*/
private void registerListener() {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_USER_PRESENT);
mContext.registerReceiver(mScreenReceiver, filter);
}
public interface ScreenStateListener {// 返回给调用者屏幕状态信息
public void onScreenOn();
public void onScreenOff();
public void onUserPresent();
}
}
EventTypes — 一些状态辨识或者类型
package com.example.qxb_810.qianghongbaodemo.common;
public final class EventTypes {
//所有事件
public static final int TYPE_ALLMASK = -1;
//通知栏
public static final int TYPE_NOTIFICATION_STATE_CHANGED = 64;
//点击事件
public static final int TYPE_VIEW_CLICKED = 1;
//控件获取焦点
public static final int TYPE_VIEW_FOCUSED = 8;
//长按事件
public static final int TYPE_VIEW_LONG_CLICKED = 2;
//页面变动
public static final int TYPE_VIEW_SCROLLED = 4096;
//控件选中
public static final int TYPE_VIEW_SELECTED = 4;
//输入框文本改变
public static final int TYPE_VIEW_TEXT_CHANGED = 16;
//输入框文本selection改变
public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 8192;
//窗口内容改变
public static final int TYPE_WINDOW_CONTENT_CHANGED = 2048;
//窗口状态改变
public static final int TYPE_WINDOW_STATE_CHANGED = 32;
//QQ的应用包名
public static final String QQ_PACKAGE_NAME = "com.tencent.mobileqq";
//QQ聊天页面
public static final String QQ_IM_CHAT_ACTIVITY = "com.tencent.mobileqq.activity.SplashActivity";
//点击拆开
public static final String QQ_CLICK_TAKE_APART = "恭喜发财";
//口令红包
public static final String QQ_CLICK_PASSWORD_DIALOG = "口令红包";
//聊天页面,输入框ID
public static final String QQ_CHAT_MESSAGE_INPUT = "com.tencent.mobileqq:id/input";
//聊天页面,发送按钮
public static final String QQ_CHAT_MESSAGE_SEND = "com.tencent.mobileqq:id/fun_btn";
}
MainActivity.java
package com.example.qxb_810.qianghongbaodemo;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
requestPermissions();
//打开系统设置中辅助功能
Intent intent = new Intent(android.provider.Settings.ACTION_ACCESSIBILITY_SETTINGS);
startActivity(intent);
Toast.makeText(MainActivity.this, "找到微信/QQ自动抢红包服务,开启即可", Toast.LENGTH_LONG).show();
}
/**
* 动态申请权限 ---- API23后需要动态申请权限
*/
private void requestPermissions() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
// 读写存储权限 和联网权限
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WAKE_LOCK}, 1);
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BIND_ACCESSIBILITY_SERVICE}, 1);
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE}, 1);
}
}
}
清单文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.qxb_810.qianghongbaodemo">
<application
android:allowBackup="true"
android:icon="@mipmap/app_icon"
android:label="@string/app_name"
android:roundIcon="@mipmap/app_icon"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:enabled="true"
android:exported="true"
android:label="QQ自动抢红包服务"
android:name=".service.QQAccessibilityService"
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/envelope_service_config_qq"/>
</service>
<service
android:enabled="true"
android:exported="true"
android:label="WX自动抢红包服务"
android:name=".service.WXAccessibilityService"
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/envelope_service_config_wx"/>
</service>
</application>
<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
</manifest>