diff --git a/.idea/dictionaries/Stardust.xml b/.idea/dictionaries/Stardust.xml index 60983c2a..803965af 100644 --- a/.idea/dictionaries/Stardust.xml +++ b/.idea/dictionaries/Stardust.xml @@ -3,6 +3,7 @@ dismissable interruptible + loopers prefill scriptable tasker diff --git a/app/src/main/assets/help/documentation/事件与按键、触摸监听.md b/app/src/main/assets/help/documentation/事件与按键、触摸监听.md index a12f7a4b..57c868b1 100644 --- a/app/src/main/assets/help/documentation/事件与按键、触摸监听.md +++ b/app/src/main/assets/help/documentation/事件与按键、触摸监听.md @@ -89,7 +89,7 @@ events.onKeyDown("menu", function(event){ ### events.onTouch(listener) * listener \ 参数为Point的函数 -注册一个触摸监听函数。 +注册一个触摸监听函数。相当于`on("touch", listener)`。 例如: ``` @@ -147,6 +147,28 @@ events.loop(); ``` +### obverseNotification() + + + + +### toast事件 + + + +### 事件: 'notification' +* notification \ 通知 + +``` +events.observeNotification(); +events.on("notification", function(notification){ + log(notification. +}); + +``` + + + # EventEmitter ### EventEmitter.defaultMaxListeners @@ -155,7 +177,7 @@ events.loop(); 设置 EventEmitter.defaultMaxListeners 要谨慎,因为会影响所有 EventEmitter 实例,包括之前创建的。 因而,调用 emitter.setMaxListeners(n) 优先于 EventEmitter.defaultMaxListeners。 -注意,与NodeJs不同,**这是一个硬性限制**。 EventEmitter 实例不允许添加更多的监听器,监听器超过最大数量时会抛出TooManyListenersException。 +注意,与Node.js不同,**这是一个硬性限制**。 EventEmitter 实例不允许添加更多的监听器,监听器超过最大数量时会抛出TooManyListenersException。 ``` emitter.setMaxListeners(emitter.getMaxListeners() + 1); emitter.once('event', () => { diff --git a/app/src/main/assets/js/functions.json b/app/src/main/assets/js/functions.json index 3a6c03dc..aeea2c54 100644 --- a/app/src/main/assets/js/functions.json +++ b/app/src/main/assets/js/functions.json @@ -1,5 +1,5 @@ { - "global" : { + "global": { "modules": [ "app", "automator", @@ -39,7 +39,7 @@ "openConsole", "clearConsole" ], - "dialogs":[ + "dialogs": [ "rawInput", "input", "alert", @@ -142,12 +142,12 @@ "Text" ], "timers": [ - "loop", - "setTimeout", - "clearTimeout", - "setInterval", - "clearInterval", - "setImmediate", + "loop", + "setTimeout", + "clearTimeout", + "setInterval", + "clearInterval", + "setImmediate", "clearImmediate" ], "web": [ @@ -211,7 +211,7 @@ "error", "assert" ], - "dialogs":[ + "dialogs": [ "select", "singleChoice", "multiChoice", @@ -248,6 +248,8 @@ "onKeyUp", "onceKeyDown", "onceKeyUp", + "onToast", + "onNotification", "removeAllKeyDownListeners", "removeAllKeyUpListeners", "onTouch", 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 14cbb43d..d32bf329 100644 --- a/app/src/main/java/com/stardust/scriptdroid/autojs/AutoJs.java +++ b/app/src/main/java/com/stardust/scriptdroid/autojs/AutoJs.java @@ -1,6 +1,7 @@ package com.stardust.scriptdroid.autojs; import android.app.Activity; +import android.app.Notification; import android.content.Context; import android.os.Build; import android.os.Bundle; @@ -36,6 +37,7 @@ import com.stardust.scriptdroid.tool.AccessibilityServiceTool; import com.stardust.scriptdroid.ui.console.JraskaConsole; import com.stardust.view.accessibility.AccessibilityServiceUtils; import com.stardust.view.accessibility.LayoutInspector; +import com.stardust.view.accessibility.NotificationListener; /** @@ -55,6 +57,7 @@ public class AutoJs { } private final AccessibilityActionRecorder mAccessibilityActionRecorder = new AccessibilityActionRecorder(); + private final NotificationListener.Observer mNotificationObserver; private final LayoutInspector mLayoutInspector = new LayoutInspector(); private final Context mContext; private final UiHandler mUiHandler; @@ -68,6 +71,7 @@ public class AutoJs { mContext = context; mUiHandler = new UiHandler(context); mAppUtils = new AppUtils(context); + mNotificationObserver = new NotificationListener.Observer(context); mAccessibilityInfoProvider = new AccessibilityInfoProvider(context.getPackageManager()); mScriptEngineService = buildScriptEngineService(); addAccessibilityServiceDelegates(); @@ -130,6 +134,7 @@ public class AutoJs { private void addAccessibilityServiceDelegates() { AccessibilityService.addDelegate(100, mAccessibilityInfoProvider); + AccessibilityService.addDelegate(200, mNotificationObserver); AccessibilityService.addDelegate(300, mAccessibilityActionRecorder); } @@ -198,6 +203,11 @@ public class AutoJs { return mAccessibilityInfoProvider; } + @Override + public NotificationListener.Observer getNotificationObserver() { + return mNotificationObserver; + } + } private class ScreenCaptureRequesterImpl extends ScreenCaptureRequester.AbstractScreenCaptureRequester { diff --git a/app/src/main/java/com/stardust/scriptdroid/external/floatingwindow/menu/HoverMenuService.java b/app/src/main/java/com/stardust/scriptdroid/external/floatingwindow/menu/HoverMenuService.java index 962a28f3..f33a831e 100644 --- a/app/src/main/java/com/stardust/scriptdroid/external/floatingwindow/menu/HoverMenuService.java +++ b/app/src/main/java/com/stardust/scriptdroid/external/floatingwindow/menu/HoverMenuService.java @@ -20,7 +20,6 @@ import com.stardust.scriptdroid.autojs.AutoJs; import com.stardust.view.accessibility.NodeInfo; import com.stardust.scriptdroid.external.floatingwindow.menu.view.FloatingLayoutBoundsView; import com.stardust.scriptdroid.external.floatingwindow.menu.view.FloatingLayoutHierarchyView; -import com.stardust.scriptdroid.tool.AccessibilityServiceTool; import com.stardust.theme.ThemeColorManagerCompat; import com.stardust.util.IntentUtil; import com.stardust.util.MessageEvent; @@ -189,7 +188,6 @@ public class HoverMenuService extends Service { tryInitViews(); if (mWindowHoverMenu != null) mWindowHoverMenu.show(); - AccessibilityServiceTool.enableAccessibilityServiceByRootIfNeeded(); return START_STICKY; } @@ -200,6 +198,8 @@ public class HoverMenuService extends Service { if (eventBus.isRegistered(this)) eventBus.unregister(this); setIsRunning(false); + if (mWindowViewController == null) + return; mWindowViewController.removeView(mFloatingLayoutBoundsView); mWindowViewController.removeView(mFloatingLayoutHierarchyView); } diff --git a/app/src/main/java/com/stardust/scriptdroid/external/floatingwindow/menu/content/RecordNavigatorContent.java b/app/src/main/java/com/stardust/scriptdroid/external/floatingwindow/menu/content/RecordNavigatorContent.java index c414ce56..3a67226d 100644 --- a/app/src/main/java/com/stardust/scriptdroid/external/floatingwindow/menu/content/RecordNavigatorContent.java +++ b/app/src/main/java/com/stardust/scriptdroid/external/floatingwindow/menu/content/RecordNavigatorContent.java @@ -85,9 +85,6 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat ButterKnife.bind(this, mView); HoverMenuService.getEventBus().register(this); AccessibilityService.getStickOnKeyObserver().addListener(mVolumeKeyListener); - if (Pref.isRecordVolumeControlEnable()) { - AutoJs.getInstance().ensureAccessibilityServiceEnabled(); - } if (Pref.hasRecordTrigger()) { mKeyObserver = new KeyObserver(mContext); mKeyObserver.startListening(); diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/common/ProgressDialog.java b/app/src/main/java/com/stardust/scriptdroid/ui/common/ProgressDialog.java index f7fe0413..4560fa33 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/common/ProgressDialog.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/common/ProgressDialog.java @@ -14,10 +14,14 @@ public class ProgressDialog { private MaterialDialog mDialog; public ProgressDialog(Context context) { + this(context, R.string.text_on_progress); + } + + public ProgressDialog(Context context, int resId) { mDialog = new MaterialDialog.Builder(context) .progress(true, 0) .cancelable(false) - .content(R.string.text_on_progress) + .content(resId) .show(); } diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/SideMenuFragment.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/SideMenuFragment.java index 99e5b3e3..5cf13a4c 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/SideMenuFragment.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/SideMenuFragment.java @@ -133,7 +133,12 @@ public class SideMenuFragment extends android.support.v4.app.Fragment { AccessibilityServiceTool.goToAccessibilitySetting(); return; } - final ProgressDialog progress = new ProgressDialog(getContext()); + enableAccessibilityServiceByRoot(); + + } + + private void enableAccessibilityServiceByRoot() { + final ProgressDialog progress = new ProgressDialog(getContext(), R.string.text_enable_accessibility_service_by_root_ing); UnderuseExecutors.execute(new Runnable() { @Override public void run() { @@ -156,6 +161,9 @@ public class SideMenuFragment extends android.support.v4.app.Fragment { void setFloatingWindowEnable(CompoundButton button, boolean enable) { if (enable && !HoverMenuManger.isHoverMenuShowing()) { HoverMenuManger.showHoverMenu(); + if (Pref.enableAccessibilityServiceByRoot()) { + enableAccessibilityServiceByRoot(); + } } else if (!enable && HoverMenuManger.isHoverMenuShowing()) { HoverMenuManger.hideHoverMenu(); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1925ef59..72cf7c56 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -212,6 +212,7 @@ 使用root权限开启失败 处理中 删除失败 + 正在使用root权限启用无障碍服务 diff --git a/autojs/src/main/assets/binary/root_automator b/autojs/src/main/assets/binary/root_automator new file mode 100644 index 00000000..341611a4 Binary files /dev/null and b/autojs/src/main/assets/binary/root_automator differ diff --git a/autojs/src/main/assets/javascript_engine_init.js b/autojs/src/main/assets/javascript_engine_init.js index fe447a35..2f1c8d5d 100644 --- a/autojs/src/main/assets/javascript_engine_init.js +++ b/autojs/src/main/assets/javascript_engine_init.js @@ -47,4 +47,4 @@ require("__general__")(__runtime__, this); __importClass__(android.view.KeyEvent); __importClass__(com.stardust.autojs.runtime.api.Shell); -__importClass__(com.stardust.autojs.runtime.api.InputEventSender); +__importClass__(com.stardust.autojs.runtime.api.RootAutomator); diff --git a/autojs/src/main/java/com/stardust/autojs/engine/preprocess/RootAutomatorEngine.java b/autojs/src/main/java/com/stardust/autojs/engine/preprocess/RootAutomatorEngine.java new file mode 100644 index 00000000..5d4ee3f2 --- /dev/null +++ b/autojs/src/main/java/com/stardust/autojs/engine/preprocess/RootAutomatorEngine.java @@ -0,0 +1,8 @@ +package com.stardust.autojs.engine.preprocess; + +/** + * Created by Stardust on 2017/8/1. + */ + +public class RootAutomatorEngine { +} diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/AccessibilityBridge.java b/autojs/src/main/java/com/stardust/autojs/runtime/AccessibilityBridge.java index 764efa6e..493602a8 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/AccessibilityBridge.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/AccessibilityBridge.java @@ -1,11 +1,13 @@ package com.stardust.autojs.runtime; import android.content.Context; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.view.accessibility.AccessibilityNodeInfo; import com.stardust.view.accessibility.AccessibilityInfoProvider; import com.stardust.view.accessibility.AccessibilityService; +import com.stardust.view.accessibility.NotificationListener; /** * Created by Stardust on 2017/4/2. @@ -37,6 +39,7 @@ public abstract class AccessibilityBridge { } + @NonNull public abstract AccessibilityInfoProvider getInfoProvider(); @@ -44,4 +47,6 @@ public abstract class AccessibilityBridge { mMode = mode; } + @NonNull + public abstract NotificationListener.Observer getNotificationObserver(); } 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 97356ab6..b88cc342 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,25 +1,24 @@ package com.stardust.autojs.runtime.api; +import android.app.Notification; import android.content.Context; import android.graphics.Point; import android.os.Handler; -import android.os.Looper; -import android.util.SparseArray; import android.view.KeyEvent; +import android.view.accessibility.AccessibilityEvent; import com.stardust.autojs.runtime.AccessibilityBridge; import com.stardust.autojs.runtime.ScriptException; import com.stardust.autojs.runtime.record.inputevent.TouchObserver; import com.stardust.view.accessibility.AccessibilityService; +import com.stardust.view.accessibility.NotificationListener; 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 { +public class Events extends EventEmitter implements OnKeyListener, TouchObserver.OnTouchEventListener, NotificationListener { private static final String PREFIX_KEY_DOWN = "__key_down__#"; private static final String PREFIX_KEY_UP = "__key_up__#"; @@ -32,6 +31,7 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver private boolean mListeningKey = false; private Loopers mLoopers; private Handler mHandler; + private boolean mListeningNotification = false; public Events(Context context, AccessibilityBridge accessibilityBridge, ScriptBridges bridges, Loopers loopers) { super(bridges); @@ -122,6 +122,25 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver } + public void observeNotification() { + if (mListeningNotification) + return; + mListeningNotification = true; + mAccessibilityBridge.getNotificationObserver() + .addListener(this); + } + + public Events onNotification(Object listener) { + on("notification", listener); + return this; + } + + public Events onToast(Object listener) { + on("toast", listener); + return this; + } + + public void recycle() { if (mListeningKey) { AccessibilityService service = mAccessibilityBridge.getService(); @@ -133,6 +152,9 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver if (mTouchObserver != null) { mTouchObserver.stop(); } + if (mListeningNotification) { + mAccessibilityBridge.getNotificationObserver().removeListener(this); + } } @Override @@ -169,4 +191,24 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver } + @Override + public void onNotification(final AccessibilityEvent event, final String[] notification) { + mHandler.post(new Runnable() { + @Override + public void run() { + emit("toast", new Object[]{notification}); + } + }); + } + + @Override + public void onNotification(final AccessibilityEvent event, final Notification notification) { + mHandler.post(new Runnable() { + @Override + public void run() { + emit("notification", notification); + } + }); + + } } diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/InputEventSender.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/InputEventSender.java deleted file mode 100644 index 7c60b680..00000000 --- a/autojs/src/main/java/com/stardust/autojs/runtime/api/InputEventSender.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.stardust.autojs.runtime.api; - -import com.stardust.util.ScreenMetrics; - -import java.io.BufferedOutputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; - -/** - * Created by Stardust on 2017/7/16. - */ - -public class InputEventSender { - private DataOutputStream mDeviceFile; - private ScreenMetrics mScreenMetrics; - - - public InputEventSender(String devicePath) throws FileNotFoundException { - mDeviceFile = new DataOutputStream(new FileOutputStream(devicePath)); - } - - public InputEventSender(int i) throws FileNotFoundException { - this("/dev/input/event" + i); - } - - public InputEventSender() { - - } - - - public void sendEvent(int type, int code, int value) throws IOException { - for (int i = 0; i < 16; i++) - mDeviceFile.writeByte(0); - mDeviceFile.writeShort(type); - mDeviceFile.writeShort(code); - mDeviceFile.writeInt(value); - mDeviceFile.flush(); - } - - - public void setInputDevice(int i) throws IOException { - if (mDeviceFile != null) { - mDeviceFile.close(); - } - mDeviceFile = new DataOutputStream(new FileOutputStream("/dev/input/event" + i)); - } - - public void Touch(int x, int y) throws IOException { - TouchX(x); - TouchY(y); - } - - public void setScreenMetrics(int width, int height) { - if (mScreenMetrics == null) { - mScreenMetrics = new ScreenMetrics(); - } - mScreenMetrics.setScreenMetrics(width, height); - } - - public void TouchX(int x) throws IOException { - sendEvent(3, 53, scaleX(x)); - } - - private int scaleX(int x) { - return mScreenMetrics.scaleX(x); - } - - public void TouchY(int y) throws IOException { - sendEvent(3, 54, scaleY(y)); - } - - private int scaleY(int y) { - return mScreenMetrics.scaleY(y); - - } - - - public void close() throws IOException { - mDeviceFile.close(); - } - -} - diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/RootAutomator.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/RootAutomator.java new file mode 100644 index 00000000..426f84d6 --- /dev/null +++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/RootAutomator.java @@ -0,0 +1,112 @@ +package com.stardust.autojs.runtime.api; + +import android.content.Context; + +import com.stardust.pio.PFile; +import com.stardust.pio.UncheckedIOException; +import com.stardust.util.ScreenMetrics; + +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +/** + * Created by Stardust on 2017/7/16. + */ + +public class RootAutomator { + + + private static final int DATA_TYPE_SLEEP = 0; + private static final int DATA_TYPE_EVENT = 1; + + private static final String ROOT_AUTOMATOR_EXECUTABLE_ASSET = "binary/root_automator"; + private DataOutputStream mTmpFileOutputStream; + private File mEventTmpFile; + private ScreenMetrics mScreenMetrics; + private String mDevicePath; + + public RootAutomator() { + try { + mEventTmpFile = File.createTempFile(String.valueOf(System.currentTimeMillis()), ".auto"); + mEventTmpFile.deleteOnExit(); + mTmpFileOutputStream = new DataOutputStream(new FileOutputStream(mEventTmpFile)); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + + public void sendEvent(int type, int code, int value) throws IOException { + mTmpFileOutputStream.writeByte(DATA_TYPE_EVENT); + mTmpFileOutputStream.writeShort(type); + mTmpFileOutputStream.writeShort(code); + mTmpFileOutputStream.writeInt(value); + } + + public void setInputDevice(int i) throws IOException { + mDevicePath = "/dev/input/event" + i; + } + + public void touch(int x, int y) throws IOException { + touchX(x); + touchY(y); + } + + public void setScreenMetrics(int width, int height) { + if (mScreenMetrics == null) { + mScreenMetrics = new ScreenMetrics(); + } + mScreenMetrics.setScreenMetrics(width, height); + } + + public void touchX(int x) throws IOException { + sendEvent(3, 53, scaleX(x)); + } + + private int scaleX(int x) { + return mScreenMetrics.scaleX(x); + } + + public void touchY(int y) throws IOException { + sendEvent(3, 54, scaleY(y)); + } + + public void sendSync() throws IOException { + sendEvent(0, 0, 0); + } + + private int scaleY(int y) { + return mScreenMetrics.scaleY(y); + + } + + public void sleep(int n) throws IOException { + mTmpFileOutputStream.writeByte(DATA_TYPE_SLEEP); + mTmpFileOutputStream.writeInt(n); + } + + public AbstractShell.Result writeToDevice(Context context) { + try { + mTmpFileOutputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + String executablePath = getExecutablePath(context); + return ProcessShell.execCommand(new String[]{ + "chmod 777 " + executablePath, + executablePath + " " + mEventTmpFile.getAbsolutePath() + " " + mDevicePath + }, true); + } + + public static String getExecutablePath(Context context) { + File tmp = new File(context.getCacheDir(), "root_automator"); + if (!tmp.exists()) { + PFile.copyAsset(context, ROOT_AUTOMATOR_EXECUTABLE_ASSET, tmp.getAbsolutePath()); + } + return tmp.getAbsolutePath(); + } + +} + diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/InputDevice.java b/autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/InputDevice.java new file mode 100644 index 00000000..6e9369f3 --- /dev/null +++ b/autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/InputDevice.java @@ -0,0 +1,8 @@ +package com.stardust.autojs.runtime.record.inputevent; + +/** + * Created by Stardust on 2017/8/1. + */ + +public class InputDevice { +} diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/InputEventToRootAutomatorConverter.java b/autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/InputEventToRootAutomatorConverter.java new file mode 100644 index 00000000..4aa0d032 --- /dev/null +++ b/autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/InputEventToRootAutomatorConverter.java @@ -0,0 +1,120 @@ +package com.stardust.autojs.runtime.record.inputevent; + +import android.support.annotation.NonNull; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static com.stardust.util.ScreenMetrics.getDeviceScreenHeight; +import static com.stardust.util.ScreenMetrics.getDeviceScreenWidth; + +/** + * Created by Stardust on 2017/8/1. + */ + +public class InputEventToRootAutomatorConverter extends InputEventConverter { + + + private double mLastEventTime; + private StringBuilder mCode = new StringBuilder(); + private int mTouchDevice = -1; + private int mLastTouchX = -1; + private int mLastTouchY = -1; + + public InputEventToRootAutomatorConverter() { + mCode.append("var ra = new RootAutomator();\n") + .append("ra.setScreenMetrics(").append(getDeviceScreenWidth()).append(", ") + .append(getDeviceScreenHeight()).append(");\n"); + } + + + @Override + public void convertEvent(@NonNull Event event) { + if (mLastEventTime == 0) { + mLastEventTime = event.time; + } else if (event.time - mLastEventTime > 0.005) { + mCode.append("ra.sleep(").append((long) (1000L * (event.time - mLastEventTime))).append(");\n"); + mLastEventTime = event.time; + } + 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) { + if (code == 53) { + onTouchX(device, value); + return; + } + if (code == 54) { + onTouchY(device, value); + return; + } + } + checkLastTouch(); + if (device != mTouchDevice) { + return; + } + if (type == 0 && code == 0 && value == 0) { + mCode.append("ra.sendSync();\n"); + return; + } + mCode.append("ra.sendEvent("); + mCode.append(type).append(", ") + .append(code).append(", ") + .append(value).append(");\n"); + } + + private void checkLastTouch() { + if (mLastTouchX >= 0) { + mCode.append("ra.touchX(").append(mLastTouchX).append(");\n"); + mLastTouchX = -1; + } + if (mLastTouchY >= 0) { + mCode.append("ra.touchY(").append(mLastTouchY).append(");\n"); + mLastTouchY = -1; + } + } + + private void onTouchX(int device, int value) { + if (mTouchDevice == -1) { + setTouchDevice(device); + } + mLastTouchX = value; + } + + private void onTouchY(int device, int value) { + if (mTouchDevice == -1) { + setTouchDevice(device); + } + if (mLastTouchX >= 0) { + mCode.append("ra.touch(") + .append(mLastTouchX).append(", ") + .append(value).append(");\n"); + mLastTouchX = -1; + } else { + mLastTouchY = value; + } + } + + private void setTouchDevice(int i) { + mCode.append("ra.setInputDevice(").append(i).append(");\n"); + mTouchDevice = i; + } + + @Override + public String getGetEventCommand() { + return "getevent -t"; + } + + public String getCode() { + return mCode.toString(); + } + + @Override + public void stop() { + super.stop(); + mCode.append("log(ra.writeToDevice(context));"); + } + + +} diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/TouchRecorder.java b/autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/TouchRecorder.java index d63d3d5b..92080228 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/TouchRecorder.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/TouchRecorder.java @@ -9,7 +9,7 @@ import android.content.Context; public class TouchRecorder extends InputEventRecorder { public TouchRecorder(Context context) { - super(context, new InputEventToSendEventJsConverter()); + super(context, new InputEventToRootAutomatorConverter()); listen(); } diff --git a/autojs/src/main/res/xml/accessibility_service_config.xml b/autojs/src/main/res/xml/accessibility_service_config.xml index 84c6464a..edab932f 100644 --- a/autojs/src/main/res/xml/accessibility_service_config.xml +++ b/autojs/src/main/res/xml/accessibility_service_config.xml @@ -1,7 +1,7 @@ EVENT_TYPES = Collections.singleton(AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED); + + private static final String TAG = "NotificationObserver"; + private static final String[] EMPTY = new String[0]; + + private Context mContext; + private CopyOnWriteArrayList mNotificationListeners = new CopyOnWriteArrayList<>(); + + public Observer(Context context) { + mContext = context; + } + + @Override + public void onNotification(AccessibilityEvent event, String[] notification) { + for (NotificationListener listener : mNotificationListeners) { + try { + listener.onNotification(event, notification); + } catch (Exception e) { + Log.e(TAG, "Error onNotification: " + Arrays.toString(notification) + " Listener: " + listener, e); + } + } + } + + @Override + public void onNotification(AccessibilityEvent event, Notification notification) { + for (NotificationListener listener : mNotificationListeners) { + try { + listener.onNotification(event, notification); + } catch (Exception e) { + Log.e(TAG, "Error onNotification: " + notification + " Listener: " + listener, e); + } + } + } + + public void addListener(NotificationListener listener) { + mNotificationListeners.add(listener); + } + + public boolean removeListener(NotificationListener listener) { + return mNotificationListeners.remove(listener); + } + + @Override + public boolean onAccessibilityEvent(AccessibilityService service, AccessibilityEvent event) { + if (event.getParcelableData() instanceof Notification) { + Notification notification = (Notification) event.getParcelableData(); + Log.d(TAG, "onNotification: " + notification + "; " + event); + onNotification(event, notification); + } else { + List list = event.getText(); + Log.d(TAG, "onNotification: " + list + "; " + event); + if (event.getPackageName().equals(mContext.getPackageName())) { + return false; + } + if (list != null) { + onNotification(event, ArrayUtils.toStringArray(list)); + } + } + return false; + } + + @Nullable + @Override + public Set getEventTypes() { + return EVENT_TYPES; + } + } +} diff --git a/common/src/main/java/com/stardust/util/ArrayUtils.java b/common/src/main/java/com/stardust/util/ArrayUtils.java index 2d7f7c59..2e48c01e 100644 --- a/common/src/main/java/com/stardust/util/ArrayUtils.java +++ b/common/src/main/java/com/stardust/util/ArrayUtils.java @@ -1,5 +1,7 @@ package com.stardust.util; +import java.util.List; + /** * Created by Stardust on 2017/5/8. */ @@ -23,4 +25,13 @@ public class ArrayUtils { } return unbox; } + + public static String[] toStringArray(List list) { + int i = 0; + String[] str = new String[list.size()]; + for (Object o : list) { + str[i] = o == null ? null : o.toString(); + } + return str; + } }