add events module, including EventEmiiter, KeyEvent, TouchEvent

This commit is contained in:
hyb1996
2017-07-20 15:39:17 +08:00
parent 1d23640362
commit 52cc5214f1
47 changed files with 755 additions and 82 deletions

View File

@@ -1,7 +1,8 @@
### sleep(n) ### sleep(\[n\])
* n \<Number\> 毫秒数 * n \<Number\> 毫秒数
暂停运行n**毫秒**的时间。1秒等于1000毫秒。 暂停运行n**毫秒**的时间。1秒等于1000毫秒。
如果不加参数n则会一直暂停通常用于有事件监听的脚本中使用。
### launchPackage(packageName) ### launchPackage(packageName)
* packageName \<String\> 应用包名。参见《Shell命令应用包名》章节。 * packageName \<String\> 应用包名。参见《Shell命令应用包名》章节。

View File

@@ -0,0 +1,20 @@
# events
events也是一个\[EventEmitter\],这里只介绍其自身的函数。
### events.emitter()
返回一个新的EventEmitter。
### events.observeKey()
启用按键监听例如音量键、Home键。
在安卓4.3以上才能使用。
### events.onKeyDown(keyName, listener)
* keyName \<String\> 要监听的按键名称
* listener \<Function\> 参数为一个\[KeyEvent\]
注册一个按键监听函数,。按键名称包括

View File

@@ -62,7 +62,7 @@ function isImage(item){
function notLiked(likeIcon){ function notLiked(likeIcon){
var x = likeIcon.bounds().centerX(); var x = likeIcon.bounds().centerX();
var y = likeIcon.bounds().centerY(); var y = likeIcon.bounds().centerY();
return images.detectsColor(capture, x, y, 0x767886); return images.detectsColor(capture, 0x767886, x, y);
} }
toast("请打开QQ空间并慢慢下滑"); toast("请打开QQ空间并慢慢下滑");

View File

@@ -5,6 +5,7 @@ import android.app.Application;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.os.Bundle; import android.os.Bundle;
import android.support.multidex.MultiDexApplication; import android.support.multidex.MultiDexApplication;
import android.view.KeyEvent;
import com.squareup.leakcanary.LeakCanary; import com.squareup.leakcanary.LeakCanary;
import com.stardust.app.SimpleActivityLifecycleCallbacks; import com.stardust.app.SimpleActivityLifecycleCallbacks;
@@ -19,6 +20,8 @@ import com.stardust.theme.ThemeColor;
import com.stardust.theme.ThemeColorManager; import com.stardust.theme.ThemeColorManager;
import com.stardust.util.ScreenMetrics; import com.stardust.util.ScreenMetrics;
import com.stardust.util.UiHandler; import com.stardust.util.UiHandler;
import com.stardust.view.accessibility.AccessibilityService;
import com.stardust.view.accessibility.OnKeyListener;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
@@ -71,7 +74,7 @@ public class App extends MultiDexApplication {
} }
private void initVolumeChangeObserver() { private void initVolumeChangeObserver() {
registerReceiver(mVolumeChangeObserver, new IntentFilter(VolumeChangeObserver.ACTION_VOLUME_CHANGE)); //registerReceiver(mVolumeChangeObserver, new IntentFilter(VolumeChangeObserver.ACTION_VOLUME_CHANGE));
mVolumeChangeObserver.addOnVolumeChangeListener(new VolumeChangeObserver.OnVolumeChangeListener() { mVolumeChangeObserver.addOnVolumeChangeListener(new VolumeChangeObserver.OnVolumeChangeListener() {
@Override @Override
public void onVolumeChange() { public void onVolumeChange() {
@@ -80,6 +83,14 @@ public class App extends MultiDexApplication {
} }
} }
}); });
AccessibilityService.getStickOnKeyObserver().addListener(new OnKeyListener() {
@Override
public void onKeyEvent(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && Pref.isRunningVolumeControlEnabled()) {
AutoJs.getInstance().getScriptEngineService().stopAllAndToast();
}
}
});
} }

View File

