diff --git a/app/build.gradle b/app/build.gradle index a875da02..da573077 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "com.stardust.scriptdroid" minSdkVersion 17 targetSdkVersion 23 - versionCode 151 - versionName "2.0.14 Beta2.1" + versionCode 152 + versionName "2.0.15 Alpha" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" multiDexEnabled true ndk { diff --git a/app/src/main/assets/help/catalogue.json b/app/src/main/assets/help/catalogue.json index 13871677..4dc56ada 100644 --- a/app/src/main/assets/help/catalogue.json +++ b/app/src/main/assets/help/catalogue.json @@ -49,6 +49,11 @@ "type": "markdown", "path":"documentation" }, + { + "title": "事件与按键、触摸监听", + "type": "markdown", + "path":"documentation" + }, { "title": "shell命令", "type": "markdown", diff --git a/app/src/main/assets/help/documentation/事件与按键、触摸监听.md b/app/src/main/assets/help/documentation/事件与按键、触摸监听.md new file mode 100644 index 00000000..0489ddc9 --- /dev/null +++ b/app/src/main/assets/help/documentation/事件与按键、触摸监听.md @@ -0,0 +1,384 @@ + +目录: +* [events](#events) +* [EventEmitter](#EventEmitter) +* [KeyEvent](#KeyEvent) + +# events + +events也是一个\[EventEmitter\](#EventEmitter),可以使用EventEmitter的所有函数,这里只介绍其自身的函数。 + +### events.emitter() + +返回一个新的EventEmitter。 + +### events.observeKey() + +启用按键监听,例如音量键、Home键。 + +在安卓4.3以上才能使用。 + +### events.loop() + +开始事件处理循环。**在events注册按键、触摸事件监听后必须调用该函数开始事件处理循环,否则相应事件发生时不会处理。** + +该函数是一个"死循环",调用后后面的语句将不再执行。 + +例子: +``` +events.observeKey(); +events.onKeyDown("volume_up", function(event){ + toast("音量上键被按下了"); +}); +events.onKeyDown("menu", function(event){ + toast("菜单键被按下了"); +}); +events.loop(); +//后面的语句不会再执行了 +``` + +### events.onKeyDown(keyName, listener) +* keyName \ 要监听的按键名称 +* listener \ 参数为一个[KeyEvent](#KeyEvent) + +注册一个按键监听函数,当有keyName对应的按键被按下会调用该函数。按键名称主要包括: +* volume_up 音量上键 +* volume_down 音量下键 +* home 主屏幕键 +* back 返回键 +* menu 菜单键 + +### events.onKeyUp(keyName, listener) +* keyName \ 要监听的按键名称 +* listener \ 参数为一个[KeyEvent](#KeyEvent) + + +注册一个按键监听函数,当有keyName对应的按键弹起时会调用该函数。 + +### events.onceKeyDown(keyName, listener) +* keyName \ 要监听的按键名称 +* listener \ 参数为一个[KeyEvent](#KeyEvent) + +注册一个按键监听函数,当有keyName对应的按键被按下时会调用该函数,之后会注销该按键监听。也就是listener只会被调用一次。 + +### events.onceKeyUp(keyName, listener) +* keyName \ 要监听的按键名称 +* listener \ 参数为一个[KeyEvent](#KeyEvent) + +注册一个按键监听函数,当有keyName对应的按键弹起时会调用该函数,之后会注销该按键监听。也就是listener只会被调用一次。 + +### events.removeAllKeyDownListeners(keyName) +* keyName \ 按键名称 + +删除该按键的KeyDown事件的所有监听。 + +### events.removeAllKeyUpListeners(keyName) +* keyName \ 按键名称 + +删除该按键的KeyUp事件的所有监听。 + +### events.observeTouch() + +启用屏幕触摸监听。(需要root权限) + +### events.setTouchEventTimeout(timeout) +* timeout \ 两个触摸事件的最小间隔。单位毫秒。默认为10毫秒。 + +设置两个触摸事件分发的最小时间间隔。 + +例如间隔为10毫秒的话,前一个触摸事件发生并被注册的监听器处理后,至少要过10毫秒才能分发和处理下一个触摸事件,这10毫秒之间的触摸将会被忽略。 + +### events.getTouchEventTimeout() + +返回触摸事件的最小时间间隔。 + +### events.onTouch(listener) +* listener \ 参数为(x, y)的函数 + +注册一个触摸监听函数。 + +例如: +``` +events.observeTouch(); +events.onTouch(function(x, y){ + log(x + ", " + y); +}); +events.loop(); +``` + +### events.removeAllTouchListeners() + +删除所有事件监听函数。 + +### key事件 + +当有按键被按下或弹起时会触发该事件。 +``` +"auto"; +events.observeKey(); +events.on("key", function(keyCode, event){ + //处理按键事件 +}); +events.loop(); +``` +其中监听器的参数KeyCode包括: +* KeyEvent.KEYCODE_HOME 主页键 +* KeyEvent.KEYCODE_BACK 返回键 +* KeyEvent.KEYCODE_MENU 菜单键 +* KeyEvent.KEYCODE_VOLUME_UP 音量上键 +* KeyEvent.KEYCODE_VOLUME_DOWN 音量下键 + +### key_down事件 + +当有按键被按下时会触发该事件。 +``` +"auto"; +events.observeKey(); +events.on("key_down", function(keyCode, event){ + //处理按键按下事件 +}); +events.loop(); +``` + +### key_up事件 + +当有按键弹起时会触发该事件。 +``` +"auto"; +events.observeKey(); +events.on("key_up", function(keyCode, event){ + //处理按键弹起事件 +}); +events.loop(); +``` + + +# EventEmitter + +### EventEmitter.defaultMaxListeners + +每个事件默认可以注册最多 10 个监听器。 单个 EventEmitter 实例的限制可以使用 emitter.setMaxListeners(n) 方法改变。 所有 EventEmitter 实例的默认值可以使用 EventEmitter.defaultMaxListeners 属性改变。 + +设置 EventEmitter.defaultMaxListeners 要谨慎,因为会影响所有 EventEmitter 实例,包括之前创建的。 因而,调用 emitter.setMaxListeners(n) 优先于 EventEmitter.defaultMaxListeners。 + +注意,与NodeJs不同,**这是一个硬性限制**。 EventEmitter 实例不允许添加更多的监听器,监听器超过最大数量时会抛出TooManyListenersException。 +``` +emitter.setMaxListeners(emitter.getMaxListeners() + 1); +emitter.once('event', () => { + // 做些操作 + emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0)); +}); +``` +## EventEmitter.addListener(eventName, listener) +* eventName \ +* listener \ +emitter.on(eventName, listener) 的别名。 + +### EventEmitter.emit(eventName\[, ...args\]) +* eventName +* args + +按监听器的注册顺序,同步地调用每个注册到名为 eventName 事件的监听器,并传入提供的参数。 + +如果事件有监听器,则返回 true ,否则返回 false。 + +### EventEmitter.eventNames() + +返回一个列出触发器已注册监听器的事件的数组。 数组中的值为字符串或符号。 +``` +const myEE = events.emitter(); +myEE.on('foo', () => {}); +myEE.on('bar', () => {}); + +const sym = Symbol('symbol'); +myEE.on(sym, () => {}); + +console.log(myEE.eventNames()); +// 打印: [ 'foo', 'bar', Symbol(symbol) ] +``` +### EventEmitter.getMaxListeners()# + +返回 EventEmitter 当前的最大监听器限制值,该值可以通过 emitter.setMaxListeners(n) 设置或默认为 EventEmitter.defaultMaxListeners。 + +### EventEmitter.listenerCount(eventName) +* eventName 正在被监听的事件名 + +返回正在监听名为 eventName 的事件的监听器的数量。 + +### EventEmitter.listeners(eventName) +* eventName + +返回名为 eventName 的事件的监听器数组的副本。 +``` +server.on('connection', (stream) => { + console.log('someone connected!'); +}); +console.log(util.inspect(server.listeners('connection'))); +// 打印: [ [Function] ] +``` + +### EventEmitter.on(eventName, listener) +* eventName 事件名 +* listener 回调函数 + +添加 listener 函数到名为 eventName 的事件的监听器数组的末尾。 不会检查 listener 是否已被添加。 多次调用并传入相同的 eventName 和 listener 会导致 listener 被添加与调用多次。 +``` +server.on('connection', (stream) => { + console.log('有连接!'); +}); +``` +返回一个 EventEmitter 引用,可以链式调用。 + +默认情况下,事件监听器会按照添加的顺序依次调用。 emitter.prependListener() 方法可用于将事件监听器添加到监听器数组的开头。 +``` +const myEE = events.emitter(); +myEE.on('foo', () => console.log('a')); +myEE.prependListener('foo', () => console.log('b')); +myEE.emit('foo'); +// 打印: +// b +// a +``` + + +### EventEmitter.once(eventName, listener)# +* eventName 事件名 +* listener 回调函数 + +添加一个单次 listener 函数到名为 eventName 的事件。 下次触发 eventName 事件时,监听器会被移除,然后调用。 +``` +server.once('connection', (stream) => { + console.log('首次调用!'); +}); +``` +返回一个 EventEmitter 引用,可以链式调用。 + +默认情况下,事件监听器会按照添加的顺序依次调用。 emitter.prependOnceListener() 方法可用于将事件监听器添加到监听器数组的开头。 +``` +const myEE = events.emitter(); +myEE.once('foo', () => console.log('a')); +myEE.prependOnceListener('foo', () => console.log('b')); +myEE.emit('foo'); +// 打印: +// b +// a +``` + +### EventEmitter.prependListener(eventName, listener) +* eventName 事件名 +* listener 回调函数 + +添加 listener 函数到名为 eventName 的事件的监听器数组的开头。 不会检查 listener 是否已被添加。 多次调用并传入相同的 eventName 和 listener 会导致 listener 被添加与调用多次。 +``` +server.prependListener('connection', (stream) => { + console.log('有连接!'); +}); +``` +返回一个 EventEmitter 引用,可以链式调用。 + +### EventEmitter.prependOnceListener(eventName, listener) +* eventName 事件名 +* listener 回调函数 + +添加一个单次 listener 函数到名为 eventName 的事件的监听器数组的开头。 下次触发 eventName 事件时,监听器会被移除,然后调用。 +``` +server.prependOnceListener('connection', (stream) => { + console.log('首次调用!'); +}); +``` +返回一个 EventEmitter 引用,可以链式调用。 + +### EventEmitter.removeAllListeners(\[eventName\]) +* eventName + +移除全部或指定 eventName 的监听器。 + +注意,在代码中移除其他地方添加的监听器是一个不好的做法,尤其是当 EventEmitter 实例是其他组件或模块创建的。 + +返回一个 EventEmitter 引用,可以链式调用。 + +### EventEmitter.removeListener(eventName, listener) +* eventName +* listener + +从名为 eventName 的事件的监听器数组中移除指定的 listener。 +``` +const callback = (stream) => { + console.log('有连接!'); +}; +server.on('connection', callback); +// ... +server.removeListener('connection', callback); +``` +removeListener 最多只会从监听器数组里移除一个监听器实例。 如果任何单一的监听器被多次添加到指定 eventName 的监听器数组中,则必须多次调用 removeListener 才能移除每个实例。 + + +注意,一旦一个事件被触发,所有绑定到它的监听器都会按顺序依次触发。 这意味着,在事件触发后、最后一个监听器完成执行前,任何 removeListener() 或 removeAllListeners() 调用都不会从 emit() 中移除它们。 随后的事件会像预期的那样发生。 +``` +const myEmitter = events.emitter(); + +const callbackA = () => { + console.log('A'); + myEmitter.removeListener('event', callbackB); +}; + +const callbackB = () => { + console.log('B'); +}; + +myEmitter.on('event', callbackA); + +myEmitter.on('event', callbackB); + +// callbackA 移除了监听器 callbackB,但它依然会被调用。 +// 触发是内部的监听器数组为 [callbackA, callbackB] +myEmitter.emit('event'); +// 打印: +// A +// B + +// callbackB 被移除了。 +// 内部监听器数组为 [callbackA] +myEmitter.emit('event'); +// 打印: +// A +``` +因为监听器是使用内部数组进行管理的,所以调用它会改变在监听器被移除后注册的任何监听器的位置索引。 虽然这不会影响监听器的调用顺序,但意味着由 emitter.listeners() 方法返回的监听器数组副本需要被重新创建。 + +返回一个 EventEmitter 引用,可以链式调用。 + +### EventEmitter.setMaxListeners(n) +* n + +默认情况下,如果为特定事件添加了超过 10 个监听器,则 EventEmitter 会打印一个警告。 此限制有助于寻找内存泄露。 但是,并不是所有的事件都要被限为 10 个。 emitter.setMaxListeners() 方法允许修改指定的 EventEmitter 实例的限制。 值设为 Infinity(或 0)表明不限制监听器的数量。 + +返回一个 EventEmitter 引用,可以链式调用。 + +# KeyEvent + +### KeyEvent.getAction() + +返回事件的动作。包括: +* KeyEvent.ACTION_DOWN 按下事件 +* KeyEvent.ACTION_UP 弹起事件 + +### KeyEvent.getKeyCode() + +返回按键的键值。包括: +* KeyEvent.KEYCODE_HOME 主页键 +* KeyEvent.KEYCODE_BACK 返回键 +* KeyEvent.KEYCODE_MENU 菜单键 +* KeyEvent.KEYCODE_VOLUME_UP 音量上键 +* KeyEvent.KEYCODE_VOLUME_DOWN 音量下键 + +### KeyEvent.getEventTime() + +返回事件发生的时间戳。 + +### KeyEvent.getDownTime() + +返回最近一次按下事件的时间戳。如果本身是按下事件,则与getEventTime()相同。 + +### KeyEvent.keyCodeToString(keyCode) + +把键值转换为字符串。例如KEYCODE_HOME转换为"KEYCODE_HOME"。 \ No newline at end of file diff --git a/app/src/main/assets/help/documentation/事件与按键监听.md b/app/src/main/assets/help/documentation/事件与按键监听.md deleted file mode 100644 index fb2975f4..00000000 --- a/app/src/main/assets/help/documentation/事件与按键监听.md +++ /dev/null @@ -1,20 +0,0 @@ -# events - -events也是一个\[EventEmitter\],这里只介绍其自身的函数。 - -### events.emitter() - -返回一个新的EventEmitter。 - -### events.observeKey() - -启用按键监听,例如音量键、Home键。 - -在安卓4.3以上才能使用。 - -### events.onKeyDown(keyName, listener) - -* keyName \ 要监听的按键名称 -* listener \ 参数为一个\[KeyEvent\] - -注册一个按键监听函数,。按键名称包括 \ No newline at end of file diff --git a/app/src/main/assets/sample/QQ与微信/QQ加群成员脚本.js b/app/src/main/assets/sample/QQ与微信/QQ加群成员脚本.js index 344fb9fb..92665414 100644 --- a/app/src/main/assets/sample/QQ与微信/QQ加群成员脚本.js +++ b/app/src/main/assets/sample/QQ与微信/QQ加群成员脚本.js @@ -27,6 +27,7 @@ while(true){ addAsFriend(); sleep(延迟); } + list.scrollForward(); } function isGroupMember(child){ diff --git a/app/src/main/assets/sample/QQ与微信/循环发送消息.js b/app/src/main/assets/sample/QQ与微信/循环发送消息.js index a83816da..c7a3ec26 100644 --- a/app/src/main/assets/sample/QQ与微信/循环发送消息.js +++ b/app/src/main/assets/sample/QQ与微信/循环发送消息.js @@ -7,5 +7,5 @@ sleep(500); while(true){ setText("我喜欢你"); click("发送"); - sleep(200); + sleep(100); } \ No newline at end of file diff --git a/app/src/main/assets/sample/事件与按键、触摸监听/按键监听.js b/app/src/main/assets/sample/事件与按键、触摸监听/按键监听.js new file mode 100644 index 00000000..307a5726 --- /dev/null +++ b/app/src/main/assets/sample/事件与按键、触摸监听/按键监听.js @@ -0,0 +1,34 @@ +"auto"; + +events.observeKey(); + +var keyNames = { + "KEYCODE_VOLUME_UP": "音量上键", + "KEYCODE_VOLUME_DOWN": "音量下键", + "KEYCODE_HOME": "Home键", + "KEYCODE_BACK": "返回键", + "KEYCODE_MENU": "菜单键", + "KEYCODE_POWER": "电源键", +}; + +events.on("key", function(code, event){ + var keyName = getKeyName(code, event); + if(event.getAction() == event.ACTION_DOWN){ + toast(keyName + "被按下"); + }else if(event.getAction() == event.ACTION_UP){ + toast(keyName + "弹起"); + } +}); + +events.loop(); + + + +function getKeyName(code, event){ + var keyCodeStr = event.keyCodeToString(code); + var keyName = keyNames[keyCodeStr]; + if(!keyName){ + return keyCodeStr; + } + return keyName; +} \ No newline at end of file diff --git a/app/src/main/assets/sample/事件与按键、触摸监听/触摸监听.js b/app/src/main/assets/sample/事件与按键、触摸监听/触摸监听.js new file mode 100644 index 00000000..93fd7b86 --- /dev/null +++ b/app/src/main/assets/sample/事件与按键、触摸监听/触摸监听.js @@ -0,0 +1,12 @@ + +events.observeTouch(); + +events.setTouchEventTimeout(30); + +toast("请在日志中查看触摸的点的坐标"); + +events.on("touch", function(point){ + log(point); +}); + +events.loop(); \ No newline at end of file diff --git a/app/src/main/assets/sample/事件与按键、触摸监听/长按返回退出当前程序.js b/app/src/main/assets/sample/事件与按键、触摸监听/长按返回退出当前程序.js new file mode 100644 index 00000000..80950ed2 --- /dev/null +++ b/app/src/main/assets/sample/事件与按键、触摸监听/长按返回退出当前程序.js @@ -0,0 +1,35 @@ +"auto"; + +var 长按间隔 = 1500; + +var curPackage = null; +var backPressedCount = 0; +var backPressed = false; + +events.observeKey(); + +events.onKeyDown("back", function(event){ + curPackage = currentPackage(); + backPressed = true; + backPressedCount++; + (function(count){ + events.setTimeout(function(){ + if(backPressed && count == backPressedCount){ + backBackBackBack(); + } + }, 长按间隔); + })(backPressedCount); +}); + +events.onKeyUp("back", function(event){ + backPressed = false; +}); + +events.loop(); + +function backBackBackBack(){ + while(curPackage == currentPackage()){ + back(); + sleep(200); + } +} \ No newline at end of file diff --git a/app/src/main/assets/sample/事件与按键、触摸监听/音量键控制程序.js b/app/src/main/assets/sample/事件与按键、触摸监听/音量键控制程序.js new file mode 100644 index 00000000..ab7fd388 --- /dev/null +++ b/app/src/main/assets/sample/事件与按键、触摸监听/音量键控制程序.js @@ -0,0 +1,34 @@ +"auto"; + +events.observeKey(); + +var interval = 5000; +var task = task1; + +events.onKeyDown("volume_up", function(event){ + if(task == task1){ + task = task2; + }else{ + task = task1; + } + toast("任务已切换"); +}); + +events.onKeyDown("volume_down", function(event){ + stop(); + toast("程序结束"); +}); + +task(); + +events.loop(); + +function task1(){ + toast("任务1运行中,音量下键结束,音量上键切换任务"); + events.setTimeout(task, interval); +} + +function task2(){ + toast("任务2运行中,音量下键结束,音量上键切换任务"); + events.setTimeout(task, interval); +} \ No newline at end of file diff --git a/app/src/main/java/com/stardust/scriptdroid/autojs/AutoJs.java b/app/src/main/java/com/stardust/scriptdroid/autojs/AutoJs.java index 70c18ce5..cae2104b 100644 --- a/app/src/main/java/com/stardust/scriptdroid/autojs/AutoJs.java +++ b/app/src/main/java/com/stardust/scriptdroid/autojs/AutoJs.java @@ -6,6 +6,7 @@ import android.os.Build; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.annotation.RequiresApi; +import android.view.KeyEvent; import com.stardust.app.OnActivityResultDelegate; import com.stardust.app.SimpleActivityLifecycleCallbacks; diff --git a/autojs/src/main/assets/javascript_engine_init.js b/autojs/src/main/assets/javascript_engine_init.js index bf1fd63d..5db49b0b 100644 --- a/autojs/src/main/assets/javascript_engine_init.js +++ b/autojs/src/main/assets/javascript_engine_init.js @@ -35,5 +35,6 @@ require("__general__")(__runtime__, this); } })(__that__); +__importClass__(android.view.KeyEvent); __importClass__(com.stardust.autojs.runtime.api.Shell); __importClass__(com.stardust.autojs.runtime.api.InputEventSender); diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/EventEmitter.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/EventEmitter.java index e4ba5a99..d88a7276 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/api/EventEmitter.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/EventEmitter.java @@ -54,19 +54,13 @@ public class EventEmitter { Iterator listenerIterator = mListenerWrappers.iterator(); while (listenerIterator.hasNext()) { ListenerWrapper listenerWrapper = listenerIterator.next(); - onEvent(listenerWrapper, args); + call(listenerWrapper.listener, args); if (listenerWrapper.isOnce) { listenerIterator.remove(); } } } - private void onEvent(ListenerWrapper listenerWrapper, Object[] args) { - if (mFunctionCaller != null) { - mFunctionCaller.call(listenerWrapper.listener, args); - } - } - int count() { return mListenerWrappers.size(); } @@ -98,7 +92,8 @@ public class EventEmitter { } private Map mListenersMap = new HashMap<>(); - private int mMaxListeners = defaultMaxListeners(); + public static int defaultMaxListeners = 10; + private int mMaxListeners = defaultMaxListeners; private FunctionCaller mFunctionCaller; public EventEmitter once(String eventName, Object listener) { @@ -186,10 +181,17 @@ public class EventEmitter { } public static int defaultMaxListeners() { - return 0; + return defaultMaxListeners; } public void setFunctionCaller(FunctionCaller functionCaller) { mFunctionCaller = functionCaller; } + + protected void call(Object func, Object[] args) { + if (mFunctionCaller != null) { + mFunctionCaller.call(func, args); + } + } + } diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/Events.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/Events.java index 00efc853..28badf3b 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/api/Events.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/Events.java @@ -1,14 +1,14 @@ package com.stardust.autojs.runtime.api; import android.content.Context; +import android.graphics.Point; import android.os.Handler; import android.os.Looper; -import android.text.method.KeyListener; +import android.util.SparseArray; import android.view.KeyEvent; import com.stardust.autojs.runtime.AccessibilityBridge; import com.stardust.autojs.runtime.ScriptStopException; -import com.stardust.autojs.runtime.record.inputevent.InputEventRecorder; import com.stardust.autojs.runtime.record.inputevent.TouchObserver; import com.stardust.view.accessibility.AccessibilityService; import com.stardust.view.accessibility.OnKeyListener; @@ -23,15 +23,16 @@ 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 sLoopers = new ConcurrentHashMap<>(); private AccessibilityBridge mAccessibilityBridge; - private boolean mListeningKey = false; private Handler mHandler; private Context mContext; private TouchObserver mTouchObserver; private long mLastTouchEventMillis; private long mTouchEventTimeout = 10; + private boolean mListeningKey = false; public Events(Context context, AccessibilityBridge accessibilityBridge) { mAccessibilityBridge = accessibilityBridge; @@ -39,10 +40,19 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver } public void observeKey() { - ensureListeningKey(); + if (mListeningKey) + return; + mListeningKey = true; + prepareLoopIfNeeded(); + mAccessibilityBridge.ensureServiceEnabled(); + AccessibilityService service = mAccessibilityBridge.getService(); + if (service == null) + throw new ScriptStopException(); + service.getOnKeyObserver().addListener(this); } public void observeTouch() { + prepareLoopIfNeeded(); if (mTouchObserver != null) return; mTouchObserver = new TouchObserver(mContext); @@ -50,16 +60,19 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver mTouchObserver.observe(); } - private void ensureListeningKey() { - if (mListeningKey) { + 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; - } - mListeningKey = true; - mAccessibilityBridge.ensureServiceEnabled(); - AccessibilityService service = mAccessibilityBridge.getService(); - if (service == null) - throw new ScriptStopException(); - service.getOnKeyObserver().addListener(this); Looper.prepare(); sLoopers.put(Thread.currentThread(), Looper.myLooper()); mHandler = new Handler(); @@ -151,12 +164,17 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver } @Override - public void onTouch(int x, int y) { + public void onTouch(final int x, final int y) { if (System.currentTimeMillis() - mLastTouchEventMillis < mTouchEventTimeout) { return; } mLastTouchEventMillis = System.currentTimeMillis(); - emit("touch", x, y); + mHandler.post(new Runnable() { + @Override + public void run() { + emit("touch", new Point(x, y)); + } + }); } public static void removeThreadRecord(Thread thread) { @@ -170,5 +188,4 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver } } - } diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/TouchObserver.java b/autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/TouchObserver.java index d7ed8bf7..0d047fc7 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/TouchObserver.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/TouchObserver.java @@ -46,7 +46,7 @@ public class TouchObserver { private class TouchEventObserver extends InputEventConverter { - private int mLastTouchX, mLastTouchY; + private int mLastTouchX = -1, mLastTouchY = -1; @Override public void convertEvent(@NonNull Event event) {