add timers modules
This commit is contained in:
@@ -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 __asGlobal__ = function(obj, functions){
|
||||
@@ -27,7 +36,7 @@ require("__general__")(__runtime__, this);
|
||||
|
||||
|
||||
(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;
|
||||
for(var i = 0; i < len; i++) {
|
||||
var m = modules[i];
|
||||
|
||||
@@ -2,23 +2,6 @@
|
||||
module.exports = function(__runtime__, scope){
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,10 +19,12 @@ module.exports = function(__runtime__, scope){
|
||||
return !isStopped();
|
||||
}
|
||||
|
||||
scope.stop = function(){
|
||||
__runtime__.stop();
|
||||
scope.exit = function(){
|
||||
__runtime__.exit();
|
||||
}
|
||||
|
||||
scope.stop = scope.exit;
|
||||
|
||||
scope.setClip = function(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) {
|
||||
execution.getRuntime().onStop();
|
||||
execution.getRuntime().onExit();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.stardust.autojs.rhino.AndroidContextFactory;
|
||||
import com.stardust.autojs.rhino.RhinoAndroidHelper;
|
||||
import com.stardust.autojs.runtime.ScriptInterruptedException;
|
||||
import com.stardust.autojs.runtime.api.Events;
|
||||
import com.stardust.autojs.runtime.api.Timers;
|
||||
import com.stardust.autojs.script.ScriptSource;
|
||||
import com.stardust.pio.UncheckedIOException;
|
||||
|
||||
@@ -76,7 +77,7 @@ public class RhinoJavaScriptEngine implements ScriptEngine {
|
||||
public void forceStop() {
|
||||
Log.d(LOG_TAG, "forceStop: interrupt Thread: " + mThread);
|
||||
mThread.interrupt();
|
||||
Events.quitLooperIfNeeded(mThread);
|
||||
Timers.quitLooperIfNeeded(mThread);
|
||||
}
|
||||
|
||||
public RhinoJavaScriptEngineManager getEngineManager() {
|
||||
@@ -90,7 +91,7 @@ public class RhinoJavaScriptEngine implements ScriptEngine {
|
||||
contextCount--;
|
||||
Log.d(LOG_TAG, "contextCount = " + contextCount);
|
||||
mEngineManager.removeEngine(this);
|
||||
Events.removeThreadRecord(mThread);
|
||||
Timers.removeThreadRecord(mThread);
|
||||
mDestroyed = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,10 @@ import android.support.annotation.CallSuper;
|
||||
import com.stardust.autojs.engine.ScriptEngine;
|
||||
import com.stardust.autojs.runtime.api.AbstractShell;
|
||||
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.Events;
|
||||
import com.stardust.autojs.runtime.api.Timers;
|
||||
import com.stardust.autojs.runtime.api.UiSelector;
|
||||
import com.stardust.autojs.runtime.api.image.Images;
|
||||
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.view.accessibility.AccessibilityInfoProvider;
|
||||
|
||||
import org.mozilla.javascript.annotations.JSFunction;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
@@ -48,6 +52,12 @@ public abstract class AbstractScriptRuntime {
|
||||
@ScriptVariable
|
||||
public Events events;
|
||||
|
||||
@ScriptVariable
|
||||
public ScriptBridges bridges = new ScriptBridges();
|
||||
|
||||
@ScriptVariable
|
||||
public Timers timers = new Timers(bridges);
|
||||
|
||||
private Images images;
|
||||
|
||||
private static WeakReference<Context> applicationContext;
|
||||
@@ -63,7 +73,7 @@ public abstract class AbstractScriptRuntime {
|
||||
images = new Images(context, this, screenCaptureRequester);
|
||||
}
|
||||
dialogs = new Dialogs(app, uiHandler);
|
||||
events = new Events(context, bridge);
|
||||
events = new Events(context, bridge, bridges, timers);
|
||||
}
|
||||
|
||||
public static void setApplicationContext(Context context) {
|
||||
@@ -105,7 +115,7 @@ public abstract class AbstractScriptRuntime {
|
||||
public abstract void loadJar(String path);
|
||||
|
||||
@ScriptInterface
|
||||
public abstract void stop();
|
||||
public abstract void exit();
|
||||
|
||||
@ScriptInterface
|
||||
public abstract void setScreenMetrics(int width, int height);
|
||||
@@ -116,7 +126,7 @@ public abstract class AbstractScriptRuntime {
|
||||
public abstract void ensureAccessibilityServiceEnabled();
|
||||
|
||||
@CallSuper
|
||||
public void onStop() {
|
||||
public void onExit() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
images.releaseScreenCapturer();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.stardust.autojs.runtime;
|
||||
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import com.stardust.autojs.R;
|
||||
@@ -186,11 +185,17 @@ public class ScriptRuntime extends AbstractScriptRuntime {
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
public void exit() {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new ScriptInterruptedException();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void stop() {
|
||||
exit();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setScreenMetrics(int width, int height) {
|
||||
mScreenMetrics.setScreenMetrics(width, height);
|
||||
@@ -206,8 +211,8 @@ public class ScriptRuntime extends AbstractScriptRuntime {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
public void onExit() {
|
||||
super.onExit();
|
||||
if (mRootShell != null) {
|
||||
mRootShell.exit();
|
||||
mRootShell = null;
|
||||
|
||||
@@ -105,7 +105,7 @@ public class AppUtils {
|
||||
|
||||
@ScriptInterface
|
||||
public void openUrl(String url) {
|
||||
if (!url.startsWith("http://") || !url.startsWith("https://")) {
|
||||
if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
||||
url = "http://" + url;
|
||||
}
|
||||
mContext.startActivity(new Intent(Intent.ACTION_VIEW)
|
||||
|
||||
@@ -17,10 +17,6 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
public class EventEmitter {
|
||||
|
||||
public interface FunctionCaller {
|
||||
Object call(Object func, Object[] arg);
|
||||
}
|
||||
|
||||
private static class ListenerWrapper {
|
||||
Object listener;
|
||||
boolean isOnce;
|
||||
@@ -54,7 +50,7 @@ public class EventEmitter {
|
||||
Iterator<ListenerWrapper> listenerIterator = mListenerWrappers.iterator();
|
||||
while (listenerIterator.hasNext()) {
|
||||
ListenerWrapper listenerWrapper = listenerIterator.next();
|
||||
call(listenerWrapper.listener, args);
|
||||
mBridges.callFunction(listenerWrapper.listener, EventEmitter.this, args);
|
||||
if (listenerWrapper.isOnce) {
|
||||
listenerIterator.remove();
|
||||
}
|
||||
@@ -94,7 +90,11 @@ public class EventEmitter {
|
||||
private Map<String, Listeners> mListenersMap = new HashMap<>();
|
||||
public static int defaultMaxListeners = 10;
|
||||
private int mMaxListeners = defaultMaxListeners;
|
||||
private FunctionCaller mFunctionCaller;
|
||||
ScriptBridges mBridges;
|
||||
|
||||
public EventEmitter(ScriptBridges bridges) {
|
||||
mBridges = bridges;
|
||||
}
|
||||
|
||||
public EventEmitter once(String eventName, Object listener) {
|
||||
getListeners(eventName).add(listener, true);
|
||||
@@ -184,14 +184,5 @@ public class EventEmitter {
|
||||
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_UP = "__key_up__#";
|
||||
private static final Object[] NO_ARGUMENT = new Object[0];
|
||||
|
||||
private static ConcurrentHashMap<Thread, Looper> sLoopers = new ConcurrentHashMap<>();
|
||||
private AccessibilityBridge mAccessibilityBridge;
|
||||
private Handler mHandler;
|
||||
private Context mContext;
|
||||
private TouchObserver mTouchObserver;
|
||||
private Timers mTimers;
|
||||
private long mLastTouchEventMillis;
|
||||
private long mTouchEventTimeout = 10;
|
||||
private boolean mListeningKey = false;
|
||||
|
||||
public Events(Context context, AccessibilityBridge accessibilityBridge) {
|
||||
public Events(Context context, AccessibilityBridge accessibilityBridge, ScriptBridges bridges, Timers timers) {
|
||||
super(bridges);
|
||||
mAccessibilityBridge = accessibilityBridge;
|
||||
mContext = context;
|
||||
mTimers = timers;
|
||||
}
|
||||
|
||||
public EventEmitter emitter(){
|
||||
return new EventEmitter(mBridges);
|
||||
}
|
||||
|
||||
public void observeKey() {
|
||||
if (mListeningKey)
|
||||
return;
|
||||
mListeningKey = true;
|
||||
prepareLoopIfNeeded();
|
||||
mTimers.prepareLoopIfNeeded();
|
||||
mAccessibilityBridge.ensureServiceEnabled();
|
||||
AccessibilityService service = mAccessibilityBridge.getService();
|
||||
if (service == null)
|
||||
@@ -52,7 +56,7 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
|
||||
}
|
||||
|
||||
public void observeTouch() {
|
||||
prepareLoopIfNeeded();
|
||||
mTimers.prepareLoopIfNeeded();
|
||||
if (mTouchObserver != null)
|
||||
return;
|
||||
mTouchObserver = new TouchObserver(mContext);
|
||||
@@ -60,28 +64,6 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
|
||||
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) {
|
||||
on(PREFIX_KEY_DOWN + keyName, listener);
|
||||
return this;
|
||||
@@ -146,7 +128,7 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
|
||||
|
||||
@Override
|
||||
public void onKeyEvent(final int keyCode, final KeyEvent event) {
|
||||
mHandler.post(new Runnable() {
|
||||
mTimers.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String keyName = KeyEvent.keyCodeToString(keyCode).substring(8).toLowerCase();
|
||||
@@ -169,7 +151,7 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
|
||||
return;
|
||||
}
|
||||
mLastTouchEventMillis = System.currentTimeMillis();
|
||||
mHandler.post(new Runnable() {
|
||||
mTimers.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user