@@ -32,12 +32,12 @@ import com.stardust.util.ScreenMetrics;
import com.stardust.util.Supplier; import com.stardust.util.Supplier;
import com.stardust.util.UiHandler; import com.stardust.util.UiHandler;
import com.stardust.view.accessibility.AccessibilityInfoProvider; import com.stardust.view.accessibility.AccessibilityInfoProvider;
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.LayoutInspector; import com.stardust.autojs.runtime.record.accessibility.AccessibilityActionRecorder;
import com.stardust.scriptdroid.external.floatingwindow.menu.record.accessibility.AccessibilityActionRecorder;
import com.stardust.view.accessibility.AccessibilityService; import com.stardust.view.accessibility.AccessibilityService;
import com.stardust.scriptdroid.tool.AccessibilityServiceTool; import com.stardust.scriptdroid.tool.AccessibilityServiceTool;
import com.stardust.scriptdroid.ui.console.JraskaConsole; import com.stardust.scriptdroid.ui.console.JraskaConsole;
import com.stardust.view.accessibility.AccessibilityServiceUtils; import com.stardust.view.accessibility.AccessibilityServiceUtils;
import com.stardust.view.accessibility.LayoutInspector;
/** /**
@@ -177,7 +177,7 @@ public class AutoJs implements AccessibilityBridge {
@Nullable @Nullable
@Override @Override
public android.accessibilityservice.AccessibilityService getService() { public AccessibilityService getService() {
return AccessibilityService.getInstance(); return AccessibilityService.getInstance();
} }

View File

@@ -17,7 +17,7 @@ import com.stardust.hover.SimpleHoverMenuTransitionListener;
import com.stardust.hover.WindowHoverMenu; import com.stardust.hover.WindowHoverMenu;
import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.autojs.AutoJs; import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.NodeInfo; import com.stardust.view.accessibility.NodeInfo;
import com.stardust.scriptdroid.external.floatingwindow.menu.view.FloatingLayoutBoundsView; import com.stardust.scriptdroid.external.floatingwindow.menu.view.FloatingLayoutBoundsView;
import com.stardust.scriptdroid.external.floatingwindow.menu.view.FloatingLayoutHierarchyView; import com.stardust.scriptdroid.external.floatingwindow.menu.view.FloatingLayoutHierarchyView;
import com.stardust.scriptdroid.tool.AccessibilityServiceTool; import com.stardust.scriptdroid.tool.AccessibilityServiceTool;

View File

@@ -12,12 +12,12 @@ import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.autojs.AutoJs; 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.external.floatingwindow.menu.layout_inspector.LayoutInspector;
import com.stardust.scriptdroid.tool.AccessibilityServiceTool; import com.stardust.scriptdroid.tool.AccessibilityServiceTool;
import com.stardust.scriptdroid.ui.main.MainActivity_; import com.stardust.scriptdroid.ui.main.MainActivity_;
import com.stardust.util.ClipboardUtil; import com.stardust.util.ClipboardUtil;
import com.stardust.util.MessageEvent; import com.stardust.util.MessageEvent;
import com.stardust.view.accessibility.AccessibilityService; import com.stardust.view.accessibility.AccessibilityService;
import com.stardust.view.accessibility.LayoutInspector;
import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.Subscribe;

View File

@@ -10,16 +10,16 @@ import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import com.stardust.app.VolumeChangeObserver; import com.stardust.app.VolumeChangeObserver;
import com.stardust.autojs.runtime.record.Recorder;
import com.stardust.autojs.runtime.record.accessibility.AccessibilityActionRecorder;
import com.stardust.autojs.runtime.record.inputevent.KeyObserver;
import com.stardust.autojs.runtime.record.inputevent.TouchRecorder;
import com.stardust.scriptdroid.App; import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.Pref; import com.stardust.scriptdroid.Pref;
import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.accessibility.AccessibilityEventHelper; import com.stardust.scriptdroid.accessibility.AccessibilityEventHelper;
import com.stardust.scriptdroid.autojs.AutoJs; 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.external.floatingwindow.menu.record.Recorder;
import com.stardust.scriptdroid.external.floatingwindow.menu.record.accessibility.AccessibilityActionRecorder;
import com.stardust.scriptdroid.external.floatingwindow.menu.record.inputevent.KeyObserver;
import com.stardust.scriptdroid.external.floatingwindow.menu.record.inputevent.TouchRecorder;
import com.stardust.scriptdroid.ui.main.MainActivity; import com.stardust.scriptdroid.ui.main.MainActivity;
import com.stardust.util.MessageEvent; import com.stardust.util.MessageEvent;

View File

@@ -13,7 +13,7 @@ import android.util.AttributeSet;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.NodeInfo; import com.stardust.view.accessibility.NodeInfo;
import com.stardust.util.ViewUtil; import com.stardust.util.ViewUtil;
import java.util.ArrayList; import java.util.ArrayList;

View File

@@ -14,7 +14,7 @@ import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.NodeInfo; import com.stardust.view.accessibility.NodeInfo;
import com.stardust.util.ViewUtil; import com.stardust.util.ViewUtil;
import com.stardust.widget.LevelBeamView; import com.stardust.widget.LevelBeamView;

View File

@@ -12,7 +12,7 @@ import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.NodeInfo; import com.stardust.view.accessibility.NodeInfo;
import com.stardust.util.ClipboardUtil; import com.stardust.util.ClipboardUtil;
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration; import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
@@ -22,7 +22,6 @@ import java.util.Arrays;
import butterknife.BindView; import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import butterknife.OnClick; import butterknife.OnClick;
import butterknife.OnLongClick;
import butterknife.Optional; import butterknife.Optional;
/** /**

View File

@@ -1,6 +1,6 @@
package com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view; package com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view;
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.NodeInfo; import com.stardust.view.accessibility.NodeInfo;
/** /**
* Created by Stardust on 2017/3/10. * Created by Stardust on 2017/3/10.

View File

@@ -11,7 +11,7 @@ import com.afollestad.materialdialogs.MaterialDialog;
import com.afollestad.materialdialogs.Theme; import com.afollestad.materialdialogs.Theme;
import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.external.floatingwindow.menu.HoverMenuService; import com.stardust.scriptdroid.external.floatingwindow.menu.HoverMenuService;
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.NodeInfo; import com.stardust.view.accessibility.NodeInfo;
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view.LayoutBoundsView; import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view.LayoutBoundsView;
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view.NodeInfoView; import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view.NodeInfoView;
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view.OnNodeInfoSelectListener; import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view.OnNodeInfoSelectListener;

View File

@@ -11,7 +11,7 @@ import com.afollestad.materialdialogs.MaterialDialog;
import com.afollestad.materialdialogs.Theme; import com.afollestad.materialdialogs.Theme;
import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.external.floatingwindow.menu.HoverMenuService; import com.stardust.scriptdroid.external.floatingwindow.menu.HoverMenuService;
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.NodeInfo; import com.stardust.view.accessibility.NodeInfo;
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view.LayoutHierarchyView; import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view.LayoutHierarchyView;
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view.NodeInfoView; import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view.NodeInfoView;
import com.stardust.util.MessageIntent; import com.stardust.util.MessageIntent;

View File

@@ -1,6 +1,7 @@
package com.stardust.scriptdroid.ui.main.task; package com.stardust.scriptdroid.ui.main.task;
import android.content.Context; import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.ThemeColorRecyclerView; import android.support.v7.widget.ThemeColorRecyclerView;
@@ -11,6 +12,8 @@ import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
import android.workground.WrapContentLinearLayoutManager; import android.workground.WrapContentLinearLayoutManager;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.autojs.ScriptEngineService; import com.stardust.autojs.ScriptEngineService;
import com.stardust.autojs.execution.ScriptExecution; import com.stardust.autojs.execution.ScriptExecution;
import com.stardust.autojs.execution.ScriptExecutionListener; import com.stardust.autojs.execution.ScriptExecutionListener;
@@ -43,9 +46,19 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView implements Abst
@Override @Override
public void onClick(View v) { public void onClick(View v) {
int position = getChildViewHolder((View) v.getParent()).getAdapterPosition(); int position = getChildViewHolder((View) v.getParent()).getAdapterPosition();
if(position >= 0){ if (position >= 0) {
mScriptEngines.get(position).forceStop(); final ScriptEngine engine = mScriptEngines.get(position);
}else { engine.forceStop();
postDelayed(new Runnable() {
@Override
public void run() {
if (!engine.isDestroyed()) {
onScriptANR(engine);
}
}
}, 3000);
} else {
updateEngineList(); updateEngineList();
} }
} }
@@ -128,6 +141,10 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView implements Abst
AutoJs.getInstance().getScriptEngineService().unregisterGlobalScriptExecutionListener(mScriptExecutionListener); AutoJs.getInstance().getScriptEngineService().unregisterGlobalScriptExecutionListener(mScriptExecutionListener);
} }
private void onScriptANR(final ScriptEngine engine) {
// TODO: 2017/7/19 强制停止
}
@Override @Override
public void onEngineCreate(final ScriptEngine engine) { public void onEngineCreate(final ScriptEngine engine) {
synchronized (mScriptEngines) { synchronized (mScriptEngines) {

View File

@@ -208,6 +208,8 @@
<string name="text_accessibility_settings">打开无障碍服务</string> <string name="text_accessibility_settings">打开无障碍服务</string>
<string name="text_discard_record">放弃录制</string> <string name="text_discard_record">放弃录制</string>
<string name="text_inspect_failed">布局抓取失败,请关闭悬浮窗后动一下页面重试</string> <string name="text_inspect_failed">布局抓取失败,请关闭悬浮窗后动一下页面重试</string>
<string name="script_anr">没有相应,要强制停止吗</string>
<string-array name="record_control_keys"> <string-array name="record_control_keys">
<item></item> <item></item>

View File

@@ -27,7 +27,7 @@ require("__general__")(__runtime__, this);
(function(scope){ (function(scope){
var modules = ['app', 'automator', 'console', 'dialogs', 'io', 'selector', 'shell', 'web', 'ui', "images"]; var modules = ['app', 'automator', 'console', 'dialogs', 'io', 'selector', 'shell', 'web', 'ui', "images", "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];

View File

@@ -0,0 +1,24 @@
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;
}

View File

@@ -9,9 +9,7 @@ module.exports = function(__runtime__, scope){
scope.log(text); scope.log(text);
} }
scope.sleep = function(millis){ scope.sleep = __runtime__.sleep.bind(__runtime__);
__runtime__.sleep(millis);
}
scope.isStopped = function(){ scope.isStopped = function(){
return __runtime__.isStopped(); return __runtime__.isStopped();

View File

@@ -1,10 +1,12 @@
package com.stardust.autojs.engine; package com.stardust.autojs.engine;
import android.os.Looper;
import android.util.Log; import android.util.Log;
import com.stardust.autojs.rhino.AndroidContextFactory; 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.script.ScriptSource; import com.stardust.autojs.script.ScriptSource;
import com.stardust.pio.UncheckedIOException; import com.stardust.pio.UncheckedIOException;
@@ -41,6 +43,7 @@ public class RhinoJavaScriptEngine implements ScriptEngine {
private Thread mThread; private Thread mThread;
private RhinoJavaScriptEngineManager mEngineManager; private RhinoJavaScriptEngineManager mEngineManager;
private Map<String, Object> mTags = new ConcurrentHashMap<>(); private Map<String, Object> mTags = new ConcurrentHashMap<>();
private volatile boolean mDestroyed = false;
public RhinoJavaScriptEngine(RhinoJavaScriptEngineManager engineManager) { public RhinoJavaScriptEngine(RhinoJavaScriptEngineManager engineManager) {
mEngineManager = engineManager; mEngineManager = engineManager;
@@ -73,6 +76,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);
} }
public RhinoJavaScriptEngineManager getEngineManager() { public RhinoJavaScriptEngineManager getEngineManager() {
@@ -86,6 +90,13 @@ 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);
mDestroyed = true;
}
@Override
public boolean isDestroyed() {
return mDestroyed;
} }
@Override @Override

View File

@@ -25,6 +25,8 @@ public interface ScriptEngine {
void destroy(); void destroy();
boolean isDestroyed();
void setTag(String key, Object value); void setTag(String key, Object value);
Object getTag(String key); Object getTag(String key);

View File

@@ -8,6 +8,7 @@ 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.Console; import com.stardust.autojs.runtime.api.Console;
import com.stardust.autojs.runtime.api.Events;
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;
@@ -41,10 +42,12 @@ public abstract class AbstractScriptRuntime {
@ScriptVariable @ScriptVariable
public UI ui; public UI ui;
@ScriptVariable @ScriptVariable
public Dialogs dialogs; public Dialogs dialogs;
@ScriptVariable
public Events events;
private Images images; private Images images;
private static WeakReference<Context> applicationContext; private static WeakReference<Context> applicationContext;
@@ -54,11 +57,13 @@ public abstract class AbstractScriptRuntime {
this.console = console; this.console = console;
this.automator = new SimpleActionAutomator(bridge, this); this.automator = new SimpleActionAutomator(bridge, this);
this.info = bridge.getInfoProvider(); this.info = bridge.getInfoProvider();
this.ui = new UI(uiHandler.getContext()); Context context = uiHandler.getContext();
this.ui = new UI(context);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
images = new Images(uiHandler.getContext(), this, screenCaptureRequester); images = new Images(context, this, screenCaptureRequester);
} }
dialogs = new Dialogs(app, uiHandler); dialogs = new Dialogs(app, uiHandler);
events = new Events(context, bridge);
} }
public static void setApplicationContext(Context context) { public static void setApplicationContext(Context context) {
@@ -115,6 +120,7 @@ public abstract class AbstractScriptRuntime {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
images.releaseScreenCapturer(); images.releaseScreenCapturer();
} }
events.recycle();
} }
public Object getImages() { public Object getImages() {

View File

@@ -1,11 +1,11 @@
package com.stardust.autojs.runtime; package com.stardust.autojs.runtime;
import android.accessibilityservice.AccessibilityService;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import com.stardust.automator.AccessibilityEventCommandHost; import com.stardust.automator.AccessibilityEventCommandHost;
import com.stardust.automator.simple_action.SimpleActionPerformHost; import com.stardust.automator.simple_action.SimpleActionPerformHost;
import com.stardust.view.accessibility.AccessibilityInfoProvider; import com.stardust.view.accessibility.AccessibilityInfoProvider;
import com.stardust.view.accessibility.AccessibilityService;
/** /**
* Created by Stardust on 2017/4/2. * Created by Stardust on 2017/4/2.

View File

@@ -1,6 +1,7 @@
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;
@@ -85,7 +86,6 @@ public class ScriptRuntime extends AbstractScriptRuntime {
private UiHandler mUiHandler; private UiHandler mUiHandler;
private AccessibilityBridge mAccessibilityBridge; private AccessibilityBridge mAccessibilityBridge;
private AbstractShell mRootShell; private AbstractShell mRootShell;
private Supplier<AbstractShell> mShellSupplier; private Supplier<AbstractShell> mShellSupplier;
private ScreenMetrics mScreenMetrics = new ScreenMetrics(); private ScreenMetrics mScreenMetrics = new ScreenMetrics();

View File

@@ -0,0 +1,195 @@
package com.stardust.autojs.runtime.api;
import android.support.annotation.NonNull;
import com.stardust.autojs.runtime.ScriptStopException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TooManyListenersException;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Created by Stardust on 2017/7/19.
*/
public class EventEmitter {
public interface FunctionCaller {
Object call(Object func, Object[] arg);
}
private static class ListenerWrapper {
Object listener;
boolean isOnce;
public ListenerWrapper(Object listener, boolean isOnce) {
this.listener = listener;
this.isOnce = isOnce;
}
}
private class Listeners {
private CopyOnWriteArrayList<ListenerWrapper> mListenerWrappers = new CopyOnWriteArrayList<>();
void add(Object listener, boolean once) {
ensureListenersNotAtLimit();
mListenerWrappers.add(new ListenerWrapper(listener, once));
}
private void ensureListenersNotAtLimit() {
if (mMaxListeners != 0 && mListenersMap.size() >= mMaxListeners) {
throw new ScriptStopException(new TooManyListenersException("max = " + mMaxListeners));
}
}
boolean empty() {
return mListenerWrappers.isEmpty();
}
void emit(Object[] args) {
Iterator<ListenerWrapper> listenerIterator = mListenerWrappers.iterator();
while (listenerIterator.hasNext()) {
ListenerWrapper listenerWrapper = listenerIterator.next();
onEvent(listenerWrapper, 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();
}
Object[] toArray() {
Iterator<ListenerWrapper> listenerIterator = mListenerWrappers.iterator();
ArrayList<Object> listeners = new ArrayList<>(mListenerWrappers.size());
while (listenerIterator.hasNext()) {
listeners.add(listenerIterator.next().listener);
}
return listeners.toArray(new Object[listeners.size()]);
}
void prepend(Object listener, boolean once) {
ensureListenersNotAtLimit();
mListenerWrappers.add(0, new ListenerWrapper(listener, once));
}
void remove(Object listener) {
Iterator<ListenerWrapper> listenerIterator = mListenerWrappers.iterator();
while (listenerIterator.hasNext()) {
ListenerWrapper l = listenerIterator.next();
if (l.listener == listener) {
listenerIterator.remove();
break;
}
}
}
}
private Map<String, Listeners> mListenersMap = new HashMap<>();
private int mMaxListeners = defaultMaxListeners();
private FunctionCaller mFunctionCaller;
public EventEmitter once(String eventName, Object listener) {
getListeners(eventName).add(listener, true);
return this;
}
@NonNull
private Listeners getListeners(String eventName) {
Listeners listeners = mListenersMap.get(eventName);
if (listeners == null) {
listeners = new Listeners();
mListenersMap.put(eventName, listeners);
}
return listeners;
}
public EventEmitter on(String eventName, Object listener) {
getListeners(eventName).add(listener, false);
return this;
}
public EventEmitter addListener(String eventName, Object listener) {
return on(eventName, listener);
}
public boolean emit(String eventName, Object... args) {
Listeners listeners = mListenersMap.get(eventName);
if (listeners == null || listeners.empty())
return false;
listeners.emit(args);
return true;
}
public String[] eventNames() {
return mListenersMap.keySet().toArray(new String[mListenersMap.size()]);
}
public int listenerCount(String eventName) {
Listeners listeners = mListenersMap.get(eventName);
if (listeners == null)
return 0;
return listeners.count();
}
public Object[] listeners(String eventName) {
return getListeners(eventName).toArray();
}
public EventEmitter prependListener(String eventName, Object listener) {
getListeners(eventName).prepend(listener, false);
return this;
}
public EventEmitter prependOnceListener(String eventName, Object listener) {
getListeners(eventName).prepend(listener, true);
return this;
}
public EventEmitter removeAllListeners() {
mListenersMap.clear();
return this;
}
public EventEmitter removeAllListeners(String eventName) {
mListenersMap.remove(eventName);
return this;
}
public EventEmitter removeListener(String eventName, Object listener) {
Listeners listeners = mListenersMap.get(eventName);
if (listeners != null)
listeners.remove(listener);
return this;
}
public EventEmitter setMaxListeners(int n) {
mMaxListeners = n;
return this;
}
public int getMaxListeners() {
return mMaxListeners;
}
public static int defaultMaxListeners() {
return 0;
}
public void setFunctionCaller(FunctionCaller functionCaller) {
mFunctionCaller = functionCaller;
}
}

View File

@@ -0,0 +1,174 @@
package com.stardust.autojs.runtime.api;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.text.method.KeyListener;
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;
import java.util.concurrent.ConcurrentHashMap;
/**
* Created by Stardust on 2017/7/18.
*/
public class Events extends EventEmitter implements OnKeyListener, TouchObserver.OnTouchEventListener {
private static final String PREFIX_KEY_DOWN = "__key_down__#";
private static final String PREFIX_KEY_UP = "__key_up__#";
private static ConcurrentHashMap<Thread, Looper> 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;
public Events(Context context, AccessibilityBridge accessibilityBridge) {
mAccessibilityBridge = accessibilityBridge;
mContext = context;
}
public void observeKey() {
ensureListeningKey();
}
public void observeTouch() {
if (mTouchObserver != null)
return;
mTouchObserver = new TouchObserver(mContext);
mTouchObserver.setOnTouchEventListener(this);
mTouchObserver.observe();
}
private void ensureListeningKey() {
if (mListeningKey) {
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();
}
public void loop() {
Looper.loop();
}
public Events onKeyDown(String keyName, Object listener) {
on(PREFIX_KEY_DOWN + keyName, listener);
return this;
}
public Events onceKeyDown(String keyName, Object listener) {
once(PREFIX_KEY_DOWN + keyName, listener);
return this;
}
public Events removeAllKeyDownListeners(String keyName) {
removeAllListeners(PREFIX_KEY_DOWN + keyName);
return this;
}
public Events onKeyUp(String keyName, Object listener) {
on(PREFIX_KEY_UP + keyName, listener);
return this;
}
public Events onceKeyUp(String keyName, Object listener) {
once(PREFIX_KEY_UP + keyName, listener);
return this;
}
public Events removeAllKeyUpListeners(String keyName) {
removeAllListeners(PREFIX_KEY_UP + keyName);
return this;
}
public Events onTouch(Object listener) {
on("touch", listener);
return this;
}
public Events removeAllTouchListeners() {
removeAllListeners("touch");
return this;
}
public long getTouchEventTimeout() {
return mTouchEventTimeout;
}
public void setTouchEventTimeout(long touchEventTimeout) {
mTouchEventTimeout = touchEventTimeout;
}
public void recycle() {
if (mListeningKey) {
AccessibilityService service = mAccessibilityBridge.getService();
if (service != null) {
service.getOnKeyObserver().removeListener(this);
mListeningKey = false;
}
}
if (mTouchObserver != null) {
mTouchObserver.stop();
}
}
@Override
public void onKeyEvent(final int keyCode, final KeyEvent event) {
mHandler.post(new Runnable() {
@Override
public void run() {
String keyName = KeyEvent.keyCodeToString(keyCode).substring(8).toLowerCase();
emit(keyName, event);
if (event.getAction() == KeyEvent.ACTION_DOWN) {
emit(PREFIX_KEY_DOWN + keyName, event);
emit("key_down", keyCode, event);
} else if (event.getAction() == KeyEvent.ACTION_UP) {
emit(PREFIX_KEY_UP + keyName, event);
emit("key_up", keyCode, event);
}
emit("key", keyCode, event);
}
});
}
@Override
public void onTouch(int x, int y) {
if (System.currentTimeMillis() - mLastTouchEventMillis < mTouchEventTimeout) {
return;
}
mLastTouchEventMillis = System.currentTimeMillis();
emit("touch", x, y);
}
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();
}
}
}

View File

@@ -117,8 +117,7 @@ public class UiSelector extends UiGlobalSelector {
@ScriptInterface @ScriptInterface
@NonNull @NonNull
public UiObjectCollection untilFind() { public UiObjectCollection untilFind() {
UiObjectCollection uiObjectCollection; UiObjectCollection uiObjectCollection = find();
uiObjectCollection = find();
while (uiObjectCollection.empty()) { while (uiObjectCollection.empty()) {
if (Thread.currentThread().isInterrupted()) { if (Thread.currentThread().isInterrupted()) {
throw new ScriptInterruptedException(); throw new ScriptInterruptedException();

View File

@@ -0,0 +1,50 @@
package com.stardust.autojs.runtime.internal;
/**
* Created by Stardust on 2017/7/19.
*/
public class Functions {
@SuppressWarnings("unchecked")
public static Object call(Func func, Object[] args) {
if (func instanceof Func0) {
return ((Func0) func).call();
} else if (func instanceof Func1) {
return ((Func1) func).call(args[0]);
} else if (func instanceof Func2) {
return ((Func2) func).call(args[0], args[1]);
} else if (func instanceof Func3) {
return ((Func3) func).call(args[0], args[1], args[2]);
} else if (func instanceof Func4) {
return ((Func4) func).call(args[0], args[1], args[2], args[3]);
}
throw new IllegalArgumentException("Unknown func: " + func);
}
public interface Func {
}
public interface Func0<R> extends Func {
R call();
}
public interface Func1<T1, R> extends Func {
R call(T1 t1);
}
public interface Func2<T1, T2, R> extends Func {
R call(T1 t1, T2 t2);
}
public interface Func3<T1, T2, T3, R> extends Func {
R call(T1 t1, T2 t2, T3 t3);
}
public interface Func4<T1, T2, T3, T4, R> extends Func {
R call(T1 t1, T2 t2, T3 t3, T4 t4);
}
}

View File

@@ -1,4 +1,4 @@
package com.stardust.scriptdroid.external.floatingwindow.menu.record; package com.stardust.autojs.runtime.record;
import java.util.Arrays; import java.util.Arrays;

View File

@@ -1,4 +1,4 @@
package com.stardust.scriptdroid.external.floatingwindow.menu.record.accessibility; package com.stardust.autojs.runtime.record.accessibility;
import android.accessibilityservice.AccessibilityService; import android.accessibilityservice.AccessibilityService;
import android.os.Build; import android.os.Build;
@@ -8,9 +8,9 @@ import android.view.accessibility.AccessibilityNodeInfo;
import com.stardust.automator.UiObject; import com.stardust.automator.UiObject;
import com.stardust.automator.simple_action.FilterAction; import com.stardust.automator.simple_action.FilterAction;
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.NodeInfo;
import com.stardust.util.SparseArrayEntries; import com.stardust.util.SparseArrayEntries;
import com.stardust.view.accessibility.AccessibilityNodeInfoHelper; import com.stardust.view.accessibility.AccessibilityNodeInfoHelper;
import com.stardust.view.accessibility.NodeInfo;
import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.EventBus;

View File

@@ -1,9 +1,9 @@
package com.stardust.scriptdroid.external.floatingwindow.menu.record.accessibility; package com.stardust.autojs.runtime.record.accessibility;
import android.accessibilityservice.AccessibilityService; import android.accessibilityservice.AccessibilityService;
import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityEvent;
import com.stardust.scriptdroid.external.floatingwindow.menu.record.Recorder; import com.stardust.autojs.runtime.record.Recorder;
import com.stardust.view.accessibility.AccessibilityDelegate; import com.stardust.view.accessibility.AccessibilityDelegate;
import java.util.Arrays; import java.util.Arrays;

View File

@@ -1,4 +1,4 @@
package com.stardust.scriptdroid.external.floatingwindow.menu.record.inputevent; package com.stardust.autojs.runtime.record.inputevent;
/** /**
* Created by Stardust on 2017/3/7. * Created by Stardust on 2017/3/7.

View File

@@ -1,14 +1,10 @@
package com.stardust.scriptdroid.external.floatingwindow.menu.record.inputevent; package com.stardust.autojs.runtime.record.inputevent;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.text.TextUtils; import android.text.TextUtils;
import android.widget.Toast; import android.widget.Toast;
import com.flurry.android.FlurryAgent; import com.stardust.autojs.runtime.record.Recorder;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.external.floatingwindow.menu.record.Recorder;
import com.stardust.util.MapEntries;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -66,6 +62,9 @@ public abstract class InputEventConverter {
} }
private final static Pattern LAST_INT_PATTERN = Pattern.compile("[^0-9]+([0-9]+)$");
protected boolean mConverting = false; protected boolean mConverting = false;
private int mState = Recorder.STATE_NOT_START; private int mState = Recorder.STATE_NOT_START;
@@ -117,14 +116,21 @@ public abstract class InputEventConverter {
} catch (EventFormatException e) { } catch (EventFormatException e) {
e.printStackTrace(); e.printStackTrace();
if (mFirstEventFormatError) { if (mFirstEventFormatError) {
Toast.makeText(App.getApp(), R.string.text_record_format_error, Toast.LENGTH_SHORT).show();
mFirstEventFormatError = false; mFirstEventFormatError = false;
FlurryAgent.logEvent("EventFormatException", new MapEntries<String, String>()
.entry("message", e.getMessage())
.map());
} }
return null; return null;
} }
} }
public static int parseDeviceNumber(String device) {
Matcher matcher = LAST_INT_PATTERN.matcher(device);
if (matcher.find()) {
String someNumberStr = matcher.group(1);
return Integer.parseInt(someNumberStr);
}
return -1;
}
} }

View File

@@ -1,10 +1,9 @@
package com.stardust.scriptdroid.external.floatingwindow.menu.record.inputevent; package com.stardust.autojs.runtime.record.inputevent;
import android.content.Context; import android.content.Context;
import com.stardust.autojs.runtime.api.Shell; import com.stardust.autojs.runtime.api.Shell;
import com.stardust.scriptdroid.App; import com.stardust.autojs.runtime.record.Recorder;
import com.stardust.scriptdroid.external.floatingwindow.menu.record.Recorder;
/** /**
* Created by Stardust on 2017/3/6. * Created by Stardust on 2017/3/6.

View File

@@ -1,4 +1,4 @@
package com.stardust.scriptdroid.external.floatingwindow.menu.record.inputevent; package com.stardust.autojs.runtime.record.inputevent;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;

View File

@@ -1,4 +1,4 @@
package com.stardust.scriptdroid.external.floatingwindow.menu.record.inputevent; package com.stardust.autojs.runtime.record.inputevent;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;

View File

@@ -1,6 +1,5 @@
package com.stardust.scriptdroid.external.floatingwindow.menu.record.inputevent; package com.stardust.autojs.runtime.record.inputevent;
import android.media.Image;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@@ -15,7 +14,6 @@ import static com.stardust.util.ScreenMetrics.getDeviceScreenWidth;
public class InputEventToSendEventJsConverter extends InputEventConverter { public class InputEventToSendEventJsConverter extends InputEventConverter {
private final static Pattern LAST_INT_PATTERN = Pattern.compile("[^0-9]+([0-9]+)$");
private double mLastEventTime; private double mLastEventTime;
private StringBuilder mCode = new StringBuilder(); private StringBuilder mCode = new StringBuilder();
private int mTouchDevice = -1; private int mTouchDevice = -1;
@@ -73,15 +71,6 @@ public class InputEventToSendEventJsConverter extends InputEventConverter {
} }
private int parseDeviceNumber(String device) {
Matcher matcher = LAST_INT_PATTERN.matcher(device);
if (matcher.find()) {
String someNumberStr = matcher.group(1);
return Integer.parseInt(someNumberStr);
}
return -1;
}
private void onTouchX(int device, int value) { private void onTouchX(int device, int value) {
if (mTouchDevice == -1) { if (mTouchDevice == -1) {
setTouchDevice(device); setTouchDevice(device);

View File

@@ -1,4 +1,4 @@
package com.stardust.scriptdroid.external.floatingwindow.menu.record.inputevent; package com.stardust.autojs.runtime.record.inputevent;
import android.content.Context; import android.content.Context;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;

View File

@@ -0,0 +1,102 @@
package com.stardust.autojs.runtime.record.inputevent;
import android.content.Context;
import android.support.annotation.NonNull;
/**
* Created by Stardust on 2017/7/20.
*/
public class TouchObserver {
public interface OnTouchEventListener {
void onTouch(int x, int y);
}
private int mTouchX, mTouchY;
private InputEventRecorder mRecorder;
private OnTouchEventListener mOnTouchEventListener;
public TouchObserver(Context context) {
mRecorder = new InputEventRecorder(context, new TouchEventObserver());
}
public void observe() {
mRecorder.listen();
mRecorder.start();
}
public void stop() {
mRecorder.stop();
}
public void setOnTouchEventListener(OnTouchEventListener onTouchEventListener) {
mOnTouchEventListener = onTouchEventListener;
}
private void onTouch(int x, int y) {
mTouchX = x;
mTouchY = y;
if(mOnTouchEventListener != null){
mOnTouchEventListener.onTouch(x, y);
}
}
private class TouchEventObserver extends InputEventConverter {
private int mLastTouchX, mLastTouchY;
@Override
public void convertEvent(@NonNull Event event) {
int device = parseDeviceNumber(event.device);
int type = (int) Long.parseLong(event.type, 16);
int code = (int) Long.parseLong(event.code, 16);
int value = (int) Long.parseLong(event.value, 16);
if (type != 3) {
return;
}
if (code == 53) {
onTouchX(value);
return;
}
if (code == 54) {
onTouchY(value);
return;
}
if (mLastTouchX >= 0) {
onTouch(mLastTouchX, mTouchY);
mLastTouchX = -1;
return;
}
if (mLastTouchY >= 0) {
onTouch(mTouchX, mLastTouchY);
mLastTouchY = -1;
}
}
private void onTouchX(int value) {
mLastTouchX = value;
}
private void onTouchY(int value) {
if (mLastTouchX > 0) {
onTouch(mLastTouchX, value);
return;
}
mLastTouchY = value;
}
@Override
public String getGetEventCommand() {
return "getevent -t";
}
@Override
public String getCode() {
return null;
}
}
}

View File

@@ -1,4 +1,4 @@
package com.stardust.scriptdroid.external.floatingwindow.menu.record.inputevent; package com.stardust.autojs.runtime.record.inputevent;
import android.content.Context; import android.content.Context;

View File

@@ -2,9 +2,10 @@
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask" android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackGeneric" android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagIncludeNotImportantViews|flagReportViewIds|flagRetrieveInteractiveWindows|flagRequestEnhancedWebAccessibility" android:accessibilityFlags="flagIncludeNotImportantViews|flagReportViewIds|flagRetrieveInteractiveWindows|flagRequestEnhancedWebAccessibility|flagRequestFilterKeyEvents"
android:canPerformGestures="true" android:canPerformGestures="true"
android:canRequestEnhancedWebAccessibility="true" android:canRequestEnhancedWebAccessibility="true"
android:canRequestFilterKeyEvents="true"
android:canRetrieveWindowContent="true" android:canRetrieveWindowContent="true"
android:description="@string/text_accessibility_service_description" android:description="@string/text_accessibility_service_description"
android:notificationTimeout="100"/> android:notificationTimeout="100"/>

View File

@@ -1,5 +1,7 @@
package com.stardust.automator.simple_action; package com.stardust.automator.simple_action;
import android.graphics.BitmapFactory;
import com.stardust.automator.UiObject; import com.stardust.automator.UiObject;
import java.util.List; import java.util.List;

View File

@@ -1,19 +1,12 @@
package com.stardust.view.accessibility; package com.stardust.view.accessibility;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.Context; import android.content.Context;
import android.graphics.Rect;
import android.os.Build; import android.os.Build;
import android.os.Handler; import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log; import android.util.Log;
import android.view.InputDevice; import android.view.KeyEvent;
import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import com.stardust.util.ScreenMetrics;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
@@ -22,6 +15,9 @@ import java.util.SortedMap;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
@@ -39,11 +35,14 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
private static final ReentrantLock LOCK = new ReentrantLock(); private static final ReentrantLock LOCK = new ReentrantLock();
private static final Condition ENABLED = LOCK.newCondition(); private static final Condition ENABLED = LOCK.newCondition();
private static AccessibilityService instance; private static AccessibilityService instance;
private static final OnKeyListener.Observer stickOnKeyObserver = new OnKeyListener.Observer();
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 volatile AccessibilityNodeInfo mRootInActiveWindow; private volatile AccessibilityNodeInfo mRootInActiveWindow;
private Timer mTimer; private Timer mTimer;
private Handler mHandler; private Handler mHandler;
private ExecutorService mKeyEventExecutor;
public static void addDelegate(int uniquePriority, AccessibilityDelegate delegate) { public static void addDelegate(int uniquePriority, AccessibilityDelegate delegate) {
mDelegates.put(uniquePriority, delegate); mDelegates.put(uniquePriority, delegate);
@@ -85,6 +84,25 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
} }
@Override
protected boolean onKeyEvent(final KeyEvent event) {
if (mKeyEventExecutor == null) {
mKeyEventExecutor = Executors.newSingleThreadExecutor();
}
mKeyEventExecutor.execute(new Runnable() {
@Override
public void run() {
stickOnKeyObserver.onKeyEvent(event.getKeyCode(), event);
mOnKeyObserver.onKeyEvent(event.getKeyCode(), event);
}
});
return false;
}
public OnKeyListener.Observer getOnKeyObserver() {
return mOnKeyObserver;
}
@Override @Override
public AccessibilityNodeInfo getRootInActiveWindow() { public AccessibilityNodeInfo getRootInActiveWindow() {
return mRootInActiveWindow; return mRootInActiveWindow;
@@ -93,7 +111,10 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
@Override @Override
public void onDestroy() { public void onDestroy() {
instance = null; instance = null;
mTimer.cancel(); if (mTimer != null)
mTimer.cancel();
if (mKeyEventExecutor != null)
mKeyEventExecutor.shutdownNow();
super.onDestroy(); super.onDestroy();
} }
@@ -155,5 +176,7 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
} }
} }
public static OnKeyListener.Observer getStickOnKeyObserver() {
return stickOnKeyObserver;
}
} }

View File

@@ -1,4 +1,4 @@
package com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector; package com.stardust.view.accessibility;
import android.os.Build; import android.os.Build;
import android.support.annotation.RequiresApi; import android.support.annotation.RequiresApi;

View File

@@ -1,4 +1,4 @@
package com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector; package com.stardust.view.accessibility;
import android.graphics.Rect; import android.graphics.Rect;
import android.support.annotation.Keep; import android.support.annotation.Keep;

View File

@@ -0,0 +1,42 @@
package com.stardust.view.accessibility;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Created by Stardust on 2017/7/18.
*/
public interface OnKeyListener {
void onKeyEvent(int keyCode, KeyEvent event);
class Observer implements OnKeyListener {
private static final String TAG = "OnKeyListenerObserver";
private CopyOnWriteArrayList<OnKeyListener> mOnKeyListeners = new CopyOnWriteArrayList<>();
@Override
public void onKeyEvent(int keyCode, KeyEvent event) {
for (OnKeyListener listener : mOnKeyListeners) {
try {
listener.onKeyEvent(keyCode, event);
} catch (Exception e) {
Log.e(TAG, "Error OnKeyEvent: " + event + " Listener: " + listener, e);
}
}
}
public void addListener(OnKeyListener listener) {
mOnKeyListeners.add(listener);
}
public boolean removeListener(OnKeyListener listener) {
return mOnKeyListeners.remove(listener);
}
}
}

View File

@@ -151,7 +151,7 @@ public class AutoJs implements AccessibilityBridge {
@Nullable @Nullable
@Override @Override
public android.accessibilityservice.AccessibilityService getService() { public AccessibilityService getService() {
return AccessibilityService.getInstance(); return AccessibilityService.getInstance();
} }