mirror of
https://github.com/TonyJiangWJ/Auto.js.git
synced 2026-06-24 21:33:16 +08:00
commit
a9abb60f37
33
Readme.md
33
Readme.md
@ -1,19 +1,31 @@
|
||||
# AutoJs
|
||||
# Auto.js
|
||||
## 简介
|
||||
一个**不需要Root权限**的类似按键精灵的自动操作软件,可以实现自动点击、滑动、输入文字、打开应用等。
|
||||
一个主要由无障碍服务实现的**不需要Root权限**的类似按键精灵的自动操作软件,可以实现自动点击、滑动、输入文字、打开应用等。
|
||||
|
||||
同时有[Sublime Text 插件](https://github.com/hyb1996/AutoJs-Sublime-Plugin)可提供基础的在桌面开发的功能。
|
||||
|
||||
下载地址:[酷安](http://www.coolapk.com/apk/com.stardust.scriptdroid)
|
||||
|
||||
特性:
|
||||
### 特性
|
||||
* 简单易用的自动操作函数
|
||||
* 悬浮窗录制和运行
|
||||
* 丰富的文档、教程与示例
|
||||
* 更专业&强大的选择器API,提供对屏幕上的控件的寻找、遍历、获取信息、操作等。类似于Google的UI测试框架UiAutomator,您也可以把他当做移动版UI测试框架使用
|
||||
* 采用JavaScript为脚本语言,支持简单的代码补全。您也可以把他当作简便的JavaScript IDE使用
|
||||
* 带有界面分析工具,类似Android Studio的LayoutInspector,可以分析界面层次和范围、获取界面上的控件信息
|
||||
* 支持使用Root权限以提供更强大的屏幕点击、滑动、录制功能和运行shell命令
|
||||
* 支持使用Root权限以提供更强大的屏幕点击、滑动、录制功能和运行shell命令。录制录制可产生js文件或二进制文件,录制动作的回放比较流畅
|
||||
* 提供截取屏幕、保存截图、图片找色等函数,可进行简单的游戏脚本制作;未来将加入找图功能
|
||||
* 与Python类似的文件处理API,以及更多日常工具函数
|
||||
* 可以用e4x编写简单的界面,并且未来将加入打包为独立应用功能,可用于制作简单的应用
|
||||
|
||||
### 文档
|
||||
可在[这里](https://github.com/hyb1996/NoRootScriptDroid/tree/master/app/src/main/assets/help/documentation)查看在线文档,或者在应用内帮助页面查看。
|
||||
|
||||
目前文档不是很完善。
|
||||
|
||||
### 示例
|
||||
可在[这里](https://github.com/hyb1996/NoRootScriptDroid/tree/master/app/src/main/assets/sample)查看一些示例,或者直接在应用内查看和运行。
|
||||
|
||||
### 截图
|
||||
|
||||

|
||||
|
||||
@ -27,6 +39,17 @@
|
||||
|
||||

|
||||
|
||||
### Todo
|
||||
|
||||
* 脚本社区或脚本市场
|
||||
* 更方便地悬浮窗编辑、运行脚本
|
||||
* 更方便地脚本编辑,在编辑器界面可搜索、查看函数
|
||||
* 智能生成选择器代码
|
||||
* 更详细的文档和向导(Developer Guide)
|
||||
* 全新的脚本
|
||||
* 找图功能
|
||||
* 脚本打包为独立应用功能
|
||||
|
||||
## License
|
||||
基于[Mozilla Public License Version 2.0](https://github.com/hyb1996/NoRootScriptDroid/blob/master/LICENSE.md)并附加以下条款:
|
||||
* **非商业性使用** — 不得将此项目及其衍生的项目的源代码和二进制产品用于任何商业和盈利用途
|
||||
|
||||
@ -9,8 +9,8 @@ android {
|
||||
applicationId "com.stardust.scriptdroid"
|
||||
minSdkVersion 17
|
||||
targetSdkVersion 23
|
||||
versionCode 162
|
||||
versionName "2.0.16 Beta2"
|
||||
versionCode 163
|
||||
versionName "2.0.16 Beta2.1"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
multiDexEnabled true
|
||||
ndk {
|
||||
@ -116,7 +116,6 @@ dependencies {
|
||||
compile 'io.mattcarroll.hover:hover:0.9.7'
|
||||
compile 'com.bignerdranch.android:expandablerecyclerview:3.0.0-RC1'
|
||||
compile 'com.yqritc:recyclerview-flexibledivider:1.4.0'
|
||||
compile 'com.ashokvarma.android:bottom-navigation-bar:2.0.1'
|
||||
compile 'com.wang.avi:library:2.1.3'
|
||||
compile "io.reactivex.rxjava2:rxjava:2.1.0"
|
||||
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
|
||||
@ -126,7 +125,7 @@ dependencies {
|
||||
compile 'com.android.volley:volley:1.0.0'
|
||||
compile 'com.flurry.android:analytics:7.0.0@aar'
|
||||
compile 'com.pushtorefresh.storio:sqlite:1.12.3'
|
||||
// 920 Text Editor
|
||||
// 920 Text Editors
|
||||
compile 'com.afollestad.material-dialogs:commons:0.9.2.3'
|
||||
compile 'com.makeramen:roundedimageview:2.2.1'
|
||||
compile 'com.rengwuxian.materialedittext:library:2.0.3'
|
||||
|
||||
@ -58,13 +58,13 @@ for(var i = 0; i < 100; i++){
|
||||
模拟按下物理按键上。
|
||||
|
||||
### Down()
|
||||
模拟按下物理按键上。
|
||||
模拟按下物理按键下。
|
||||
|
||||
### Left()
|
||||
模拟按下物理按键上。
|
||||
模拟按下物理按键左。
|
||||
|
||||
### Right()
|
||||
模拟按下物理按键上。
|
||||
模拟按下物理按键右。
|
||||
|
||||
### OK()
|
||||
模拟按下物理按键确定。
|
||||
|
||||
@ -2,9 +2,8 @@
|
||||
|
||||
RootAutomator是一个使用Root权限来模拟触摸的对象,用它可以完成触摸与多点触摸,并且这些动作的执行没有延迟。
|
||||
|
||||
构造RootAutomator需要一个context参数。
|
||||
```
|
||||
var ra = RootAutomator(context);
|
||||
var ra = RootAutomator();
|
||||
```
|
||||
|
||||
### RootAutomator.tap(x, y\[, id\])
|
||||
@ -14,7 +13,7 @@ var ra = RootAutomator(context);
|
||||
|
||||
点击位置(x, y)。其中id是一个整数值,用于区分多点触摸,不同的id表示不同的"手指",例如:
|
||||
```
|
||||
var ra = RootAutomator(context);
|
||||
var ra = RootAutomator();
|
||||
//让"手指1"点击位置(100, 100)
|
||||
ra.tap(100, 100, 1);
|
||||
//让"手指2"点击位置(200, 200);
|
||||
|
||||
@ -12,4 +12,3 @@ setInterval(function(){
|
||||
toast(i * 5 + "秒");
|
||||
}, 5000);
|
||||
|
||||
loop();
|
||||
@ -8,4 +8,3 @@ setInterval(function(){
|
||||
}
|
||||
}, 4000);
|
||||
|
||||
loop();
|
||||
|
||||
@ -40,6 +40,7 @@ public class DocumentationActivity extends BaseActivity {
|
||||
super.onCreate(savedInstanceState);
|
||||
setUpUI();
|
||||
handleIntent(getIntent());
|
||||
setToolbarAsBack(mTitle);
|
||||
}
|
||||
|
||||
private void handleIntent(Intent intent) {
|
||||
@ -68,7 +69,6 @@ public class DocumentationActivity extends BaseActivity {
|
||||
|
||||
private void setUpUI() {
|
||||
setContentView(R.layout.activity_document);
|
||||
setToolbarAsBack(mTitle);
|
||||
setUpLoadingView();
|
||||
}
|
||||
|
||||
|
||||
@ -107,9 +107,13 @@ public class HelpCatalogueActivity extends BaseActivity {
|
||||
if (CATALOGUES == null) {
|
||||
readCatalogues();
|
||||
} else {
|
||||
mLoadingIndicatorView.hide();
|
||||
handleIntent();
|
||||
onCataloguesAvailable();
|
||||
}
|
||||
}
|
||||
|
||||
private void onCataloguesAvailable(){
|
||||
mLoadingIndicatorView.hide();
|
||||
handleIntent();
|
||||
setToolbarAsBack(mTitle);
|
||||
}
|
||||
|
||||
@ -121,8 +125,7 @@ public class HelpCatalogueActivity extends BaseActivity {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mLoadingIndicatorView.hide();
|
||||
handleIntent();
|
||||
onCataloguesAvailable();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -326,22 +326,4 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
|
||||
return mActivityResultMediator;
|
||||
}
|
||||
|
||||
public static void onRecordStop(Context context, String script) {
|
||||
Intent intent = new Intent(context, MainActivity_.class)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
.putExtra(EXTRA_ACTION, ACTION_ON_RECORD_STOP);
|
||||
IntentExtras.newExtras()
|
||||
.put(ARGUMENT_SCRIPT, script)
|
||||
.putInIntent(intent);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
|
||||
public static void onRootRecordStop(Context context, String path) {
|
||||
Intent intent = new Intent(context, MainActivity_.class)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
.putExtra(EXTRA_ACTION, ACTION_ON_ROOT_RECORD_STOP)
|
||||
.putExtra(ARGUMENT_PATH, path);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
}
|
||||
@ -19,7 +19,7 @@
|
||||
<license>Apache Software License 2.0</license>
|
||||
</notice>
|
||||
<notice>
|
||||
<name>StorIO </name>
|
||||
<name>StorIO</name>
|
||||
<url>https://github.com/pushtorefresh/storio</url>
|
||||
<license>Apache Software License 2.0</license>
|
||||
</notice>
|
||||
@ -85,7 +85,7 @@
|
||||
</notice>
|
||||
<notice>
|
||||
<name>Expandable RecyclerView</name>
|
||||
<copyright>Copyright (c) 2014 Big Nerd Ranch</copyright>
|
||||
<copyright>Copyright (c) 2015 Big Nerd Ranch</copyright>
|
||||
<url>https://github.com/bignerdranch/expandable-recycler-view</url>
|
||||
<license>MIT License</license>
|
||||
</notice>
|
||||
@ -107,4 +107,16 @@
|
||||
<url>https://github.com/google/volley</url>
|
||||
<license>Apache Software License 2.0</license>
|
||||
</notice>
|
||||
<notice>
|
||||
<name>Settings Compat</name>
|
||||
<copyright>Copyright 2016 czy1121</copyright>
|
||||
<url>https://github.com/czy1121/settingscompat</url>
|
||||
<license>Apache Software License 2.0</license>
|
||||
</notice>
|
||||
<notice>
|
||||
<name>Zip4j</name>
|
||||
<copyright/>
|
||||
<url>http://www.lingala.net/zip4j/</url>
|
||||
<license>Apache Software License 2.0</license>
|
||||
</notice>
|
||||
</notices>
|
||||
@ -246,7 +246,7 @@
|
||||
<string-array name="ad_showing_mode_keys">
|
||||
<item>默认</item>
|
||||
<item>每天显示一次</item>
|
||||
<item>关闭广告(╥﹏╥)</item>
|
||||
<item>关闭广告</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="ad_showing_mode_values">
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
module.exports = function(__runtime__, scope){
|
||||
function RootAutomator(){
|
||||
this.__ra__ = Object.create(new com.stardust.autojs.runtime.api.RootAutomator(scope.context));
|
||||
this.__ra__ = Object.create(new com.stardust.autojs.runtime.api.RootAutomator(scope.context));
|
||||
var methods = ["sendEvent", "touch", "setScreenMetrics", "touchX", "touchY", "sendSync", "sendMtSync", "tap",
|
||||
"swipe", "press", "longPress", "touchDown", "touchUp", "touchMove", "getDefaultId", "setDefaultId", "exit"];
|
||||
for(var i = 0; i < methods.length; i++){
|
||||
var method = methods[i];
|
||||
this[method] = this.__ra__[method].bind(this.__ra__);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
var p = RootAutomator.prototype;
|
||||
return RootAutomator;
|
||||
|
||||
@ -177,9 +177,9 @@ public class ScriptRuntime {
|
||||
public void init() {
|
||||
if (loopers != null)
|
||||
throw new IllegalStateException("already initialized");
|
||||
loopers = new Loopers();
|
||||
events = new Events(mUiHandler.getContext(), accessibilityBridge, bridges, loopers);
|
||||
timers = new Timers(bridges);
|
||||
loopers = new Loopers(timers);
|
||||
events = new Events(mUiHandler.getContext(), accessibilityBridge, bridges, loopers);
|
||||
}
|
||||
|
||||
public static void setApplicationContext(Context context) {
|
||||
|
||||
@ -6,6 +6,7 @@ import android.os.MessageQueue;
|
||||
import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
|
||||
import com.stardust.lang.ThreadCompat;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
@ -14,12 +15,13 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class Loopers {
|
||||
|
||||
public volatile boolean waitWhenIdle = false;
|
||||
private volatile Looper mServantLooper;
|
||||
private static volatile ConcurrentHashMap<Thread, Looper> sLoopers = new ConcurrentHashMap<>();
|
||||
private Timers mTimers;
|
||||
|
||||
public volatile boolean waitWhenIdle = false;
|
||||
|
||||
public Loopers() {
|
||||
public Loopers(Timers timers) {
|
||||
mTimers = timers;
|
||||
if (Looper.myLooper() == Looper.getMainLooper()) {
|
||||
waitWhenIdle = true;
|
||||
}
|
||||
@ -27,13 +29,20 @@ public class Loopers {
|
||||
@Override
|
||||
public boolean queueIdle() {
|
||||
Looper l = Looper.myLooper();
|
||||
if (l != null && !waitWhenIdle)
|
||||
if (l != null && shouldQuitLooper())
|
||||
l.quit();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean shouldQuitLooper() {
|
||||
if (mTimers.hasPendingCallback()) {
|
||||
return false;
|
||||
}
|
||||
return !waitWhenIdle;
|
||||
}
|
||||
|
||||
|
||||
private void initServantThread() {
|
||||
new ThreadCompat(new Runnable() {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.stardust.autojs.runtime.api;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.SystemClock;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.stardust.autojs.runtime.ScriptBridges;
|
||||
@ -15,19 +16,20 @@ public class Timers {
|
||||
private int mCallbackMaxId = 0;
|
||||
private ScriptBridges mBridges;
|
||||
private Handler mHandler;
|
||||
private long mFutureCallbackUptimeMillis = 0;
|
||||
|
||||
public Timers(ScriptBridges bridges) {
|
||||
mBridges = bridges;
|
||||
}
|
||||
|
||||
private void ensureHander(){
|
||||
if(mHandler == null){
|
||||
private void ensureHandler() {
|
||||
if (mHandler == null) {
|
||||
mHandler = new Handler();
|
||||
}
|
||||
}
|
||||
|
||||
public int setTimeout(final Object callback, long delay, final Object... args) {
|
||||
ensureHander();
|
||||
ensureHandler();
|
||||
mCallbackMaxId++;
|
||||
final int id = mCallbackMaxId;
|
||||
Runnable r = new Runnable() {
|
||||
@ -38,41 +40,44 @@ public class Timers {
|
||||
}
|
||||
};
|
||||
mHandlerCallbacks.put(id, r);
|
||||
mHandler.postDelayed(r, delay);
|
||||
postDelayed(r, delay);
|
||||
return id;
|
||||
}
|
||||
|
||||
public void post(Runnable r) {
|
||||
ensureHander();
|
||||
mHandler.post(r);
|
||||
}
|
||||
|
||||
public void clearTimeout(int id) {
|
||||
clearCallback(id);
|
||||
public boolean clearTimeout(int id) {
|
||||
return clearCallback(id);
|
||||
}
|
||||
|
||||
public int setInterval(final Object listener, final long interval, final Object... args) {
|
||||
ensureHander();
|
||||
ensureHandler();
|
||||
mCallbackMaxId++;
|
||||
final int id = mCallbackMaxId;
|
||||
Runnable r = new Runnable() {
|
||||
final Runnable r = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mHandlerCallbacks.get(id) == null)
|
||||
return;
|
||||
mBridges.callFunction(listener, null, args);
|
||||
mHandler.postDelayed(this, interval);
|
||||
postDelayed(this, interval);
|
||||
}
|
||||
};
|
||||
mHandlerCallbacks.put(id, r);
|
||||
mHandler.postDelayed(r, interval);
|
||||
postDelayed(r, interval);
|
||||
return id;
|
||||
}
|
||||
|
||||
public void clearInterval(int id) {
|
||||
clearTimeout(id);
|
||||
private void postDelayed(Runnable r, long interval) {
|
||||
long uptime = SystemClock.uptimeMillis() + interval;
|
||||
mHandler.postAtTime(r, uptime);
|
||||
mFutureCallbackUptimeMillis = Math.max(mFutureCallbackUptimeMillis, uptime);
|
||||
}
|
||||
|
||||
public boolean clearInterval(int id) {
|
||||
return clearCallback(id);
|
||||
}
|
||||
|
||||
public int setImmediate(final Object listener, final Object... args) {
|
||||
ensureHander();
|
||||
ensureHandler();
|
||||
mCallbackMaxId++;
|
||||
final int id = mCallbackMaxId;
|
||||
Runnable r = new Runnable() {
|
||||
@ -83,21 +88,27 @@ public class Timers {
|
||||
}
|
||||
};
|
||||
mHandlerCallbacks.put(id, r);
|
||||
mHandler.post(r);
|
||||
postDelayed(r, 0);
|
||||
return id;
|
||||
}
|
||||
|
||||
public void clearImmediate(int id) {
|
||||
clearCallback(id);
|
||||
public boolean clearImmediate(int id) {
|
||||
return clearCallback(id);
|
||||
}
|
||||
|
||||
private void clearCallback(int id) {
|
||||
private boolean clearCallback(int id) {
|
||||
Runnable callback = mHandlerCallbacks.get(id);
|
||||
if (callback != null) {
|
||||
mHandler.removeCallbacks(callback);
|
||||
mHandlerCallbacks.remove(id);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public boolean hasPendingCallback() {
|
||||
|
||||
return mFutureCallbackUptimeMillis > SystemClock.uptimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user