diff --git a/app-release-1.17.0305(1)内测.apk b/app-release-1.17.0305(1)内测.apk deleted file mode 100644 index 543956b6..00000000 Binary files a/app-release-1.17.0305(1)内测.apk and /dev/null differ diff --git a/app-release-1.17.0305内测.apk b/app-release-1.17.0305内测.apk deleted file mode 100644 index 8a8ffd55..00000000 Binary files a/app-release-1.17.0305内测.apk and /dev/null differ diff --git a/app-release-1.17.0306内测.apk b/app-release-1.17.0306内测.apk deleted file mode 100644 index 0ba1c2eb..00000000 Binary files a/app-release-1.17.0306内测.apk and /dev/null differ diff --git a/app-release-1.17.0226.apk b/app-release-1.17.0308内测.apk similarity index 51% rename from app-release-1.17.0226.apk rename to app-release-1.17.0308内测.apk index e0369f5a..717dc351 100644 Binary files a/app-release-1.17.0226.apk and b/app-release-1.17.0308内测.apk differ diff --git a/app/build.gradle b/app/build.gradle index 6fbc814b..c654a7db 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -7,12 +7,11 @@ android { applicationId "com.stardust.scriptdroid" minSdkVersion 19 targetSdkVersion 23 - versionCode 38 - versionName "1.17.0306内测" + versionCode 39 + versionName "1.17.0308内测" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" multiDexEnabled true - } buildTypes { release { @@ -65,7 +64,11 @@ dependencies { compile 'com.jraska:console:0.4.3' compile 'com.jraska:console-timber-tree:0.4.3' compile 'com.heinrichreimersoftware:android-issue-reporter:eae4c73cbeb91e98da83fe79a3dea088a8b97448' - compile group: 'org.mozilla', name: 'rhino', version: '1.7' + //compile 'com.github.jackpal.Android-Terminal-Emulator:emulatorview:v1.0.70' + //compile 'com.github.jackpal.Android-Terminal-Emulator:libtermexec:v1.0.70' + compile(name: 'libtermexec-release', ext: 'aar') + compile(name: 'emulatorview-release', ext: 'aar') + compile(name: 'term-debug', ext: 'aar') compile 'com.afollestad.material-dialogs:commons:0.9.2.3' compile 'com.makeramen:roundedimageview:2.2.1' diff --git a/app/libs/JSTransformer.jar b/app/libs/JSTransformer.jar deleted file mode 100644 index b154ed4c..00000000 Binary files a/app/libs/JSTransformer.jar and /dev/null differ diff --git a/app/libs/emulatorview-release.aar b/app/libs/emulatorview-release.aar new file mode 100644 index 00000000..13663844 Binary files /dev/null and b/app/libs/emulatorview-release.aar differ diff --git a/app/libs/libtermexec-release.aar b/app/libs/libtermexec-release.aar new file mode 100644 index 00000000..f49ae349 Binary files /dev/null and b/app/libs/libtermexec-release.aar differ diff --git a/app/libs/mutable-theme-debug.aar b/app/libs/mutable-theme-debug.aar deleted file mode 100644 index 1fb7af45..00000000 Binary files a/app/libs/mutable-theme-debug.aar and /dev/null differ diff --git a/app/libs/rhino-1.7.7.1.jar b/app/libs/rhino-1.7.7.1.jar new file mode 100644 index 00000000..a8b9417a Binary files /dev/null and b/app/libs/rhino-1.7.7.1.jar differ diff --git a/app/libs/term-debug.aar b/app/libs/term-debug.aar new file mode 100644 index 00000000..b32ad432 Binary files /dev/null and b/app/libs/term-debug.aar differ diff --git a/app/src/main/assets/javasccript_engine_init.js b/app/src/main/assets/javasccript_engine_init.js index 1773a277..287b1387 100644 --- a/app/src/main/assets/javasccript_engine_init.js +++ b/app/src/main/assets/javasccript_engine_init.js @@ -159,7 +159,10 @@ var Tap = function(x, y){ return shell("input tap " + x + " " + y, true).code == 1; } -var Swipe = function(x1, y1, x2, y2){ +var Swipe = function(x1, y1, x2, y2, duration){ + if(arguments.length == 5){ + return shell("input swipe " + x1 + " " + y1 + " " + x2 + " " + y2 + " " + duration, true).code == 1; + } return shell("input swipe " + x1 + " " + y1 + " " + x2 + " " + y2, true).code == 1; } @@ -219,6 +222,8 @@ var Text = function(text){ return shell("input text " + text, true).code == 1; } +__importClassOld__(com.stardust.scriptdroid.droid.runtime.Shell); + /* importClass("com.stardust.scriptdroid.service.AccessibilityDelegate"); diff --git a/app/src/main/assets/sample_simple_calculator.js b/app/src/main/assets/sample_simple_calculator.js index b480987a..81ff0a49 100644 --- a/app/src/main/assets/sample_simple_calculator.js +++ b/app/src/main/assets/sample_simple_calculator.js @@ -2,7 +2,7 @@ importClass("com.afollestad.materialdialogs.MaterialDialog"); -new ThemeColorMaterialDialogBuilder(activity) +new MaterialDialog.Builder(activity) .title("简单计算器") .input("请输入算式", "1+1", function(dialog, input){ eval("var ans = (" + input + ")"); diff --git a/app/src/main/java/com/stardust/scriptdroid/App.java b/app/src/main/java/com/stardust/scriptdroid/App.java index ed64a42b..9eec3d4b 100644 --- a/app/src/main/java/com/stardust/scriptdroid/App.java +++ b/app/src/main/java/com/stardust/scriptdroid/App.java @@ -15,9 +15,6 @@ import com.stardust.theme.ThemeColorManager; import com.stardust.util.CrashHandler; import com.stardust.util.StateObserver; -import org.mozilla.javascript.Context; -import org.mozilla.javascript.Scriptable; - import java.lang.ref.WeakReference; /** diff --git a/app/src/main/java/com/stardust/scriptdroid/droid/runtime/DroidRuntime.java b/app/src/main/java/com/stardust/scriptdroid/droid/runtime/DroidRuntime.java index b74b5a7e..aa1e15e3 100644 --- a/app/src/main/java/com/stardust/scriptdroid/droid/runtime/DroidRuntime.java +++ b/app/src/main/java/com/stardust/scriptdroid/droid/runtime/DroidRuntime.java @@ -25,7 +25,6 @@ import com.stardust.scriptdroid.droid.runtime.action.ActionFactory; import com.stardust.scriptdroid.droid.runtime.action.ActionPerformAccessibilityDelegate; import com.stardust.scriptdroid.droid.runtime.action.ActionTarget; import com.stardust.scriptdroid.droid.runtime.action.GetTextAction; -import com.stardust.scriptdroid.droid.runtime.api.IDroidRuntime; import com.stardust.scriptdroid.file.FileUtils; import com.stardust.scriptdroid.service.AccessibilityDelegate; import com.stardust.scriptdroid.service.AccessibilityWatchDogService; @@ -45,7 +44,7 @@ import timber.log.Timber; * Created by Stardust on 2017/1/27. */ -public class DroidRuntime implements IDroidRuntime { +public class DroidRuntime { private static final String TAG = "DroidRuntime"; private static DroidRuntime runtime = new DroidRuntime(); @@ -61,18 +60,15 @@ public class DroidRuntime implements IDroidRuntime { mUIHandler = new Handler(App.getApp().getMainLooper()); } - @Override public void launchPackage(String packageName) { PackageManager packageManager = App.getApp().getPackageManager(); App.getApp().startActivity(packageManager.getLaunchIntentForPackage(packageName)); } - @Override public void launch(String packageName, String className) { App.getApp().startActivity(new Intent().setClassName(packageName, className).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); } - @Override public void launchApp(String appName) { PackageManager packageManager = App.getApp().getPackageManager(); List installedApplications = packageManager.getInstalledApplications(PackageManager.GET_META_DATA); @@ -84,22 +80,18 @@ public class DroidRuntime implements IDroidRuntime { } } - @Override public String[] getPackageName(String appName) { return new String[0]; } - @Override public ActionTarget text(String text, int i) { return new ActionTarget.TextActionTarget(text, i); } - @Override public ActionTarget bounds(int left, int top, int right, int bottom) { return new ActionTarget.BoundsActionTarget(new Rect(left, top, right, bottom)); } - @Override public ActionTarget editable(int i) { return new ActionTarget.EditableActionTarget(i); } @@ -108,32 +100,26 @@ public class DroidRuntime implements IDroidRuntime { return new ActionTarget.IdActionTarget(id); } - @Override public boolean click(ActionTarget target) { return performAction(target.createAction(AccessibilityNodeInfo.ACTION_CLICK)); } - @Override public boolean longClick(ActionTarget target) { return performAction(target.createAction(AccessibilityNodeInfo.ACTION_LONG_CLICK)); } - @Override public boolean scrollUp(ActionTarget target) { return performAction(target.createAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD)); } - @Override public boolean scrollDown(ActionTarget target) { return performAction(target.createAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD)); } - @Override public boolean scrollUp(int i) { return performAction(ActionFactory.createScrollAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD, i)); } - @Override public boolean scrollDown(int i) { return performAction(ActionFactory.createScrollAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD, i)); } @@ -146,17 +132,14 @@ public class DroidRuntime implements IDroidRuntime { return performAction(ActionFactory.createScrollMaxAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD)); } - @Override public boolean focus(ActionTarget target) { return performAction(target.createAction(AccessibilityNodeInfo.ACTION_FOCUS)); } - @Override public boolean select(ActionTarget target) { return performAction(target.createAction(AccessibilityNodeInfo.ACTION_SELECT)); } - @Override public boolean setText(ActionTarget target, String text) { return performAction(target.createAction(AccessibilityNodeInfo.ACTION_SET_TEXT, text)); } @@ -170,7 +153,6 @@ public class DroidRuntime implements IDroidRuntime { }); } - @Override public boolean paste(ActionTarget target) { return performAction(target.createAction(AccessibilityNodeInfo.ACTION_PASTE)); } @@ -230,7 +212,6 @@ public class DroidRuntime implements IDroidRuntime { return performAction(new GetTextAction()); } - @Override public void toast(final String text) { mUIHandler.post(new Runnable() { @Override @@ -240,7 +221,6 @@ public class DroidRuntime implements IDroidRuntime { }); } - @Override public void sleep(long millis) { try { Thread.sleep(millis); @@ -275,12 +255,10 @@ public class DroidRuntime implements IDroidRuntime { return ActionPerformAccessibilityDelegate.getLatestActivity(); } - @Override public boolean isStopped() { return Thread.currentThread().isInterrupted(); } - @Override public void stop() { Thread.interrupted(); } @@ -289,7 +267,6 @@ public class DroidRuntime implements IDroidRuntime { return FileUtils.readString(new File(Environment.getExternalStorageDirectory() + "/" + path)); } - @Override public ThemeColorMaterialDialogBuilder dialog() { if (App.currentActivity() == null) { Toast.makeText(App.getApp(), R.string.text_cannot_create_dialog_when_app_invisible, Toast.LENGTH_SHORT).show(); diff --git a/app/src/main/java/com/stardust/scriptdroid/droid/runtime/Shell.java b/app/src/main/java/com/stardust/scriptdroid/droid/runtime/Shell.java new file mode 100644 index 00000000..3e7bf331 --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/droid/runtime/Shell.java @@ -0,0 +1,85 @@ +package com.stardust.scriptdroid.droid.runtime; + +/** + * Created by Stardust on 2017/3/7. + */ + +public class Shell extends com.stardust.scriptdroid.tool.Shell { + + public Shell(boolean root) { + super(root); + } + + public void Tap(int x, int y) { + execute("input tap " + x + " " + y); + } + + public void Swipe(int x1, int y1, int x2, int y2) { + execute("input swipe " + x1 + " " + y1 + " " + x2 + " " + y2); + } + + public void Swipe(int x1, int y1, int x2, int y2, long duration) { + execute("input swipe " + x1 + " " + y1 + " " + x2 + " " + y2 + " " + duration); + } + + public void KeyCode(int keyCode) { + execute("input keyevent " + keyCode); + } + + public void KeyCode(String keyCode) { + execute("input keyevent " + keyCode); + } + + public void Home() { + KeyCode(3); + } + + public void Back() { + KeyCode(4); + } + + public void Power() { + KeyCode(26); + } + + public void Up() { + KeyCode(19); + } + + public void Down() { + KeyCode(20); + } + + public void Left() { + KeyCode(21); + } + + public void Right() { + KeyCode(22); + } + + public void OK() { + KeyCode(23); + } + + public void VolumeUp() { + KeyCode(24); + } + + public void VolumeDown() { + KeyCode(25); + } + + public void Menu() { + KeyCode(1); + } + + public void Camera() { + KeyCode(27); + } + + public void Text(String text) { + execute("input text " + text); + } + +} diff --git a/app/src/main/java/com/stardust/scriptdroid/droid/runtime/api/IDroidRuntime.java b/app/src/main/java/com/stardust/scriptdroid/droid/runtime/api/IDroidRuntime.java deleted file mode 100644 index 27a9934f..00000000 --- a/app/src/main/java/com/stardust/scriptdroid/droid/runtime/api/IDroidRuntime.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.stardust.scriptdroid.droid.runtime.api; - -import com.afollestad.materialdialogs.MaterialDialog; -import com.stardust.scriptdroid.droid.runtime.action.ActionTarget; -import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder; - -/** - * Created by Stardust on 2017/1/27. - */ -public interface IDroidRuntime { - - void launchPackage(String packageName); - - void launch(String packageName, String className); - - void launchApp(String appName); - - String[] getPackageName(String appName); - - ActionTarget text(String text, int i); - - ActionTarget bounds(int left, int top, int right, int bottom); - - ActionTarget editable(int i); - - boolean click(ActionTarget target); - - boolean longClick(ActionTarget target); - - boolean scrollUp(ActionTarget target); - - boolean scrollDown(ActionTarget target); - - boolean scrollUp(int i); - - boolean scrollDown(int i); - - boolean focus(ActionTarget target); - - boolean select(ActionTarget target); - - boolean setText(ActionTarget target, String text); - - boolean paste(ActionTarget target); - - void toast(String text); - - void sleep(long millis); - - boolean isStopped(); - - void stop(); - - ThemeColorMaterialDialogBuilder dialog(); -} diff --git a/app/src/main/java/com/stardust/scriptdroid/droid/script/DuktapeJavaScriptEngine.java b/app/src/main/java/com/stardust/scriptdroid/droid/script/DuktapeJavaScriptEngine.java index c158e974..e6ccdd6b 100644 --- a/app/src/main/java/com/stardust/scriptdroid/droid/script/DuktapeJavaScriptEngine.java +++ b/app/src/main/java/com/stardust/scriptdroid/droid/script/DuktapeJavaScriptEngine.java @@ -1,19 +1,5 @@ package com.stardust.scriptdroid.droid.script; -import com.efurture.script.JSTransformer; -import com.stardust.scriptdroid.App; -import com.stardust.scriptdroid.droid.Droid; -import com.stardust.scriptdroid.droid.runtime.api.IDroidRuntime; - -import java.io.IOException; -import java.io.StringReader; -import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; - /** * Created by Stardust on 2017/1/27. */ diff --git a/app/src/main/java/com/stardust/scriptdroid/droid/script/JavaScriptEngine.java b/app/src/main/java/com/stardust/scriptdroid/droid/script/JavaScriptEngine.java index 9b95602e..242ac11d 100644 --- a/app/src/main/java/com/stardust/scriptdroid/droid/script/JavaScriptEngine.java +++ b/app/src/main/java/com/stardust/scriptdroid/droid/script/JavaScriptEngine.java @@ -2,8 +2,9 @@ package com.stardust.scriptdroid.droid.script; import com.stardust.scriptdroid.App; import com.stardust.scriptdroid.BuildConfig; -import com.stardust.scriptdroid.droid.script.file.AssetScript; +import com.stardust.scriptdroid.file.FileUtils; +import java.io.IOException; import java.util.HashMap; import java.util.Map; @@ -15,10 +16,6 @@ public abstract class JavaScriptEngine { Map mVariableMap = new HashMap<>(); - protected String preprocess(String script) { - return script; - } - public abstract Object execute(String script); public void set(String varName, Object value) { @@ -33,11 +30,17 @@ public abstract class JavaScriptEngine { private static final String INIT_SCRIPT = readInitScript(); private static String readInitScript() { - return AssetScript.read(App.getApp(), "javasccript_engine_init.js"); + try { + return FileUtils.readString(App.getApp().getAssets().open("javasccript_engine_init.js")); + } catch (IOException e) { + e.printStackTrace(); + return "Error: Unable to read init script."; + } } static String getInitScript() { if (BuildConfig.DEBUG) { + // 调试时不缓存INIT_SCRIPT否则修改javasccript_engine_init.js后不会更新 return readInitScript(); } else { return INIT_SCRIPT; diff --git a/app/src/main/java/com/stardust/scriptdroid/droid/script/RhinoJavaScriptEngine.java b/app/src/main/java/com/stardust/scriptdroid/droid/script/RhinoJavaScriptEngine.java index 7274bdf2..a3e19887 100644 --- a/app/src/main/java/com/stardust/scriptdroid/droid/script/RhinoJavaScriptEngine.java +++ b/app/src/main/java/com/stardust/scriptdroid/droid/script/RhinoJavaScriptEngine.java @@ -2,8 +2,8 @@ package com.stardust.scriptdroid.droid.script; import com.stardust.scriptdroid.App; import com.stardust.scriptdroid.droid.Droid; +import com.stardust.scriptdroid.droid.runtime.DroidRuntime; import com.stardust.scriptdroid.droid.runtime.ScriptStopException; -import com.stardust.scriptdroid.droid.runtime.api.IDroidRuntime; import org.mozilla.javascript.Context; import org.mozilla.javascript.ContextFactory; @@ -27,7 +27,7 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine { private final Set mThreads = new HashSet<>(); - public RhinoJavaScriptEngine(IDroidRuntime runtime) { + public RhinoJavaScriptEngine(DroidRuntime runtime) { set("droid", runtime); } diff --git a/app/src/main/java/com/stardust/scriptdroid/droid/script/file/AssetScript.java b/app/src/main/java/com/stardust/scriptdroid/droid/script/file/AssetScript.java deleted file mode 100644 index 2e63dd65..00000000 --- a/app/src/main/java/com/stardust/scriptdroid/droid/script/file/AssetScript.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.stardust.scriptdroid.droid.script.file; - -import android.content.Context; -import android.util.Log; - -import com.efurture.script.JSTransformer; - -import java.io.BufferedInputStream; -import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; -import java.io.FileInputStream; -import java.io.InputStream; -import java.io.InputStreamReader; - -public class AssetScript { - - - - public static String read(Context context, String fileName){ - try { - InputStream is = context.getAssets().open(fileName); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - - BufferedInputStream bufferIn = new BufferedInputStream(is); - byte[] buffer = new byte[2048]; - int length = 0; - while ((length = bufferIn.read(buffer)) >= 0){ - output.write(buffer, 0, length); - } - String script = output.toString(); - Log.e("compiled ScriptEngine", script); - return script; - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - public static String toScript(Context context, String fileName){ - try { - InputStream is = context.getAssets().open(fileName); - BufferedReader br = new BufferedReader(new InputStreamReader(is)); - String script = JSTransformer.parse(br); - Log.e("ScriptEngine", script); - return script; - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - - public static String toScript(String fileName){ - try { - InputStream is = new FileInputStream(fileName); - BufferedReader br = new BufferedReader(new InputStreamReader(is)); - String script = JSTransformer.parse(br); - Log.e("ScriptEngine", script); - return script; - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - - public static String toScript(InputStream is){ - try { - BufferedReader br = new BufferedReader(new InputStreamReader(is)); - String script = JSTransformer.parse(br); - Log.e("ScriptEngine", script); - return script; - } catch (Exception e) { - throw new RuntimeException(e); - } - } -} diff --git a/app/src/main/java/com/stardust/scriptdroid/record/inputevent/EventFormatException.java b/app/src/main/java/com/stardust/scriptdroid/record/inputevent/EventFormatException.java new file mode 100644 index 00000000..e6e8c15e --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/record/inputevent/EventFormatException.java @@ -0,0 +1,25 @@ +package com.stardust.scriptdroid.record.inputevent; + +/** + * Created by Stardust on 2017/3/7. + */ + +public class EventFormatException extends RuntimeException { + + + public static EventFormatException forEventStr(String eventStr, NumberFormatException e) { + return new EventFormatException(eventStr, e); + } + + public EventFormatException(Exception e) { + super(e); + } + + public EventFormatException(String eventStr, Exception e) { + super("eventStr=" + eventStr, e); + } + + public EventFormatException(String eventStr) { + super("eventStr=" + eventStr); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/stardust/scriptdroid/record/inputevent/InputEventConverter.java b/app/src/main/java/com/stardust/scriptdroid/record/inputevent/InputEventConverter.java new file mode 100644 index 00000000..c685b354 --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/record/inputevent/InputEventConverter.java @@ -0,0 +1,110 @@ +package com.stardust.scriptdroid.record.inputevent; + +import android.support.annotation.NonNull; + +import com.stardust.scriptdroid.App; +import com.stardust.scriptdroid.R; +import com.stardust.scriptdroid.droid.runtime.DroidRuntime; +import com.stardust.scriptdroid.ui.main.MainActivity; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Created by Stardust on 2017/3/7. + */ + +public abstract class InputEventConverter { + + + static class Event { + + static final Pattern PATTERN = Pattern.compile("^\\[([^\\]]*)\\]\\s+([^:]*):\\s+([^\\s]*)\\s+([^\\s]*)\\s+([^\\s]*)\\s*$"); + + static Event parseEvent(String eventStr) { + Matcher matcher = Event.PATTERN.matcher(eventStr); + if (!matcher.matches()) { + throw new EventFormatException(eventStr); + } + double time; + try { + time = Double.parseDouble(matcher.group(1)); + } catch (NumberFormatException e) { + throw new EventFormatException(eventStr, e); + } + return new Event(time, matcher.group(2), matcher.group(3), matcher.group(4), matcher.group(5)); + } + + + double time; + String device; + String type; + String code; + String value; + + public Event(double time, String device, String type, String code, String value) { + this.time = time; + this.device = device; + this.type = type; + this.code = code; + this.value = value; + } + + + @Override + public String toString() { + return "Event{" + + "time=" + time + + ", device='" + device + '\'' + + ", type='" + type + '\'' + + ", code='" + code + '\'' + + ", value='" + value + '\'' + + '}'; + } + } + + + protected boolean mStarted = false; + + public void parseAndAddEventIfFormatCorrect(String eventStr) { + Event event = parseEventOrNull(eventStr); + if (event != null) { + addEvent(event); + } + } + + public abstract void addEvent(@NonNull Event event); + + + public void start() { + mStarted = true; + } + + public void pause() { + mStarted = false; + } + + public void stop() { + mStarted = false; + } + + public abstract String getCode(); + + public Event parseEventOrNull(String eventStr) { + try { + return Event.parseEvent(eventStr); + } catch (EventFormatException e) { + e.printStackTrace(); + return null; + } + } + + public void notifyRecordStopped() { + MainActivity.onRootRecordStopped(App.getApp()); + } + + public void notifyRecordStarted() { + DroidRuntime.getRuntime().toast(App.getApp().getString(R.string.text_start_record)); + } + +} diff --git a/app/src/main/java/com/stardust/scriptdroid/record/inputevent/InputEventRecorder.java b/app/src/main/java/com/stardust/scriptdroid/record/inputevent/InputEventRecorder.java new file mode 100644 index 00000000..4b265b8e --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/record/inputevent/InputEventRecorder.java @@ -0,0 +1,116 @@ +package com.stardust.scriptdroid.record.inputevent; + +import android.preference.PreferenceManager; +import android.text.TextUtils; +import android.util.Pair; + +import com.stardust.scriptdroid.App; +import com.stardust.scriptdroid.tool.Shell; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import jackpal.androidterm.ShellTermSession; +import jackpal.androidterm.emulatorview.TermSession; +import jackpal.androidterm.util.TermSettings; + +/** + * Created by Stardust on 2017/3/6. + */ + +public abstract class InputEventRecorder { + + private Thread mRecordThread; + private TermSession mTermSession; + private String mGetEventCommand; + protected InputEventConverter mInputEventConverter; + + protected InputEventRecorder(String getEventCommand, InputEventConverter inputEventConverter) { + mGetEventCommand = getEventCommand; + mInputEventConverter = inputEventConverter; + } + + public void listen() { + TermSettings settings = new TermSettings(App.getApp().getResources(), PreferenceManager.getDefaultSharedPreferences(App.getApp())); + try { + mTermSession = new ShellTermSession(settings, "su\r") { + boolean enter = false; + + @Override + protected void processInput(byte[] data, int offset, int count) { + String[] lines = new String(data, offset, count).split("\n"); + for (String line : lines) { + System.out.println(line); + if (!enter && line.endsWith("data # ")) { + mTermSession.write(mGetEventCommand + "\r"); + enter = true; + } else if (enter) { + parseAndRecordEvent(line); + } + } + appendToEmulator(data, offset, count); + } + }; + mTermSession.initializeEmulator(80, 40); + mTermSession.write("su\r"); + mRecordThread = new Thread(new Runnable() { + @Override + public void run() { + try { + //readOutput(mTermSession); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + mRecordThread.start(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + } + + public void start() { + mInputEventConverter.start(); + } + + public void pause() { + mInputEventConverter.pause(); + } + + private void readOutput(TermSession shell) { + boolean enter = false; + String line; + try { + BufferedReader succeedReader = new BufferedReader(new InputStreamReader(mTermSession.getTermIn())); + while ((line = succeedReader.readLine()) != null) { + System.out.println(line); + if (!enter && line.endsWith("data # ")) { + mTermSession.write(mGetEventCommand + "\r"); + enter = true; + } else if (enter) { + parseAndRecordEvent(line); + } + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected abstract void parseAndRecordEvent(String eventStr); + + public abstract String getCode(); + + public void stop() { + mRecordThread.interrupt(); + mTermSession.finish(); + mInputEventConverter.stop(); + } + +} diff --git a/app/src/main/java/com/stardust/scriptdroid/record/inputevent/InputEventToJsConverter.java b/app/src/main/java/com/stardust/scriptdroid/record/inputevent/InputEventToJsConverter.java new file mode 100644 index 00000000..48ac9f3e --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/record/inputevent/InputEventToJsConverter.java @@ -0,0 +1,171 @@ +package com.stardust.scriptdroid.record.inputevent; + +import android.support.annotation.NonNull; + +import com.stardust.scriptdroid.droid.runtime.DroidRuntime; +import com.stardust.util.MapEntries; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by Stardust on 2017/3/7. + */ + +public class InputEventToJsConverter extends InputEventConverter { + + + interface EventHandler { + void handle(Event event); + } + + abstract static class Router implements EventHandler { + + private Map mEventHandlerMap = new HashMap<>(); + + EventHandler getHandler(String key) { + return mEventHandlerMap.get(key); + } + + Router put(String key, EventHandler handler) { + mEventHandlerMap.put(key, handler); + return this; + } + + @Override + public void handle(Event event) { + EventHandler handler = mEventHandlerMap.get(getKey(event)); + if (handler != null) { + handler.handle(event); + } + } + + protected abstract String getKey(Event event); + } + + private class TypeRouter extends Router { + + TypeRouter() { + put("EV_ABS", new AbsHandler()); + put("EV_SYN", new SyncHandler()); + put("EV_KEY", new KeyHandler()); + } + + @Override + protected String getKey(Event event) { + return event.type; + } + } + + private static class Point { + int x, y; + } + + private class AbsHandler implements EventHandler { + + @Override + public void handle(Event event) { + if (event.code.equals("ABS_MT_POSITION_X")) { + mTouchPoint.x = Integer.parseInt(event.value, 16); + mTouchTime = event.time; + } else if (event.code.equals("ABS_MT_POSITION_Y")) { + mTouchPoint.y = Integer.parseInt(event.value, 16); + mTouchTime = event.time; + } + } + } + + private class SyncHandler implements EventHandler { + + @Override + public void handle(Event event) { + if (mTouchDown) { + if (mSwipe) { + appendCodeIfNotStopped(event); + mSwipe = false; + } else { + mLastTouchPoint.x = mTouchPoint.x; + mLastTouchPoint.y = mTouchPoint.y; + mSwipe = true; + } + } + } + + private void appendCodeIfNotStopped(Event event) { + if (!mStarted) + return; + long interval = (long) (1000 * (event.time - mTouchTime)); + mCode.append("sh.Swipe(") + .append(mLastTouchPoint.x).append(", ").append(mLastTouchPoint.y).append(", ") + .append(mTouchPoint.x).append(", ").append(mTouchPoint.y); + if (interval >= 1) { + mCode.append(", ").append(interval); + } + mCode.append(");\n"); + } + } + + private class KeyHandler implements EventHandler { + + private Map mKeyPressCodeMap = new MapEntries<>(new HashMap()) + .entry("KEY_HOME", "Home") + .entry("KEY_MENU", "Menu") + .entry("KEY_VOLUMEDOWN", "VolumeDown") + .entry("KEY_VOLUMEUP", "VolumeUp") + .entry("KEY_BACK", "Back") + .map(); + + @Override + public void handle(Event event) { + if (event.code.equals("BTN_TOUCH")) { + mTouchDown = event.value.equals("DOWN"); + if (!mTouchDown && mSwipe) { + if (mStarted) + mCode.append("sh.Tap(").append(mLastTouchPoint.x).append(", ").append(mLastTouchPoint.y).append(");\n"); + mSwipe = false; + } + } else if (event.value.equals("UP")) { + if (!mStarted && event.code.equals("KEY_VOLUMEUP")) { + mStarted = true; + notifyRecordStarted(); + } else if (mStarted && event.code.equals("KEY_VOLUMEDOWN")) { + mStarted = false; + notifyRecordStopped(); + } else { + appendKeyPressCode(event); + } + } + } + + private void appendKeyPressCode(Event event) { + String code = mKeyPressCodeMap.get(event.code); + if (code != null) { + mCode.append("sh.").append(code).append("();\n"); + } + } + } + + private EventHandler mEventHandler = new TypeRouter(); + private StringBuilder mCode = new StringBuilder().append("var sh = new Shell(true);\n"); + private Point mTouchPoint = new Point(), mLastTouchPoint = new Point(); + private boolean mTouchDown = false, mSwipe = false; + private double mTouchTime; + + + @Override + public void addEvent(@NonNull Event event) { + mEventHandler.handle(event); + } + + @Override + public void stop() { + super.stop(); + mCode.append("sh.exitAndWaitFor();"); + } + + public String getCode() { + return mCode.toString(); + } + + +} diff --git a/app/src/main/java/com/stardust/scriptdroid/record/inputevent/InputEventToJsRecorder.java b/app/src/main/java/com/stardust/scriptdroid/record/inputevent/InputEventToJsRecorder.java new file mode 100644 index 00000000..edfd6887 --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/record/inputevent/InputEventToJsRecorder.java @@ -0,0 +1,23 @@ +package com.stardust.scriptdroid.record.inputevent; + +/** + * Created by Stardust on 2017/3/7. + */ + +public class InputEventToJsRecorder extends InputEventRecorder { + + + public InputEventToJsRecorder() { + super("getevent -t -l", new InputEventToJsConverter()); + } + + @Override + protected void parseAndRecordEvent(String eventStr) { + mInputEventConverter.parseAndAddEventIfFormatCorrect(eventStr); + } + + @Override + public String getCode() { + return mInputEventConverter.getCode(); + } +} diff --git a/app/src/main/java/com/stardust/scriptdroid/record/inputevent/InputEventToSendEventConverter.java b/app/src/main/java/com/stardust/scriptdroid/record/inputevent/InputEventToSendEventConverter.java new file mode 100644 index 00000000..39fec2bd --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/record/inputevent/InputEventToSendEventConverter.java @@ -0,0 +1,49 @@ +package com.stardust.scriptdroid.record.inputevent; + +import android.support.annotation.NonNull; + +import java.text.DecimalFormat; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + +/** + * Created by Stardust on 2017/3/7. + */ + +public class InputEventToSendEventConverter extends InputEventConverter { + + private static final DecimalFormat DELAY_FORMAT = new DecimalFormat("#.###"); + + private double mLastEventTime; + private StringBuilder mSendEventCommands = new StringBuilder(); + + @Override + public void addEvent(@NonNull Event event) { + if (mLastEventTime == 0) { + mLastEventTime = event.time; + } else if (event.time - mLastEventTime > 0.1) { + mSendEventCommands.append("sleep ").append(DELAY_FORMAT.format(event.time - mLastEventTime)).append("\n"); + mLastEventTime = event.time; + } + mSendEventCommands.append("sendevent ") + .append(event.device).append(" ") + .append(hex2dec(event.type)).append(" ") + .append(hex2dec(event.code)).append(" ") + .append(hex2dec(event.value)).append("\n"); + + } + + public String getCode() { + return mSendEventCommands.toString(); + } + + private static String hex2dec(String hex) { + try { + return String.valueOf((int) Long.parseLong(hex, 16)); + } catch (NumberFormatException e) { + throw new EventFormatException(e); + } + } + +} diff --git a/app/src/main/java/com/stardust/scriptdroid/record/inputevent/InputEventToSendEventRecorder.java b/app/src/main/java/com/stardust/scriptdroid/record/inputevent/InputEventToSendEventRecorder.java new file mode 100644 index 00000000..1810f741 --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/record/inputevent/InputEventToSendEventRecorder.java @@ -0,0 +1,26 @@ +package com.stardust.scriptdroid.record.inputevent; + +/** + * Created by Stardust on 2017/3/7. + */ + +public class InputEventToSendEventRecorder extends InputEventRecorder { + + private InputEventToSendEventConverter mEventConverter; + + protected InputEventToSendEventRecorder() { + super("getevent -t", new InputEventToSendEventConverter()); + } + + + @Override + protected void parseAndRecordEvent(String eventStr) { + mEventConverter.parseAndAddEventIfFormatCorrect(eventStr); + } + + @Override + public String getCode() { + return mEventConverter.getCode(); + } + +} diff --git a/app/src/main/java/com/stardust/scriptdroid/record/root/InputEventConverter.java b/app/src/main/java/com/stardust/scriptdroid/record/root/InputEventConverter.java deleted file mode 100644 index f960ee13..00000000 --- a/app/src/main/java/com/stardust/scriptdroid/record/root/InputEventConverter.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.stardust.scriptdroid.record.root; - -import android.text.TextUtils; -import android.util.Pair; - -import com.jecelyin.common.utils.StringUtils; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Created by Stardust on 2017/3/6. - */ - -public class InputEventConverter { - - public static Pair convert(String line) { - int j = line.indexOf(']'); - double time = 0; - if (j > 0) { - time = Double.parseDouble(line.substring(1, j)); - line = line.substring(j + 2); - } - String[] str = line.split(" ", 4); - for (int i = 1; i < 4; i++) { - str[i] = hex2dec(str[i]); - } - str[0] = str[0].substring(0, str[0].length() - 1); - return new Pair<>(time, "sendevent " + TextUtils.join(" ", str)); - } - - private static String hex2dec(String hex) { - return String.valueOf((int) Long.parseLong(hex, 16)); - } - - private static class SingleEvent { - - private static final Pattern PATTERN = Pattern.compile("^\\[([^\\]]*)\\]\\s+([^:]*):\\s+([^\\s]*)\\s+([^\\s]*)\\s+([^\\s]*)$"); - - double time; - String device; - String type; - String code; - String value; - - - SingleEvent(String str) { - Matcher matcher = PATTERN.matcher(str); - matcher.matches(); - time = Double.parseDouble(matcher.group(1)); - device = matcher.group(2); - type = matcher.group(3); - code = matcher.group(4); - value = matcher.group(5); - } - - @Override - public String toString() { - return "SingleEvent{" + - "time=" + time + - ", device='" + device + '\'' + - ", type='" + type + '\'' + - ", code='" + code + '\'' + - ", value='" + value + '\'' + - '}'; - } - } - - public String convertToCode(String events) { - BufferedReader reader = new BufferedReader(new StringReader(events)); - String line; - StringBuilder code = new StringBuilder(); - try { - EventConverter converter = null; - while ((line = reader.readLine()) != null) { - SingleEvent event = new SingleEvent(line); - if (event.value.equals("DOWN") && event.type.equals("BIN_TOUCH")) { - converter = new EventConverter(); - } else if (event.value.equals("UP") && event.type.equals("BIN_TOUCH")) { - code.append(converter.toString()); - converter = null; - } else if (converter != null) { - - } - } - } catch (IOException e) { - e.printStackTrace(); - } - return code.toString(); - } - - public static class EventConverter { - - List mSingleEvents = new ArrayList<>(); - - public void add(SingleEvent event) { - if (event.type.equals("ABS_MT_POSITION_X") || event.type.equals("ABS_MT_POSITION_Y")) { - - } - } - - } - - -} diff --git a/app/src/main/java/com/stardust/scriptdroid/record/root/InputEventRecorder.java b/app/src/main/java/com/stardust/scriptdroid/record/root/InputEventRecorder.java deleted file mode 100644 index 5a8d41fd..00000000 --- a/app/src/main/java/com/stardust/scriptdroid/record/root/InputEventRecorder.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.stardust.scriptdroid.record.root; - -import android.util.Pair; - -import com.stardust.scriptdroid.tool.Shell; - -import java.io.BufferedReader; -import java.io.CharArrayWriter; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.text.DecimalFormat; - -/** - * Created by Stardust on 2017/3/6. - */ - -public class InputEventRecorder { - - private Thread mRecordThread; - private Shell mShell; - - public void record() { - mShell = new Shell(true); - mRecordThread = new Thread(new Runnable() { - @Override - public void run() { - try { - mShell.execute("getevent -t"); - readOutput(mShell); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - mRecordThread.start(); - } - - private void readOutput(Shell shell) { - String line; - try { - BufferedReader succeedReader = shell.getSucceedReader(); - StringBuilder succeedOutput = shell.getSucceedOutput(); - double time = 0; - DecimalFormat df = new DecimalFormat("#.###"); - while ((line = succeedReader.readLine()) != null) { - if (line.startsWith("[")) { - Pair c = InputEventConverter.convert(line); - if (time == 0) { - time = c.first; - } else if (c.first - time > 0.1f) { - succeedOutput.append("sleep ").append(df.format(c.first - time)).append("\n"); - time = c.first; - } - succeedOutput.append(c.second).append("\n"); - } - } - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - public String stop() { - mRecordThread.interrupt(); - mShell.destroy(); - return mShell.getSucceedOutput().toString(); - } - - -} diff --git a/app/src/main/java/com/stardust/scriptdroid/tool/Shell.java b/app/src/main/java/com/stardust/scriptdroid/tool/Shell.java index 4e8124af..0e0efddb 100644 --- a/app/src/main/java/com/stardust/scriptdroid/tool/Shell.java +++ b/app/src/main/java/com/stardust/scriptdroid/tool/Shell.java @@ -1,14 +1,29 @@ package com.stardust.scriptdroid.tool; +import android.app.Activity; +import android.content.res.AssetFileDescriptor; +import android.os.ParcelFileDescriptor; +import android.preference.PreferenceManager; import android.util.Log; -import com.stardust.scriptdroid.record.root.InputEventConverter; +import com.stardust.scriptdroid.App; +import com.stericson.RootShell.RootShell; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; +import java.io.File; import java.io.IOException; import java.io.InputStreamReader; +import jackpal.androidterm.ShellTermSession; +import jackpal.androidterm.Term; +import jackpal.androidterm.emulatorview.TermSession; +import jackpal.androidterm.util.TermSettings; + /** * Created by Stardust on 2017/1/20. *

@@ -33,13 +48,56 @@ public class Shell { private StringBuilder mSucceedOutput = new StringBuilder(); private StringBuilder mErrorOutput = new StringBuilder(); + public static String bytesToString(byte[] data, int base, int length) { + StringBuilder buf = new StringBuilder(); + + for(int i = 0; i < length; ++i) { + byte b = data[base + i]; + if(b >= 32 && b <= 126) { + buf.append((char)b); + } else { + buf.append(String.format("\\x%02x", new Object[]{Byte.valueOf(b)})); + } + } + + return buf.toString(); + } + + + public static void test(final Activity activity) { + TermSettings settings = new TermSettings(App.getApp().getResources(), PreferenceManager.getDefaultSharedPreferences(App.getApp())); + try { + final ShellTermSession termSession = new ShellTermSession(settings, ""); + termSession.initializeEmulator(80, 40); + termSession.write("su\r"); + termSession.write("getevent\r"); + new Thread(new Runnable() { + @Override + public void run() { + BufferedReader reader = new BufferedReader(new InputStreamReader(termSession.getTermIn())); + try { + while (reader.ready()){ + String line = reader.readLine(); + System.out.println(line); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + }).start(); + } catch (IOException e) { + e.printStackTrace(); + } + + } + public Shell() { this(false); } public Shell(boolean root) { try { - mProcess = Runtime.getRuntime().exec(root ? COMMAND_SU : COMMAND_SH); + mProcess = new ProcessBuilder(root ? COMMAND_SU : COMMAND_SH).redirectErrorStream(true).start(); mCommandOutputStream = new DataOutputStream(mProcess.getOutputStream()); mSucceedReader = new BufferedReader(new InputStreamReader(mProcess.getInputStream())); mErrorReader = new BufferedReader(new InputStreamReader(mProcess.getErrorStream())); @@ -49,6 +107,7 @@ public class Shell { } public Shell execute(String command) { + try { mCommandOutputStream.writeBytes(command); if (!command.endsWith(COMMAND_LINE_END)) { @@ -76,9 +135,9 @@ public class Shell { } public Shell readSucceedOutput() { - String line; try { - while ((line = mSucceedReader.readLine()) != null) { + while (mSucceedReader.ready()) { + String line = mSucceedReader.readLine(); mSucceedOutput.append(line).append("\n"); } } catch (IOException e) { @@ -129,6 +188,14 @@ public class Shell { return mErrorReader; } + public int waitFor() { + try { + return mProcess.waitFor(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + /** * Command执行结果 * diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/MainActivity.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/MainActivity.java index 02ee2eef..f97d455e 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/MainActivity.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/MainActivity.java @@ -29,20 +29,25 @@ import com.afollestad.materialdialogs.MaterialDialog; import com.afollestad.materialdialogs.folderselector.FileChooserDialog; import com.stardust.app.NotRemindAgainDialog; import com.stardust.app.OnActivityResultDelegate; +import com.stardust.scriptdroid.App; import com.stardust.scriptdroid.BuildConfig; import com.stardust.scriptdroid.Pref; import com.stardust.scriptdroid.R; +import com.stardust.scriptdroid.droid.runtime.DroidRuntime; import com.stardust.scriptdroid.droid.script.file.ScriptFile; import com.stardust.scriptdroid.droid.script.file.ScriptFileList; import com.stardust.scriptdroid.droid.script.file.SharedPrefScriptFileList; import com.stardust.scriptdroid.external.notification.record.ActionRecordSwitchNotification; import com.stardust.scriptdroid.file.FileUtils; import com.stardust.scriptdroid.file.SampleFileManager; -import com.stardust.scriptdroid.record.root.InputEventRecorder; +import com.stardust.scriptdroid.record.inputevent.InputEventRecorder; +import com.stardust.scriptdroid.record.inputevent.InputEventToJsConverter; +import com.stardust.scriptdroid.record.inputevent.InputEventToJsRecorder; import com.stardust.scriptdroid.service.AccessibilityWatchDogService; import com.stardust.scriptdroid.tool.AccessibilityServiceTool; import com.stardust.scriptdroid.tool.BackPressedHandler; import com.stardust.scriptdroid.tool.ImageSelector; +import com.stardust.scriptdroid.tool.Shell; import com.stardust.scriptdroid.ui.BaseActivity; import com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation; import com.stardust.scriptdroid.ui.settings.SettingsActivity; @@ -64,6 +69,7 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File public static final String ACTION_NOTIFY_SCRIPT_LIST_CHANGE = "ACTION_NOTIFY_SCRIPT_LIST_CHANGE"; private static final String ACTION_ON_ACTION_RECORD_STOPPED = "ACTION_ON_ACTION_RECORD_STOPPED"; private static final String ARGUMENT_SCRIPT = "ARGUMENT_SCRIPT"; + private static final String ACTION_ON_ROOT_RECORD_STOPPED = "ACTION_ON_ROOT_RECORD_STOPPED"; private SlidingUpPanel mAddFilePanel; private ScriptListRecyclerView mScriptListRecyclerView; @@ -79,6 +85,7 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File checkPermissions(); registerReceivers(); handleIntent(getIntent()); + //Shell.test(this); } private void registerReceivers() { @@ -226,6 +233,17 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File Snackbar.make(mDrawerLayout, R.string.hint_start_record, Snackbar.LENGTH_SHORT).show(); } + private InputEventRecorder mInputEventRecorder; + + @ViewBinding.Click(R.id.root_record) + private void startRootRecord() { + if (mInputEventRecorder == null) { + mInputEventRecorder = new InputEventToJsRecorder(); + mInputEventRecorder.listen(); + } + Snackbar.make(mDrawerLayout, R.string.hint_start_root_record, Snackbar.LENGTH_SHORT).show(); + } + @ViewBinding.Click(R.id.setting) private void startSettingActivity() { startActivity(new Intent(this, SettingsActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); @@ -275,6 +293,13 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File case ACTION_ON_ACTION_RECORD_STOPPED: handleRecordedScript(intent.getStringExtra(ARGUMENT_SCRIPT)); break; + case ACTION_ON_ROOT_RECORD_STOPPED: + if (mInputEventRecorder != null) { + mInputEventRecorder.stop(); + handleRecordedScript(mInputEventRecorder.getCode()); + mInputEventRecorder = null; + } + break; } } @@ -294,6 +319,14 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File } } }) + .negativeText(R.string.text_cancel) + .onNegative(new MaterialDialog.SingleButtonCallback() { + @Override + public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) { + dialog.dismiss(); + } + }) + .canceledOnTouchOutside(false) .show(); } @@ -331,6 +364,14 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File } + public static void onRootRecordStopped(Context context) { + Intent intent = new Intent(context, MainActivity.class) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + .putExtra(EXTRA_ACTION, ACTION_ON_ROOT_RECORD_STOPPED); + context.startActivity(intent); + } + + private class Receiver extends BroadcastReceiver { @Override diff --git a/app/src/main/jniLibs/armeabi/libjackpal-androidterm5.so b/app/src/main/jniLibs/armeabi/libjackpal-androidterm5.so new file mode 100644 index 00000000..8abd6b57 Binary files /dev/null and b/app/src/main/jniLibs/armeabi/libjackpal-androidterm5.so differ diff --git a/app/src/main/jniLibs/armeabi/libjackpal-termexec2.so b/app/src/main/jniLibs/armeabi/libjackpal-termexec2.so new file mode 100644 index 00000000..a413d87f Binary files /dev/null and b/app/src/main/jniLibs/armeabi/libjackpal-termexec2.so differ diff --git a/app/src/main/jniLibs/mips/libjackpal-androidterm5.so b/app/src/main/jniLibs/mips/libjackpal-androidterm5.so new file mode 100644 index 00000000..93fd25a7 Binary files /dev/null and b/app/src/main/jniLibs/mips/libjackpal-androidterm5.so differ diff --git a/app/src/main/jniLibs/mips/libjackpal-termexec2.so b/app/src/main/jniLibs/mips/libjackpal-termexec2.so new file mode 100644 index 00000000..ae9d250d Binary files /dev/null and b/app/src/main/jniLibs/mips/libjackpal-termexec2.so differ diff --git a/app/src/main/jniLibs/x86/libjackpal-androidterm5.so b/app/src/main/jniLibs/x86/libjackpal-androidterm5.so new file mode 100644 index 00000000..2d19d7a6 Binary files /dev/null and b/app/src/main/jniLibs/x86/libjackpal-androidterm5.so differ diff --git a/app/src/main/jniLibs/x86/libjackpal-termexec2.so b/app/src/main/jniLibs/x86/libjackpal-termexec2.so new file mode 100644 index 00000000..0139a261 Binary files /dev/null and b/app/src/main/jniLibs/x86/libjackpal-termexec2.so differ diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index aa38005d..6e8ad470 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -133,6 +133,31 @@ + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1ede0659..0d178ac8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -135,4 +135,6 @@ 主题色 选择图片 帮助 + 录制脚本(root) + 使用音量上键,音量下键结束录制 diff --git a/app/src/test/java/com/stardust/scriptdroid/ExampleUnitTest.java b/app/src/test/java/com/stardust/scriptdroid/ExampleUnitTest.java index 6f51a0fc..baa43816 100644 --- a/app/src/test/java/com/stardust/scriptdroid/ExampleUnitTest.java +++ b/app/src/test/java/com/stardust/scriptdroid/ExampleUnitTest.java @@ -1,28 +1,9 @@ package com.stardust.scriptdroid; -import android.text.TextUtils; -import android.util.Pair; +import com.stardust.scriptdroid.record.inputevent.InputEventToJsConverter; +import com.stardust.scriptdroid.record.inputevent.InputEventToSendEventConverter; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import com.stardust.scriptdroid.record.root.InputEventConverter; -import com.stardust.scriptdroid.ui.help.HelpCatalogueActivity; - -import org.json.JSONObject; import org.junit.Test; -import org.mozilla.javascript.Context; -import org.mozilla.javascript.ContextFactory; -import org.mozilla.javascript.ImporterTopLevel; -import org.mozilla.javascript.Scriptable; - -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** * Example local unit test, which will execute on the development machine (host). @@ -38,6 +19,8 @@ public class ExampleUnitTest { @Test public void test() { - System.out.println(new SingleEvent("[ 109722.085815] /dev/input/event1: EV_SYN SYN_REPORT 00000000")); + InputEventToJsConverter converter = new InputEventToJsConverter(); + converter.parseAndAddEventIfFormatCorrect("[ 140123.672100] /dev/input/event3: EV_ABS ABS_MT_POSITION_X 0000005f"); + System.out.println(converter.getCode()); } } \ No newline at end of file