背景
之所以产生这个项目,是因为:
1、之前在做小车时,想通过手机来控制小车的行径,所以得要先研究下Android开发
2、某次在码代码时,错过了群里的好几个大红包,于是想着,可不可以来个自动抢红包的,省的每次都去关注手机
于是乎,就出现了这个项目了。
同时由于对这个很感兴趣,想快速的完成,所以这两个星期就把小车放下了,专来研究抢红包。
一、应该要具备哪些知识点

基础快速掌握
不懂Android开发怎么办?
学!
先去网上搜索开发自动抢红包,需要哪些材料。
最后看了好几篇文章好,核心点是AccessibilityService这么个Android组件。
好,问题来了,AccessibilityService是什么鬼?
继续查找资料,但发现,看看了几篇文章后,还是看不懂,连建个Android Project都搞不了。
于是就从Android开发基础开始看起,
网上有很多的教程,我看的是“菜鸟教程–安卓开发”,
跟着这里的教程,用业余时间看了3-4天左右,只是看到了Service那章就停了,感觉应该是差不多可以动手了。
最后能达到的效果是:
1、能使用Android Studio创建工程
2、能编写多个Activity之间通信
3、能在Activity中启动Service,且能互相通讯
然后的重点就是去理解AccessibilityService
关于AccessibilityService的具体我就不详写了,网上有很多,推荐这篇写的蛮好的:http://www.jianshu.com/p/959217070c87
这个过程,会遇到很多问题,及新的知识点,也就要各个击破了,要认真的去查询资料。
这个期间,为了分别了解每个知识点,都实验了如下项目:
1、app的自动安装
2、微信的自动回复
能做到以上两个,基本上对开发抢红包就没有什么难度了。
现在总结,利用AccessibilityService进行相关的操作,就是要理解:
1、事件响应的处理
2、app每个控件的查找
其实,有做过前端开发和桌面开发的同学,就比较容易上手了,套路几乎是一致的。
(偷下懒,思维跨度太大了,就直接上代码了,代码里也有注释)
WxHongBaoService.java
package com.example.xxh.wxhongbao;
import android.accessibilityservice.AccessibilityService;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Intent;
import android.util.Log;
import android.view.KeyEvent;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import java.io.IOException;
import java.util.List;
/**
* Created by xxh on 2017/9/21.
*/
public class WxHongBaoService extends AccessibilityService {
private final String TAG = "WXHONGBAO";
private void log(String msg)
{
Log.i(TAG, msg);
}
@Override
protected void onServiceConnected() {
super.onServiceConnected();
log("service connected");
}
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
int eventType = event.getEventType();
switch (eventType) {
case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
doNotification(event);
break;
case AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED:
case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
//doWxHome();
findAndOpenHB();
clickHB();
quitDetaiHB();
break;
}
}
@Override
public void onInterrupt() {
}
/**
* 模拟back按键
*/
private void pressBackButton(){
AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
if(nodeInfo == null)
return;;
List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/hc");
if(list != null && list.size() > 0) {
for(AccessibilityNodeInfo n : list) {
n.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
/**
* 找红包 并打开红包
*/
private void findAndOpenHB()
{
AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
if(nodeInfo == null)
return;
List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/a8q"); // 红包整块
if(list != null && list.size() > 0) {
for(AccessibilityNodeInfo n : list) {
List<AccessibilityNodeInfo> noClick = n.findAccessibilityNodeInfosByText("领取红包"); // 未被领取
if(noClick != null && noClick.size() > 0) {
for (AccessibilityNodeInfo n1 : noClick) {
log("***********找到***********");
n.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
}
}
/**
* 拆红包
*/
private void clickHB()
{
AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
if(nodeInfo == null)
return;;
List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/bp6");
if(list != null && list.size() > 0) {
for(AccessibilityNodeInfo n : list) {
log("***********拆开***********");
n.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
/**
* 退出 红包详情页面 拆开红包后的页面 如果在此页面的话 有红包来 触发不了以上事件
*/
private void quitDetaiHB()
{
AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
if(nodeInfo == null)
return;;
List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText("红包详情");
if(list != null && list.size() > 0) {
log("退出红包详情");
pressBackButton();
back2Home();
}
}
/**
* 在微信首页 打开聊天窗口
*/
private void doWxHome()
{
AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
if(nodeInfo == null)
return;;
List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/aja");
if(list != null && list.size() > 0) {
for(AccessibilityNodeInfo n : list) {
List<AccessibilityNodeInfo> child = n.findAccessibilityNodeInfosByText("[微信红包]");
if(child!=null && child.size()>0) {
log("***********打开窗口***********");
n.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
}
/**
* 响应通知事件, 如果是红包通知, 则进入聊天界面
*/
private void doNotification(final AccessibilityEvent event)
{
if(event.getParcelableData() != null && event.getParcelableData() instanceof Notification) {
Notification notification = (Notification)event.getParcelableData();
String content = notification.tickerText.toString();
log("接收到通知信息: " + content);
int idx = content.indexOf("[微信红包]");
if(idx > 0) {
PendingIntent pendingIntent = notification.contentIntent;
try {
pendingIntent.send();
}catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
}
}
}
/**
* 回到系统桌面
*/
private void back2Home() {
Intent home = new Intent(Intent.ACTION_MAIN);
home.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
home.addCategory(Intent.CATEGORY_HOME);
startActivity(home);
}
}
创建了一个主界面
MainActivity.java
package com.example.xxh.wxhongbao;
import android.content.Intent;
import android.provider.Settings;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private final String TAG = "MAINACTIVITY";
private Button open_service_btn;
private void log(String msg)
{
Log.i(TAG, msg);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
open_service_btn = (Button)findViewById(R.id.open_service_btn);
open_service_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 打开辅助服务
final String mAction = Settings.ACTION_ACCESSIBILITY_SETTINGS;
Intent intent = new Intent(mAction);
startActivity(intent);
}
});
if(isAccessibilitySettingsOn()) {
Toast.makeText(this, "你的辅助服务已开启,现在就可以开心的抢红包了", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "你的辅助服务没开启,请开启", Toast.LENGTH_LONG).show();
}
}
/**
* 判断辅助服务是否开启
*/
private boolean isAccessibilitySettingsOn()
{
int isEnable = 0;
final String service = getPackageName() + "/" + WxHongBaoService.class.getCanonicalName();
log(service);
try {
isEnable = Settings.Secure.getInt(getApplicationContext().getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED);
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
TextUtils.SimpleStringSplitter simpleStringSplitter = new TextUtils.SimpleStringSplitter(':');// 多个服务使用冒号隔开
if(isEnable == 1) {
String settingValue = Settings.Secure.getString(getApplicationContext().getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
if(settingValue != null) {
simpleStringSplitter.setString(settingValue);
while (simpleStringSplitter.hasNext()) {
String accessibilityServcie = simpleStringSplitter.next();
log("["+accessibilityServcie + "]"+accessibilityServcie.length());
log("["+service + "]"+service.length());
if(accessibilityServcie.equalsIgnoreCase(service)) {
return true;
}
}
}
}
return false;
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.xxh.wxhongbao" > <uses-permission android:name="android.permission.DISABLE_KEYGUARD" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" /> <uses-permission android:name="android.permission.GET_TASKS" /> <uses-permission android:name="android.permission.REORDER_TASKS" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher1" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" 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:name=".WxHongBaoService" 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> </application> </manifest>
res/xml/accessibility.xml Accessibility配置文件
<?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:packageNames="com.tencent.mm" android:notificationTimeout="100" />