add timers modules
This commit is contained in:
@@ -54,6 +54,11 @@
|
|||||||
"type": "markdown",
|
"type": "markdown",
|
||||||
"path":"documentation"
|
"path":"documentation"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"title": "定时器",
|
||||||
|
"type": "markdown",
|
||||||
|
"path":"documentation"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"title": "shell命令",
|
"title": "shell命令",
|
||||||
"type": "markdown",
|
"type": "markdown",
|
||||||
|
|||||||
@@ -110,6 +110,21 @@ events.loop();
|
|||||||
|
|
||||||
删除所有事件监听函数。
|
删除所有事件监听函数。
|
||||||
|
|
||||||
|
### events.setTimeout(callback, delay)
|
||||||
|
* callback \<Function\> 回调函数
|
||||||
|
* delay \<Number\> 延迟
|
||||||
|
|
||||||
|
延迟大约delay毫秒后执行callback。该函数只有在events.loop()被使用时才有效。
|
||||||
|
|
||||||
|
返回一个整数表示这个设置的timeout, 可由clearTimeout取消。
|
||||||
|
|
||||||
|
|
||||||
|
### events.clearTimeout(id)
|
||||||
|
|
||||||
|
* id \<Number\> 由 setTimeout() 返回的 ID 值。该值标识要取消的延迟执行回调。
|
||||||
|
|
||||||
|
取消由 setTimeout() 方法设置的 timeout。
|
||||||
|
|
||||||
### key事件
|
### key事件
|
||||||
|
|
||||||
当有按键被按下或弹起时会触发该事件。
|
当有按键被按下或弹起时会触发该事件。
|
||||||
|
|||||||
66
app/src/main/assets/help/documentation/定时器.md
Normal file
66
app/src/main/assets/help/documentation/定时器.md
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
timer 模块暴露了一个全局的 API,用于在某个未来时间段调用调度函数。 因为定时器函数是全局的,所以使用该 API 无需调用 timer.***
|
||||||
|
|
||||||
|
Auto.js 中的计时器函数实现了与 Web 浏览器提供的定时器类似的 API,除了它使用了一个不同的内部实现,它是基于 Android Looper-Handler机制构建的。其实现机制与Node.js比较相似。
|
||||||
|
|
||||||
|
不同于Web浏览器和Node.js,在Auto.js中,必须显式地调用loop()函数开始Looper循环才能使所有计时器开始工作。loop()函数是一个"死循环", 在他之后的语句将不会被执行。
|
||||||
|
|
||||||
|
### loop()
|
||||||
|
|
||||||
|
开始Looper循环。使所有定时器工作所必须。
|
||||||
|
注意,何时调用loop不会影响setTimeout等函数的计时,例如:
|
||||||
|
```
|
||||||
|
setTimout(function(){
|
||||||
|
toast("hello");
|
||||||
|
exit();
|
||||||
|
}, 2000);
|
||||||
|
sleep(1000);
|
||||||
|
loop();
|
||||||
|
```
|
||||||
|
这段代码将在运行后大约2秒显示"hello"。
|
||||||
|
|
||||||
|
### setImmediate(callback\[, ...args\])
|
||||||
|
* callback \<Function\> 在 Auto.js 循环的当前回合结束时要调用的函数。
|
||||||
|
* ...args \<any\> 当调用 callback 时要传入的可选参数。
|
||||||
|
|
||||||
|
预定立即执行的 callback,它是在 I/O 事件的回调之后被触发。 返回一个用于 clearImmediate() 的 id。
|
||||||
|
|
||||||
|
当多次调用 setImmediate() 时,callback 函数会按照它们被创建的顺序依次执行。 每次事件循环迭代都会处理整个回调队列。 如果一个立即定时器是被一个正在执行的回调排入队列的,则该定时器直到下一次事件循环迭代才会被触发。
|
||||||
|
|
||||||
|
### setInterval(callback, delay\[, ...args\])
|
||||||
|
* callback \<Function\> 当定时器到点时要调用的函数。
|
||||||
|
* delay \<number\> 调用 callback 之前要等待的毫秒数。
|
||||||
|
* ...args \<any\> 当调用 callback 时要传入的可选参数。
|
||||||
|
|
||||||
|
预定每隔 delay 毫秒重复执行的 callback。 返回一个用于 clearInterval() 的 id。
|
||||||
|
|
||||||
|
当 delay 小于 0 时,delay 会被设为 0。
|
||||||
|
|
||||||
|
### setTimeout(callback, delay\[, ...args\])
|
||||||
|
* callback \<Function\> 当定时器到点时要调用的函数。
|
||||||
|
* delay \<number\> 调用 callback 之前要等待的毫秒数。
|
||||||
|
* ...args \<any\> 当调用 callback 时要传入的可选参数。
|
||||||
|
|
||||||
|
预定在 delay 毫秒之后执行的单次 callback。 返回一个用于 clearTimeout() 的 id。
|
||||||
|
|
||||||
|
callback 可能不会精确地在 delay 毫秒被调用。 Auto.js 不能保证回调被触发的确切时间,也不能保证它们的顺序。 回调会在尽可能接近所指定的时间上调用。
|
||||||
|
|
||||||
|
当 delay 小于 0 时,delay 会被设为 0。
|
||||||
|
|
||||||
|
setImmediate()、setInterval() 和 setTimeout() 方法每次都会返回表示预定的计时器的id。 它们可用于取消定时器并防止触发。
|
||||||
|
|
||||||
|
|
||||||
|
### clearImmediate(id)#
|
||||||
|
* id \<Number\> 一个 setImmediate() 返回的 id。
|
||||||
|
|
||||||
|
取消一个由 setImmediate() 创建的 Immediate 对象。
|
||||||
|
|
||||||
|
### clearInterval(id)#
|
||||||
|
* id \<Number\> 一个 setInterval() 返回的 id。
|
||||||
|
|
||||||
|
取消一个由 setInterval() 创建的 Timeout 对象。
|
||||||
|
|
||||||
|
### clearTimeout(id)
|
||||||
|
* id \<Number\> 一个 setTimeout() 返回的 id。
|
||||||
|
|
||||||
|
取消一个由 setTimeout() 创建的 Timeout 对象。
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ events.on("key", function(code, event){
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
events.loop();
|
loop();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,4 +9,4 @@ events.on("touch", function(point){
|
|||||||
log(point);
|
log(point);
|
||||||
});
|
});
|
||||||
|
|
||||||
events.loop();
|
loop();
|
||||||
@@ -3,29 +3,22 @@
|
|||||||
var 长按间隔 = 1500;
|
var 长按间隔 = 1500;
|
||||||
|
|
||||||
var curPackage = null;
|
var curPackage = null;
|
||||||
var backPressedCount = 0;
|
var timeoutId = null;
|
||||||
var backPressed = false;
|
|
||||||
|
|
||||||
events.observeKey();
|
events.observeKey();
|
||||||
|
|
||||||
events.onKeyDown("back", function(event){
|
events.onKeyDown("back", function(event){
|
||||||
curPackage = currentPackage();
|
curPackage = currentPackage();
|
||||||
backPressed = true;
|
timeoutId = setTimeout(function(){
|
||||||
backPressedCount++;
|
backBackBackBack();
|
||||||
(function(count){
|
}, 长按间隔);
|
||||||
events.setTimeout(function(){
|
|
||||||
if(backPressed && count == backPressedCount){
|
|
||||||
backBackBackBack();
|
|
||||||
}
|
|
||||||
}, 长按间隔);
|
|
||||||
})(backPressedCount);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
events.onKeyUp("back", function(event){
|
events.onKeyUp("back", function(event){
|
||||||
backPressed = false;
|
clearTimeout(timeoutId);
|
||||||
});
|
});
|
||||||
|
|
||||||
events.loop();
|
loop();
|
||||||
|
|
||||||
function backBackBackBack(){
|
function backBackBackBack(){
|
||||||
while(curPackage == currentPackage()){
|
while(curPackage == currentPackage()){
|
||||||
|
|||||||
@@ -15,20 +15,20 @@ events.onKeyDown("volume_up", function(event){
|
|||||||
});
|
});
|
||||||
|
|
||||||
events.onKeyDown("volume_down", function(event){
|
events.onKeyDown("volume_down", function(event){
|
||||||
stop();
|
|
||||||
toast("程序结束");
|
toast("程序结束");
|
||||||
|
exit();
|
||||||
});
|
});
|
||||||
|
|
||||||
task();
|
task();
|
||||||
|
|
||||||
events.loop();
|
loop();
|
||||||
|
|
||||||
function task1(){
|
function task1(){
|
||||||
toast("任务1运行中,音量下键结束,音量上键切换任务");
|
toast("任务1运行中,音量下键结束,音量上键切换任务");
|
||||||
events.setTimeout(task, interval);
|
setTimeout(task, interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
function task2(){
|
function task2(){
|
||||||
toast("任务2运行中,音量下键结束,音量上键切换任务");
|
toast("任务2运行中,音量下键结束,音量上键切换任务");
|
||||||
events.setTimeout(task, interval);
|
setTimeout(task, interval);
|
||||||
}
|
}
|
||||||
15
app/src/main/assets/sample/定时器/定时执行.js
Normal file
15
app/src/main/assets/sample/定时器/定时执行.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
toast("静等20秒,你会看到想看的...");
|
||||||
|
|
||||||
|
var i = 0;
|
||||||
|
|
||||||
|
setTimeout(function(){
|
||||||
|
app.openUrl("http://music.163.com/#/song?id=109628&autoplay=true&market=baiduhd");
|
||||||
|
exit();
|
||||||
|
}, 20 * 1000);
|
||||||
|
|
||||||
|
setInterval(function(){
|
||||||
|
i++;
|
||||||
|
toast(i * 5 + "秒");
|
||||||
|
}, 5000);
|
||||||
|
|
||||||
|
loop();
|
||||||
11
app/src/main/assets/sample/定时器/循环执行.js
Normal file
11
app/src/main/assets/sample/定时器/循环执行.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
var i = 0;
|
||||||
|
|
||||||
|
setInterval(function(){
|
||||||
|
i++;
|
||||||
|
toast(i * 4 + "秒");
|
||||||
|
if(i == 5){
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
}, 4000);
|
||||||
|
|
||||||
|
loop();
|
||||||
@@ -40,8 +40,6 @@ public class App extends MultiDexApplication {
|
|||||||
return instance.get();
|
return instance.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
private VolumeChangeObserver mVolumeChangeObserver = new VolumeChangeObserver();
|
|
||||||
|
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
instance = new WeakReference<>(this);
|
instance = new WeakReference<>(this);
|
||||||
@@ -74,19 +72,12 @@ public class App extends MultiDexApplication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initVolumeChangeObserver() {
|
private void initVolumeChangeObserver() {
|
||||||
//registerReceiver(mVolumeChangeObserver, new IntentFilter(VolumeChangeObserver.ACTION_VOLUME_CHANGE));
|
|
||||||
mVolumeChangeObserver.addOnVolumeChangeListener(new VolumeChangeObserver.OnVolumeChangeListener() {
|
|
||||||
@Override
|
|
||||||
public void onVolumeChange() {
|
|
||||||
if (Pref.isRunningVolumeControlEnabled()) {
|
|
||||||
AutoJs.getInstance().getScriptEngineService().stopAllAndToast();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
AccessibilityService.getStickOnKeyObserver().addListener(new OnKeyListener() {
|
AccessibilityService.getStickOnKeyObserver().addListener(new OnKeyListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onKeyEvent(int keyCode, KeyEvent event) {
|
public void onKeyEvent(int keyCode, KeyEvent event) {
|
||||||
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && Pref.isRunningVolumeControlEnabled()) {
|
if (event.getAction() == KeyEvent.ACTION_DOWN &&
|
||||||
|
(keyCode == KeyEvent.KEYCODE_VOLUME_UP)
|
||||||
|
&& Pref.isRunningVolumeControlEnabled()) {
|
||||||
AutoJs.getInstance().getScriptEngineService().stopAllAndToast();
|
AutoJs.getInstance().getScriptEngineService().stopAllAndToast();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,10 +85,6 @@ public class App extends MultiDexApplication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public VolumeChangeObserver getVolumeChangeObserver() {
|
|
||||||
return mVolumeChangeObserver;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UiHandler getUiHandler() {
|
public UiHandler getUiHandler() {
|
||||||
return mUiHandler;
|
return mUiHandler;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.v7.widget.SwitchCompat;
|
import android.support.v7.widget.SwitchCompat;
|
||||||
|
import android.view.KeyEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.stardust.app.VolumeChangeObserver;
|
|
||||||
import com.stardust.autojs.runtime.record.Recorder;
|
import com.stardust.autojs.runtime.record.Recorder;
|
||||||
import com.stardust.autojs.runtime.record.accessibility.AccessibilityActionRecorder;
|
import com.stardust.autojs.runtime.record.accessibility.AccessibilityActionRecorder;
|
||||||
import com.stardust.autojs.runtime.record.inputevent.KeyObserver;
|
import com.stardust.autojs.runtime.record.inputevent.KeyObserver;
|
||||||
@@ -22,6 +22,8 @@ import com.stardust.scriptdroid.autojs.AutoJs;
|
|||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.HoverMenuService;
|
import com.stardust.scriptdroid.external.floatingwindow.menu.HoverMenuService;
|
||||||
import com.stardust.scriptdroid.ui.main.MainActivity;
|
import com.stardust.scriptdroid.ui.main.MainActivity;
|
||||||
import com.stardust.util.MessageEvent;
|
import com.stardust.util.MessageEvent;
|
||||||
|
import com.stardust.view.accessibility.AccessibilityService;
|
||||||
|
import com.stardust.view.accessibility.OnKeyListener;
|
||||||
|
|
||||||
import org.greenrobot.eventbus.Subscribe;
|
import org.greenrobot.eventbus.Subscribe;
|
||||||
|
|
||||||
@@ -62,10 +64,12 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
|
|||||||
private Context mContext;
|
private Context mContext;
|
||||||
private boolean mDiscard = false;
|
private boolean mDiscard = false;
|
||||||
private KeyObserver mKeyObserver;
|
private KeyObserver mKeyObserver;
|
||||||
private VolumeChangeObserver.OnVolumeChangeListener mOnVolumeChangeListener = new VolumeChangeObserver.OnVolumeChangeListener() {
|
private OnKeyListener mVolumeKeyListener = new OnKeyListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onVolumeChange() {
|
public void onKeyEvent(int keyCode, KeyEvent event) {
|
||||||
if (Pref.isRecordVolumeControlEnable()) {
|
if (event.getAction() == KeyEvent.ACTION_DOWN &&
|
||||||
|
(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)
|
||||||
|
&& Pref.isRecordVolumeControlEnable()) {
|
||||||
if (mRecorder == null) {
|
if (mRecorder == null) {
|
||||||
startRecord();
|
startRecord();
|
||||||
} else if (alreadyStartedRecord()) {
|
} else if (alreadyStartedRecord()) {
|
||||||
@@ -80,7 +84,10 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
|
|||||||
mView = View.inflate(context, R.layout.floating_window_record, null);
|
mView = View.inflate(context, R.layout.floating_window_record, null);
|
||||||
ButterKnife.bind(this, mView);
|
ButterKnife.bind(this, mView);
|
||||||
HoverMenuService.getEventBus().register(this);
|
HoverMenuService.getEventBus().register(this);
|
||||||
App.getApp().getVolumeChangeObserver().addOnVolumeChangeListener(mOnVolumeChangeListener);
|
AccessibilityService.getStickOnKeyObserver().addListener(mVolumeKeyListener);
|
||||||
|
if (Pref.isRecordVolumeControlEnable()) {
|
||||||
|
AutoJs.getInstance().ensureServiceEnabled();
|
||||||
|
}
|
||||||
if (Pref.hasRecordTrigger()) {
|
if (Pref.hasRecordTrigger()) {
|
||||||
mKeyObserver = new KeyObserver(mContext);
|
mKeyObserver = new KeyObserver(mContext);
|
||||||
mKeyObserver.startListening();
|
mKeyObserver.startListening();
|
||||||
@@ -181,7 +188,7 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
|
|||||||
|
|
||||||
public void onMenuExit() {
|
public void onMenuExit() {
|
||||||
HoverMenuService.getEventBus().unregister(this);
|
HoverMenuService.getEventBus().unregister(this);
|
||||||
App.getApp().getVolumeChangeObserver().removeOnVolumeChangeListener(mOnVolumeChangeListener);
|
AccessibilityService.getStickOnKeyObserver().addListener(mVolumeKeyListener);
|
||||||
if (mKeyObserver != null) {
|
if (mKeyObserver != null) {
|
||||||
mKeyObserver.stopListening();
|
mKeyObserver.stopListening();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,8 +81,8 @@
|
|||||||
<string name="text_file_write_fail">文件写入失败</string>
|
<string name="text_file_write_fail">文件写入失败</string>
|
||||||
<string name="text_join_qq_group">加入QQ互赞&交流群</string>
|
<string name="text_join_qq_group">加入QQ互赞&交流群</string>
|
||||||
<string name="text_copied">已复制到剪贴板</string>
|
<string name="text_copied">已复制到剪贴板</string>
|
||||||
<string name="text_use_volume_control_record">使用音量键控制</string>
|
<string name="text_use_volume_control_record">使用音量下键控制</string>
|
||||||
<string name="summary_use_volume_control_record">开启后每次音量变化会开始或停止脚本录制</string>
|
<string name="summary_use_volume_control_record">开启后每次音量下键会开始或停止脚本录制</string>
|
||||||
<string name="key_use_volume_control_record">key_use_volume_control_record</string>
|
<string name="key_use_volume_control_record">key_use_volume_control_record</string>
|
||||||
<string name="text_mobile_qq_not_installed">未安装手机QQ</string>
|
<string name="text_mobile_qq_not_installed">未安装手机QQ</string>
|
||||||
<string name="text_edit">编辑</string>
|
<string name="text_edit">编辑</string>
|
||||||
@@ -129,7 +129,7 @@
|
|||||||
<string name="go_to_accessibility_settings"><![CDATA[请打开设置->无障碍服务->AutoJs并开启]]></string>
|
<string name="go_to_accessibility_settings"><![CDATA[请打开设置->无障碍服务->AutoJs并开启]]></string>
|
||||||
<string name="text_script_running">脚本运行</string>
|
<string name="text_script_running">脚本运行</string>
|
||||||
<string name="key_use_volume_control_running">key_use_volume_control_running</string>
|
<string name="key_use_volume_control_running">key_use_volume_control_running</string>
|
||||||
<string name="text_use_volume_to_stop_running">每次音量键变化停止所有脚本</string>
|
<string name="text_use_volume_to_stop_running">音量上键停止所有脚本</string>
|
||||||
<string name="text_need_to_enable_accessibility_service">需要启用无障碍服务</string>
|
<string name="text_need_to_enable_accessibility_service">需要启用无障碍服务</string>
|
||||||
<string name="key_run_mode">运行方式</string>
|
<string name="key_run_mode">运行方式</string>
|
||||||
<string name="text_on">已开启</string>
|
<string name="text_on">已开启</string>
|
||||||
|
|||||||
@@ -13,6 +13,15 @@ if(__engine_name__ == "rhino"){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__runtime__.bridges.setFunctionCaller(function(func, target, args){
|
||||||
|
var arr = [];
|
||||||
|
var len = args.length;
|
||||||
|
for(var i = 0; i < len; i++){
|
||||||
|
arr.push(args[i]);
|
||||||
|
}
|
||||||
|
return func.apply(target, arr);
|
||||||
|
});
|
||||||
|
|
||||||
var __that__ = this;
|
var __that__ = this;
|
||||||
|
|
||||||
var __asGlobal__ = function(obj, functions){
|
var __asGlobal__ = function(obj, functions){
|
||||||
@@ -27,7 +36,7 @@ require("__general__")(__runtime__, this);
|
|||||||
|
|
||||||
|
|
||||||
(function(scope){
|
(function(scope){
|
||||||
var modules = ['app', 'automator', 'console', 'dialogs', 'io', 'selector', 'shell', 'web', 'ui', "images", "events"];
|
var modules = ['app', 'automator', 'console', 'dialogs', 'io', 'selector', 'shell', 'web', 'ui', "images", "timers", "events"];
|
||||||
var len = modules.length;
|
var len = modules.length;
|
||||||
for(var i = 0; i < len; i++) {
|
for(var i = 0; i < len; i++) {
|
||||||
var m = modules[i];
|
var m = modules[i];
|
||||||
|
|||||||
@@ -2,23 +2,6 @@
|
|||||||
module.exports = function(__runtime__, scope){
|
module.exports = function(__runtime__, scope){
|
||||||
var events = Object.create(__runtime__.events);
|
var events = Object.create(__runtime__.events);
|
||||||
|
|
||||||
var caller = function(func, args){
|
|
||||||
var arr = [];
|
|
||||||
var len = args.length;
|
|
||||||
for(var i = 0; i < len; i++){
|
|
||||||
arr.push(args[i]);
|
|
||||||
}
|
|
||||||
return func.apply(null, arr);
|
|
||||||
};
|
|
||||||
|
|
||||||
events.setFunctionCaller(caller);
|
|
||||||
|
|
||||||
events.emitter = function(){
|
|
||||||
var e = new com.stardust.autojs.runtime.api.EventEmitter();
|
|
||||||
e.setFunctionCaller(caller);
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,10 +19,12 @@ module.exports = function(__runtime__, scope){
|
|||||||
return !isStopped();
|
return !isStopped();
|
||||||
}
|
}
|
||||||
|
|
||||||
scope.stop = function(){
|
scope.exit = function(){
|
||||||
__runtime__.stop();
|
__runtime__.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scope.stop = scope.exit;
|
||||||
|
|
||||||
scope.setClip = function(text){
|
scope.setClip = function(text){
|
||||||
__runtime__.setClip(text);
|
__runtime__.setClip(text);
|
||||||
}
|
}
|
||||||
|
|||||||
9
autojs/src/main/assets/modules/__timers__.js
Normal file
9
autojs/src/main/assets/modules/__timers__.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
module.exports = function(__runtime__, scope){
|
||||||
|
var timers = Object.create(__runtime__.timers);
|
||||||
|
|
||||||
|
scope.__asGlobal__(timers, ['loop', 'setTimeout', 'clearTimeout', 'setInterval', 'clearInterval', 'setImmediate', 'clearImmediate']);
|
||||||
|
|
||||||
|
return timers;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ public class ScriptEngineService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onFinish(ScriptExecution execution) {
|
private void onFinish(ScriptExecution execution) {
|
||||||
execution.getRuntime().onStop();
|
execution.getRuntime().onExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import com.stardust.autojs.rhino.AndroidContextFactory;
|
|||||||
import com.stardust.autojs.rhino.RhinoAndroidHelper;
|
import com.stardust.autojs.rhino.RhinoAndroidHelper;
|
||||||
import com.stardust.autojs.runtime.ScriptInterruptedException;
|
import com.stardust.autojs.runtime.ScriptInterruptedException;
|
||||||
import com.stardust.autojs.runtime.api.Events;
|
import com.stardust.autojs.runtime.api.Events;
|
||||||
|
import com.stardust.autojs.runtime.api.Timers;
|
||||||
import com.stardust.autojs.script.ScriptSource;
|
import com.stardust.autojs.script.ScriptSource;
|
||||||
import com.stardust.pio.UncheckedIOException;
|
import com.stardust.pio.UncheckedIOException;
|
||||||
|
|
||||||
@@ -76,7 +77,7 @@ public class RhinoJavaScriptEngine implements ScriptEngine {
|
|||||||
public void forceStop() {
|
public void forceStop() {
|
||||||
Log.d(LOG_TAG, "forceStop: interrupt Thread: " + mThread);
|
Log.d(LOG_TAG, "forceStop: interrupt Thread: " + mThread);
|
||||||
mThread.interrupt();
|
mThread.interrupt();
|
||||||
Events.quitLooperIfNeeded(mThread);
|
Timers.quitLooperIfNeeded(mThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RhinoJavaScriptEngineManager getEngineManager() {
|
public RhinoJavaScriptEngineManager getEngineManager() {
|
||||||
@@ -90,7 +91,7 @@ public class RhinoJavaScriptEngine implements ScriptEngine {
|
|||||||
contextCount--;
|
contextCount--;
|
||||||
Log.d(LOG_TAG, "contextCount = " + contextCount);
|
Log.d(LOG_TAG, "contextCount = " + contextCount);
|
||||||
mEngineManager.removeEngine(this);
|
mEngineManager.removeEngine(this);
|
||||||
Events.removeThreadRecord(mThread);
|
Timers.removeThreadRecord(mThread);
|
||||||
mDestroyed = true;
|
mDestroyed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,10 @@ import android.support.annotation.CallSuper;
|
|||||||
import com.stardust.autojs.engine.ScriptEngine;
|
import com.stardust.autojs.engine.ScriptEngine;
|
||||||
import com.stardust.autojs.runtime.api.AbstractShell;
|
import com.stardust.autojs.runtime.api.AbstractShell;
|
||||||
import com.stardust.autojs.runtime.api.AppUtils;
|
import com.stardust.autojs.runtime.api.AppUtils;
|
||||||
|
import com.stardust.autojs.runtime.api.ScriptBridges;
|
||||||
import com.stardust.autojs.runtime.api.Console;
|
import com.stardust.autojs.runtime.api.Console;
|
||||||
import com.stardust.autojs.runtime.api.Events;
|
import com.stardust.autojs.runtime.api.Events;
|
||||||
|
import com.stardust.autojs.runtime.api.Timers;
|
||||||
import com.stardust.autojs.runtime.api.UiSelector;
|
import com.stardust.autojs.runtime.api.UiSelector;
|
||||||
import com.stardust.autojs.runtime.api.image.Images;
|
import com.stardust.autojs.runtime.api.image.Images;
|
||||||
import com.stardust.autojs.runtime.api.image.ScreenCaptureRequester;
|
import com.stardust.autojs.runtime.api.image.ScreenCaptureRequester;
|
||||||
@@ -19,6 +21,8 @@ import com.stardust.util.ScreenMetrics;
|
|||||||
import com.stardust.util.UiHandler;
|
import com.stardust.util.UiHandler;
|
||||||
import com.stardust.view.accessibility.AccessibilityInfoProvider;
|
import com.stardust.view.accessibility.AccessibilityInfoProvider;
|
||||||
|
|
||||||
|
import org.mozilla.javascript.annotations.JSFunction;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,6 +52,12 @@ public abstract class AbstractScriptRuntime {
|
|||||||
@ScriptVariable
|
@ScriptVariable
|
||||||
public Events events;
|
public Events events;
|
||||||
|
|
||||||
|
@ScriptVariable
|
||||||
|
public ScriptBridges bridges = new ScriptBridges();
|
||||||
|
|
||||||
|
@ScriptVariable
|
||||||
|
public Timers timers = new Timers(bridges);
|
||||||
|
|
||||||
private Images images;
|
private Images images;
|
||||||
|
|
||||||
private static WeakReference<Context> applicationContext;
|
private static WeakReference<Context> applicationContext;
|
||||||
@@ -63,7 +73,7 @@ public abstract class AbstractScriptRuntime {
|
|||||||
images = new Images(context, this, screenCaptureRequester);
|
images = new Images(context, this, screenCaptureRequester);
|
||||||
}
|
}
|
||||||
dialogs = new Dialogs(app, uiHandler);
|
dialogs = new Dialogs(app, uiHandler);
|
||||||
events = new Events(context, bridge);
|
events = new Events(context, bridge, bridges, timers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setApplicationContext(Context context) {
|
public static void setApplicationContext(Context context) {
|
||||||
@@ -105,7 +115,7 @@ public abstract class AbstractScriptRuntime {
|
|||||||
public abstract void loadJar(String path);
|
public abstract void loadJar(String path);
|
||||||
|
|
||||||
@ScriptInterface
|
@ScriptInterface
|
||||||
public abstract void stop();
|
public abstract void exit();
|
||||||
|
|
||||||
@ScriptInterface
|
@ScriptInterface
|
||||||
public abstract void setScreenMetrics(int width, int height);
|
public abstract void setScreenMetrics(int width, int height);
|
||||||
@@ -116,7 +126,7 @@ public abstract class AbstractScriptRuntime {
|
|||||||
public abstract void ensureAccessibilityServiceEnabled();
|
public abstract void ensureAccessibilityServiceEnabled();
|
||||||
|
|
||||||
@CallSuper
|
@CallSuper
|
||||||
public void onStop() {
|
public void onExit() {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||||
images.releaseScreenCapturer();
|
images.releaseScreenCapturer();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package com.stardust.autojs.runtime;
|
package com.stardust.autojs.runtime;
|
||||||
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
|
||||||
import com.stardust.autojs.R;
|
import com.stardust.autojs.R;
|
||||||
@@ -186,11 +185,17 @@ public class ScriptRuntime extends AbstractScriptRuntime {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stop() {
|
public void exit() {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
throw new ScriptInterruptedException();
|
throw new ScriptInterruptedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public void stop() {
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setScreenMetrics(int width, int height) {
|
public void setScreenMetrics(int width, int height) {
|
||||||
mScreenMetrics.setScreenMetrics(width, height);
|
mScreenMetrics.setScreenMetrics(width, height);
|
||||||
@@ -206,8 +211,8 @@ public class ScriptRuntime extends AbstractScriptRuntime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStop() {
|
public void onExit() {
|
||||||
super.onStop();
|
super.onExit();
|
||||||
if (mRootShell != null) {
|
if (mRootShell != null) {
|
||||||
mRootShell.exit();
|
mRootShell.exit();
|
||||||
mRootShell = null;
|
mRootShell = null;
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ public class AppUtils {
|
|||||||
|
|
||||||
@ScriptInterface
|
@ScriptInterface
|
||||||
public void openUrl(String url) {
|
public void openUrl(String url) {
|
||||||
if (!url.startsWith("http://") || !url.startsWith("https://")) {
|
if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
||||||
url = "http://" + url;
|
url = "http://" + url;
|
||||||
}
|
}
|
||||||
mContext.startActivity(new Intent(Intent.ACTION_VIEW)
|
mContext.startActivity(new Intent(Intent.ACTION_VIEW)
|
||||||
|
|||||||
@@ -17,10 +17,6 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
|||||||
|
|
||||||
public class EventEmitter {
|
public class EventEmitter {
|
||||||
|
|
||||||
public interface FunctionCaller {
|
|
||||||
Object call(Object func, Object[] arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ListenerWrapper {
|
private static class ListenerWrapper {
|
||||||
Object listener;
|
Object listener;
|
||||||
boolean isOnce;
|
boolean isOnce;
|
||||||
@@ -54,7 +50,7 @@ public class EventEmitter {
|
|||||||
Iterator<ListenerWrapper> listenerIterator = mListenerWrappers.iterator();
|
Iterator<ListenerWrapper> listenerIterator = mListenerWrappers.iterator();
|
||||||
while (listenerIterator.hasNext()) {
|
while (listenerIterator.hasNext()) {
|
||||||
ListenerWrapper listenerWrapper = listenerIterator.next();
|
ListenerWrapper listenerWrapper = listenerIterator.next();
|
||||||
call(listenerWrapper.listener, args);
|
mBridges.callFunction(listenerWrapper.listener, EventEmitter.this, args);
|
||||||
if (listenerWrapper.isOnce) {
|
if (listenerWrapper.isOnce) {
|
||||||
listenerIterator.remove();
|
listenerIterator.remove();
|
||||||
}
|
}
|
||||||
@@ -94,7 +90,11 @@ public class EventEmitter {
|
|||||||
private Map<String, Listeners> mListenersMap = new HashMap<>();
|
private Map<String, Listeners> mListenersMap = new HashMap<>();
|
||||||
public static int defaultMaxListeners = 10;
|
public static int defaultMaxListeners = 10;
|
||||||
private int mMaxListeners = defaultMaxListeners;
|
private int mMaxListeners = defaultMaxListeners;
|
||||||
private FunctionCaller mFunctionCaller;
|
ScriptBridges mBridges;
|
||||||
|
|
||||||
|
public EventEmitter(ScriptBridges bridges) {
|
||||||
|
mBridges = bridges;
|
||||||
|
}
|
||||||
|
|
||||||
public EventEmitter once(String eventName, Object listener) {
|
public EventEmitter once(String eventName, Object listener) {
|
||||||
getListeners(eventName).add(listener, true);
|
getListeners(eventName).add(listener, true);
|
||||||
@@ -184,14 +184,5 @@ public class EventEmitter {
|
|||||||
return defaultMaxListeners;
|
return defaultMaxListeners;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFunctionCaller(FunctionCaller functionCaller) {
|
|
||||||
mFunctionCaller = functionCaller;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void call(Object func, Object[] args) {
|
|
||||||
if (mFunctionCaller != null) {
|
|
||||||
mFunctionCaller.call(func, args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,27 +23,31 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
|
|||||||
|
|
||||||
private static final String PREFIX_KEY_DOWN = "__key_down__#";
|
private static final String PREFIX_KEY_DOWN = "__key_down__#";
|
||||||
private static final String PREFIX_KEY_UP = "__key_up__#";
|
private static final String PREFIX_KEY_UP = "__key_up__#";
|
||||||
private static final Object[] NO_ARGUMENT = new Object[0];
|
|
||||||
|
|
||||||
private static ConcurrentHashMap<Thread, Looper> sLoopers = new ConcurrentHashMap<>();
|
|
||||||
private AccessibilityBridge mAccessibilityBridge;
|
private AccessibilityBridge mAccessibilityBridge;
|
||||||
private Handler mHandler;
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private TouchObserver mTouchObserver;
|
private TouchObserver mTouchObserver;
|
||||||
|
private Timers mTimers;
|
||||||
private long mLastTouchEventMillis;
|
private long mLastTouchEventMillis;
|
||||||
private long mTouchEventTimeout = 10;
|
private long mTouchEventTimeout = 10;
|
||||||
private boolean mListeningKey = false;
|
private boolean mListeningKey = false;
|
||||||
|
|
||||||
public Events(Context context, AccessibilityBridge accessibilityBridge) {
|
public Events(Context context, AccessibilityBridge accessibilityBridge, ScriptBridges bridges, Timers timers) {
|
||||||
|
super(bridges);
|
||||||
mAccessibilityBridge = accessibilityBridge;
|
mAccessibilityBridge = accessibilityBridge;
|
||||||
mContext = context;
|
mContext = context;
|
||||||
|
mTimers = timers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EventEmitter emitter(){
|
||||||
|
return new EventEmitter(mBridges);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void observeKey() {
|
public void observeKey() {
|
||||||
if (mListeningKey)
|
if (mListeningKey)
|
||||||
return;
|
return;
|
||||||
mListeningKey = true;
|
mListeningKey = true;
|
||||||
prepareLoopIfNeeded();
|
mTimers.prepareLoopIfNeeded();
|
||||||
mAccessibilityBridge.ensureServiceEnabled();
|
mAccessibilityBridge.ensureServiceEnabled();
|
||||||
AccessibilityService service = mAccessibilityBridge.getService();
|
AccessibilityService service = mAccessibilityBridge.getService();
|
||||||
if (service == null)
|
if (service == null)
|
||||||
@@ -52,7 +56,7 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void observeTouch() {
|
public void observeTouch() {
|
||||||
prepareLoopIfNeeded();
|
mTimers.prepareLoopIfNeeded();
|
||||||
if (mTouchObserver != null)
|
if (mTouchObserver != null)
|
||||||
return;
|
return;
|
||||||
mTouchObserver = new TouchObserver(mContext);
|
mTouchObserver = new TouchObserver(mContext);
|
||||||
@@ -60,28 +64,6 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
|
|||||||
mTouchObserver.observe();
|
mTouchObserver.observe();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTimeout(final Object listener, long t) {
|
|
||||||
prepareLoopIfNeeded();
|
|
||||||
mHandler.postDelayed(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
call(listener, NO_ARGUMENT);
|
|
||||||
}
|
|
||||||
}, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void prepareLoopIfNeeded() {
|
|
||||||
if (Looper.myLooper() != null)
|
|
||||||
return;
|
|
||||||
Looper.prepare();
|
|
||||||
sLoopers.put(Thread.currentThread(), Looper.myLooper());
|
|
||||||
mHandler = new Handler();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loop() {
|
|
||||||
Looper.loop();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Events onKeyDown(String keyName, Object listener) {
|
public Events onKeyDown(String keyName, Object listener) {
|
||||||
on(PREFIX_KEY_DOWN + keyName, listener);
|
on(PREFIX_KEY_DOWN + keyName, listener);
|
||||||
return this;
|
return this;
|
||||||
@@ -146,7 +128,7 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onKeyEvent(final int keyCode, final KeyEvent event) {
|
public void onKeyEvent(final int keyCode, final KeyEvent event) {
|
||||||
mHandler.post(new Runnable() {
|
mTimers.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
String keyName = KeyEvent.keyCodeToString(keyCode).substring(8).toLowerCase();
|
String keyName = KeyEvent.keyCodeToString(keyCode).substring(8).toLowerCase();
|
||||||
@@ -169,7 +151,7 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mLastTouchEventMillis = System.currentTimeMillis();
|
mLastTouchEventMillis = System.currentTimeMillis();
|
||||||
mHandler.post(new Runnable() {
|
mTimers.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
emit("touch", new Point(x, y));
|
emit("touch", new Point(x, y));
|
||||||
@@ -177,15 +159,5 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void removeThreadRecord(Thread thread) {
|
|
||||||
sLoopers.remove(thread);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void quitLooperIfNeeded(Thread thread) {
|
|
||||||
Looper looper = sLoopers.get(thread);
|
|
||||||
if (looper != null) {
|
|
||||||
looper.quit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.stardust.autojs.runtime.api;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Stardust on 2017/7/21.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ScriptBridges {
|
||||||
|
|
||||||
|
|
||||||
|
public interface FunctionCaller {
|
||||||
|
|
||||||
|
Object[] NO_ARGUMENTS = new Object[0];
|
||||||
|
|
||||||
|
Object call(Object func, Object target, Object[] arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
private FunctionCaller mFunctionCaller;
|
||||||
|
|
||||||
|
public void setFunctionCaller(FunctionCaller functionCaller) {
|
||||||
|
mFunctionCaller = functionCaller;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object callFunction(Object func, Object target, Object[] args) {
|
||||||
|
if (mFunctionCaller == null)
|
||||||
|
throw new IllegalStateException("no function caller");
|
||||||
|
return mFunctionCaller.call(func, target, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
121
autojs/src/main/java/com/stardust/autojs/runtime/api/Timers.java
Normal file
121
autojs/src/main/java/com/stardust/autojs/runtime/api/Timers.java
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
package com.stardust.autojs.runtime.api;
|
||||||
|
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.util.SparseArray;
|
||||||
|
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Stardust on 2017/7/21.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Timers {
|
||||||
|
|
||||||
|
private static ConcurrentHashMap<Thread, Looper> sLoopers = new ConcurrentHashMap<>();
|
||||||
|
private Handler mHandler;
|
||||||
|
private SparseArray<Runnable> mHandlerCallbacks = new SparseArray<>();
|
||||||
|
private int mCallbackMaxId = 0;
|
||||||
|
private ScriptBridges mBridges;
|
||||||
|
|
||||||
|
public Timers(ScriptBridges bridges) {
|
||||||
|
mBridges = bridges;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int setTimeout(final Object listener, long delay, final Object... args) {
|
||||||
|
prepareLoopIfNeeded();
|
||||||
|
mCallbackMaxId++;
|
||||||
|
final int id = mCallbackMaxId;
|
||||||
|
Runnable r = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mBridges.callFunction(listener, null, args);
|
||||||
|
mHandlerCallbacks.remove(id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mHandlerCallbacks.put(id, r);
|
||||||
|
mHandler.postDelayed(r, delay);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void post(Runnable r) {
|
||||||
|
mHandler.post(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearTimeout(int id) {
|
||||||
|
clearCallback(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int setInterval(final Object listener, final long interval, final Object... args) {
|
||||||
|
prepareLoopIfNeeded();
|
||||||
|
mCallbackMaxId++;
|
||||||
|
final int id = mCallbackMaxId;
|
||||||
|
Runnable r = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mBridges.callFunction(listener, null, args);
|
||||||
|
mHandler.postDelayed(this, interval);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mHandlerCallbacks.put(id, r);
|
||||||
|
mHandler.postDelayed(r, interval);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearInterval(int id) {
|
||||||
|
clearTimeout(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int setImmediate(final Object listener, final Object... args) {
|
||||||
|
prepareLoopIfNeeded();
|
||||||
|
mCallbackMaxId++;
|
||||||
|
final int id = mCallbackMaxId;
|
||||||
|
Runnable r = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mBridges.callFunction(listener, null, args);
|
||||||
|
mHandlerCallbacks.remove(id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mHandlerCallbacks.put(id, r);
|
||||||
|
mHandler.post(r);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearImmediate(int id) {
|
||||||
|
clearCallback(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearCallback(int id) {
|
||||||
|
Runnable callback = mHandlerCallbacks.get(id);
|
||||||
|
if (callback != null) {
|
||||||
|
mHandler.removeCallbacks(callback);
|
||||||
|
mHandlerCallbacks.remove(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void prepareLoopIfNeeded() {
|
||||||
|
if (Looper.myLooper() != null)
|
||||||
|
return;
|
||||||
|
Looper.prepare();
|
||||||
|
sLoopers.put(Thread.currentThread(), Looper.myLooper());
|
||||||
|
mHandler = new Handler();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loop() {
|
||||||
|
Looper.loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void removeThreadRecord(Thread thread) {
|
||||||
|
sLoopers.remove(thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void quitLooperIfNeeded(Thread thread) {
|
||||||
|
Looper looper = sLoopers.get(thread);
|
||||||
|
if (looper != null) {
|
||||||
|
looper.quit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -39,8 +39,6 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
|
|||||||
private static boolean containsAllEventTypes = false;
|
private static boolean containsAllEventTypes = false;
|
||||||
private static final Set<Integer> eventTypes = new HashSet<>();
|
private static final Set<Integer> eventTypes = new HashSet<>();
|
||||||
private OnKeyListener.Observer mOnKeyObserver = new OnKeyListener.Observer();
|
private OnKeyListener.Observer mOnKeyObserver = new OnKeyListener.Observer();
|
||||||
private volatile AccessibilityNodeInfo mRootInActiveWindow;
|
|
||||||
private Timer mTimer;
|
|
||||||
private Handler mHandler;
|
private Handler mHandler;
|
||||||
private ExecutorService mKeyEventExecutor;
|
private ExecutorService mKeyEventExecutor;
|
||||||
|
|
||||||
@@ -105,14 +103,16 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AccessibilityNodeInfo getRootInActiveWindow() {
|
public AccessibilityNodeInfo getRootInActiveWindow() {
|
||||||
return mRootInActiveWindow;
|
try {
|
||||||
|
return super.getRootInActiveWindow();
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
instance = null;
|
instance = null;
|
||||||
if (mTimer != null)
|
|
||||||
mTimer.cancel();
|
|
||||||
if (mKeyEventExecutor != null)
|
if (mKeyEventExecutor != null)
|
||||||
mKeyEventExecutor.shutdownNow();
|
mKeyEventExecutor.shutdownNow();
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
@@ -128,23 +128,6 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
|
|||||||
ENABLED.signalAll();
|
ENABLED.signalAll();
|
||||||
LOCK.unlock();
|
LOCK.unlock();
|
||||||
mHandler = new Handler();
|
mHandler = new Handler();
|
||||||
mTimer = new Timer();
|
|
||||||
mTimer.schedule(new TimerTask() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
mHandler.post(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
AccessibilityNodeInfo root = superGetRootInActiveWindow();
|
|
||||||
if (root != null) {
|
|
||||||
mRootInActiveWindow = root;
|
|
||||||
Log.d(TAG, "getRootInActiveWindow: " + root);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
}, 0, 100);
|
|
||||||
// FIXME: 2017/2/12 有时在无障碍中开启服务后这里不会调用服务也不会运行,安卓的BUG???
|
// FIXME: 2017/2/12 有时在无障碍中开启服务后这里不会调用服务也不会运行,安卓的BUG???
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user