├── .gitignore ├── README.md ├── abllib ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── levine │ │ │ └── abllib │ │ │ ├── AblConfig.java │ │ │ ├── AblService.java │ │ │ ├── AblStepBase.java │ │ │ ├── AblStepHandler.java │ │ │ ├── AblSteps.java │ │ │ ├── FindViewCountDown.java │ │ │ ├── callback │ │ │ ├── AniCallBack.java │ │ │ ├── AnisCallBack.java │ │ │ └── GestureCallBack.java │ │ │ └── utils │ │ │ ├── AblUtil.java │ │ │ └── AblViewUtil.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── xml │ │ └── abl_service.xml │ └── test │ └── java │ └── com │ └── levine │ └── abllib │ └── ExampleUnitTest.java ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── luoyi │ │ └── android │ │ └── com │ │ └── abldemo │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── luoyi │ │ │ └── android │ │ │ └── com │ │ │ └── abldemo │ │ │ ├── MainActivity.java │ │ │ ├── TestAblStep1.java │ │ │ └── TestAblStep2.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ └── view_test.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── luoyi │ └── android │ └── com │ └── abldemo │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── resource ├── 20230303100049.jpg ├── 20230303103749.jpg └── 微信图片_20230403143012.jpg └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | 15 | # Gradle files 16 | .gradle/ 17 | build/ 18 | 19 | # Local configuration file (sdk path, etc) 20 | local.properties 21 | 22 | # Proguard folder generated by Eclipse 23 | proguard/ 24 | 25 | 26 | # Android Studio project files 27 | *.iml 28 | .gradle 29 | .idea 30 | build -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Abllib (此开源库已不再维护,已重新开发更加易用稳定的库[Assists](https://github.com/ven-coder/assists)) 2 | 3 | [Demo:https://github.com/Levine1992/Abllib](https://github.com/Levine1992/Abllib) 4 | 5 | **AccessibilityService无障碍服务库,一行代码启用,快速开发复杂的自动操作业务** 6 | 7 | **AccessibilityService可以帮助我们做一些自动操作手机的动作,像微信自动抢红包、各种应用市场的自动安装功能就是利用的AccessibilityService服务, 8 | 利用这个服务我们可以做更多有意思的事,但是直接继承这个服务,要实现一些复杂点的业务逻辑就很麻烦,所以写了这个库。** 9 | 10 | ### 引用 11 | project build.gradle中添加 12 | 13 | ``` 14 | allprojects { 15 | repositories { 16 | ... 17 | maven { url 'https://jitpack.io' } 18 | } 19 | } 20 | ``` 21 | app build.gradle中添加 22 | 23 | ``` 24 | dependencies { 25 | ... 26 | implementation 'com.github.Levine1992:Abllib:V1.0' 27 | } 28 | ``` 29 | 30 | ### 初始化一些配置 31 | 32 | ``` 33 | AblConfig.Builder() 34 | .setLogTag("123456")//logtag,不设置默认是abllib 35 | .setStepMsgDelayMillis(2000)//步骤延迟时间 36 | .setFindViewMillisInFuture(10000)//寻找界面超时时间 37 | .setFindViewCountDownInterval(200)//寻找界面间隔时间 38 | .build().init(); 39 | ``` 40 | ### 使用说明 41 | 新建具体的自动操作的步骤器继承AblStepBase,如果自动操作业务多可以分开多建几个,区分开便于维护,但是步骤的id最好不要重复 42 | 43 | ``` 44 | public class TestAblStep1 extends AblStepBase { 45 | @Override 46 | public void onStep(int step, Message msg) { 47 | switch (step) { 48 | case AblSteps.STEP_1://步骤1 49 | AblViewUtil.findById( 50 | "luoyi.android.com.abldemo:id/btn_3",//传入需要获取抓取的界面的id 51 | 0,//由于抓到的界面有可能有多个所以传入要获取第几个,一般0就可以 52 | new AniCallBack() {//回调 53 | @Override 54 | public void succ(AccessibilityNodeInfo info) { 55 | info.performAction(AccessibilityNodeInfo.ACTION_CLICK);//抓到后执行点击界面操作 56 | AblStepHandler.sendMsg(AblSteps.STEP_2);//执行步骤2 57 | } 58 | 59 | @Override 60 | public void fail() {//处理抓取失败逻辑 61 | 62 | } 63 | } 64 | ); 65 | break; 66 | case AblSteps.STEP_2://步骤2 67 | AblViewUtil.back();//返回 68 | AblStepHandler.sendMsg(AblSteps.STEP_1); 69 | break; 70 | } 71 | } 72 | ``` 73 | 74 | ``` 75 | public class TestAblStep2 extends AblStepBase { 76 | @Override 77 | public void onStep(int step, Message msg) { 78 | switch (step) { 79 | case AblSteps.STEP_3://步骤3 80 | 81 | break; 82 | case AblSteps.STEP_4://步骤4 83 | 84 | break; 85 | } 86 | } 87 | ``` 88 | 89 | 90 | 初始化这些步骤器 91 | 92 | ``` 93 | AblStepHandler.getInstance().initStepClass(new TestAblStep1(),new TestAblStep2()); 94 | ``` 95 | 96 | 执行 97 | 98 | ``` 99 | AblStepHandler.getInstance().setStop(false);//开启步骤器 100 | AblStepHandler.sendMsg(AblSteps.STEP_1);//执行步骤,如果设置步骤间隔时间为2000,则会延迟两秒执行 101 | ``` 102 | 103 | *** 104 | 105 | **AccessibilityService技术交流群** 106 |
107 | 108 | 如果群二维码失效可直接加我**Wechat:1483232332**拉进群 109 |
110 | -------------------------------------------------------------------------------- /abllib/.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | 15 | # Gradle files 16 | .gradle/ 17 | build/ 18 | 19 | # Local configuration file (sdk path, etc) 20 | local.properties 21 | 22 | # Proguard folder generated by Eclipse 23 | proguard/ 24 | 25 | 26 | # Android Studio project files 27 | *.iml 28 | .gradle 29 | .idea 30 | build -------------------------------------------------------------------------------- /abllib/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 28 5 | defaultConfig { 6 | minSdkVersion 20 7 | targetSdkVersion 28 8 | } 9 | compileOptions { 10 | sourceCompatibility = '1.8' 11 | targetCompatibility = '1.8' 12 | } 13 | } 14 | 15 | dependencies { 16 | implementation 'com.android.support:appcompat-v7:28.0.0' 17 | api 'com.blankj:utilcode:1.23.7' 18 | } 19 | -------------------------------------------------------------------------------- /abllib/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /abllib/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /abllib/src/main/java/com/levine/abllib/AblConfig.java: -------------------------------------------------------------------------------- 1 | package com.levine.abllib; 2 | 3 | import com.blankj.utilcode.util.LogUtils; 4 | 5 | /** 6 | * 2019/4/21 7 | * 17:49 8 | * Levine 9 | * wechat 1483232332 10 | */ 11 | public class AblConfig { 12 | 13 | private String mLogTag; 14 | private boolean mIsLog; 15 | private long mStepMsgDelayMillis;//消息延迟发送时间 16 | private long findViewMillisInFuture;//查找view倒计时总时长 17 | private long findViewCountDownInterval;//查找view检查间隔时间 18 | /** 19 | * 所监测的APP包名,如果不设置将会监听整个系统的界面变化,如果设置后只会监听指定包名的APP 20 | * 【暂时不用】 21 | */ 22 | public static String[] sMonitoringPackageNames; 23 | 24 | private AblConfig(Builder builder) { 25 | mLogTag = builder.mLogTag; 26 | mIsLog = builder.mIsLog; 27 | sMonitoringPackageNames = builder.mMonitoringPackageNames; 28 | mStepMsgDelayMillis = builder.mStepMsgDelayMillis; 29 | findViewCountDownInterval = builder.findViewCountDownInterval; 30 | findViewMillisInFuture = builder.findViewMillisInFuture; 31 | } 32 | 33 | public void init() { 34 | LogUtils.getConfig().setGlobalTag(mLogTag); 35 | LogUtils.getConfig().setLogSwitch(mIsLog); 36 | AblStepHandler.getInstance().setStepMsgDelayMillis(mStepMsgDelayMillis); 37 | FindViewCountDown.countDownInterval = findViewCountDownInterval; 38 | FindViewCountDown.millisInFuture = findViewMillisInFuture; 39 | } 40 | 41 | public static Builder Builder() { 42 | return new Builder(); 43 | } 44 | 45 | public static class Builder { 46 | private String mLogTag = "abllib"; 47 | private boolean mIsLog = true; 48 | private String[] mMonitoringPackageNames; 49 | private long mStepMsgDelayMillis = 2000;//步骤延迟发送时间 50 | private long findViewMillisInFuture = 10000;//查找view倒计时总时长 51 | private long findViewCountDownInterval = 500;//查找view检查间隔时间 52 | 53 | public Builder setLogTag(String logTag) { 54 | mLogTag = logTag; 55 | return this; 56 | } 57 | 58 | public Builder setLog(boolean log) { 59 | mIsLog = log; 60 | return this; 61 | } 62 | 63 | public Builder setMonitoringPackageNames(String... monitoringPackageNames) { 64 | mMonitoringPackageNames = monitoringPackageNames; 65 | return this; 66 | } 67 | 68 | public Builder setStepMsgDelayMillis(long stepMsgDelayMillis) { 69 | mStepMsgDelayMillis = stepMsgDelayMillis; 70 | return this; 71 | } 72 | 73 | public Builder setFindViewMillisInFuture(long findViewMillisInFuture) { 74 | this.findViewMillisInFuture = findViewMillisInFuture; 75 | return this; 76 | } 77 | 78 | public Builder setFindViewCountDownInterval(long findViewCountDownInterval) { 79 | this.findViewCountDownInterval = findViewCountDownInterval; 80 | return this; 81 | } 82 | 83 | public AblConfig build() { 84 | return new AblConfig(this); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /abllib/src/main/java/com/levine/abllib/AblService.java: -------------------------------------------------------------------------------- 1 | package com.levine.abllib; 2 | 3 | import android.accessibilityservice.AccessibilityService; 4 | import android.accessibilityservice.AccessibilityServiceInfo; 5 | import android.view.accessibility.AccessibilityEvent; 6 | 7 | import com.blankj.utilcode.util.LogUtils; 8 | 9 | /** 10 | * 2019/4/21 11 | * 11:29 12 | * Levine 13 | * wechat 1483232332 14 | */ 15 | public class AblService extends AccessibilityService { 16 | 17 | private static AblService mAblService; 18 | 19 | public static AblService getInstance() { 20 | if (mAblService == null) { 21 | throw new NullPointerException("AblService辅助服务未开启"); 22 | } 23 | return mAblService; 24 | } 25 | 26 | @Override 27 | public void onCreate() { 28 | super.onCreate(); 29 | mAblService = this; 30 | init(); 31 | } 32 | 33 | private void init() { 34 | 35 | } 36 | 37 | @Override 38 | protected boolean onGesture(int gestureId) { 39 | return super.onGesture(gestureId); 40 | } 41 | 42 | 43 | @Override 44 | protected void onServiceConnected() { 45 | super.onServiceConnected(); 46 | LogUtils.v("onServiceConnected"); 47 | AccessibilityServiceInfo config = new AccessibilityServiceInfo(); 48 | //配置监听的事件类型为界面变化|点击事件 49 | config.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED | AccessibilityEvent.TYPE_VIEW_CLICKED; 50 | config.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC; 51 | config.flags = AccessibilityServiceInfo.FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY; 52 | setServiceInfo(config); 53 | } 54 | 55 | @Override 56 | public void onAccessibilityEvent(AccessibilityEvent event) { 57 | // LogUtils.v(event.getPackageName() + ""); 58 | } 59 | 60 | @Override 61 | public void onInterrupt() { 62 | 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /abllib/src/main/java/com/levine/abllib/AblStepBase.java: -------------------------------------------------------------------------------- 1 | package com.levine.abllib; 2 | 3 | /** 4 | * 2019/4/21 5 | * 16:44 6 | * Levine 7 | * wechat 1483232332 8 | */ 9 | public abstract class AblStepBase implements AblStepHandler.StepListener { 10 | } 11 | -------------------------------------------------------------------------------- /abllib/src/main/java/com/levine/abllib/AblStepHandler.java: -------------------------------------------------------------------------------- 1 | package com.levine.abllib; 2 | 3 | 4 | import android.os.Handler; 5 | import android.os.Looper; 6 | import android.os.Message; 7 | import android.support.annotation.NonNull; 8 | 9 | import com.blankj.utilcode.util.LogUtils; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | /** 15 | * 2019/4/21 16 | * 14:36 17 | * Levine 18 | * wechat 1483232332 19 | */ 20 | public class AblStepHandler extends Handler { 21 | 22 | private static AblStepHandler instance; 23 | private List mStepListeners = new ArrayList<>(); 24 | private boolean isStop = true;//是否停止 25 | private String[] mDatas;//数据 26 | private long mStepMsgDelayMillis = 2000;//消息延迟发送时间 27 | private List mInitializedSteps = new ArrayList<>();//已经初始化过的步骤 28 | 29 | private AblStepHandler() { 30 | super(Looper.getMainLooper()); 31 | } 32 | 33 | public static AblStepHandler getInstance() { 34 | if (instance == null) { 35 | synchronized (AblStepHandler.class) { 36 | if (instance == null) { 37 | instance = new AblStepHandler(); 38 | } 39 | } 40 | } 41 | return instance; 42 | } 43 | 44 | /** 45 | * 发送handler执行消息 46 | * 47 | * @param step 步骤 48 | * @param delayMillis 延迟时间 49 | * @param datas 数据 50 | */ 51 | public static void sendMsg(int step, long delayMillis, String... datas) { 52 | AblStepHandler ablStepHandler = AblStepHandler.getInstance(); 53 | if (datas != null && datas.length > 0) { 54 | ablStepHandler.setDatas(datas); 55 | } 56 | ablStepHandler.sendEmptyMessageDelayed(step, delayMillis); 57 | } 58 | 59 | /** 60 | * 发送handler执行消息 61 | * 62 | * @param step 步骤 63 | * @param delayMillis 延迟时间 64 | */ 65 | public static void sendMsg(int step, long delayMillis) { 66 | sendMsg(step, delayMillis, new String[]{}); 67 | } 68 | 69 | /** 70 | * 发送handler执行消息 71 | * 72 | * @param step 步骤 73 | * @param datas 数据 74 | */ 75 | public static void sendMsg(int step, String... datas) { 76 | sendMsg(step, AblStepHandler.getInstance().getStepMsgDelayMillis(), datas); 77 | } 78 | 79 | /** 80 | * 发送handler执行消息 81 | * 82 | * @param step 步骤 83 | */ 84 | public static void sendMsg(int step) { 85 | sendMsg(step, AblStepHandler.getInstance().getStepMsgDelayMillis(), new String[]{}); 86 | } 87 | 88 | /** 89 | * 根据viewid或文字发送执行消息 90 | * 91 | * @param millisInFuture view查找超时时间 92 | * @param countDownInterval 查找间隔时间 93 | * @param step 步骤 94 | */ 95 | public static void sendMsgByView( 96 | long millisInFuture, 97 | long countDownInterval, 98 | int step, 99 | String... nextMsgViewIdOrText 100 | ) { 101 | FindViewCountDown.start(millisInFuture, countDownInterval, step, nextMsgViewIdOrText); 102 | } 103 | 104 | /** 105 | * 根据viewid或文字发送执行消息 106 | * 107 | * @param millisInFuture view查找超时时间 108 | * @param countDownInterval 查找间隔时间 109 | * @param callBack 回调,注:如果回调不为空将不发送消息,要发送消息就自己在成功的回调里发送 110 | * @param viewIdOrText viewid或者文字内容 111 | */ 112 | public static void sendMsgByView( 113 | long millisInFuture, 114 | long countDownInterval, 115 | @NonNull FindViewCountDown.CallBack callBack, 116 | String... viewIdOrText 117 | ) { 118 | FindViewCountDown.start(millisInFuture, countDownInterval, callBack, viewIdOrText); 119 | } 120 | 121 | /** 122 | * 根据viewid或文字发送执行消息 123 | * 124 | * @param step 步骤 125 | * @param viewIdOrText viewid或者文字内容 126 | */ 127 | public static void sendMsgByView( 128 | int step, 129 | String... viewIdOrText 130 | ) { 131 | FindViewCountDown.start(step, viewIdOrText); 132 | } 133 | 134 | /** 135 | * 根据viewid或文字发送执行消息 136 | * 137 | * @param callBack 回调,注:如果回调不为空将不发送消息,要发送消息就自己在成功的回调里发送 138 | * @param viewIdOrText viewid或者文字内容 139 | */ 140 | public static void sendMsgByView( 141 | @NonNull FindViewCountDown.CallBack callBack, 142 | String... viewIdOrText 143 | ) { 144 | FindViewCountDown.start(callBack, viewIdOrText); 145 | } 146 | 147 | 148 | public String[] getDatas() { 149 | return mDatas; 150 | } 151 | 152 | public void setDatas(String... datas) { 153 | mDatas = datas; 154 | } 155 | 156 | public long getStepMsgDelayMillis() { 157 | return mStepMsgDelayMillis; 158 | } 159 | 160 | public void setStepMsgDelayMillis(long msgDelayMillis) { 161 | mStepMsgDelayMillis = msgDelayMillis; 162 | } 163 | 164 | public boolean isStop() { 165 | 166 | return isStop; 167 | } 168 | 169 | public void setStop(boolean stop) { 170 | isStop = stop; 171 | } 172 | 173 | @Override 174 | public void handleMessage(Message msg) { 175 | super.handleMessage(msg); 176 | if (isStop) return; 177 | LogUtils.v("step", msg.what); 178 | for (StepListener stepListener : mStepListeners) { 179 | stepListener.onStep(msg.what, msg); 180 | } 181 | } 182 | 183 | private void addStepListener(StepListener handleMessageListener) { 184 | mStepListeners.add(handleMessageListener); 185 | } 186 | 187 | public void removeStepListener(StepListener handleMessageListener) { 188 | mStepListeners.remove(handleMessageListener); 189 | } 190 | 191 | /** 192 | * 初始化步骤实现类 193 | * 194 | * @param ablStepBases 继承了StepBase的实现类 195 | */ 196 | public void initStepClass(AblStepBase... ablStepBases) { 197 | for (AblStepBase ablStepBase : ablStepBases) { 198 | if (mInitializedSteps.contains(ablStepBase.getClass().getName())) { 199 | LogUtils.e(ablStepBase.getClass().getName() + "已经初始化,请勿重复初始化"); 200 | continue; 201 | } 202 | addStepListener(ablStepBase); 203 | mInitializedSteps.add(ablStepBase.getClass().getName()); 204 | } 205 | } 206 | 207 | public interface StepListener { 208 | void onStep(int step, Message msg); 209 | } 210 | 211 | } 212 | -------------------------------------------------------------------------------- /abllib/src/main/java/com/levine/abllib/AblSteps.java: -------------------------------------------------------------------------------- 1 | package com.levine.abllib; 2 | 3 | /** 4 | * 2019/4/21 5 | * 18:33 6 | * Levine 7 | * wechat 1483232332 8 | */ 9 | public class AblSteps { 10 | /** 11 | * 全局静态常量步骤标识1~200,不够自己再加,从200开始加,基本应该都是够的了 12 | */ 13 | public final static int STEP_1 = 1; 14 | public final static int STEP_2 = 2; 15 | public final static int STEP_3 = 3; 16 | public final static int STEP_4 = 4; 17 | public final static int STEP_5 = 5; 18 | public final static int STEP_6 = 6; 19 | public final static int STEP_7 = 7; 20 | public final static int STEP_8 = 8; 21 | public final static int STEP_9 = 9; 22 | /*****************************************/ 23 | public final static int STEP_10 = 10; 24 | public final static int STEP_11 = 11; 25 | public final static int STEP_12 = 12; 26 | public final static int STEP_13 = 13; 27 | public final static int STEP_14 = 14; 28 | public final static int STEP_15 = 15; 29 | public final static int STEP_16 = 16; 30 | public final static int STEP_17 = 17; 31 | public final static int STEP_18 = 18; 32 | public final static int STEP_19 = 19; 33 | /*****************************************/ 34 | public final static int STEP_20 = 20; 35 | public final static int STEP_21 = 21; 36 | public final static int STEP_22 = 22; 37 | public final static int STEP_23 = 23; 38 | public final static int STEP_24 = 24; 39 | public final static int STEP_25 = 25; 40 | public final static int STEP_26 = 26; 41 | public final static int STEP_27 = 27; 42 | public final static int STEP_28 = 28; 43 | public final static int STEP_29 = 29; 44 | /*****************************************/ 45 | public final static int STEP_30 = 30; 46 | public final static int STEP_31 = 31; 47 | public final static int STEP_32 = 32; 48 | public final static int STEP_33 = 33; 49 | public final static int STEP_34 = 34; 50 | public final static int STEP_35 = 35; 51 | public final static int STEP_36 = 36; 52 | public final static int STEP_37 = 37; 53 | public final static int STEP_38 = 38; 54 | public final static int STEP_39 = 39; 55 | /*****************************************/ 56 | public final static int STEP_40 = 40; 57 | public final static int STEP_41 = 41; 58 | public final static int STEP_42 = 42; 59 | public final static int STEP_43 = 43; 60 | public final static int STEP_44 = 44; 61 | public final static int STEP_45 = 45; 62 | public final static int STEP_46 = 46; 63 | public final static int STEP_47 = 47; 64 | public final static int STEP_48 = 48; 65 | public final static int STEP_49 = 49; 66 | /*****************************************/ 67 | public final static int STEP_50 = 50; 68 | public final static int STEP_51 = 51; 69 | public final static int STEP_52 = 52; 70 | public final static int STEP_53 = 53; 71 | public final static int STEP_54 = 54; 72 | public final static int STEP_55 = 55; 73 | public final static int STEP_56 = 56; 74 | public final static int STEP_57 = 57; 75 | public final static int STEP_58 = 58; 76 | public final static int STEP_59 = 59; 77 | /*****************************************/ 78 | public final static int STEP_60 = 60; 79 | public final static int STEP_61 = 61; 80 | public final static int STEP_62 = 62; 81 | public final static int STEP_63 = 63; 82 | public final static int STEP_64 = 64; 83 | public final static int STEP_65 = 65; 84 | public final static int STEP_66 = 66; 85 | public final static int STEP_67 = 67; 86 | public final static int STEP_68 = 68; 87 | public final static int STEP_69 = 69; 88 | /*****************************************/ 89 | public final static int STEP_70 = 70; 90 | public final static int STEP_71 = 71; 91 | public final static int STEP_72 = 72; 92 | public final static int STEP_73 = 73; 93 | public final static int STEP_74 = 74; 94 | public final static int STEP_75 = 75; 95 | public final static int STEP_76 = 76; 96 | public final static int STEP_77 = 77; 97 | public final static int STEP_78 = 78; 98 | public final static int STEP_79 = 79; 99 | /*****************************************/ 100 | public final static int STEP_80 = 80; 101 | public final static int STEP_81 = 81; 102 | public final static int STEP_82 = 82; 103 | public final static int STEP_83 = 83; 104 | public final static int STEP_84 = 84; 105 | public final static int STEP_85 = 85; 106 | public final static int STEP_86 = 86; 107 | public final static int STEP_87 = 87; 108 | public final static int STEP_88 = 88; 109 | public final static int STEP_89 = 89; 110 | /*****************************************/ 111 | public final static int STEP_90 = 90; 112 | public final static int STEP_91 = 91; 113 | public final static int STEP_92 = 92; 114 | public final static int STEP_93 = 93; 115 | public final static int STEP_94 = 94; 116 | public final static int STEP_95 = 95; 117 | public final static int STEP_96 = 96; 118 | public final static int STEP_97 = 97; 119 | public final static int STEP_98 = 98; 120 | public final static int STEP_99 = 99; 121 | /*****************************************/ 122 | public final static int STEP_100 = 100; 123 | public final static int STEP_101 = 101; 124 | public final static int STEP_102 = 102; 125 | public final static int STEP_103 = 103; 126 | public final static int STEP_104 = 104; 127 | public final static int STEP_105 = 105; 128 | public final static int STEP_106 = 106; 129 | public final static int STEP_107 = 107; 130 | public final static int STEP_108 = 108; 131 | public final static int STEP_109 = 109; 132 | /*****************************************/ 133 | public final static int STEP_110 = 110; 134 | public final static int STEP_111 = 111; 135 | public final static int STEP_112 = 112; 136 | public final static int STEP_113 = 113; 137 | public final static int STEP_114 = 114; 138 | public final static int STEP_115 = 115; 139 | public final static int STEP_116 = 116; 140 | public final static int STEP_117 = 117; 141 | public final static int STEP_118 = 118; 142 | public final static int STEP_119 = 119; 143 | /*****************************************/ 144 | public final static int STEP_120 = 120; 145 | public final static int STEP_121 = 121; 146 | public final static int STEP_122 = 122; 147 | public final static int STEP_123 = 123; 148 | public final static int STEP_124 = 124; 149 | public final static int STEP_125 = 125; 150 | public final static int STEP_126 = 126; 151 | public final static int STEP_127 = 127; 152 | public final static int STEP_128 = 128; 153 | public final static int STEP_129 = 129; 154 | /*****************************************/ 155 | public final static int STEP_130 = 130; 156 | public final static int STEP_131 = 131; 157 | public final static int STEP_132 = 132; 158 | public final static int STEP_133 = 133; 159 | public final static int STEP_134 = 134; 160 | public final static int STEP_135 = 135; 161 | public final static int STEP_136 = 136; 162 | public final static int STEP_137 = 137; 163 | public final static int STEP_138 = 138; 164 | public final static int STEP_139 = 139; 165 | /*****************************************/ 166 | public final static int STEP_140 = 140; 167 | public final static int STEP_141 = 141; 168 | public final static int STEP_142 = 142; 169 | public final static int STEP_143 = 143; 170 | public final static int STEP_144 = 144; 171 | public final static int STEP_145 = 145; 172 | public final static int STEP_146 = 146; 173 | public final static int STEP_147 = 147; 174 | public final static int STEP_148 = 148; 175 | public final static int STEP_149 = 149; 176 | /*****************************************/ 177 | public final static int STEP_150 = 150; 178 | public final static int STEP_151 = 151; 179 | public final static int STEP_152 = 152; 180 | public final static int STEP_153 = 153; 181 | public final static int STEP_154 = 154; 182 | public final static int STEP_155 = 155; 183 | public final static int STEP_156 = 156; 184 | public final static int STEP_157 = 157; 185 | public final static int STEP_158 = 158; 186 | public final static int STEP_159 = 159; 187 | /*****************************************/ 188 | public final static int STEP_160 = 160; 189 | public final static int STEP_161 = 161; 190 | public final static int STEP_162 = 162; 191 | public final static int STEP_163 = 163; 192 | public final static int STEP_164 = 164; 193 | public final static int STEP_165 = 165; 194 | public final static int STEP_166 = 166; 195 | public final static int STEP_167 = 167; 196 | public final static int STEP_168 = 168; 197 | public final static int STEP_169 = 169; 198 | /*****************************************/ 199 | public final static int STEP_170 = 170; 200 | public final static int STEP_171 = 171; 201 | public final static int STEP_172 = 172; 202 | public final static int STEP_173 = 173; 203 | public final static int STEP_174 = 174; 204 | public final static int STEP_175 = 175; 205 | public final static int STEP_176 = 176; 206 | public final static int STEP_177 = 177; 207 | public final static int STEP_178 = 178; 208 | public final static int STEP_179 = 179; 209 | /*****************************************/ 210 | public final static int STEP_180 = 180; 211 | public final static int STEP_181 = 181; 212 | public final static int STEP_182 = 182; 213 | public final static int STEP_183 = 183; 214 | public final static int STEP_184 = 184; 215 | public final static int STEP_185 = 185; 216 | public final static int STEP_186 = 186; 217 | public final static int STEP_187 = 187; 218 | public final static int STEP_188 = 188; 219 | public final static int STEP_189 = 189; 220 | /*****************************************/ 221 | public final static int STEP_190 = 190; 222 | public final static int STEP_191 = 191; 223 | public final static int STEP_192 = 192; 224 | public final static int STEP_193 = 193; 225 | public final static int STEP_194 = 194; 226 | public final static int STEP_195 = 195; 227 | public final static int STEP_196 = 196; 228 | public final static int STEP_197 = 197; 229 | public final static int STEP_198 = 198; 230 | public final static int STEP_199 = 199; 231 | public final static int STEP_200 = 200; 232 | } 233 | -------------------------------------------------------------------------------- /abllib/src/main/java/com/levine/abllib/FindViewCountDown.java: -------------------------------------------------------------------------------- 1 | package com.levine.abllib; 2 | 3 | import android.os.CountDownTimer; 4 | import android.support.annotation.NonNull; 5 | import android.view.accessibility.AccessibilityNodeInfo; 6 | 7 | import com.levine.abllib.utils.AblViewUtil; 8 | 9 | /** 10 | * 寻找界面倒计时 11 | * 2019/4/21 12 | * 15:21 13 | * Levine 14 | * wechat 1483232332 15 | */ 16 | public class FindViewCountDown { 17 | 18 | private static DownTimer mDownTimer; 19 | public static long millisInFuture = 10000;//默认倒计时总时长 20 | public static long countDownInterval = 500;//间隔时间 21 | 22 | private static class DownTimer extends CountDownTimer { 23 | 24 | private String[] mMsgViewIdOrText; 25 | private int mStep; 26 | private CallBack mCallback; 27 | 28 | public DownTimer( 29 | long millisInFuture, 30 | long countDownInterval, 31 | int step, CallBack callback, 32 | String... viewIdOrText 33 | ) { 34 | super(millisInFuture, countDownInterval); 35 | mMsgViewIdOrText = viewIdOrText.clone(); 36 | mStep = step; 37 | mCallback = callback; 38 | } 39 | 40 | @Override 41 | public void onTick(long l) { 42 | if (AblStepHandler.getInstance().isStop()) { 43 | cancel(); 44 | return; 45 | } 46 | for (String string : mMsgViewIdOrText) { 47 | AccessibilityNodeInfo fromId = AblViewUtil.findById(string, 0); 48 | AccessibilityNodeInfo fromText = AblViewUtil.findByText(string, 0); 49 | if (fromId != null || fromText != null) { 50 | cancel(); 51 | if (mCallback != null) { 52 | mCallback.succ(); 53 | } else { 54 | AblStepHandler.sendMsg(mStep); 55 | } 56 | return; 57 | } 58 | } 59 | } 60 | 61 | @Override 62 | public void onFinish() { 63 | if (mCallback != null) mCallback.fail(); 64 | } 65 | } 66 | 67 | public interface CallBack { 68 | void succ(); 69 | 70 | default void fail() { 71 | } 72 | } 73 | 74 | /** 75 | * 根据viewid或文字发送执行消息 76 | * 77 | * @param millisInFuture view查找超时时间 78 | * @param countDownInterval 查找间隔时间 79 | * @param step 步骤 80 | * @param viewIdOrText viewid或者文字内容 81 | */ 82 | public static void start( 83 | long millisInFuture, 84 | long countDownInterval, 85 | int step, 86 | String... viewIdOrText 87 | ) { 88 | start(millisInFuture, countDownInterval, step, null, viewIdOrText); 89 | } 90 | 91 | /** 92 | * 根据viewid或文字发送执行消息 93 | * 94 | * @param millisInFuture view查找超时时间 95 | * @param countDownInterval 查找间隔时间 96 | * @param callBack 回调,注:如果回调不为空将不发送消息,要发送消息就自己在成功的回调里发送 97 | * @param viewIdOrText viewid或者文字内容 98 | */ 99 | public static void start( 100 | long millisInFuture, 101 | long countDownInterval, 102 | @NonNull CallBack callBack, 103 | String... viewIdOrText 104 | ) { 105 | start(millisInFuture, countDownInterval, 0, callBack, viewIdOrText); 106 | } 107 | 108 | /** 109 | * 根据viewid或文字发送执行消息 110 | * 111 | * @param callBack 回调,注:如果回调不为空将不发送消息,要发送消息就自己在成功的回调里发送 112 | * @param viewIdOrText viewid或者文字内容 113 | */ 114 | public static void start( 115 | @NonNull CallBack callBack, 116 | String... viewIdOrText 117 | ) { 118 | start(millisInFuture, countDownInterval, 0, callBack, viewIdOrText); 119 | } 120 | 121 | /** 122 | * 根据viewid或文字发送执行消息 123 | * 124 | * @param step 步骤 125 | * @param viewIdOrText viewid或者文字内容 126 | */ 127 | public static void start( 128 | int step, 129 | String... viewIdOrText 130 | ) { 131 | start(millisInFuture, countDownInterval, step, null, viewIdOrText); 132 | } 133 | 134 | /** 135 | * 根据viewid或文字发送执行消息 136 | * 137 | * @param millisInFuture view查找超时时间 138 | * @param countDownInterval 查找间隔时间 139 | * @param step 步骤 140 | * @param callBack 回调,注:如果回调不为空将不发送消息,要发送消息就自己在成功的回调里发送 141 | * @param viewIdOrText viewid或者文字内容 142 | */ 143 | private static void start( 144 | long millisInFuture, 145 | long countDownInterval, 146 | int step, 147 | CallBack callBack, 148 | String... viewIdOrText 149 | ) { 150 | if (mDownTimer != null) mDownTimer.cancel(); 151 | mDownTimer = new DownTimer(millisInFuture, countDownInterval, step, callBack, viewIdOrText); 152 | mDownTimer.start(); 153 | } 154 | 155 | public static DownTimer getDownTimer() { 156 | return mDownTimer; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /abllib/src/main/java/com/levine/abllib/callback/AniCallBack.java: -------------------------------------------------------------------------------- 1 | package com.levine.abllib.callback; 2 | 3 | import android.view.accessibility.AccessibilityNodeInfo; 4 | 5 | /** 6 | * 2019/4/21 7 | * 13:05 8 | * Levine 9 | * wechat 1483232332 10 | */ 11 | public interface AniCallBack { 12 | void succ(AccessibilityNodeInfo info); 13 | 14 | default void fail() { 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /abllib/src/main/java/com/levine/abllib/callback/AnisCallBack.java: -------------------------------------------------------------------------------- 1 | package com.levine.abllib.callback; 2 | 3 | import android.view.accessibility.AccessibilityNodeInfo; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * 2019/4/21 9 | * 13:04 10 | * Levine 11 | * wechat 1483232332 12 | */ 13 | public interface AnisCallBack { 14 | void succ(List infos); 15 | 16 | default void fail() { 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /abllib/src/main/java/com/levine/abllib/callback/GestureCallBack.java: -------------------------------------------------------------------------------- 1 | package com.levine.abllib.callback; 2 | 3 | import android.accessibilityservice.GestureDescription; 4 | 5 | /** 6 | * 2019/4/21 7 | * 13:20 8 | * Levine 9 | * wechat 1483232332 10 | */ 11 | public interface GestureCallBack { 12 | void succ(GestureDescription gestureDescription); 13 | 14 | void fail(GestureDescription gestureDescription); 15 | } 16 | -------------------------------------------------------------------------------- /abllib/src/main/java/com/levine/abllib/utils/AblUtil.java: -------------------------------------------------------------------------------- 1 | package com.levine.abllib.utils; 2 | 3 | import android.app.ActivityManager; 4 | import android.app.AppOpsManager; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.graphics.PixelFormat; 8 | import android.net.Uri; 9 | import android.os.Binder; 10 | import android.os.Build; 11 | import android.provider.Settings; 12 | import android.view.Gravity; 13 | import android.view.View; 14 | import android.view.ViewGroup; 15 | import android.view.WindowManager; 16 | 17 | import com.blankj.utilcode.util.LogUtils; 18 | import com.blankj.utilcode.util.ToastUtils; 19 | import com.levine.abllib.AblConfig; 20 | import com.levine.abllib.AblService; 21 | 22 | import java.lang.reflect.Field; 23 | import java.lang.reflect.Method; 24 | import java.util.List; 25 | 26 | import static com.blankj.utilcode.util.ActivityUtils.startActivity; 27 | 28 | /** 29 | * 2019/4/21 30 | * 18:21 31 | * Levine 32 | * wechat 1483232332 33 | */ 34 | public class AblUtil { 35 | 36 | /*** 37 | * 检查悬浮窗开启权限 38 | * @param context 39 | * @return 40 | */ 41 | public static boolean checkFloatPermission(Context context) { 42 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) 43 | return true; 44 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { 45 | try { 46 | Class cls = Class.forName("android.content.Context"); 47 | Field declaredField = cls.getDeclaredField("APP_OPS_SERVICE"); 48 | declaredField.setAccessible(true); 49 | Object obj = declaredField.get(cls); 50 | if (!(obj instanceof String)) { 51 | return false; 52 | } 53 | String str2 = (String) obj; 54 | obj = cls.getMethod("getSystemService", String.class).invoke(context, str2); 55 | cls = Class.forName("android.app.AppOpsManager"); 56 | Field declaredField2 = cls.getDeclaredField("MODE_ALLOWED"); 57 | declaredField2.setAccessible(true); 58 | Method checkOp = cls.getMethod("checkOp", Integer.TYPE, Integer.TYPE, String.class); 59 | int result = (Integer) checkOp.invoke(obj, 24, Binder.getCallingUid(), context.getPackageName()); 60 | return result == declaredField2.getInt(cls); 61 | } catch (Exception e) { 62 | return false; 63 | } 64 | } else { 65 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 66 | AppOpsManager appOpsMgr = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); 67 | if (appOpsMgr == null) 68 | return false; 69 | int mode = appOpsMgr.checkOpNoThrow("android:system_alert_window", android.os.Process.myUid(), context 70 | .getPackageName()); 71 | return Settings.canDrawOverlays(context) || mode == AppOpsManager.MODE_ALLOWED || mode == AppOpsManager.MODE_IGNORED; 72 | } else { 73 | return Settings.canDrawOverlays(context); 74 | } 75 | } 76 | } 77 | 78 | /** 79 | * 添加悬浮界面 80 | * 81 | * @param context 82 | * @param view 83 | */ 84 | public static void addSuspensionWindowView(Context context, View view) { 85 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 86 | if (Settings.canDrawOverlays(context)) { 87 | addSuspensionView(context, view); 88 | } else { 89 | ToastUtils.showShort("请先开启允许显示在其他应用上权限"); 90 | } 91 | } else { 92 | addSuspensionView(context, view); 93 | } 94 | } 95 | 96 | public static void removeSuspensionWindowView(Context context, View view) { 97 | WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 98 | windowManager.removeView(view); 99 | } 100 | 101 | /** 102 | * 添加悬浮界面 103 | * 104 | * @param context 105 | * @param view 106 | */ 107 | private static void addSuspensionView(Context context, View view) { 108 | WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 109 | WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(); 110 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 111 | layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; 112 | } else { 113 | layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE; 114 | } 115 | layoutParams.format = PixelFormat.TRANSLUCENT;// 支持透明 116 | // layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;// 焦点 117 | layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;//窗口的宽和高 118 | layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT; 119 | layoutParams.x = 0;//窗口位置的偏移量 120 | layoutParams.y = 0; 121 | layoutParams.gravity = Gravity.CENTER; 122 | windowManager.addView(view, layoutParams);//添加窗口 123 | } 124 | 125 | /** 126 | * 打开悬浮窗授权界面 127 | * 128 | * @param context 129 | */ 130 | public static void openDrawOverlaysAnth(Context context) { 131 | Intent intent = new Intent( 132 | Settings.ACTION_MANAGE_OVERLAY_PERMISSION, 133 | Uri.parse("package:" + context.getPackageName()) 134 | ); 135 | context.startActivity(intent); 136 | } 137 | 138 | /** 139 | * 检查是否是需要监听的APP包名 140 | * 141 | * @param thisPackageName APP包名 142 | * @return 143 | */ 144 | public static boolean checkPackageName(String thisPackageName) { 145 | if (AblConfig.sMonitoringPackageNames != null && AblConfig.sMonitoringPackageNames.length > 0) { 146 | for (String packageName : AblConfig.sMonitoringPackageNames) { 147 | if (packageName.contentEquals(thisPackageName)) { 148 | return true; 149 | } 150 | } 151 | return false; 152 | } 153 | return true; 154 | } 155 | 156 | /** 157 | * 打开无障碍服务设置 158 | */ 159 | public static void openAccessibilitySettings() { 160 | Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS); 161 | startActivity(intent); 162 | } 163 | 164 | /** 165 | * 辅助服务是否开启 166 | * 167 | * @return 168 | */ 169 | public static boolean isAccessibilityServiceOpen(Context context) { 170 | ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 171 | List services = am.getRunningServices(Short.MAX_VALUE); 172 | for (ActivityManager.RunningServiceInfo info : services) { 173 | LogUtils.v(info.service.getClassName()); 174 | if (info.service.getClassName().equals(AblService.class.getName())) { 175 | return true; 176 | } 177 | } 178 | return false; 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /abllib/src/main/java/com/levine/abllib/utils/AblViewUtil.java: -------------------------------------------------------------------------------- 1 | package com.levine.abllib.utils; 2 | 3 | import android.accessibilityservice.AccessibilityService; 4 | import android.accessibilityservice.GestureDescription; 5 | import android.annotation.TargetApi; 6 | import android.content.ClipData; 7 | import android.content.ClipboardManager; 8 | import android.content.Context; 9 | import android.graphics.Path; 10 | import android.os.Build; 11 | import android.support.annotation.Nullable; 12 | import android.view.accessibility.AccessibilityNodeInfo; 13 | 14 | import com.blankj.utilcode.util.ScreenUtils; 15 | import com.levine.abllib.AblService; 16 | import com.levine.abllib.callback.AniCallBack; 17 | import com.levine.abllib.callback.AnisCallBack; 18 | import com.levine.abllib.callback.GestureCallBack; 19 | 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | 23 | /** 24 | * 界面操作工具类 25 | * wechat 1483232332 26 | */ 27 | public class AblViewUtil { 28 | 29 | /** 30 | * 根据id获取view 31 | * 32 | * @param parent 33 | * @param id 界面id 34 | * @param position 35 | * @return 36 | */ 37 | public static AccessibilityNodeInfo findById( 38 | AccessibilityNodeInfo parent, 39 | String id, 40 | int position, 41 | @Nullable AniCallBack callBack 42 | ) { 43 | if (parent != null) { 44 | List accessibilityNodeInfos = 45 | parent.findAccessibilityNodeInfosByViewId(id); 46 | if (accessibilityNodeInfos != null && 47 | !accessibilityNodeInfos.isEmpty() && 48 | position < accessibilityNodeInfos.size()) { 49 | if (callBack != null) { 50 | callBack.succ(accessibilityNodeInfos.get(position)); 51 | } 52 | return accessibilityNodeInfos.get(position); 53 | } 54 | } 55 | if (callBack != null) { 56 | callBack.fail(); 57 | } 58 | return null; 59 | } 60 | 61 | public static AccessibilityNodeInfo findById( 62 | AccessibilityNodeInfo parent, 63 | String id, 64 | int position 65 | ) { 66 | return findById(parent, id, position, null); 67 | } 68 | 69 | public static AccessibilityNodeInfo findById(String id, int position) { 70 | return findById(AblService.getInstance().getRootInActiveWindow(), id, position, null); 71 | } 72 | 73 | public static AccessibilityNodeInfo findById(String id, int position, AniCallBack callBack) { 74 | return findById(AblService.getInstance().getRootInActiveWindow(), id, position, callBack); 75 | } 76 | 77 | public static List findById( 78 | AccessibilityNodeInfo parent, 79 | String id, 80 | @Nullable AnisCallBack anisCallBack 81 | ) { 82 | if (parent != null) { 83 | List accessibilityNodeInfos = 84 | parent.findAccessibilityNodeInfosByViewId(id); 85 | if (accessibilityNodeInfos != null && 86 | !accessibilityNodeInfos.isEmpty()) { 87 | if (anisCallBack != null) anisCallBack.succ(accessibilityNodeInfos); 88 | return accessibilityNodeInfos; 89 | } 90 | } 91 | if (anisCallBack != null) anisCallBack.fail(); 92 | return new ArrayList<>(); 93 | } 94 | 95 | public static List findById( 96 | AccessibilityNodeInfo parent, 97 | String id 98 | ) { 99 | return findById(parent, id, null); 100 | } 101 | 102 | public static List findById(String id) { 103 | return findById(AblService.getInstance().getRootInActiveWindow(), id, null); 104 | } 105 | 106 | public static List findById(String id, AnisCallBack anisCallBack) { 107 | return findById(AblService.getInstance().getRootInActiveWindow(), id, anisCallBack); 108 | } 109 | 110 | /** 111 | * 根据文本获取view 112 | * 113 | * @param parent 114 | * @param text 115 | * @param position 116 | * @return 117 | */ 118 | public static AccessibilityNodeInfo findByText(AccessibilityNodeInfo parent, String text, int position) { 119 | if (parent != null) { 120 | List accessibilityNodeInfos = 121 | parent.findAccessibilityNodeInfosByText(text); 122 | if (accessibilityNodeInfos != null && 123 | !accessibilityNodeInfos.isEmpty() && 124 | position < accessibilityNodeInfos.size()) { 125 | return accessibilityNodeInfos.get(position); 126 | } 127 | } 128 | return null; 129 | } 130 | 131 | public static AccessibilityNodeInfo findByText(String text, int position) { 132 | return findByText(AblService.getInstance().getRootInActiveWindow(), text, position); 133 | } 134 | 135 | public static List findByText(AccessibilityNodeInfo parent, String text) { 136 | if (parent != null) { 137 | List accessibilityNodeInfos = 138 | parent.findAccessibilityNodeInfosByText(text); 139 | if (accessibilityNodeInfos != null && 140 | !accessibilityNodeInfos.isEmpty()) { 141 | return accessibilityNodeInfos; 142 | } 143 | } 144 | return new ArrayList<>(); 145 | } 146 | 147 | public static List findByText(String text) { 148 | return findByText(AblService.getInstance().getRootInActiveWindow(), text); 149 | } 150 | 151 | /** 152 | * 手势模拟 153 | * 154 | * @param start_position 开始位置,长度为2的数组,下标0为x轴,下标1为y轴 155 | * @param end_position 156 | * @param startTime 开始间隔时间 157 | * @param duration 持续时间 158 | * @param callback 回调 159 | */ 160 | @TargetApi(Build.VERSION_CODES.N) 161 | public static void dispatch_gesture( 162 | float[] start_position, 163 | float[] end_position, 164 | long startTime, 165 | long duration, 166 | @Nullable GestureCallBack callback 167 | ) { 168 | Path path = new Path(); 169 | path.moveTo(start_position[0], start_position[1]); 170 | path.lineTo(end_position[0], end_position[1]); 171 | GestureDescription.Builder builder = new GestureDescription.Builder(); 172 | GestureDescription.StrokeDescription strokeDescription = 173 | new GestureDescription.StrokeDescription(path, startTime, duration); 174 | GestureDescription gestureDescription = builder.addStroke(strokeDescription).build(); 175 | AblService.getInstance().dispatchGesture(gestureDescription, new AccessibilityService.GestureResultCallback() { 176 | @Override 177 | public void onCompleted(GestureDescription gestureDescription) { 178 | if (callback != null) callback.succ(gestureDescription); 179 | } 180 | 181 | @Override 182 | public void onCancelled(GestureDescription gestureDescription) { 183 | if (callback != null) callback.fail(gestureDescription); 184 | } 185 | }, null); 186 | } 187 | 188 | /** 189 | * x轴居中竖直滑动屏幕 190 | * 191 | * @param yRatio y轴份数 192 | * @param startSlideRatio y轴开始的份数 193 | * @param stopSlideRatio y轴结束的份数 194 | */ 195 | public static void scrollVertical( 196 | int yRatio, 197 | int startSlideRatio, 198 | int stopSlideRatio, 199 | long startTime, 200 | long duration, 201 | @Nullable GestureCallBack callback 202 | ) { 203 | int screenHeight = ScreenUtils.getScreenHeight(); 204 | int screenWidth = ScreenUtils.getScreenWidth(); 205 | int start = (screenHeight / yRatio) * startSlideRatio; 206 | int stop = (screenHeight / yRatio) * stopSlideRatio; 207 | dispatch_gesture( 208 | new float[]{screenWidth >> 1, start}, 209 | new float[]{screenWidth >> 1, stop}, 210 | startTime, 211 | duration, 212 | callback 213 | ); 214 | 215 | } 216 | 217 | /** 218 | * 竖直滑动,y轴分为20份 219 | * 220 | * @param startSlideRatio 开始份数 221 | * @param stopSlideRatio 结束份数 222 | */ 223 | public static void scrollVertical( 224 | int startSlideRatio, 225 | int stopSlideRatio 226 | ) { 227 | int screenHeight = ScreenUtils.getScreenHeight(); 228 | int screenWidth = ScreenUtils.getScreenWidth(); 229 | int start = (screenHeight / 20) * startSlideRatio; 230 | int stop = (screenHeight / 20) * stopSlideRatio; 231 | dispatch_gesture( 232 | new float[]{screenWidth >> 1, start}, 233 | new float[]{screenWidth >> 1, stop}, 234 | 50, 235 | 500, 236 | null 237 | ); 238 | 239 | } 240 | 241 | /** 242 | * x轴居中竖直滑动屏幕 243 | * 244 | * @param startY y轴开始位置 245 | * @param stopY y轴结束位置 246 | */ 247 | public static void scrollVertical( 248 | float startY, 249 | float stopY, 250 | long startTime, 251 | long duration, 252 | @Nullable GestureCallBack callback 253 | ) { 254 | int screenWidth = ScreenUtils.getScreenWidth(); 255 | dispatch_gesture( 256 | new float[]{screenWidth >> 1, startY}, 257 | new float[]{screenWidth >> 1, stopY}, 258 | startTime, 259 | duration, 260 | callback 261 | ); 262 | 263 | } 264 | 265 | 266 | /** 267 | * y轴居中横向滑动 268 | * 269 | * @param xRatio x轴份数 270 | * @param startSlideRatio x轴开始滑动份数 271 | * @param stopSlideRatio x轴结束滑动份数 272 | * @param startTime 开始延迟时间 273 | * @param duration 滑动持续时间 274 | * @param callback 回调 275 | */ 276 | public void scrollHorizontal( 277 | int xRatio, 278 | int startSlideRatio, 279 | int stopSlideRatio, 280 | long startTime, 281 | long duration, 282 | @Nullable GestureCallBack callback 283 | ) { 284 | int screenHeight = ScreenUtils.getScreenHeight(); 285 | int screenWidth = ScreenUtils.getScreenWidth(); 286 | int start = (screenWidth / xRatio) * startSlideRatio; 287 | int stop = (screenWidth / xRatio) * stopSlideRatio; 288 | dispatch_gesture( 289 | new float[]{start, screenHeight >> 1}, 290 | new float[]{stop, screenHeight >> 1}, 291 | startTime, 292 | duration, 293 | callback 294 | ); 295 | } 296 | 297 | /** 298 | * y轴居中横向滑动 299 | * 300 | * @param startX x轴开始位置 301 | * @param stopX x轴结束位置 302 | * @param startTime 开始延迟时间 303 | * @param duration 滑动持续时间 304 | * @param callback 回调 305 | */ 306 | public void scrollHorizontal( 307 | int startX, 308 | int stopX, 309 | long startTime, 310 | long duration, 311 | @Nullable GestureCallBack callback 312 | ) { 313 | int screenHeight = ScreenUtils.getScreenHeight(); 314 | dispatch_gesture( 315 | new float[]{startX, screenHeight >> 1}, 316 | new float[]{stopX, screenHeight >> 1}, 317 | startTime, 318 | duration, 319 | callback 320 | ); 321 | } 322 | 323 | /** 324 | * 点击屏幕 325 | * 326 | * @param ratio 屏幕长宽份数 327 | * @param xRatio 屏幕宽ratio份的比例 328 | * @param yRatio 329 | */ 330 | public static void clickScreen( 331 | int ratio, 332 | int xRatio, 333 | int yRatio, 334 | @Nullable GestureCallBack callback 335 | ) { 336 | int screenHeight = ScreenUtils.getScreenHeight(); 337 | int screenWidth = ScreenUtils.getScreenWidth(); 338 | int y = (screenHeight / ratio) * yRatio; 339 | int x = (screenWidth / ratio) * xRatio; 340 | dispatch_gesture( 341 | new float[]{x, y}, 342 | new float[]{x, y}, 343 | 100, 344 | 50, 345 | callback 346 | ); 347 | } 348 | 349 | /** 350 | * 点击屏幕 351 | */ 352 | public static void clickScreen( 353 | int xRatio, 354 | int yRatio 355 | ) { 356 | int screenHeight = ScreenUtils.getScreenHeight(); 357 | int screenWidth = ScreenUtils.getScreenWidth(); 358 | int y = (screenHeight / 20) * yRatio; 359 | int x = (screenWidth / 20) * xRatio; 360 | dispatch_gesture( 361 | new float[]{x, y}, 362 | new float[]{x, y}, 363 | 100, 364 | 50, 365 | null 366 | ); 367 | } 368 | 369 | public static void clickScreen( 370 | float x, 371 | float y 372 | ) { 373 | dispatch_gesture( 374 | new float[]{x, y}, 375 | new float[]{x, y}, 376 | 100, 377 | 2000, 378 | null 379 | ); 380 | } 381 | 382 | public static void clickScreen( 383 | float x, 384 | float y, 385 | long duration 386 | ) { 387 | dispatch_gesture( 388 | new float[]{x, y}, 389 | new float[]{x, y}, 390 | 100, 391 | duration, 392 | null 393 | ); 394 | } 395 | 396 | /** 397 | * 点击屏幕 398 | * 399 | * @param x x轴像素 400 | * @param y 401 | * @param startTime 开始间隔时间 402 | * @param duration 持续时间 403 | */ 404 | public static void clickScreen( 405 | float x, 406 | float y, 407 | long startTime, 408 | long duration, 409 | @Nullable GestureCallBack callback 410 | ) { 411 | dispatch_gesture( 412 | new float[]{x, y}, 413 | new float[]{x, y}, 414 | startTime, 415 | duration, 416 | callback 417 | ); 418 | } 419 | 420 | /** 421 | * 返回 422 | */ 423 | public static void back() { 424 | AblService.getInstance().performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK); 425 | } 426 | 427 | /** 428 | * 黏贴文本至view 429 | * 430 | * @param info 431 | * @param text 432 | */ 433 | public static void paste(AccessibilityNodeInfo info, String text) { 434 | ClipData clip = ClipData.newPlainText(System.currentTimeMillis() + "", text); 435 | ClipboardManager clipboardManager = (ClipboardManager) AblService.getInstance().getSystemService(Context.CLIPBOARD_SERVICE); 436 | assert clipboardManager != null; 437 | clipboardManager.setPrimaryClip(clip); 438 | ClipData abc = clipboardManager.getPrimaryClip(); 439 | if (info != null) info.performAction(AccessibilityNodeInfo.ACTION_PASTE); 440 | } 441 | } 442 | -------------------------------------------------------------------------------- /abllib/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /abllib/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /abllib/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /abllib/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /abllib/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ven-coder/Abllib/2c99ecaf4835ffc1e0278bd2acdc5b7e97c18b8b/abllib/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /abllib/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ven-coder/Abllib/2c99ecaf4835ffc1e0278bd2acdc5b7e97c18b8b/abllib/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /abllib/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ven-coder/Abllib/2c99ecaf4835ffc1e0278bd2acdc5b7e97c18b8b/abllib/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /abllib/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ven-coder/Abllib/2c99ecaf4835ffc1e0278bd2acdc5b7e97c18b8b/abllib/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /abllib/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ven-coder/Abllib/2c99ecaf4835ffc1e0278bd2acdc5b7e97c18b8b/abllib/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /abllib/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ven-coder/Abllib/2c99ecaf4835ffc1e0278bd2acdc5b7e97c18b8b/abllib/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /abllib/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ven-coder/Abllib/2c99ecaf4835ffc1e0278bd2acdc5b7e97c18b8b/abllib/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /abllib/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ven-coder/Abllib/2c99ecaf4835ffc1e0278bd2acdc5b7e97c18b8b/abllib/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /abllib/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ven-coder/Abllib/2c99ecaf4835ffc1e0278bd2acdc5b7e97c18b8b/abllib/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /abllib/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ven-coder/Abllib/2c99ecaf4835ffc1e0278bd2acdc5b7e97c18b8b/abllib/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /abllib/src/main/res/xml/abl_service.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /abllib/src/test/java/com/levine/abllib/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.levine.abllib; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 28 5 | defaultConfig { 6 | applicationId "luoyi.android.com.abldemo" 7 | minSdkVersion 20 8 | targetSdkVersion 28 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | 20 | compileOptions { 21 | sourceCompatibility = '1.8' 22 | targetCompatibility = '1.8' 23 | } 24 | 25 | } 26 | 27 | dependencies { 28 | implementation fileTree(include: ['*.jar'], dir: 'libs') 29 | implementation 'com.android.support:appcompat-v7:28.0.0' 30 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 31 | testImplementation 'junit:junit:4.12' 32 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 33 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 34 | implementation project(':abllib') 35 | // implementation 'com.github.Levine1992:Abllib:V1.0' 36 | } 37 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/luoyi/android/com/abldemo/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package luoyi.android.com.abldemo; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("luoyi.android.com.abldemo", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/java/luoyi/android/com/abldemo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package luoyi.android.com.abldemo; 2 | 3 | import android.annotation.TargetApi; 4 | import android.content.Context; 5 | import android.os.Build; 6 | import android.os.Bundle; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.view.View; 9 | import android.view.WindowManager; 10 | 11 | import com.blankj.utilcode.util.ToastUtils; 12 | import com.levine.abllib.AblConfig; 13 | import com.levine.abllib.AblService; 14 | import com.levine.abllib.AblStepHandler; 15 | import com.levine.abllib.AblSteps; 16 | import com.levine.abllib.utils.AblUtil; 17 | 18 | public class MainActivity extends AppCompatActivity { 19 | 20 | @Override 21 | protected void onCreate(Bundle savedInstanceState) { 22 | super.onCreate(savedInstanceState); 23 | setContentView(R.layout.activity_main); 24 | AblConfig.Builder() 25 | .setLogTag("123456") 26 | .setStepMsgDelayMillis(2000) 27 | .setFindViewCountDownInterval(200) 28 | .setFindViewMillisInFuture(10000) 29 | .build().init(); 30 | AblStepHandler.getInstance().initStepClass(new TestAblStep1()); 31 | findViewById(R.id.btn_1).setOnClickListener(new View.OnClickListener() { 32 | @Override 33 | public void onClick(View v) { 34 | AblUtil.openDrawOverlaysAnth(MainActivity.this); 35 | } 36 | }); 37 | findViewById(R.id.btn_2).setOnClickListener(new View.OnClickListener() { 38 | @Override 39 | public void onClick(View v) { 40 | AblUtil.addSuspensionWindowView(MainActivity.this, initWindowView()); 41 | } 42 | }); 43 | findViewById(R.id.btn_3).setOnClickListener(new View.OnClickListener() { 44 | @Override 45 | public void onClick(View v) { 46 | AblUtil.openAccessibilitySettings(); 47 | } 48 | }); 49 | findViewById(R.id.btn_4).setOnClickListener(new View.OnClickListener() { 50 | @Override 51 | public void onClick(View v) { 52 | if (AblUtil.isAccessibilityServiceOpen(MainActivity.this)) { 53 | AblStepHandler.getInstance().setStop(false); 54 | AblStepHandler.sendMsg(AblSteps.STEP_1); 55 | } else { 56 | ToastUtils.showShort("请先开启辅助服务"); 57 | } 58 | 59 | } 60 | }); 61 | findViewById(R.id.btn_5).setOnClickListener(new View.OnClickListener() { 62 | @Override 63 | public void onClick(View v) { 64 | AblStepHandler.getInstance().setStop(true); 65 | } 66 | }); 67 | findViewById(R.id.btn_6).setOnClickListener(new View.OnClickListener() { 68 | @TargetApi(Build.VERSION_CODES.N) 69 | @Override 70 | public void onClick(View v) { 71 | AblService.getInstance().disableSelf(); 72 | } 73 | }); 74 | } 75 | 76 | private View initWindowView() { 77 | View view = View.inflate(this, R.layout.view_test, null); 78 | view.findViewById(R.id.btn_1).setOnClickListener(new View.OnClickListener() { 79 | @Override 80 | public void onClick(View v) { 81 | if (AblUtil.isAccessibilityServiceOpen(MainActivity.this)) { 82 | AblStepHandler.getInstance().setStop(false); 83 | AblStepHandler.sendMsg(AblSteps.STEP_1); 84 | } else { 85 | ToastUtils.showShort("请先开启辅助服务"); 86 | } 87 | } 88 | }); 89 | view.findViewById(R.id.btn_2).setOnClickListener(new View.OnClickListener() { 90 | @Override 91 | public void onClick(View v) { 92 | AblStepHandler.getInstance().setStop(true); 93 | } 94 | }); 95 | view.findViewById(R.id.btn_3).setOnClickListener(new View.OnClickListener() { 96 | @TargetApi(Build.VERSION_CODES.N) 97 | @Override 98 | public void onClick(View v) { 99 | AblService.getInstance().disableSelf(); 100 | } 101 | }); 102 | view.findViewById(R.id.btn_4).setOnClickListener(new View.OnClickListener() { 103 | @Override 104 | public void onClick(View v) { 105 | WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); 106 | windowManager.removeView(view); 107 | } 108 | }); 109 | return view; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /app/src/main/java/luoyi/android/com/abldemo/TestAblStep1.java: -------------------------------------------------------------------------------- 1 | package luoyi.android.com.abldemo; 2 | 3 | import android.os.Message; 4 | import android.view.accessibility.AccessibilityNodeInfo; 5 | 6 | import com.levine.abllib.AblStepHandler; 7 | import com.levine.abllib.AblSteps; 8 | import com.levine.abllib.utils.AblViewUtil; 9 | import com.levine.abllib.AblStepBase; 10 | import com.levine.abllib.callback.AniCallBack; 11 | 12 | /** 13 | * 2019/4/21 14 | * 17:01 15 | * Levine 16 | * wechat 1483232332 17 | */ 18 | public class TestAblStep1 extends AblStepBase { 19 | @Override 20 | public void onStep(int step, Message msg) { 21 | switch (step) { 22 | case AblSteps.STEP_1: 23 | AblViewUtil.findById( 24 | "luoyi.android.com.abldemo:id/btn_3", 25 | 0, 26 | new AniCallBack() { 27 | @Override 28 | public void succ(AccessibilityNodeInfo info) { 29 | info.performAction(AccessibilityNodeInfo.ACTION_CLICK); 30 | AblStepHandler.sendMsg(AblSteps.STEP_2); 31 | } 32 | } 33 | ); 34 | break; 35 | case AblSteps.STEP_2: 36 | AblViewUtil.back(); 37 | AblStepHandler.sendMsg(AblSteps.STEP_1); 38 | break; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/luoyi/android/com/abldemo/TestAblStep2.java: -------------------------------------------------------------------------------- 1 | package luoyi.android.com.abldemo; 2 | 3 | import android.os.Message; 4 | 5 | import com.levine.abllib.AblStepBase; 6 | 7 | /** 8 | * 2019/4/21 9 | * 17:01 10 | * Levine 11 | * wechat 1483232332 12 | */ 13 | public class TestAblStep2 extends AblStepBase { 14 | @Override 15 | public void onStep(int step, Message msg) { 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 |