refactor(module autojs): to support .auto record file

This commit is contained in:
hyb1996
2017-08-03 13:06:55 +08:00
parent 6a3392cfe6
commit 2f5573d9c2
58 changed files with 981 additions and 753 deletions

View File

@@ -9,8 +9,8 @@ android {
applicationId "com.stardust.scriptdroid" applicationId "com.stardust.scriptdroid"
minSdkVersion 17 minSdkVersion 17
targetSdkVersion 23 targetSdkVersion 23
versionCode 156 versionCode 157
versionName "2.0.15 Alpha4" versionName "2.0.16 Alpha"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true multiDexEnabled true
ndk { ndk {

View File

@@ -2,7 +2,7 @@ package com.stardust.scriptdroid.statics;
import android.support.test.InstrumentationRegistry; import android.support.test.InstrumentationRegistry;
import com.stardust.autojs.script.FileScriptSource; import com.stardust.autojs.script.JavaScriptFileSource;
import com.stardust.autojs.script.ScriptSource; import com.stardust.autojs.script.ScriptSource;
import com.stardust.autojs.script.StringScriptSource; import com.stardust.autojs.script.StringScriptSource;
import com.stardust.util.MapEntries; import com.stardust.util.MapEntries;
@@ -46,7 +46,7 @@ public class SQLiteStaticsStorageTest {
public void testTwoRecord() { public void testTwoRecord() {
mStorage.clear(); mStorage.clear();
mStorage.record(new StringScriptSource("Name", "Script")); mStorage.record(new StringScriptSource("Name", "Script"));
mStorage.record(new FileScriptSource("/test/test.js")); mStorage.record(new JavaScriptFileSource("/test/test.js"));
assertEquals(mStorage.getAll(), new MapEntries<String, String>() assertEquals(mStorage.getAll(), new MapEntries<String, String>()
.entry("Name.js", "1") .entry("Name.js", "1")
.entry("/test/test.js", "1") .entry("/test/test.js", "1")
@@ -56,10 +56,10 @@ public class SQLiteStaticsStorageTest {
@Test @Test
public void testRepeatedRecord() { public void testRepeatedRecord() {
mStorage.clear(); mStorage.clear();
mStorage.record(new FileScriptSource("/test/test.js")); mStorage.record(new JavaScriptFileSource("/test/test.js"));
mStorage.record(new StringScriptSource("Name", "Script")); mStorage.record(new StringScriptSource("Name", "Script"));
mStorage.record(new FileScriptSource("/test/test.js")); mStorage.record(new JavaScriptFileSource("/test/test.js"));
mStorage.record(new FileScriptSource("/test/test.js")); mStorage.record(new JavaScriptFileSource("/test/test.js"));
assertEquals(mStorage.getAll(), new MapEntries<String, String>() assertEquals(mStorage.getAll(), new MapEntries<String, String>()
.entry("Name.js", "1") .entry("Name.js", "1")
.entry("/test/test.js", "3") .entry("/test/test.js", "3")
@@ -70,7 +70,7 @@ public class SQLiteStaticsStorageTest {
@Test @Test
public void getMax() throws Exception { public void getMax() throws Exception {
mStorage.clear(); mStorage.clear();
put(new FileScriptSource("/test/test.js"), 50); put(new JavaScriptFileSource("/test/test.js"), 50);
put(new StringScriptSource("Name4", "Script"), 10); put(new StringScriptSource("Name4", "Script"), 10);
put(new StringScriptSource("Name5", "Script"), 5); put(new StringScriptSource("Name5", "Script"), 5);
put(new StringScriptSource("Name6", "Script"), 4); put(new StringScriptSource("Name6", "Script"), 4);

View File

@@ -19,7 +19,7 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:name=".App" android:name=".App"
android:allowBackup="false" android:allowBackup="false"
android:icon="@drawable/ic_android_eat_js" android:icon="@drawable/autojs_material"
android:label="@string/_app_name" android:label="@string/_app_name"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme" android:theme="@style/AppTheme"

View File

@@ -1,7 +1,6 @@
package com.stardust.scriptdroid.autojs; package com.stardust.scriptdroid.autojs;
import android.app.Activity; import android.app.Activity;
import android.app.Notification;
import android.content.Context; import android.content.Context;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
@@ -12,7 +11,10 @@ import com.stardust.app.OnActivityResultDelegate;
import com.stardust.app.SimpleActivityLifecycleCallbacks; import com.stardust.app.SimpleActivityLifecycleCallbacks;
import com.stardust.autojs.ScriptEngineService; import com.stardust.autojs.ScriptEngineService;
import com.stardust.autojs.ScriptEngineServiceBuilder; import com.stardust.autojs.ScriptEngineServiceBuilder;
import com.stardust.autojs.engine.RhinoJavaScriptEngineManager; import com.stardust.autojs.engine.LoopBasedJavaScriptEngine;
import com.stardust.autojs.engine.RhinoJavaScriptEngine;
import com.stardust.autojs.engine.RootAutomatorEngine;
import com.stardust.autojs.engine.ScriptEngine;
import com.stardust.autojs.engine.ScriptEngineManager; import com.stardust.autojs.engine.ScriptEngineManager;
import com.stardust.autojs.runtime.AccessibilityBridge; import com.stardust.autojs.runtime.AccessibilityBridge;
import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.autojs.runtime.ScriptRuntime;
@@ -21,6 +23,8 @@ 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.image.ScreenCaptureRequester; import com.stardust.autojs.runtime.api.image.ScreenCaptureRequester;
import com.stardust.autojs.script.AutoFileSource;
import com.stardust.autojs.script.JavaScriptSource;
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;
@@ -58,6 +62,7 @@ public class AutoJs {
private final AccessibilityActionRecorder mAccessibilityActionRecorder = new AccessibilityActionRecorder(); private final AccessibilityActionRecorder mAccessibilityActionRecorder = new AccessibilityActionRecorder();
private final NotificationListener.Observer mNotificationObserver; private final NotificationListener.Observer mNotificationObserver;
private ScriptEngineManager mScriptEngineManager;
private final LayoutInspector mLayoutInspector = new LayoutInspector(); private final LayoutInspector mLayoutInspector = new LayoutInspector();
private final Context mContext; private final Context mContext;
private final UiHandler mUiHandler; private final UiHandler mUiHandler;
@@ -65,12 +70,14 @@ public class AutoJs {
private final AccessibilityInfoProvider mAccessibilityInfoProvider; private final AccessibilityInfoProvider mAccessibilityInfoProvider;
private final ScreenCaptureRequester mScreenCaptureRequester = new ScreenCaptureRequesterImpl(); private final ScreenCaptureRequester mScreenCaptureRequester = new ScreenCaptureRequesterImpl();
private final ScriptEngineService mScriptEngineService; private final ScriptEngineService mScriptEngineService;
private final Console mGlobalConsole;
private AutoJs(final Context context) { private AutoJs(final Context context) {
mContext = context; mContext = context;
mUiHandler = new UiHandler(context); mUiHandler = new UiHandler(context);
mAppUtils = new AppUtils(context); mAppUtils = new AppUtils(context);
mGlobalConsole = new JraskaConsole();
mNotificationObserver = new NotificationListener.Observer(context); mNotificationObserver = new NotificationListener.Observer(context);
mAccessibilityInfoProvider = new AccessibilityInfoProvider(context.getPackageManager()); mAccessibilityInfoProvider = new AccessibilityInfoProvider(context.getPackageManager());
mScriptEngineService = buildScriptEngineService(); mScriptEngineService = buildScriptEngineService();
@@ -80,33 +87,44 @@ public class AutoJs {
} }
private ScriptEngineService buildScriptEngineService() { private ScriptEngineService buildScriptEngineService() {
ScriptEngineManager manager = createScriptEngineManager(mContext); initScriptEngineManager();
final Console globalConsole = new JraskaConsole();
return new ScriptEngineServiceBuilder() return new ScriptEngineServiceBuilder()
.uiHandler(mUiHandler) .uiHandler(mUiHandler)
.globalConsole(globalConsole) .globalConsole(mGlobalConsole)
.engineManger(manager) .engineManger(mScriptEngineManager)
.runtime(new Supplier<com.stardust.autojs.runtime.ScriptRuntime>() {
@Override
public com.stardust.autojs.runtime.ScriptRuntime get() {
return new ScriptRuntime.Builder()
.setConsole(new StardustConsole(mUiHandler, globalConsole))
.setScreenCaptureRequester(mScreenCaptureRequester)
.setAccessibilityBridge(new AccessibilityBridgeImpl())
.setUiHandler(mUiHandler)
.setAppUtils(mAppUtils)
.setShellSupplier(new Supplier<AbstractShell>() {
@Override
public AbstractShell get() {
return new Shell(mContext, true);
}
}).build();
}
})
.build(); .build();
} }
private void initScriptEngineManager() {
mScriptEngineManager = new ScriptEngineManager(mContext);
mScriptEngineManager.registerEngine(JavaScriptSource.ENGINE, new Supplier<ScriptEngine>() {
@Override
public ScriptEngine get() {
LoopBasedJavaScriptEngine engine = new LoopBasedJavaScriptEngine(mContext);
engine.setRuntime(new ScriptRuntime.Builder()
.setConsole(new StardustConsole(mUiHandler, mGlobalConsole))
.setScreenCaptureRequester(mScreenCaptureRequester)
.setAccessibilityBridge(new AccessibilityBridgeImpl())
.setUiHandler(mUiHandler)
.setAppUtils(mAppUtils)
.setShellSupplier(new Supplier<AbstractShell>() {
@Override
public AbstractShell get() {
return new Shell(mContext, true);
}
}).build());
return engine;
}
});
mScriptEngineManager.registerEngine(AutoFileSource.ENGINE, new Supplier<ScriptEngine>() {
@Override
public ScriptEngine get() {
return new RootAutomatorEngine(mContext);
}
});
}
private void registerActivityLifecycleCallbacks() { private void registerActivityLifecycleCallbacks() {
App.getApp().registerActivityLifecycleCallbacks(new SimpleActivityLifecycleCallbacks() { App.getApp().registerActivityLifecycleCallbacks(new SimpleActivityLifecycleCallbacks() {
@@ -128,10 +146,6 @@ public class AutoJs {
}); });
} }
private ScriptEngineManager createScriptEngineManager(Context context) {
return new RhinoJavaScriptEngineManager(context);
}
private void addAccessibilityServiceDelegates() { private void addAccessibilityServiceDelegates() {
AccessibilityService.addDelegate(100, mAccessibilityInfoProvider); AccessibilityService.addDelegate(100, mAccessibilityInfoProvider);
AccessibilityService.addDelegate(200, mNotificationObserver); AccessibilityService.addDelegate(200, mNotificationObserver);

View File

@@ -1,5 +1,6 @@
package com.stardust.scriptdroid.autojs; package com.stardust.scriptdroid.autojs;
import com.stardust.autojs.engine.JavaScriptEngine;
import com.stardust.autojs.execution.ScriptExecution; import com.stardust.autojs.execution.ScriptExecution;
import com.stardust.autojs.execution.ScriptExecutionListener; import com.stardust.autojs.execution.ScriptExecutionListener;
import com.stardust.scriptdroid.App; import com.stardust.scriptdroid.App;
@@ -29,7 +30,8 @@ public class ScriptExecutionGlobalListener implements ScriptExecutionListener {
if (millis == null) if (millis == null)
return; return;
double seconds = (System.currentTimeMillis() - millis) / 1000.0; double seconds = (System.currentTimeMillis() - millis) / 1000.0;
execution.getRuntime().console.verbose(App.getApp().getString(R.string.text_execution_finished), execution.getSource().toString(), seconds); AutoJs.getInstance().getScriptEngineService().getGlobalConsole()
.verbose(App.getApp().getString(R.string.text_execution_finished), execution.getSource().toString(), seconds);
} }
@Override @Override

View File

@@ -3,9 +3,8 @@ package com.stardust.scriptdroid.external;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.widget.Toast;
import com.stardust.autojs.script.FileScriptSource; import com.stardust.autojs.script.JavaScriptFileSource;
import com.stardust.autojs.script.ScriptSource; import com.stardust.autojs.script.ScriptSource;
import com.stardust.autojs.script.SequenceScriptSource; import com.stardust.autojs.script.SequenceScriptSource;
import com.stardust.autojs.script.StringScriptSource; import com.stardust.autojs.script.StringScriptSource;
@@ -36,7 +35,7 @@ public class CommonUtils {
if (path == null && script != null) { if (path == null && script != null) {
source = new StringScriptSource(script); source = new StringScriptSource(script);
} else if (path != null && new PathChecker(context).checkAndToastError(path)) { } else if (path != null && new PathChecker(context).checkAndToastError(path)) {
ScriptSource fileScriptSource = new FileScriptSource(path); JavaScriptFileSource fileScriptSource = new JavaScriptFileSource(path);
if (script != null) { if (script != null) {
source = new SequenceScriptSource(fileScriptSource.getName(), new StringScriptSource(script), fileScriptSource); source = new SequenceScriptSource(fileScriptSource.getName(), new StringScriptSource(script), fileScriptSource);
} else { } else {

View File

@@ -159,9 +159,10 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
mStopRecord.setVisibility(state == Recorder.STATE_STOPPED ? View.GONE : View.VISIBLE); mStopRecord.setVisibility(state == Recorder.STATE_STOPPED ? View.GONE : View.VISIBLE);
mDiscardRecord.setVisibility(state == Recorder.STATE_STOPPED ? View.GONE : View.VISIBLE); mDiscardRecord.setVisibility(state == Recorder.STATE_STOPPED ? View.GONE : View.VISIBLE);
mStartOrPauseRecordIcon.setImageResource(state == Recorder.STATE_RECORDING ? R.drawable.ic_pause_white_24dp : R.drawable.ic_play_arrow_white_48dp); mStartOrPauseRecordIcon.setImageResource(state == Recorder.STATE_RECORDING ? R.drawable.ic_pause_white_24dp : R.drawable.ic_play_arrow_white_48dp);
//我知道这样写代码会被打 但我懒... mStartOrPauseRecordText.setText(
mStartOrPauseRecordText.setText(state == Recorder.STATE_RECORDING ? R.string.text_pause_record : state == Recorder.STATE_RECORDING ? R.string.text_pause_record :
state == Recorder.STATE_PAUSED ? R.string.text_resume_record : R.string.text_start_record); state == Recorder.STATE_PAUSED ? R.string.text_resume_record :
R.string.text_start_record);
} }
@@ -206,7 +207,11 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
@Override @Override
public void onStop() { public void onStop() {
if (!mDiscard) { if (!mDiscard) {
MainActivity.onRecordStop(mContext, mRecorder.getCode()); if (mRecorder instanceof TouchRecorder) {
MainActivity.importScriptFile(mContext, mRecorder.getCode());
} else {
MainActivity.onRecordStop(mContext, mRecorder.getCode());
}
} }
mRecorder = null; mRecorder = null;
} }

View File

@@ -1,21 +1,12 @@
package com.stardust.scriptdroid.external.open; package com.stardust.scriptdroid.external.open;
import android.app.Activity; import android.app.Activity;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.widget.Toast; import android.widget.Toast;
import com.stardust.scriptdroid.script.PathChecker;
import com.stardust.autojs.script.FileScriptSource;
import com.stardust.autojs.script.SequenceScriptSource;
import com.stardust.autojs.script.ScriptSource;
import com.stardust.autojs.script.StringScriptSource;
import com.stardust.scriptdroid.external.CommonUtils; import com.stardust.scriptdroid.external.CommonUtils;
import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.script.Scripts;
import java.io.File;
/** /**
* Created by Stardust on 2017/2/22. * Created by Stardust on 2017/2/22.

View File

@@ -4,9 +4,7 @@ import android.app.Activity;
import android.os.Bundle; import android.os.Bundle;
import android.widget.Toast; import android.widget.Toast;
import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.scriptdroid.script.PathChecker; import com.stardust.scriptdroid.script.PathChecker;
import com.stardust.autojs.script.FileScriptSource;
import com.stardust.scriptdroid.external.CommonUtils; import com.stardust.scriptdroid.external.CommonUtils;
import com.stardust.scriptdroid.script.ScriptFile; import com.stardust.scriptdroid.script.ScriptFile;
import com.stardust.scriptdroid.script.Scripts; import com.stardust.scriptdroid.script.Scripts;

View File

@@ -1,7 +1,11 @@
package com.stardust.scriptdroid.script; package com.stardust.scriptdroid.script;
import android.os.Environment; import android.os.Environment;
import android.renderscript.Script;
import com.stardust.autojs.script.AutoFileSource;
import com.stardust.autojs.script.JavaScriptFileSource;
import com.stardust.autojs.script.ScriptSource;
import com.stardust.pio.PFile; import com.stardust.pio.PFile;
import java.io.File; import java.io.File;
@@ -15,9 +19,16 @@ import java.util.ArrayList;
public class ScriptFile extends File { public class ScriptFile extends File {
public static final int TYPE_UNKNOWN = 0;
public static final int TYPE_AUTO = 1;
public static final int TYPE_JAVA_SCRIPT = 2;
private int mType = -1;
private String mSimplifyPath; private String mSimplifyPath;
private String mSimplifiedName; private String mSimplifiedName;
public ScriptFile(String path) { public ScriptFile(String path) {
super(path); super(path);
init(); init();
@@ -51,6 +62,15 @@ public class ScriptFile extends File {
return mSimplifyPath; return mSimplifyPath;
} }
public int getType() {
if (mType == -1) {
mType = getName().endsWith(".js") ? TYPE_JAVA_SCRIPT :
getName().endsWith(".auto") ? TYPE_AUTO :
TYPE_UNKNOWN;
}
return mType;
}
@Override @Override
public ScriptFile getParentFile() { public ScriptFile getParentFile() {
String p = this.getParent(); String p = this.getParent();
@@ -64,7 +84,8 @@ public class ScriptFile extends File {
return listFiles(new FileFilter() { return listFiles(new FileFilter() {
@Override @Override
public boolean accept(File file) { public boolean accept(File file) {
return (file.isDirectory() || file.getName().endsWith(".js")) && !file.getName().startsWith("."); return (file.getName().endsWith(".js") || file.getName().endsWith(".auto") ||
file.isDirectory()) && !file.getName().startsWith(".");
} }
}); });
} }
@@ -101,4 +122,12 @@ public class ScriptFile extends File {
public boolean moveTo(ScriptFile to) { public boolean moveTo(ScriptFile to) {
return renameTo(new File(to, getName())); return renameTo(new File(to, getName()));
} }
public ScriptSource toSource(){
if(getType() == TYPE_JAVA_SCRIPT){
return new JavaScriptFileSource(this);
}else {
return new AutoFileSource(this);
}
}
} }

View File

@@ -2,7 +2,6 @@ package com.stardust.scriptdroid.script;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri; import android.net.Uri;
import com.stardust.autojs.execution.ExecutionConfig; import com.stardust.autojs.execution.ExecutionConfig;
@@ -10,12 +9,10 @@ import com.stardust.autojs.execution.ScriptExecution;
import com.stardust.autojs.execution.ScriptExecutionListener; import com.stardust.autojs.execution.ScriptExecutionListener;
import com.stardust.autojs.execution.SimpleScriptExecutionListener; import com.stardust.autojs.execution.SimpleScriptExecutionListener;
import com.stardust.autojs.runtime.ScriptInterruptedException; import com.stardust.autojs.runtime.ScriptInterruptedException;
import com.stardust.autojs.script.FileScriptSource; import com.stardust.autojs.script.JavaScriptFileSource;
import com.stardust.autojs.script.ScriptSource; import com.stardust.autojs.script.ScriptSource;
import com.stardust.autojs.script.SequenceScriptSource;
import com.stardust.autojs.script.StringScriptSource; import com.stardust.autojs.script.StringScriptSource;
import com.stardust.scriptdroid.App; import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.BuildConfig;
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.CommonUtils; import com.stardust.scriptdroid.external.CommonUtils;
@@ -27,8 +24,6 @@ import com.stardust.util.AssetsCache;
import java.io.File; import java.io.File;
import javax.xml.parsers.DocumentBuilderFactory;
/** /**
* Created by Stardust on 2017/5/3. * Created by Stardust on 2017/5/3.
*/ */
@@ -85,7 +80,7 @@ public class Scripts {
} }
public static ScriptExecution run(ScriptFile file) { public static ScriptExecution run(ScriptFile file) {
return run(new FileScriptSource(file), file.getParent()); return run(file.toSource(), file.getParent());
} }
public static ScriptExecution run(ScriptSource source, String directoryPath) { public static ScriptExecution run(ScriptSource source, String directoryPath) {
@@ -114,7 +109,7 @@ public class Scripts {
} }
public static ScriptExecution runRepeatedly(ScriptFile scriptFile, int loopTimes, long delay, long interval) { public static ScriptExecution runRepeatedly(ScriptFile scriptFile, int loopTimes, long delay, long interval) {
ScriptSource source = new FileScriptSource(scriptFile); ScriptSource source = new JavaScriptFileSource(scriptFile);
String directoryPath = scriptFile.getParent(); String directoryPath = scriptFile.getParent();
return AutoJs.getInstance().getScriptEngineService().execute(source, new ExecutionConfig() return AutoJs.getInstance().getScriptEngineService().execute(source, new ExecutionConfig()
.requirePath(directoryPath, StorageScriptProvider.DEFAULT_DIRECTORY_PATH) .requirePath(directoryPath, StorageScriptProvider.DEFAULT_DIRECTORY_PATH)

View File

@@ -2,6 +2,7 @@ package com.stardust.scriptdroid.ui.common;
import android.app.Activity; import android.app.Activity;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
import android.support.v4.widget.DrawerLayout; import android.support.v4.widget.DrawerLayout;
import android.text.InputType; import android.text.InputType;
@@ -64,11 +65,11 @@ public class ScriptOperations {
} }
public void newScriptFileForScript(final String script) { public void newScriptFileForScript(final String script) {
showFileNameInputDialog("") showFileNameInputDialog("", "js")
.subscribe(new Consumer<String>() { .subscribe(new Consumer<String>() {
@Override @Override
public void accept(@io.reactivex.annotations.NonNull String input) throws Exception { public void accept(@io.reactivex.annotations.NonNull String input) throws Exception {
createScriptFile(getCurrentDirectoryPath() + input + ".js", script); createScriptFile(getCurrentDirectoryPath() + input + ".js", script, false);
} }
}); });
} }
@@ -81,7 +82,7 @@ public class ScriptOperations {
return mCurrentDirectory; return mCurrentDirectory;
} }
public void createScriptFile(String path, String script) { public void createScriptFile(String path, String script, boolean edit) {
if (PFile.createIfNotExists(path)) { if (PFile.createIfNotExists(path)) {
if (script != null) { if (script != null) {
try { try {
@@ -91,7 +92,8 @@ public class ScriptOperations {
} }
} }
notifyScriptFileChanged(); notifyScriptFileChanged();
Scripts.edit(path); if (edit)
Scripts.edit(path);
} else { } else {
Snackbar.make(mView, R.string.text_create_fail, Snackbar.LENGTH_LONG).show(); Snackbar.make(mView, R.string.text_create_fail, Snackbar.LENGTH_LONG).show();
} }
@@ -102,16 +104,25 @@ public class ScriptOperations {
} }
public Observable<String> importFile(final String pathFrom) { public Observable<String> importFile(final String pathFrom) {
try { return showFileNameInputDialog(PFile.getNameWithoutExtension(pathFrom), PFile.getExtension(pathFrom))
return importFile(PFile.getNameWithoutExtension(pathFrom), new FileInputStream(pathFrom)); .observeOn(Schedulers.io())
} catch (FileNotFoundException e) { .map(new Function<String, String>() {
showMessage(R.string.file_not_exists); @Override
return Observable.error(e); public String apply(@io.reactivex.annotations.NonNull String s) throws Exception {
} final String pathTo = getCurrentDirectoryPath() + s + "." + PFile.getExtension(pathFrom);
if (PFile.copy(pathFrom, pathTo)) {
showMessage(R.string.text_import_succeed);
} else {
showMessage(R.string.text_import_fail);
}
notifyScriptFileChanged();
return pathTo;
}
});
} }
public Observable<String> importFile(String prefix, final InputStream inputStream) { public Observable<String> importFile(String prefix, final InputStream inputStream) {
return showFileNameInputDialog(PFile.getNameWithoutExtension(prefix)) return showFileNameInputDialog(PFile.getNameWithoutExtension(prefix), "js")
.observeOn(Schedulers.io()) .observeOn(Schedulers.io())
.map(new Function<String, String>() { .map(new Function<String, String>() {
@Override @Override
@@ -130,7 +141,7 @@ public class ScriptOperations {
public void newDirectory() { public void newDirectory() {
showNameInputDialog("", new InputCallback(true)) showNameInputDialog("", new InputCallback())
.subscribe(new Consumer<String>() { .subscribe(new Consumer<String>() {
@Override @Override
public void accept(@io.reactivex.annotations.NonNull String path) throws Exception { public void accept(@io.reactivex.annotations.NonNull String path) throws Exception {
@@ -158,8 +169,8 @@ public class ScriptOperations {
} }
private Observable<String> showFileNameInputDialog(String prefix) { private Observable<String> showFileNameInputDialog(String prefix, String ext) {
return showNameInputDialog(prefix, new InputCallback(false)); return showNameInputDialog(prefix, new InputCallback(ext));
} }
private Observable<String> showNameInputDialog(String prefix, MaterialDialog.InputCallback textWatcher) { private Observable<String> showNameInputDialog(String prefix, MaterialDialog.InputCallback textWatcher) {
@@ -196,7 +207,8 @@ public class ScriptOperations {
public Observable<Boolean> rename(final ScriptFile file) { public Observable<Boolean> rename(final ScriptFile file) {
String originalName = file.getSimplifiedName(); String originalName = file.getSimplifiedName();
return showNameInputDialog(originalName, new InputCallback(file.isDirectory(), originalName)) return showNameInputDialog(originalName, new InputCallback(file.isDirectory() ? null : PFile.getExtension(file.getName()),
originalName))
.map(new Function<String, Boolean>() { .map(new Function<String, Boolean>() {
@Override @Override
public Boolean apply(@io.reactivex.annotations.NonNull String newName) throws Exception { public Boolean apply(@io.reactivex.annotations.NonNull String newName) throws Exception {
@@ -207,17 +219,21 @@ public class ScriptOperations {
private class InputCallback implements MaterialDialog.InputCallback { private class InputCallback implements MaterialDialog.InputCallback {
private boolean mIsDirectory = false;
private String mExcluded; private String mExcluded;
private boolean mIsFirstTextChanged = true; private boolean mIsFirstTextChanged = true;
private String mExtension;
InputCallback(boolean isDirectory, String excluded) { InputCallback(@Nullable String ext, String excluded) {
mIsDirectory = isDirectory; mExtension = "." + ext;
mExcluded = excluded; mExcluded = excluded;
} }
InputCallback(boolean isDirectory) { InputCallback(String ext) {
mIsDirectory = isDirectory; this(ext, null);
}
public InputCallback() {
this(null);
} }
@Override @Override
@@ -233,7 +249,7 @@ public class ScriptOperations {
if (input == null || input.length() == 0) { if (input == null || input.length() == 0) {
errorResId = R.string.text_name_should_not_be_empty; errorResId = R.string.text_name_should_not_be_empty;
} else if (!input.equals(mExcluded)) { } else if (!input.equals(mExcluded)) {
if (new File(getCurrentDirectory(), mIsDirectory ? input.toString() : input.toString() + ".js").exists()) { if (new File(getCurrentDirectory(), mExtension == null ? input.toString() : input.toString() + mExtension).exists()) {
errorResId = R.string.text_file_exists; errorResId = R.string.text_file_exists;
} }
} }

View File

@@ -22,8 +22,9 @@ import com.jecelyin.editor.v2.ui.EditorDelegate;
import com.jecelyin.editor.v2.view.EditorView; import com.jecelyin.editor.v2.view.EditorView;
import com.jecelyin.editor.v2.view.menu.MenuDef; import com.jecelyin.editor.v2.view.menu.MenuDef;
import com.stardust.app.OnActivityResultDelegate; import com.stardust.app.OnActivityResultDelegate;
import com.stardust.autojs.engine.JavaScriptEngine;
import com.stardust.autojs.execution.ScriptExecution; import com.stardust.autojs.execution.ScriptExecution;
import com.stardust.autojs.script.FileScriptSource; import com.stardust.autojs.script.JavaScriptFileSource;
import com.stardust.autojs.script.JsBeautifier; import com.stardust.autojs.script.JsBeautifier;
import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.autojs.AutoJs; import com.stardust.scriptdroid.autojs.AutoJs;
@@ -211,7 +212,7 @@ public class EditActivity extends Editor920Activity implements OnActivityResultD
private void run() { private void run() {
Snackbar.make(mView, R.string.text_start_running, Snackbar.LENGTH_SHORT).show(); Snackbar.make(mView, R.string.text_start_running, Snackbar.LENGTH_SHORT).show();
setMenuStatus(R.id.run, MenuDef.STATUS_DISABLED); setMenuStatus(R.id.run, MenuDef.STATUS_DISABLED);
mScriptExecution = Scripts.runWithBroadcastSender(new FileScriptSource(mName, mFile), mFile.getParent()); mScriptExecution = Scripts.runWithBroadcastSender(new JavaScriptFileSource(mName, mFile), mFile.getParent());
} }
@@ -288,7 +289,7 @@ public class EditActivity extends Editor920Activity implements OnActivityResultD
private void showConsole() { private void showConsole() {
if (mScriptExecution != null) { if (mScriptExecution != null) {
mScriptExecution.getRuntime().console.show(); ((JavaScriptEngine) mScriptExecution.getEngine()).getRuntime().console.show();
} }
} }

View File

@@ -16,6 +16,7 @@ import com.jecelyin.editor.v2.ui.EditorDelegate;
import com.jecelyin.editor.v2.view.EditorView; import com.jecelyin.editor.v2.view.EditorView;
import com.jecelyin.editor.v2.view.menu.MenuDef; import com.jecelyin.editor.v2.view.menu.MenuDef;
import com.stardust.app.OnActivityResultDelegate; import com.stardust.app.OnActivityResultDelegate;
import com.stardust.autojs.engine.JavaScriptEngine;
import com.stardust.autojs.execution.ScriptExecution; import com.stardust.autojs.execution.ScriptExecution;
import com.stardust.autojs.script.StringScriptSource; import com.stardust.autojs.script.StringScriptSource;
import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.R;
@@ -27,7 +28,6 @@ import com.stardust.scriptdroid.ui.common.ScriptOperations;
import com.stardust.scriptdroid.ui.edit.editor920.Editor920Activity; import com.stardust.scriptdroid.ui.edit.editor920.Editor920Activity;
import com.stardust.scriptdroid.ui.edit.editor920.Editor920Utils; import com.stardust.scriptdroid.ui.edit.editor920.Editor920Utils;
import com.stardust.scriptdroid.ui.help.HelpCatalogueActivity; import com.stardust.scriptdroid.ui.help.HelpCatalogueActivity;
import com.stardust.scriptdroid.ui.main.MainActivity;
import com.stardust.theme.ThemeColorManager; import com.stardust.theme.ThemeColorManager;
import com.stardust.util.AssetsCache; import com.stardust.util.AssetsCache;
import com.stardust.util.SparseArrayEntries; import com.stardust.util.SparseArrayEntries;
@@ -182,7 +182,7 @@ public class ViewSampleActivity extends Editor920Activity implements OnActivityR
private void showConsole() { private void showConsole() {
if (mScriptExecution != null) { if (mScriptExecution != null) {
mScriptExecution.getRuntime().console.show(); ((JavaScriptEngine) mScriptExecution.getEngine()).getRuntime().console.show();
} }
} }

View File

@@ -9,8 +9,6 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout; import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager;
@@ -36,10 +34,8 @@ import com.stardust.scriptdroid.Pref;
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.HoverMenuManger; import com.stardust.scriptdroid.external.floatingwindow.HoverMenuManger;
import com.stardust.scriptdroid.external.open.ImportIntentActivity;
import com.stardust.scriptdroid.script.ScriptFile; import com.stardust.scriptdroid.script.ScriptFile;
import com.stardust.scriptdroid.script.StorageScriptProvider; import com.stardust.scriptdroid.script.StorageScriptProvider;
import com.stardust.scriptdroid.script.sample.Sample;
import com.stardust.scriptdroid.ui.common.ScriptOperations; import com.stardust.scriptdroid.ui.common.ScriptOperations;
import com.stardust.scriptdroid.ui.main.task.TaskManagerFragment_; import com.stardust.scriptdroid.ui.main.task.TaskManagerFragment_;
import com.stardust.util.IntentExtras; import com.stardust.util.IntentExtras;
@@ -54,7 +50,6 @@ import com.stardust.scriptdroid.ui.settings.SettingsActivity_;
import com.stardust.scriptdroid.ui.update.VersionGuard; import com.stardust.scriptdroid.ui.update.VersionGuard;
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder; import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
import com.stardust.util.BackPressedHandler; import com.stardust.util.BackPressedHandler;
import com.stardust.util.Callback;
import com.stardust.util.MessageEvent; import com.stardust.util.MessageEvent;
import com.stardust.view.DrawerAutoClose; import com.stardust.view.DrawerAutoClose;
import com.stardust.view.accessibility.AccessibilityServiceUtils; import com.stardust.view.accessibility.AccessibilityServiceUtils;
@@ -68,8 +63,6 @@ import org.androidannotations.annotations.ViewById;
import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.Subscribe;
import java.io.File;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@EActivity(R.layout.activity_main) @EActivity(R.layout.activity_main)
@@ -80,13 +73,14 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
private static final String LOG_TAG = "MainActivity"; private static final String LOG_TAG = "MainActivity";
private static final String EXTRA_ACTION = "EXTRA_ACTION"; private static final String EXTRA_ACTION = "EXTRA_ACTION";
private static final String ACTION_ON_ACTION_RECORD_STOPPED = "ACTION_ON_ACTION_RECORD_STOPPED"; private static final String ACTION_ON_RECORD_STOP = "ACTION_ON_RECORD_STOP";
private static final String ACTION_IMPORT_SCRIPT = "ACTION_IMPORT_SCRIPT"; private static final String ACTION_IMPORT_SCRIPT = "ACTION_IMPORT_SCRIPT";
private static final String ARGUMENT_SCRIPT = "ARGUMENT_SCRIPT"; private static final String ARGUMENT_SCRIPT = "ARGUMENT_SCRIPT";
private static final String ARGUMENT_PATH = "ARGUMENT_PATH"; private static final String ARGUMENT_PATH = "ARGUMENT_PATH";
private static final String ACTION_IMPORT_SAMPLE = "I cannot find the way back to you...Eating...17.4.29"; private static final String ACTION_IMPORT_SAMPLE = "I cannot find the way back to you...Eating...17.4.29";
private static final String ARGUMENT_SAMPLE = "Take a chance on me...ok...?"; private static final String ARGUMENT_SAMPLE = "Take a chance on me...ok...?";
private static final String ARGUMENT_INPUT_STREAM = "17.7.12, Hi...could we start all over again..."; private static final String ARGUMENT_INPUT_STREAM = "17.7.12, Hi...could we start all over again...";
private static final String ACTION_ON_ROOT_RECORD_STOP = "ACTION_ON_ROOT_RECORD_STOP";
@ViewById(R.id.drawer_layout) @ViewById(R.id.drawer_layout)
@@ -111,6 +105,7 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
mVersionGuard = new VersionGuard(this); mVersionGuard = new VersionGuard(this);
showAnnunciationIfNeeded(); showAnnunciationIfNeeded();
//Stop download service of ad sdk //Stop download service of ad sdk
// FIXME: 2017/8/1 Service not stopped!
stopService(new Intent(this, DownloadService.class)); stopService(new Intent(this, DownloadService.class));
} }
@@ -305,7 +300,7 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
if (action == null) if (action == null)
return; return;
switch (action) { switch (action) {
case ACTION_ON_ACTION_RECORD_STOPPED: case ACTION_ON_RECORD_STOP:
IntentExtras extras = IntentExtras.fromIntent(intent); IntentExtras extras = IntentExtras.fromIntent(intent);
String script = extras.get(ARGUMENT_SCRIPT); String script = extras.get(ARGUMENT_SCRIPT);
extras.clear(); extras.clear();
@@ -321,12 +316,14 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
String path = intent.getStringExtra(ARGUMENT_PATH); String path = intent.getStringExtra(ARGUMENT_PATH);
if (path != null) { if (path != null) {
new ScriptOperations(MainActivity.this, mDrawerLayout) new ScriptOperations(MainActivity.this, mDrawerLayout)
.importFile(intent.getStringExtra(ARGUMENT_PATH)); .importFile(intent.getStringExtra(ARGUMENT_PATH))
.subscribe();
return; return;
} }
InputStream inputStream = IntentExtras.fromIntent(intent).getAndClear(ARGUMENT_INPUT_STREAM); InputStream inputStream = IntentExtras.fromIntent(intent).getAndClear(ARGUMENT_INPUT_STREAM);
new ScriptOperations(MainActivity.this, mDrawerLayout) new ScriptOperations(MainActivity.this, mDrawerLayout)
.importFile("", inputStream); .importFile("", inputStream)
.subscribe();
} }
private void handleRecordedScript(final String script) { private void handleRecordedScript(final String script) {
@@ -416,7 +413,7 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
public static void onRecordStop(Context context, String script) { public static void onRecordStop(Context context, String script) {
Intent intent = new Intent(context, MainActivity_.class) Intent intent = new Intent(context, MainActivity_.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(EXTRA_ACTION, ACTION_ON_ACTION_RECORD_STOPPED); .putExtra(EXTRA_ACTION, ACTION_ON_RECORD_STOP);
IntentExtras.newExtras() IntentExtras.newExtras()
.put(ARGUMENT_SCRIPT, script) .put(ARGUMENT_SCRIPT, script)
.putInIntent(intent); .putInIntent(intent);
@@ -424,4 +421,11 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
} }
public static void onRootRecordStop(Context context, String path) {
Intent intent = new Intent(context, MainActivity_.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(EXTRA_ACTION, ACTION_ON_ROOT_RECORD_STOP)
.putExtra(ARGUMENT_PATH, path);
context.startActivity(intent);
}
} }

View File

@@ -94,7 +94,12 @@ public class MyScriptListFragment extends Fragment {
mScriptListRecyclerView.setOnItemClickListener(new ScriptAndFolderListRecyclerView.OnScriptFileClickListener() { mScriptListRecyclerView.setOnItemClickListener(new ScriptAndFolderListRecyclerView.OnScriptFileClickListener() {
@Override @Override
public void onClick(ScriptFile file, int position) { public void onClick(ScriptFile file, int position) {
EditActivity.editFile(getContext(), file); if (file.getType() == ScriptFile.TYPE_JAVA_SCRIPT) {
Scripts.edit(file);
} else {
mSelectedScriptFile = file;
mScriptFileOperationDialog.show();
}
} }
}); });
mScriptListRecyclerView.setOnItemLongClickListener(new ScriptAndFolderListRecyclerView.OnScriptFileLongClickListener() { mScriptListRecyclerView.setOnItemLongClickListener(new ScriptAndFolderListRecyclerView.OnScriptFileLongClickListener() {

View File

@@ -11,6 +11,7 @@ import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import android.workground.WrapContentLinearLayoutManager; import android.workground.WrapContentLinearLayoutManager;
@@ -412,14 +413,24 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
private class FileViewHolder extends DefaultViewHolder { private class FileViewHolder extends DefaultViewHolder {
private ImageView mIcon;
FileViewHolder(View itemView) { FileViewHolder(View itemView) {
super(itemView); super(itemView);
mIcon = (ImageView) itemView.findViewById(R.id.icon);
if (mScriptFileOperationEnabled) { if (mScriptFileOperationEnabled) {
itemView.findViewById(R.id.run).setOnClickListener(mOnRunClickListener); itemView.findViewById(R.id.run).setOnClickListener(mOnRunClickListener);
} else { } else {
itemView.findViewById(R.id.run).setVisibility(GONE); itemView.findViewById(R.id.run).setVisibility(GONE);
} }
} }
@Override
public void bind(ScriptFile file) {
super.bind(file);
mIcon.setImageResource(file.getType() == ScriptFile.TYPE_AUTO ? R.drawable.record_icon_18
: R.drawable.ic_node_js_black);
}
} }
} }

View File

@@ -1,7 +1,6 @@
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;
@@ -12,14 +11,12 @@ 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.engine.ScriptEngineManager;
import com.stardust.autojs.execution.ScriptExecution; import com.stardust.autojs.execution.ScriptExecution;
import com.stardust.autojs.execution.ScriptExecutionListener; import com.stardust.autojs.execution.ScriptExecutionListener;
import com.stardust.autojs.execution.SimpleScriptExecutionListener; import com.stardust.autojs.execution.SimpleScriptExecutionListener;
import com.stardust.autojs.engine.ScriptEngine; import com.stardust.autojs.engine.ScriptEngine;
import com.stardust.autojs.engine.AbstractScriptEngineManager;
import com.stardust.autojs.script.ScriptSource; import com.stardust.autojs.script.ScriptSource;
import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.autojs.AutoJs; import com.stardust.scriptdroid.autojs.AutoJs;
@@ -32,7 +29,7 @@ import java.util.List;
* Created by Stardust on 2017/3/24. * Created by Stardust on 2017/3/24.
*/ */
public class TaskListRecyclerView extends ThemeColorRecyclerView implements AbstractScriptEngineManager.EngineLifecycleCallback { public class TaskListRecyclerView extends ThemeColorRecyclerView implements ScriptEngineManager.EngineLifecycleCallback {
private final OnClickListener mOnItemClickListenerProxy = new OnClickListener() { private final OnClickListener mOnItemClickListenerProxy = new OnClickListener() {
@@ -184,7 +181,7 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView implements Abst
@Override @Override
public void onBindViewHolder(ViewHolder holder, int position) { public void onBindViewHolder(ViewHolder holder, int position) {
holder.bind((ScriptSource) mScriptEngines.get(position).getTag("script")); holder.bind((ScriptSource) mScriptEngines.get(position).getTag(ScriptEngine.TAG_SOURCE));
} }
@Override @Override

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

View File

@@ -6,7 +6,7 @@
<item <item
android:bottom="214dp" android:bottom="214dp"
android:drawable="@drawable/ic_android_eat_js" android:drawable="@drawable/autojs_material"
android:gravity="center" android:gravity="center"
android:left="100dp" android:left="100dp"
android:right="100dp" android:right="100dp"

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -47,7 +47,7 @@
android:layout_width="90dp" android:layout_width="90dp"
android:layout_height="90dp" android:layout_height="90dp"
android:layout_centerInParent="true" android:layout_centerInParent="true"
android:src="@drawable/ic_android_eat_js"/> android:src="@drawable/autojs_material"/>
<TextView <TextView
android:id="@+id/version" android:id="@+id/version"

View File

@@ -50,7 +50,7 @@
android:layout_width="72dp" android:layout_width="72dp"
android:layout_height="72dp" android:layout_height="72dp"
android:layout_gravity="center" android:layout_gravity="center"
android:src="@drawable/ic_android_eat_js"> android:src="@drawable/autojs_material">
</ImageView> </ImageView>

View File

@@ -2,12 +2,12 @@ package com.stardust.autojs;
import android.content.Context; import android.content.Context;
import com.stardust.autojs.engine.AbstractScriptEngineManager; import com.stardust.autojs.engine.JavaScriptEngine;
import com.stardust.autojs.engine.ScriptEngine; import com.stardust.autojs.engine.ScriptEngine;
import com.stardust.autojs.engine.ScriptEngineManager; import com.stardust.autojs.engine.ScriptEngineManager;
import com.stardust.autojs.execution.ScriptExecuteActivity;
import com.stardust.autojs.execution.ExecutionConfig; import com.stardust.autojs.execution.ExecutionConfig;
import com.stardust.autojs.execution.RunnableScriptExecution; import com.stardust.autojs.execution.RunnableScriptExecution;
import com.stardust.autojs.execution.ScriptExecuteActivity;
import com.stardust.autojs.execution.ScriptExecution; import com.stardust.autojs.execution.ScriptExecution;
import com.stardust.autojs.execution.ScriptExecutionListener; import com.stardust.autojs.execution.ScriptExecutionListener;
import com.stardust.autojs.execution.ScriptExecutionObserver; import com.stardust.autojs.execution.ScriptExecutionObserver;
@@ -15,9 +15,9 @@ import com.stardust.autojs.execution.ScriptExecutionTask;
import com.stardust.autojs.execution.SimpleScriptExecutionListener; import com.stardust.autojs.execution.SimpleScriptExecutionListener;
import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.autojs.runtime.api.Console; import com.stardust.autojs.runtime.api.Console;
import com.stardust.autojs.script.JavaScriptSource;
import com.stardust.autojs.script.ScriptSource; import com.stardust.autojs.script.ScriptSource;
import com.stardust.lang.ThreadCompat; import com.stardust.lang.ThreadCompat;
import com.stardust.util.Supplier;
import com.stardust.util.UiHandler; import com.stardust.util.UiHandler;
import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.EventBus;
@@ -44,7 +44,10 @@ public class ScriptEngineService {
private static final ScriptExecutionListener GLOBAL_LISTENER = new SimpleScriptExecutionListener() { private static final ScriptExecutionListener GLOBAL_LISTENER = new SimpleScriptExecutionListener() {
@Override @Override
public void onStart(ScriptExecution execution) { public void onStart(ScriptExecution execution) {
execution.getRuntime().console.setTitle(execution.getSource().getName()); if (execution.getEngine() instanceof JavaScriptEngine) {
((JavaScriptEngine) execution.getEngine()).getRuntime()
.console.setTitle(execution.getSource().getName());
}
EVENT_BUS.post(new ScriptExecutionEvent(ScriptExecutionEvent.ON_START, execution.getSource().toString())); EVENT_BUS.post(new ScriptExecutionEvent(ScriptExecutionEvent.ON_START, execution.getSource().toString()));
} }
@@ -54,7 +57,9 @@ public class ScriptEngineService {
} }
private void onFinish(ScriptExecution execution) { private void onFinish(ScriptExecution execution) {
execution.getRuntime().onExit(); if (execution.getEngine() instanceof JavaScriptEngine) {
((JavaScriptEngine) execution.getEngine()).getRuntime().onExit();
}
} }
@Override @Override
@@ -62,14 +67,16 @@ public class ScriptEngineService {
e.printStackTrace(); e.printStackTrace();
onFinish(execution); onFinish(execution);
if (!causedByInterrupted(e)) { if (!causedByInterrupted(e)) {
execution.getRuntime().console.error(getScriptTrace(e)); if (execution.getEngine() instanceof JavaScriptEngine) {
((JavaScriptEngine) execution.getEngine()).getRuntime()
.console.error(getScriptTrace(e));
}
EVENT_BUS.post(new ScriptExecutionEvent(ScriptExecutionEvent.ON_EXCEPTION, e.getMessage())); EVENT_BUS.post(new ScriptExecutionEvent(ScriptExecutionEvent.ON_EXCEPTION, e.getMessage()));
} }
} }
}; };
private final Supplier<? extends ScriptRuntime> mRuntimeSupplier;
private final Context mContext; private final Context mContext;
private UiHandler mUiHandler; private UiHandler mUiHandler;
private final Console mGlobalConsole; private final Console mGlobalConsole;
@@ -78,7 +85,6 @@ public class ScriptEngineService {
private ScriptExecutionObserver mScriptExecutionObserver = new ScriptExecutionObserver(); private ScriptExecutionObserver mScriptExecutionObserver = new ScriptExecutionObserver();
ScriptEngineService(ScriptEngineServiceBuilder builder) { ScriptEngineService(ScriptEngineServiceBuilder builder) {
mRuntimeSupplier = builder.mRuntimeSupplier;
mUiHandler = builder.mUiHandler; mUiHandler = builder.mUiHandler;
mContext = mUiHandler.getContext(); mContext = mUiHandler.getContext();
mScriptEngineManager = builder.mScriptEngineManager; mScriptEngineManager = builder.mScriptEngineManager;
@@ -94,20 +100,11 @@ public class ScriptEngineService {
return mGlobalConsole; return mGlobalConsole;
} }
public ScriptEngine createScriptEngine() { public void registerEngineLifecycleCallback(ScriptEngineManager.EngineLifecycleCallback engineLifecycleCallback) {
ScriptEngine engine = mScriptEngineManager.createEngine();
return engine;
}
public ScriptRuntime createScriptRuntime() {
return mRuntimeSupplier.get();
}
public void registerEngineLifecycleCallback(AbstractScriptEngineManager.EngineLifecycleCallback engineLifecycleCallback) {
mEngineLifecycleObserver.registerCallback(engineLifecycleCallback); mEngineLifecycleObserver.registerCallback(engineLifecycleCallback);
} }
public void unregisterEngineLifecycleCallback(AbstractScriptEngineManager.EngineLifecycleCallback engineLifecycleCallback) { public void unregisterEngineLifecycleCallback(ScriptEngineManager.EngineLifecycleCallback engineLifecycleCallback) {
mEngineLifecycleObserver.unregisterCallback(engineLifecycleCallback); mEngineLifecycleObserver.unregisterCallback(engineLifecycleCallback);
} }
@@ -125,23 +122,23 @@ public class ScriptEngineService {
} else { } else {
task.setExecutionListener(mScriptExecutionObserver); task.setExecutionListener(mScriptExecutionObserver);
} }
if (isUiMode(task)) { ScriptSource source = task.getSource();
return ScriptExecuteActivity.execute(mContext, this, task); if (source instanceof JavaScriptSource && isUiMode((JavaScriptSource) source)) {
return ScriptExecuteActivity.execute(mContext, mScriptEngineManager, task);
} else { } else {
RunnableScriptExecution scriptExecution = new RunnableScriptExecution(this, task); RunnableScriptExecution r = new RunnableScriptExecution(mScriptEngineManager, task);
if (task.getConfig().runInNewThread) { if (task.getConfig().runInNewThread) {
new ThreadCompat(scriptExecution).start(); new ThreadCompat(r).start();
} else { } else {
scriptExecution.run(); r.run();
} }
return scriptExecution; return r;
} }
} }
private boolean isUiMode(ScriptExecutionTask task) { private boolean isUiMode(JavaScriptSource source) {
ScriptSource source = task.getSource();
int mode = source.getExecutionMode(); int mode = source.getExecutionMode();
return (mode & ScriptSource.EXECUTION_MODE_UI) != 0; return (mode & JavaScriptSource.EXECUTION_MODE_UI) != 0;
} }
public ScriptExecution execute(ScriptSource source, ScriptExecutionListener listener, ExecutionConfig config) { public ScriptExecution execute(ScriptSource source, ScriptExecutionListener listener, ExecutionConfig config) {
@@ -186,14 +183,14 @@ public class ScriptEngineService {
return mScriptEngineManager.getEngines(); return mScriptEngineManager.getEngines();
} }
private static class EngineLifecycleObserver implements AbstractScriptEngineManager.EngineLifecycleCallback { private static class EngineLifecycleObserver implements ScriptEngineManager.EngineLifecycleCallback {
private final Set<AbstractScriptEngineManager.EngineLifecycleCallback> mEngineLifecycleCallbacks = new LinkedHashSet<>(); private final Set<ScriptEngineManager.EngineLifecycleCallback> mEngineLifecycleCallbacks = new LinkedHashSet<>();
@Override @Override
public void onEngineCreate(ScriptEngine engine) { public void onEngineCreate(ScriptEngine engine) {
synchronized (mEngineLifecycleCallbacks) { synchronized (mEngineLifecycleCallbacks) {
for (AbstractScriptEngineManager.EngineLifecycleCallback callback : mEngineLifecycleCallbacks) { for (ScriptEngineManager.EngineLifecycleCallback callback : mEngineLifecycleCallbacks) {
callback.onEngineCreate(engine); callback.onEngineCreate(engine);
} }
} }
@@ -202,20 +199,20 @@ public class ScriptEngineService {
@Override @Override
public void onEngineRemove(ScriptEngine engine) { public void onEngineRemove(ScriptEngine engine) {
synchronized (mEngineLifecycleCallbacks) { synchronized (mEngineLifecycleCallbacks) {
for (AbstractScriptEngineManager.EngineLifecycleCallback callback : mEngineLifecycleCallbacks) { for (ScriptEngineManager.EngineLifecycleCallback callback : mEngineLifecycleCallbacks) {
callback.onEngineRemove(engine); callback.onEngineRemove(engine);
} }
} }
} }
void registerCallback(AbstractScriptEngineManager.EngineLifecycleCallback callback) { void registerCallback(ScriptEngineManager.EngineLifecycleCallback callback) {
synchronized (mEngineLifecycleCallbacks) { synchronized (mEngineLifecycleCallbacks) {
mEngineLifecycleCallbacks.add(callback); mEngineLifecycleCallbacks.add(callback);
} }
} }
void unregisterCallback(AbstractScriptEngineManager.EngineLifecycleCallback callback) { void unregisterCallback(ScriptEngineManager.EngineLifecycleCallback callback) {
synchronized (mEngineLifecycleCallbacks) { synchronized (mEngineLifecycleCallbacks) {
mEngineLifecycleCallbacks.remove(callback); mEngineLifecycleCallbacks.remove(callback);
} }

View File

@@ -1,6 +1,5 @@
package com.stardust.autojs; package com.stardust.autojs;
import com.stardust.autojs.engine.AbstractScriptEngineManager;
import com.stardust.autojs.engine.ScriptEngineManager; import com.stardust.autojs.engine.ScriptEngineManager;
import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.autojs.runtime.api.Console; import com.stardust.autojs.runtime.api.Console;
@@ -13,7 +12,6 @@ import com.stardust.util.UiHandler;
public class ScriptEngineServiceBuilder { public class ScriptEngineServiceBuilder {
Supplier<? extends ScriptRuntime> mRuntimeSupplier;
ScriptEngineManager mScriptEngineManager; ScriptEngineManager mScriptEngineManager;
Console mGlobalConsole; Console mGlobalConsole;
UiHandler mUiHandler; UiHandler mUiHandler;
@@ -22,11 +20,6 @@ public class ScriptEngineServiceBuilder {
} }
public ScriptEngineServiceBuilder runtime(Supplier<? extends ScriptRuntime> runtimeSupplier) {
mRuntimeSupplier = runtimeSupplier;
return this;
}
public ScriptEngineServiceBuilder uiHandler(UiHandler uiHandler) { public ScriptEngineServiceBuilder uiHandler(UiHandler uiHandler) {
mUiHandler = uiHandler; mUiHandler = uiHandler;
return this; return this;

View File

@@ -1,86 +0,0 @@
package com.stardust.autojs.engine;
import android.content.Context;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Created by Stardust on 2017/1/27.
*/
public abstract class AbstractScriptEngineManager implements ScriptEngineManager {
private static final String TAG = "AbstractScriptEngineManager";
private Map<String, Object> mGlobalVariableMap = new HashMap<>();
private final Set<ScriptEngine> mEngines = new HashSet<>();
private EngineLifecycleCallback mEngineLifecycleCallback;
private android.content.Context mAndroidContext;
public AbstractScriptEngineManager(Context androidContext) {
mAndroidContext = androidContext;
}
public ScriptEngine createEngine() {
ScriptEngine engine = createEngineInner();
putProperties(engine);
addEngine(engine);
return engine;
}
private void addEngine(ScriptEngine engine) {
synchronized (mEngines) {
mEngines.add(engine);
if (mEngineLifecycleCallback != null) {
mEngineLifecycleCallback.onEngineCreate(engine);
}
}
}
public void putGlobal(String varName, Object value) {
mGlobalVariableMap.put(varName, value);
}
public void setEngineLifecycleCallback(EngineLifecycleCallback engineLifecycleCallback) {
mEngineLifecycleCallback = engineLifecycleCallback;
}
public Set<ScriptEngine> getEngines() {
return mEngines;
}
protected abstract ScriptEngine createEngineInner();
public android.content.Context getAndroidContext() {
return mAndroidContext;
}
protected void putProperties(ScriptEngine engine) {
for (Map.Entry<String, Object> variable : mGlobalVariableMap.entrySet()) {
engine.put(variable.getKey(), variable.getValue());
}
}
public void removeEngine(ScriptEngine engine) {
synchronized (mEngines) {
if (mEngines.remove(engine) && mEngineLifecycleCallback != null) {
mEngineLifecycleCallback.onEngineRemove(engine);
}
}
}
public int stopAll() {
synchronized (mEngines) {
int n = mEngines.size();
for (ScriptEngine engine : mEngines) {
engine.forceStop();
}
return n;
}
}
}

View File

@@ -0,0 +1,25 @@
package com.stardust.autojs.engine;
import com.stardust.autojs.execution.ScriptExecution;
import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.autojs.script.JavaScriptSource;
/**
* Created by Stardust on 2017/8/3.
*/
public abstract class JavaScriptEngine extends ScriptEngine.AbstractScriptEngine<JavaScriptSource> {
private ScriptRuntime mRuntime;
public ScriptRuntime getRuntime() {
return mRuntime;
}
public void setRuntime(ScriptRuntime runtime) {
mRuntime = runtime;
put("__runtime__", runtime);
}
}

View File

@@ -1,10 +1,12 @@
package com.stardust.autojs.engine; package com.stardust.autojs.engine;
import android.content.Context;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.os.MessageQueue; import android.os.MessageQueue;
import com.stardust.autojs.runtime.api.Loopers; import com.stardust.autojs.runtime.api.Loopers;
import com.stardust.autojs.script.JavaScriptSource;
import com.stardust.autojs.script.ScriptSource; import com.stardust.autojs.script.ScriptSource;
/** /**
@@ -16,12 +18,12 @@ public class LoopBasedJavaScriptEngine extends RhinoJavaScriptEngine {
private Handler mHandler; private Handler mHandler;
private boolean mLooping = false; private boolean mLooping = false;
public LoopBasedJavaScriptEngine(RhinoJavaScriptEngineManager engineManager) { public LoopBasedJavaScriptEngine(Context context) {
super(engineManager); super(context);
} }
@Override @Override
public Object execute(final ScriptSource source) { public Object execute(final JavaScriptSource source) {
Runnable r = new Runnable() { Runnable r = new Runnable() {
@Override @Override
public void run() { public void run() {

View File

@@ -1,14 +1,14 @@
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.BuildConfig;
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.JavaScriptSource;
import com.stardust.autojs.runtime.api.Timers; import com.stardust.autojs.script.StringScriptSource;
import com.stardust.autojs.script.ScriptSource; import com.stardust.pio.PFile;
import com.stardust.pio.UncheckedIOException; import com.stardust.pio.UncheckedIOException;
import org.mozilla.javascript.Context; import org.mozilla.javascript.Context;
@@ -25,30 +25,26 @@ import java.io.Reader;
import java.net.URI; import java.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/** /**
* Created by Stardust on 2017/4/2. * Created by Stardust on 2017/4/2.
*/ */
public class RhinoJavaScriptEngine implements ScriptEngine { public class RhinoJavaScriptEngine extends JavaScriptEngine {
private static final String LOG_TAG = "RhinoJavaScriptEngine"; private static final String LOG_TAG = "RhinoJavaScriptEngine";
private static int contextCount = 0; private static int contextCount = 0;
private static StringScriptSource sInitScript;
private String[] mRequirePath = new String[0]; private String[] mRequirePath = new String[0];
private Context mContext; private Context mContext;
private Scriptable mScriptable; private Scriptable mScriptable;
private Thread mThread; private Thread mThread;
private RhinoJavaScriptEngineManager mEngineManager; private android.content.Context mAndroidContext;
private Map<String, Object> mTags = new ConcurrentHashMap<>();
private volatile boolean mDestroyed = false;
public RhinoJavaScriptEngine(RhinoJavaScriptEngineManager engineManager) { public RhinoJavaScriptEngine(android.content.Context context) {
mEngineManager = engineManager; mAndroidContext = context;
mThread = Thread.currentThread();
mContext = createContext(); mContext = createContext();
mScriptable = createScope(mContext); mScriptable = createScope(mContext);
} }
@@ -59,7 +55,7 @@ public class RhinoJavaScriptEngine implements ScriptEngine {
} }
@Override @Override
public Object execute(ScriptSource source) { public Object execute(JavaScriptSource source) {
Reader reader = source.getNonNullScriptReader(); Reader reader = source.getNonNullScriptReader();
try { try {
reader = preprocess(reader); reader = preprocess(reader);
@@ -79,33 +75,14 @@ public class RhinoJavaScriptEngine implements ScriptEngine {
mThread.interrupt(); mThread.interrupt();
} }
public RhinoJavaScriptEngineManager getEngineManager() {
return mEngineManager;
}
@Override @Override
public synchronized void destroy() { public synchronized void destroy() {
super.destroy();
Log.d(LOG_TAG, "on destroy"); Log.d(LOG_TAG, "on destroy");
Context.exit(); Context.exit();
contextCount--; contextCount--;
Log.d(LOG_TAG, "contextCount = " + contextCount); Log.d(LOG_TAG, "contextCount = " + contextCount);
mEngineManager.removeEngine(this);
mDestroyed = true;
}
@Override
public boolean isDestroyed() {
return mDestroyed;
}
@Override
public synchronized void setTag(String key, Object value) {
mTags.put(key, value);
}
@Override
public synchronized Object getTag(String key) {
return mTags.get(key);
} }
public Thread getThread() { public Thread getThread() {
@@ -114,15 +91,25 @@ public class RhinoJavaScriptEngine implements ScriptEngine {
@Override @Override
public void init() { public void init() {
ScriptableObject.putProperty(mScriptable, "__engine_name__", "rhino"); mThread = Thread.currentThread();
ScriptableObject.putProperty(mScriptable, "__engine__", this); ScriptableObject.putProperty(mScriptable, "__engine__", this);
mRequirePath = (String[]) getTag("__require_path__"); mRequirePath = (String[]) getTag(TAG_PATH);
initRequireBuilder(mContext, mScriptable); initRequireBuilder(mContext, mScriptable);
mContext.evaluateString(mScriptable, mEngineManager.getInitScript().getScript(), "<init>", 1, null); mContext.evaluateString(mScriptable, getInitScript().getScript(), "<init>", 1, null);
} }
public void setRequirePath(String... requirePath) { private JavaScriptSource getInitScript() {
setTag("__require_path__", requirePath); if (sInitScript == null || BuildConfig.DEBUG)
sInitScript = new StringScriptSource(readInitScript());
return sInitScript;
}
private String readInitScript() {
try {
return PFile.read(mAndroidContext.getAssets().open("javascript_engine_init.js"));
} catch (IOException e) {
throw new RuntimeException(e);
}
} }
void initRequireBuilder(Context context, Scriptable scope) { void initRequireBuilder(Context context, Scriptable scope) {
@@ -130,10 +117,10 @@ public class RhinoJavaScriptEngine implements ScriptEngine {
for (String path : mRequirePath) { for (String path : mRequirePath) {
list.add(new File(path).toURI()); list.add(new File(path).toURI());
} }
AssetAndUrlModuleSourceProvider provider = new AssetAndUrlModuleSourceProvider(getEngineManager().getAndroidContext(), list); AssetAndUrlModuleSourceProvider provider = new AssetAndUrlModuleSourceProvider(mAndroidContext, list);
new RequireBuilder() new RequireBuilder()
.setModuleScriptProvider(new SoftCachingModuleScriptProvider(provider)) .setModuleScriptProvider(new SoftCachingModuleScriptProvider(provider))
.setSandboxed(false) .setSandboxed(true)
.createRequire(context, scope) .createRequire(context, scope)
.install(scope); .install(scope);
} }
@@ -154,9 +141,9 @@ public class RhinoJavaScriptEngine implements ScriptEngine {
protected Context createContext() { protected Context createContext() {
if (!ContextFactory.hasExplicitGlobal()) { if (!ContextFactory.hasExplicitGlobal()) {
ContextFactory.initGlobal(new InterruptibleAndroidContextFactory(new File(mEngineManager.getAndroidContext().getCacheDir(), "classes"))); ContextFactory.initGlobal(new InterruptibleAndroidContextFactory(new File(mAndroidContext.getCacheDir(), "classes")));
} }
Context context = new RhinoAndroidHelper(mEngineManager.getAndroidContext()).enterContext(); Context context = new RhinoAndroidHelper(mAndroidContext).enterContext();
contextCount++; contextCount++;
context.setOptimizationLevel(-1); context.setOptimizationLevel(-1);
context.setLanguageVersion(Context.VERSION_ES6); context.setLanguageVersion(Context.VERSION_ES6);

View File

@@ -1,65 +0,0 @@
package com.stardust.autojs.engine;
import com.stardust.autojs.BuildConfig;
import com.stardust.autojs.script.ScriptSource;
import com.stardust.autojs.script.SequenceScriptSource;
import com.stardust.autojs.script.StringScriptSource;
import com.stardust.pio.PFile;
import java.io.IOException;
/**
* Created by Stardust on 2017/3/1.
*/
public class RhinoJavaScriptEngineManager extends AbstractScriptEngineManager {
private String[] mFunctions;
private ScriptSource mCustomInitScript;
private ScriptSource mInitScript;
public RhinoJavaScriptEngineManager(android.content.Context context) {
super(context);
}
protected RhinoJavaScriptEngine createEngineInner() {
RhinoJavaScriptEngine engine = new LoopBasedJavaScriptEngine(this);
return engine;
}
public void setInitScript(String script) {
setInitScriptSource(new StringScriptSource(script));
}
public void setInitScriptSource(ScriptSource initScriptSource) {
if (BuildConfig.DEBUG) {
mCustomInitScript = initScriptSource;
} else {
mInitScript = new SequenceScriptSource("<init>", new StringScriptSource(readInitScript()), initScriptSource);
}
}
private String readInitScript() {
try {
return PFile.read(getAndroidContext().getAssets().open("javascript_engine_init.js"));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
ScriptSource getInitScript() {
if (mInitScript == null || BuildConfig.DEBUG) {
// 调试时不缓存INIT_SCRIPT否则修改javascript_engine_init.js后不会更新
if (mCustomInitScript != null) {
mInitScript = new SequenceScriptSource("<init>", new StringScriptSource(readInitScript()), mCustomInitScript);
} else {
mInitScript = new StringScriptSource(readInitScript());
}
}
return mInitScript;
}
}

View File

@@ -0,0 +1,101 @@
package com.stardust.autojs.engine;
import android.content.Context;
import android.preference.PreferenceManager;
import android.util.Log;
import com.stardust.autojs.runtime.api.AbstractShell;
import com.stardust.autojs.runtime.api.ProcessShell;
import com.stardust.autojs.runtime.record.inputevent.InputDevices;
import com.stardust.autojs.script.AutoFileSource;
import com.stardust.autojs.script.JavaScriptFileSource;
import com.stardust.autojs.script.ScriptSource;
import com.stardust.pio.PFile;
import java.io.File;
/**
* Created by Stardust on 2017/8/1.
*/
public class RootAutomatorEngine extends ScriptEngine.AbstractScriptEngine<AutoFileSource> {
public static final int VERSION = 1;
private static final String KEY_TOUCH_DEVICE = RootAutomatorEngine.class.getName() + ".touch_device";
private static final String LOG_TAG = "RootAutomatorEngine";
private static int sTouchDevice = -1;
private static final String ROOT_AUTOMATOR_EXECUTABLE_ASSET = "binary/root_automator";
private Context mContext;
private String mDeviceNameOrPath;
private Thread mThread;
public RootAutomatorEngine(Context context, String deviceNameOrPath) {
mContext = context;
if (sTouchDevice < 0) {
sTouchDevice = PreferenceManager.getDefaultSharedPreferences(context).getInt(KEY_TOUCH_DEVICE, -1);
}
if (sTouchDevice >= 0) {
mDeviceNameOrPath = "/dev/input/event" + sTouchDevice;
PreferenceManager.getDefaultSharedPreferences(context)
.edit()
.putInt(KEY_TOUCH_DEVICE, sTouchDevice)
.apply();
} else {
mDeviceNameOrPath = deviceNameOrPath;
}
}
public RootAutomatorEngine(Context context) {
this(context, InputDevices.getTouchDeviceName());
}
public AbstractShell.Result execute(String autoFile) {
String executablePath = getExecutablePath(mContext);
AbstractShell.Result r = ProcessShell.execCommand(new String[]{
"chmod 777 " + executablePath,
executablePath + " " + autoFile + " -d " + mDeviceNameOrPath
}, true);
Log.d(LOG_TAG, "exec: " + autoFile + " result:" + r);
return r;
}
private static String getExecutablePath(Context context) {
File tmp = new File(context.getCacheDir(), "root_automator");
PFile.copyAsset(context, ROOT_AUTOMATOR_EXECUTABLE_ASSET, tmp.getAbsolutePath());
return tmp.getAbsolutePath();
}
public static void setTouchDevice(int device) {
sTouchDevice = device;
}
public static int getTouchDevice(Context context) {
if (sTouchDevice >= 0)
return sTouchDevice;
return PreferenceManager.getDefaultSharedPreferences(context).getInt(KEY_TOUCH_DEVICE, -1);
}
@Override
public void put(String name, Object value) {
}
@Override
public Object execute(AutoFileSource source) {
return execute(source.getFile().getAbsolutePath());
}
@Override
public void forceStop() {
mThread.interrupt();
}
@Override
public void init() {
mThread = Thread.currentThread();
}
}

View File

@@ -1,13 +1,18 @@
package com.stardust.autojs.engine; package com.stardust.autojs.engine;
import android.support.annotation.CallSuper;
import com.stardust.autojs.runtime.ScriptException; import com.stardust.autojs.runtime.ScriptException;
import com.stardust.autojs.script.ScriptSource; import com.stardust.autojs.script.ScriptSource;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/** /**
* Created by Stardust on 2017/4/2. * Created by Stardust on 2017/4/2.
* <p> * <p>
* <p> * <p>
* A ScriptEngine is created by {@link AbstractScriptEngineManager#createEngine()}, and then can be * A ScriptEngine is created by {@link ScriptEngineManager#createEngine(String)} ()}, and then can be
* used to execute script with {@link ScriptEngine#execute(ScriptSource)} in the **same** thread. * used to execute script with {@link ScriptEngine#execute(ScriptSource)} in the **same** thread.
* When the execution finish successfully, the engine should be destroy in the thread that created it. * When the execution finish successfully, the engine should be destroy in the thread that created it.
* <p> * <p>
@@ -15,12 +20,15 @@ import com.stardust.autojs.script.ScriptSource;
* It will throw a {@link ScriptException}. * It will throw a {@link ScriptException}.
*/ */
public interface ScriptEngine { public interface ScriptEngine<S extends ScriptSource> {
String TAG_PATH = "execute_path";
String TAG_SOURCE = "source";
void put(String name, Object value); void put(String name, Object value);
Object execute(ScriptSource scriptSource); Object execute(S scriptSource);
void forceStop(); void forceStop();
@@ -32,8 +40,57 @@ public interface ScriptEngine {
Object getTag(String key); Object getTag(String key);
/**
* @hide
*/
void setOnDestroyListener(OnDestroyListener listener);
/** /**
* @hide * @hide
*/ */
void init(); void init();
interface OnDestroyListener {
void onDestroy(ScriptEngine engine);
}
abstract class AbstractScriptEngine<S extends ScriptSource> implements ScriptEngine<S> {
private Map<String, Object> mTags = new ConcurrentHashMap<>();
private OnDestroyListener mOnDestroyListener;
private boolean mDestroyed = false;
@Override
public synchronized void setTag(String key, Object value) {
mTags.put(key, value);
}
@Override
public synchronized Object getTag(String key) {
return mTags.get(key);
}
@Override
public synchronized boolean isDestroyed() {
return mDestroyed;
}
@CallSuper
@Override
public synchronized void destroy() {
mDestroyed = true;
if (mOnDestroyListener != null) {
mOnDestroyListener.onDestroy(this);
}
}
public void setOnDestroyListener(OnDestroyListener onDestroyListener) {
if (mOnDestroyListener != null)
throw new SecurityException("setOnDestroyListener can be called only once");
mOnDestroyListener = onDestroyListener;
}
}
} }

View File

@@ -0,0 +1,89 @@
package com.stardust.autojs.engine;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.stardust.autojs.script.ScriptSource;
import com.stardust.util.Supplier;
import java.util.HashMap;
import java.util.Map;
/**
* Created by Stardust on 2017/8/2.
*/
public class ScriptEngineFactory {
public static class EngineNotFoundException extends RuntimeException {
public EngineNotFoundException(String s) {
super(s);
}
}
private static ScriptEngineFactory sInstance = new ScriptEngineFactory();
private Map<String, Supplier<ScriptEngine>> mEngines = new HashMap<>();
private Map<String, Object> mGlobalVariableMap = new HashMap<>();
ScriptEngineFactory() {
}
public static ScriptEngineFactory getInstance() {
return sInstance;
}
public void putGlobal(String varName, Object value) {
mGlobalVariableMap.put(varName, value);
}
protected void putProperties(ScriptEngine engine) {
for (Map.Entry<String, Object> variable : mGlobalVariableMap.entrySet()) {
engine.put(variable.getKey(), variable.getValue());
}
}
@Nullable
public ScriptEngine createEngine(String name) {
Supplier<ScriptEngine> s = mEngines.get(name);
if (s == null) {
return null;
}
ScriptEngine engine = s.get();
putProperties(engine);
return engine;
}
@Nullable
public ScriptEngine createEngineOfSource(ScriptSource source) {
return createEngine(source.getEngineName());
}
@NonNull
public ScriptEngine createEngineByNameOrThrow(String name) {
ScriptEngine engine = createEngine(name);
if (engine == null)
throw new EngineNotFoundException("name: " + name);
return engine;
}
@NonNull
public ScriptEngine createEngineOfSourceOrThrow(ScriptSource source) {
ScriptEngine engine = createEngineOfSource(source);
if (engine == null)
throw new EngineNotFoundException("source: " + source.toString());
return engine;
}
public void registerEngine(String name, Supplier<ScriptEngine> supplier) {
mEngines.put(name, supplier);
}
public void unregisterEngine(String name) {
mEngines.remove(name);
}
}

View File

@@ -1,31 +1,140 @@
package com.stardust.autojs.engine; package com.stardust.autojs.engine;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.stardust.autojs.script.ScriptSource;
import com.stardust.util.Supplier;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set; import java.util.Set;
/** /**
* Created by Stardust on 2017/5/7. * Created by Stardust on 2017/1/27.
*/ */
public interface ScriptEngineManager { public class ScriptEngineManager {
public interface EngineLifecycleCallback {
interface EngineLifecycleCallback {
void onEngineCreate(ScriptEngine engine); void onEngineCreate(ScriptEngine engine);
void onEngineRemove(ScriptEngine engine); void onEngineRemove(ScriptEngine engine);
} }
ScriptEngine createEngine(); private static final String TAG = "ScriptEngineManager";
void putGlobal(String varName, Object value); private final Set<ScriptEngine> mEngines = new HashSet<>();
private EngineLifecycleCallback mEngineLifecycleCallback;
private Map<String, Supplier<ScriptEngine>> mEngineSuppliers = new HashMap<>();
private Map<String, Object> mGlobalVariableMap = new HashMap<>();
private android.content.Context mAndroidContext;
private ScriptEngine.OnDestroyListener mOnEngineDestroyListener = new ScriptEngine.OnDestroyListener() {
@Override
public void onDestroy(ScriptEngine engine) {
removeEngine(engine);
}
};
void setEngineLifecycleCallback(EngineLifecycleCallback engineLifecycleCallback); public ScriptEngineManager(Context androidContext) {
mAndroidContext = androidContext;
}
void removeEngine(ScriptEngine engine); private void addEngine(ScriptEngine engine) {
engine.setOnDestroyListener(mOnEngineDestroyListener);
synchronized (mEngines) {
mEngines.add(engine);
if (mEngineLifecycleCallback != null) {
mEngineLifecycleCallback.onEngineCreate(engine);
}
}
}
Set<ScriptEngine> getEngines(); public void setEngineLifecycleCallback(EngineLifecycleCallback engineLifecycleCallback) {
mEngineLifecycleCallback = engineLifecycleCallback;
}
int stopAll(); public Set<ScriptEngine> getEngines() {
return mEngines;
}
public android.content.Context getAndroidContext() {
return mAndroidContext;
}
public void removeEngine(ScriptEngine engine) {
synchronized (mEngines) {
if (mEngines.remove(engine) && mEngineLifecycleCallback != null) {
mEngineLifecycleCallback.onEngineRemove(engine);
}
}
}
public int stopAll() {
synchronized (mEngines) {
int n = mEngines.size();
for (ScriptEngine engine : mEngines) {
engine.forceStop();
}
return n;
}
}
public void putGlobal(String varName, Object value) {
mGlobalVariableMap.put(varName, value);
}
protected void putProperties(ScriptEngine engine) {
for (Map.Entry<String, Object> variable : mGlobalVariableMap.entrySet()) {
engine.put(variable.getKey(), variable.getValue());
}
}
@Nullable
public ScriptEngine createEngine(String name) {
Supplier<ScriptEngine> s = mEngineSuppliers.get(name);
if (s == null) {
return null;
}
ScriptEngine engine = s.get();
putProperties(engine);
addEngine(engine);
return engine;
}
@Nullable
public ScriptEngine createEngineOfSource(ScriptSource source) {
return createEngine(source.getEngineName());
}
@NonNull
public ScriptEngine createEngineByNameOrThrow(String name) {
ScriptEngine engine = createEngine(name);
if (engine == null)
throw new ScriptEngineFactory.EngineNotFoundException("name: " + name);
return engine;
}
@NonNull
public ScriptEngine createEngineOfSourceOrThrow(ScriptSource source) {
ScriptEngine engine = createEngineOfSource(source);
if (engine == null)
throw new ScriptEngineFactory.EngineNotFoundException("source: " + source.toString());
return engine;
}
public void registerEngine(String name, Supplier<ScriptEngine> supplier) {
mEngineSuppliers.put(name, supplier);
}
public void unregisterEngine(String name) {
mEngineSuppliers.remove(name);
}
} }

View File

@@ -1,8 +0,0 @@
package com.stardust.autojs.engine.preprocess;
/**
* Created by Stardust on 2017/8/1.
*/
public class RootAutomatorEngine {
}

View File

@@ -29,7 +29,7 @@ public class ExecutionConfig implements Serializable {
return this; return this;
} }
public String[] getRequirePath() { public String[] getExecutePath() {
return mRequirePath; return mRequirePath;
} }

View File

@@ -1,34 +0,0 @@
package com.stardust.autojs.execution;
import com.stardust.autojs.ScriptEngineService;
import com.stardust.autojs.engine.ScriptEngine;
import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.autojs.runtime.api.AbstractShell;
import com.stardust.autojs.runtime.api.ProcessShell;
import com.stardust.util.IntentExtras;
import java.util.HashMap;
import java.util.Map;
/**
* Created by Stardust on 2017/7/16.
*/
public class RootedScriptExecution extends RunnableScriptExecution {
private static int count = 0;
private static Map<String, ScriptExecutionTask> arguments = new HashMap<>();
public RootedScriptExecution(ScriptEngineService service, ScriptExecutionTask task) {
super(service, task);
}
@Override
public void run() {
}
public static void main(String[] args) {
}
}

View File

@@ -2,27 +2,24 @@ package com.stardust.autojs.execution;
import android.util.Log; import android.util.Log;
import com.stardust.autojs.ScriptEngineService;
import com.stardust.autojs.engine.RhinoJavaScriptEngine;
import com.stardust.autojs.engine.ScriptEngine; import com.stardust.autojs.engine.ScriptEngine;
import com.stardust.autojs.engine.ScriptEngineManager;
import com.stardust.autojs.runtime.ScriptInterruptedException; import com.stardust.autojs.runtime.ScriptInterruptedException;
import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.autojs.script.ScriptSource; import com.stardust.autojs.script.ScriptSource;
/** /**
* Created by Stardust on 2017/5/1. * Created by Stardust on 2017/5/1.
*/ */
public class RunnableScriptExecution extends ScriptExecution.AbstractScriptExecution implements ScriptExecution, Runnable { public class RunnableScriptExecution extends ScriptExecution.AbstractScriptExecution implements Runnable {
private static final String TAG = "RunnableScriptExecution"; private static final String TAG = "RunnableJSExecution";
private ScriptEngine mScriptEngine; private ScriptEngine mScriptEngine;
private ScriptRuntime mScriptRuntime; private ScriptEngineManager mScriptEngineManager;
private ScriptEngineService mScriptEngineService;
public RunnableScriptExecution(ScriptEngineService service, ScriptExecutionTask task) { public RunnableScriptExecution(ScriptEngineManager manager, ScriptExecutionTask task) {
super(task); super(task);
mScriptEngineService = service; mScriptEngineManager = manager;
} }
@Override @Override
@@ -31,14 +28,13 @@ public class RunnableScriptExecution extends ScriptExecution.AbstractScriptExecu
} }
public Object execute() { public Object execute() {
mScriptEngine = mScriptEngineService.createScriptEngine(); mScriptEngine = mScriptEngineManager.createEngineOfSourceOrThrow(getSource());
mScriptRuntime = mScriptEngineService.createScriptRuntime(); return execute(mScriptEngine);
return execute(mScriptRuntime, mScriptEngine);
} }
private Object execute(ScriptRuntime runtime, ScriptEngine engine) { private Object execute(ScriptEngine engine) {
try { try {
prepare(runtime, engine); prepare(engine);
return doExecution(engine); return doExecution(engine);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@@ -50,17 +46,13 @@ public class RunnableScriptExecution extends ScriptExecution.AbstractScriptExecu
return null; return null;
} }
private void prepare(ScriptRuntime runtime, ScriptEngine engine) { private void prepare(ScriptEngine engine) {
if ((getSource().getExecutionMode() & ScriptSource.EXECUTION_MODE_AUTO) != 0) { engine.setTag(ScriptEngine.TAG_PATH, getConfig().getExecutePath());
runtime.ensureAccessibilityServiceEnabled();
}
engine.put("__runtime__", runtime);
engine.setTag("__require_path__", getConfig().getRequirePath());
engine.init(); engine.init();
} }
private Object doExecution(ScriptEngine engine) { private Object doExecution(ScriptEngine engine) {
engine.setTag("script", getSource()); engine.setTag(ScriptEngine.TAG_SOURCE, getSource());
getListener().onStart(this); getListener().onStart(this);
Object result = null; Object result = null;
long delay = getConfig().delay; long delay = getConfig().delay;
@@ -95,8 +87,4 @@ public class RunnableScriptExecution extends ScriptExecution.AbstractScriptExecu
return mScriptEngine; return mScriptEngine;
} }
@Override
public ScriptRuntime getRuntime() {
return mScriptRuntime;
}
} }

View File

@@ -1,17 +1,14 @@
package com.stardust.autojs.execution; package com.stardust.autojs.execution;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import com.stardust.autojs.R;
import com.stardust.autojs.ScriptEngineService;
import com.stardust.autojs.engine.ScriptEngine; import com.stardust.autojs.engine.ScriptEngine;
import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.autojs.engine.ScriptEngineManager;
import com.stardust.autojs.script.ScriptSource; import com.stardust.autojs.script.ScriptSource;
import com.stardust.util.IntentExtras;
/** /**
* Created by Stardust on 2017/2/5. * Created by Stardust on 2017/2/5.
@@ -20,33 +17,36 @@ import com.stardust.autojs.script.ScriptSource;
public class ScriptExecuteActivity extends AppCompatActivity { public class ScriptExecuteActivity extends AppCompatActivity {
private static ActivityScriptExecution execution; private static final String EXTRA_EXECUTION = ScriptExecuteActivity.class.getName() + ".execution";
private Object mResult; private Object mResult;
private ScriptEngine mScriptEngine; private ScriptEngine mScriptEngine;
private ScriptExecutionListener mExecutionListener; private ScriptExecutionListener mExecutionListener;
private ScriptSource mScriptSource; private ScriptSource mScriptSource;
private ScriptExecution mScriptExecution;
public static ActivityScriptExecution execute(Context context, ScriptEngineService service, ScriptExecutionTask task) { public static ActivityScriptExecution execute(Context context, ScriptEngineManager manager, ScriptExecutionTask task) {
if (execution != null) { ActivityScriptExecution execution = new ActivityScriptExecution(manager, task);
return null; Intent i = new Intent(context, ScriptExecuteActivity.class)
} .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
IntentExtras.newExtras()
execution = new ActivityScriptExecution(service, task); .put(EXTRA_EXECUTION, execution)
context.startActivity(new Intent(context, ScriptExecuteActivity.class) .putInIntent(i);
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); context.startActivity(i);
return execution; return execution;
} }
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if (execution == null) { IntentExtras extras = IntentExtras.fromIntent(getIntent());
if (extras == null || extras.get(EXTRA_EXECUTION) == null) {
finish(); finish();
return; return;
} }
mScriptSource = execution.getSource(); mScriptExecution = extras.get(EXTRA_EXECUTION);
mScriptEngine = execution.getEngine(); mScriptSource = mScriptExecution.getSource();
mExecutionListener = execution.getListener(); mScriptEngine = mScriptExecution.getEngine();
mExecutionListener = mScriptExecution.getListener();
runScript(); runScript();
} }
@@ -55,27 +55,26 @@ public class ScriptExecuteActivity extends AppCompatActivity {
prepare(); prepare();
doExecution(); doExecution();
} catch (Exception e) { } catch (Exception e) {
mExecutionListener.onException(execution, e); mExecutionListener.onException(mScriptExecution, e);
super.finish(); super.finish();
} }
} }
private void doExecution() { private void doExecution() {
mScriptEngine.setTag("script", mScriptSource); mScriptEngine.setTag(ScriptEngine.TAG_SOURCE, mScriptSource);
mExecutionListener.onStart(execution); mExecutionListener.onStart(mScriptExecution);
mResult = mScriptEngine.execute(mScriptSource); mResult = mScriptEngine.execute(mScriptSource);
} }
private void prepare() { private void prepare() {
mScriptEngine.put("activity", this); mScriptEngine.put("activity", this);
mScriptEngine.put("__runtime__", execution.getRuntime()); mScriptEngine.setTag(ScriptEngine.TAG_PATH, mScriptExecution.getConfig().getExecutePath());
mScriptEngine.setTag("__require_path__", execution.getConfig().getRequirePath());
mScriptEngine.init(); mScriptEngine.init();
} }
@Override @Override
public void finish() { public void finish() {
mExecutionListener.onSuccess(execution, mResult); mExecutionListener.onSuccess(mScriptExecution, mResult);
super.finish(); super.finish();
} }
@@ -84,36 +83,27 @@ public class ScriptExecuteActivity extends AppCompatActivity {
super.onDestroy(); super.onDestroy();
mScriptEngine.put("activity", null); mScriptEngine.put("activity", null);
mScriptEngine.destroy(); mScriptEngine.destroy();
execution = null; mScriptExecution = null;
} }
private static class ActivityScriptExecution extends ScriptExecution.AbstractScriptExecution { private static class ActivityScriptExecution extends ScriptExecution.AbstractScriptExecution {
private ScriptEngine mScriptEngine; private ScriptEngine mScriptEngine;
private ScriptRuntime mScriptRuntime; private ScriptEngineManager mScriptEngineManager;
private ScriptEngineService mScriptEngineService;
ActivityScriptExecution(ScriptEngineService service, ScriptExecutionTask task) { ActivityScriptExecution(ScriptEngineManager manager, ScriptExecutionTask task) {
super(task); super(task);
mScriptEngineService = service; mScriptEngineManager = manager;
} }
@Override @Override
public ScriptEngine getEngine() { public ScriptEngine getEngine() {
if (mScriptEngine == null) { if (mScriptEngine == null) {
mScriptEngine = mScriptEngineService.createScriptEngine(); mScriptEngine = mScriptEngineManager.createEngineOfSourceOrThrow(getSource());
} }
return mScriptEngine; return mScriptEngine;
} }
@Override
public ScriptRuntime getRuntime() {
if (mScriptRuntime == null) {
mScriptRuntime = mScriptEngineService.createScriptRuntime();
}
return mScriptRuntime;
}
} }

View File

@@ -12,8 +12,6 @@ public interface ScriptExecution {
ScriptEngine getEngine(); ScriptEngine getEngine();
ScriptRuntime getRuntime();
ScriptSource getSource(); ScriptSource getSource();
ScriptExecutionListener getListener(); ScriptExecutionListener getListener();
@@ -31,9 +29,6 @@ public interface ScriptExecution {
@Override @Override
public abstract ScriptEngine getEngine(); public abstract ScriptEngine getEngine();
@Override
public abstract ScriptRuntime getRuntime();
@Override @Override
public ScriptSource getSource() { public ScriptSource getSource() {
return mScriptExecutionTask.getSource(); return mScriptExecutionTask.getSource();

View File

@@ -106,7 +106,6 @@ public abstract class AbstractShell {
private int scaleY(int y) { private int scaleY(int y) {
return mScreenMetrics.scaleY(y); return mScreenMetrics.scaleY(y);
} }
public void Tap(int x, int y) { public void Tap(int x, int y) {
@@ -114,7 +113,7 @@ public abstract class AbstractShell {
} }
public void Swipe(int x1, int y1, int x2, int y2) { public void Swipe(int x1, int y1, int x2, int y2) {
exec(com.stardust.util.TextUtils.join(" ", "input", "tap", scaleX(x1), scaleY(y1), scaleX(x2), scaleY(y2))); exec(com.stardust.util.TextUtils.join(" ", "input", "swipe", scaleX(x1), scaleY(y1), scaleX(x2), scaleY(y2)));
} }
public void Swipe(int x1, int y1, int x2, int y2, int time) { public void Swipe(int x1, int y1, int x2, int y2, int time) {

View File

@@ -17,7 +17,7 @@ import java.io.Reader;
* 来自网络~~ * 来自网络~~
*/ */
public class ProcessShell extends AbstractShell implements AutoCloseable { public class ProcessShell extends AbstractShell {
private static final String TAG = "ProcessShell"; private static final String TAG = "ProcessShell";
@@ -87,11 +87,6 @@ public class ProcessShell extends AbstractShell implements AutoCloseable {
} }
@Override
public void close() {
exit();
}
@Override @Override
public void exitAndWaitFor() { public void exitAndWaitFor() {
exec(COMMAND_EXIT); exec(COMMAND_EXIT);
@@ -158,7 +153,9 @@ public class ProcessShell extends AbstractShell implements AutoCloseable {
} }
public static Result exec(String[] commands, boolean isRoot) { public static Result exec(String[] commands, boolean isRoot) {
try (ProcessShell shell = new ProcessShell(isRoot)) { ProcessShell shell = null;
try {
shell = new ProcessShell(isRoot);
for (String command : commands) { for (String command : commands) {
shell.exec(command); shell.exec(command);
} }
@@ -170,6 +167,10 @@ public class ProcessShell extends AbstractShell implements AutoCloseable {
result.result = shell.getSucceedOutput().toString(); result.result = shell.getSucceedOutput().toString();
shell.exit(); shell.exit();
return result; return result;
} finally {
if (shell != null) {
shell.exit();
}
} }
} }
@@ -195,7 +196,6 @@ public class ProcessShell extends AbstractShell implements AutoCloseable {
os.writeBytes(COMMAND_EXIT); os.writeBytes(COMMAND_EXIT);
os.flush(); os.flush();
commandResult.code = process.waitFor(); commandResult.code = process.waitFor();
//获取错误信息
successMsg = new StringBuilder(); successMsg = new StringBuilder();
errorMsg = new StringBuilder(); errorMsg = new StringBuilder();
successResult = new BufferedReader(new InputStreamReader(process.getInputStream())); successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));

View File

@@ -2,7 +2,7 @@ package com.stardust.autojs.runtime.api;
import android.content.Context; import android.content.Context;
import com.stardust.pio.PFile; import com.stardust.autojs.engine.RootAutomatorEngine;
import com.stardust.pio.UncheckedIOException; import com.stardust.pio.UncheckedIOException;
import com.stardust.util.ScreenMetrics; import com.stardust.util.ScreenMetrics;
@@ -18,10 +18,9 @@ import java.io.IOException;
public class RootAutomator { public class RootAutomator {
private static final int DATA_TYPE_SLEEP = 0; public static final byte DATA_TYPE_SLEEP = 0;
private static final int DATA_TYPE_EVENT = 1; public static final byte DATA_TYPE_EVENT = 1;
private static final String ROOT_AUTOMATOR_EXECUTABLE_ASSET = "binary/root_automator";
private DataOutputStream mTmpFileOutputStream; private DataOutputStream mTmpFileOutputStream;
private File mEventTmpFile; private File mEventTmpFile;
private ScreenMetrics mScreenMetrics; private ScreenMetrics mScreenMetrics;
@@ -88,24 +87,11 @@ public class RootAutomator {
} }
public AbstractShell.Result writeToDevice(Context context) { public AbstractShell.Result writeToDevice(Context context) {
try { if (mDevicePath == null) {
mTmpFileOutputStream.close(); return new RootAutomatorEngine(context).execute(mEventTmpFile.getAbsolutePath());
} catch (IOException e) { } else {
e.printStackTrace(); return new RootAutomatorEngine(context, mDevicePath).execute(mEventTmpFile.getAbsolutePath());
} }
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();
} }
} }

View File

@@ -1,8 +0,0 @@
package com.stardust.autojs.runtime.record.inputevent;
/**
* Created by Stardust on 2017/8/1.
*/
public class InputDevice {
}

View File

@@ -0,0 +1,31 @@
package com.stardust.autojs.runtime.record.inputevent;
import android.content.Context;
import android.hardware.input.InputManager;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.InputDevice;
/**
* Created by Stardust on 2017/8/1.
*/
public class InputDevices {
@Nullable
public static String getTouchDeviceName() {
for (int id : InputDevice.getDeviceIds()) {
InputDevice device = InputDevice.getDevice(id);
if (supportSource(device, InputDevice.SOURCE_TOUCHSCREEN) || supportSource(device, InputDevice.SOURCE_TOUCHPAD)) {
return device.getName();
}
}
return null;
}
private static boolean supportSource(InputDevice device, int source) {
return (device.getSources() & source) == source;
}
}

View File

@@ -0,0 +1,104 @@
package com.stardust.autojs.runtime.record.inputevent;
import android.support.annotation.NonNull;
import com.stardust.autojs.engine.RootAutomatorEngine;
import com.stardust.autojs.runtime.api.RootAutomator;
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/8/2.
*/
public class InputEventToAutoFileConverter extends InputEventConverter {
private double mLastEventTime;
private int mTouchDevice = -1;
private DataOutputStream mDataOutputStream;
private File mTmpFile;
public InputEventToAutoFileConverter() {
try {
mTmpFile = File.createTempFile("Record" + System.currentTimeMillis(), ".auto");
mDataOutputStream = new DataOutputStream(new FileOutputStream(mTmpFile));
writeFileHeader();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
private void writeFileHeader() throws IOException {
mDataOutputStream.writeInt(0x00B87B6D);
mDataOutputStream.writeInt(RootAutomatorEngine.VERSION);
mDataOutputStream.writeInt(ScreenMetrics.getDeviceScreenWidth());
mDataOutputStream.writeInt(ScreenMetrics.getDeviceScreenHeight());
for (int i = 0; i < 240; i++) {
mDataOutputStream.writeByte(0);
}
}
@Override
public void convertEvent(@NonNull InputEventConverter.Event event) {
try {
convertEventOrThrow(event);
} catch (IOException e) {
e.printStackTrace();
}
}
private void convertEventOrThrow(Event event) throws IOException {
if (mLastEventTime == 0) {
mLastEventTime = event.time;
} else if (event.time - mLastEventTime > 0.001) {
mDataOutputStream.writeByte(RootAutomator.DATA_TYPE_SLEEP);
int n = (int) (1000L * (event.time - mLastEventTime));
mDataOutputStream.writeInt(n);
mLastEventTime = event.time;
}
int device = parseDeviceNumber(event.device);
short type = (short) Long.parseLong(event.type, 16);
short code = (short) Long.parseLong(event.code, 16);
int value = (int) Long.parseLong(event.value, 16);
if (type == 3) {
if (code == 53 || code == 54) {
mTouchDevice = device;
RootAutomatorEngine.setTouchDevice(device);
}
}
if (device != mTouchDevice) {
return;
}
mDataOutputStream.writeByte(RootAutomator.DATA_TYPE_EVENT);
mDataOutputStream.writeShort(type);
mDataOutputStream.writeShort(code);
mDataOutputStream.writeInt(value);
}
@Override
public String getGetEventCommand() {
return "getevent -t";
}
public String getCode() {
return mTmpFile.getAbsolutePath();
}
@Override
public void stop() {
super.stop();
try {
mDataOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@@ -32,7 +32,7 @@ public class InputEventToRootAutomatorConverter extends InputEventConverter {
public void convertEvent(@NonNull Event event) { public void convertEvent(@NonNull Event event) {
if (mLastEventTime == 0) { if (mLastEventTime == 0) {
mLastEventTime = event.time; mLastEventTime = event.time;
} else if (event.time - mLastEventTime > 0.005) { } else if (event.time - mLastEventTime > 0.001) {
mCode.append("ra.sleep(").append((long) (1000L * (event.time - mLastEventTime))).append(");\n"); mCode.append("ra.sleep(").append((long) (1000L * (event.time - mLastEventTime))).append(");\n");
mLastEventTime = event.time; mLastEventTime = event.time;
} }

View File

@@ -9,7 +9,7 @@ import android.content.Context;
public class TouchRecorder extends InputEventRecorder { public class TouchRecorder extends InputEventRecorder {
public TouchRecorder(Context context) { public TouchRecorder(Context context) {
super(context, new InputEventToRootAutomatorConverter()); super(context, new InputEventToAutoFileConverter());
listen(); listen();
} }

View File

@@ -0,0 +1,38 @@
package com.stardust.autojs.script;
import android.support.annotation.NonNull;
import com.stardust.pio.PFile;
import java.io.File;
import java.io.Reader;
/**
* Created by Stardust on 2017/8/2.
*/
public class AutoFileSource extends ScriptSource {
public static final String ENGINE = AutoFileSource.class.getName() + ".Engine";
private File mFile;
public AutoFileSource(File file) {
super(PFile.getNameWithoutExtension(file.getAbsolutePath()));
mFile = file;
}
public AutoFileSource(String path) {
this(new File(path));
}
@Override
public String getEngineName() {
return ENGINE;
}
public File getFile() {
return mFile;
}
}

View File

@@ -1,6 +1,7 @@
package com.stardust.autojs.script; package com.stardust.autojs.script;
import com.stardust.autojs.script.ScriptSource; import android.support.annotation.NonNull;
import com.stardust.pio.PFile; import com.stardust.pio.PFile;
import com.stardust.pio.UncheckedIOException; import com.stardust.pio.UncheckedIOException;
@@ -13,25 +14,26 @@ import java.io.Reader;
* Created by Stardust on 2017/4/2. * Created by Stardust on 2017/4/2.
*/ */
public class FileScriptSource extends ScriptSource { public class JavaScriptFileSource extends JavaScriptSource {
private File mFile; private File mFile;
private String mScript; private String mScript;
public FileScriptSource(File file) { public JavaScriptFileSource(File file) {
super(PFile.getNameWithoutExtension(file.getName())); super(PFile.getNameWithoutExtension(file.getName()));
mFile = file; mFile = file;
} }
public FileScriptSource(String path) { public JavaScriptFileSource(String path) {
this(new File(path)); this(new File(path));
} }
public FileScriptSource(String name, File file) { public JavaScriptFileSource(String name, File file) {
super(name); super(name);
mFile = file; mFile = file;
} }
@NonNull
@Override @Override
public String getScript() { public String getScript() {
if (mScript == null) if (mScript == null)
@@ -48,6 +50,10 @@ public class FileScriptSource extends ScriptSource {
} }
} }
public File getFile() {
return mFile;
}
@Override @Override
public String toString() { public String toString() {
return mFile.toString(); return mFile.toString();

View File

@@ -0,0 +1,90 @@
package com.stardust.autojs.script;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.stardust.util.MapEntries;
import java.io.Reader;
import java.io.StringReader;
import java.util.Map;
/**
* Created by Stardust on 2017/8/2.
*/
public abstract class JavaScriptSource extends ScriptSource {
public static final String ENGINE = "com.stardust.autojs.script.JavaScriptSource.Engine";
public static final int EXECUTION_MODE_NORMAL = 0;
public static final int EXECUTION_MODE_UI = 0x00000001;
public static final int EXECUTION_MODE_AUTO = 0x00000002;
private static final Map<String, Integer> EXECUTION_MODES = new MapEntries<String, Integer>()
.entry("ui", EXECUTION_MODE_UI)
.entry("auto", EXECUTION_MODE_AUTO)
.map();
private static final int EXECUTION_MODE_STRING_MAX_LENGTH = 7;
private int mExecutionMode = -1;
public JavaScriptSource(String name) {
super(name);
}
@NonNull
public abstract String getScript();
@Nullable
public abstract Reader getScriptReader();
@NonNull
public Reader getNonNullScriptReader() {
Reader reader = getScriptReader();
if (reader == null) {
return new StringReader(getScript());
}
return reader;
}
public String toString() {
return getName() + ".js";
}
public int getExecutionMode() {
if (mExecutionMode == -1) {
mExecutionMode = parseExecutionMode(getScript());
}
return mExecutionMode;
}
private int parseExecutionMode(String script) {
if (script == null || script.length() == 0 || script.charAt(0) != '"')
return EXECUTION_MODE_NORMAL;
int i = script.lastIndexOf("\";", EXECUTION_MODE_STRING_MAX_LENGTH + 2);
if (i == -1)
return EXECUTION_MODE_NORMAL;
String modeString = script.substring(1, i);
return parseExecutionMode(modeString.split(" "));
}
private int parseExecutionMode(String[] modeStrings) {
int mode = 0;
for (String modeString : modeStrings) {
Integer i = EXECUTION_MODES.get(modeString);
if (i != null) {
mode |= i;
}
}
return mode;
}
@Override
public String getEngineName() {
return ENGINE;
}
}

View File

@@ -19,17 +19,6 @@ import java.util.Map;
public abstract class ScriptSource implements Serializable { public abstract class ScriptSource implements Serializable {
public static final int EXECUTION_MODE_NORMAL = 0;
public static final int EXECUTION_MODE_UI = 0x00000001;
public static final int EXECUTION_MODE_AUTO = 0x00000002;
private static final Map<String, Integer> EXECUTION_MODES = new MapEntries<String, Integer>()
.entry("ui", EXECUTION_MODE_UI)
.entry("auto", EXECUTION_MODE_AUTO)
.map();
private static final int EXECUTION_MODE_STRING_MAX_LENGTH = 7;
private int mExecutionMode = -1;
private String mName; private String mName;
public ScriptSource(String name) { public ScriptSource(String name) {
@@ -40,51 +29,5 @@ public abstract class ScriptSource implements Serializable {
return mName; return mName;
} }
@NonNull public abstract String getEngineName();
public abstract String getScript();
@Nullable
public abstract Reader getScriptReader();
@NonNull
public Reader getNonNullScriptReader() {
Reader reader = getScriptReader();
if (reader == null) {
return new StringReader(getScript());
}
return reader;
}
public int getExecutionMode() {
if (mExecutionMode == -1) {
mExecutionMode = parseExecutionMode(getScript());
}
return mExecutionMode;
}
private int parseExecutionMode(String script) {
if (script == null || script.length() == 0 || script.charAt(0) != '"')
return EXECUTION_MODE_NORMAL;
int i = script.lastIndexOf("\";", EXECUTION_MODE_STRING_MAX_LENGTH + 2);
if (i == -1)
return EXECUTION_MODE_NORMAL;
String modeString = script.substring(1, i);
return parseExecutionMode(modeString.split(" "));
}
private int parseExecutionMode(String[] modeStrings) {
int mode = 0;
for (String modeString : modeStrings) {
Integer i = EXECUTION_MODES.get(modeString);
if (i != null) {
mode |= i;
}
}
return mode;
}
@Override
public String toString() {
return mName + ".js";
}
} }

View File

@@ -12,14 +12,14 @@ import java.io.StringReader;
* Created by Stardust on 2017/4/2. * Created by Stardust on 2017/4/2.
*/ */
public class SequenceScriptSource extends ScriptSource { public class SequenceScriptSource extends JavaScriptSource {
private String mScript; private String mScript;
private ScriptSource mSecondScriptSource; private JavaScriptSource mSecondScriptSource;
private ScriptSource mFirstScriptSource; private JavaScriptSource mFirstScriptSource;
public SequenceScriptSource(String name, ScriptSource firstScriptSource, ScriptSource secondScriptSource) { public SequenceScriptSource(String name, JavaScriptSource firstScriptSource, JavaScriptSource secondScriptSource) {
super(name); super(name);
mSecondScriptSource = secondScriptSource; mSecondScriptSource = secondScriptSource;
mFirstScriptSource = firstScriptSource; mFirstScriptSource = firstScriptSource;

View File

@@ -9,7 +9,7 @@ import java.io.Reader;
* Created by Stardust on 2017/4/2. * Created by Stardust on 2017/4/2.
*/ */
public class StringScriptSource extends ScriptSource { public class StringScriptSource extends JavaScriptSource {
private String mScript; private String mScript;

View File

@@ -2,8 +2,6 @@ package com.stardust.auojs.inrt;
import android.app.Application; import android.app.Application;
import com.stardust.auojs.inrt.rt.AutoJs;
/** /**
* Created by Stardust on 2017/7/1. * Created by Stardust on 2017/7/1.
*/ */
@@ -13,6 +11,5 @@ public class App extends Application {
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
AutoJs.initInstance(this);
} }
} }

View File

@@ -3,8 +3,6 @@ package com.stardust.auojs.inrt;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.os.Bundle; import android.os.Bundle;
import com.stardust.auojs.inrt.rt.AutoJs;
import com.stardust.autojs.execution.ExecutionConfig;
import com.stardust.autojs.script.StringScriptSource; import com.stardust.autojs.script.StringScriptSource;
import java.io.IOException; import java.io.IOException;
@@ -21,7 +19,7 @@ public class MainActivity extends AppCompatActivity {
is.read(data); is.read(data);
String js = new String(data); String js = new String(data);
StringScriptSource source = new StringScriptSource("<script>", js); StringScriptSource source = new StringScriptSource("<script>", js);
AutoJs.getInstance().getScriptEngineService().execute(source); //AutoJs.getInstance().getScriptEngineService().execute(source);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }

View File

@@ -1,163 +0,0 @@
package com.stardust.auojs.inrt.rt;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import com.stardust.app.OnActivityResultDelegate;
import com.stardust.app.SimpleActivityLifecycleCallbacks;
import com.stardust.auojs.inrt.R;
import com.stardust.autojs.ScriptEngineService;
import com.stardust.autojs.ScriptEngineServiceBuilder;
import com.stardust.autojs.engine.RhinoJavaScriptEngineManager;
import com.stardust.autojs.engine.ScriptEngineManager;
import com.stardust.autojs.runtime.AccessibilityBridge;
import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.autojs.runtime.ScriptStopException;
import com.stardust.autojs.runtime.api.AbstractShell;
import com.stardust.autojs.runtime.api.AppUtils;
import com.stardust.autojs.runtime.api.Shell;
import com.stardust.autojs.runtime.api.image.ScreenCaptureRequestActivity;
import com.stardust.autojs.runtime.api.image.ScreenCaptureRequester;
import com.stardust.autojs.runtime.console.StardustConsole;
import com.stardust.util.ScreenMetrics;
import com.stardust.util.Supplier;
import com.stardust.util.UiHandler;
import com.stardust.view.accessibility.AccessibilityInfoProvider;
import com.stardust.view.accessibility.AccessibilityService;
import com.stardust.view.accessibility.AccessibilityServiceUtils;
/**
* Created by Stardust on 2017/7/1.
*/
public class AutoJs {
private static AutoJs instance;
public static AutoJs getInstance() {
return instance;
}
public static void initInstance(Application context) {
instance = new AutoJs(context);
}
private final ScriptEngineService mScriptEngineService;
private final AccessibilityInfoProvider mAccessibilityInfoProvider;
private final UiHandler mUiHandler;
private final AppUtils mAppUtils;
private final Application mApplication;
private final ScreenCaptureRequester mScreenCaptureRequester = new ScreenCaptureRequester.AbstractScreenCaptureRequester() {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void request() {
Activity activity = mAppUtils.getCurrentActivity();
if (activity instanceof OnActivityResultDelegate.DelegateHost) {
ScreenCaptureRequester requester = new ActivityScreenCaptureRequester(
((OnActivityResultDelegate.DelegateHost) activity).getOnActivityResultDelegateMediator(), activity);
requester.setOnActivityResultCallback(mCallback);
requester.request();
} else {
ScreenCaptureRequestActivity.request(mUiHandler.getContext(), mCallback);
}
}
};
private AutoJs(final Application application) {
mApplication = application;
final Context context = application.getApplicationContext();
mUiHandler = new UiHandler(context);
mAppUtils = new AppUtils(context);
mAccessibilityInfoProvider = new AccessibilityInfoProvider(context.getPackageManager());
ScriptEngineManager manager = createScriptEngineManager(context);
mScriptEngineService = new ScriptEngineServiceBuilder()
.uiHandler(mUiHandler)
.engineManger(manager)
.runtime(new Supplier<ScriptRuntime>() {
@Override
public ScriptRuntime get() {
return new ScriptRuntime.Builder()
.setConsole(new StardustConsole(mUiHandler))
.setScreenCaptureRequester(mScreenCaptureRequester)
// TODO: 2017/7/31
.setAccessibilityBridge(null)
.setUiHandler(mUiHandler)
.setAppUtils(mAppUtils)
.setShellSupplier(new Supplier<AbstractShell>() {
@Override
public AbstractShell get() {
return new Shell(context, true);
}
}).build();
}
})
.build();
addAccessibilityServiceDelegates();
registerActivityLifecycleCallbacks();
}
private void registerActivityLifecycleCallbacks() {
mApplication.registerActivityLifecycleCallbacks(new SimpleActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
ScreenMetrics.initIfNeeded(activity);
mAppUtils.setCurrentActivity(activity);
}
@Override
public void onActivityPaused(Activity activity) {
mAppUtils.setCurrentActivity(null);
}
@Override
public void onActivityResumed(Activity activity) {
mAppUtils.setCurrentActivity(activity);
}
});
}
private ScriptEngineManager createScriptEngineManager(Context context) {
return new RhinoJavaScriptEngineManager(context);
}
private void addAccessibilityServiceDelegates() {
AccessibilityService.addDelegate(100, mAccessibilityInfoProvider);
}
@Nullable
public AccessibilityService getService() {
return AccessibilityService.getInstance();
}
public void ensureServiceEnabled() {
Context context = mApplication.getApplicationContext();
if (AccessibilityService.getInstance() == null) {
String errorMessage = null;
if (AccessibilityServiceUtils.isAccessibilityServiceEnabled(context, AccessibilityService.class)) {
errorMessage = context.getString(R.string.text_auto_operate_service_enabled_but_not_running);
} else {
errorMessage = context.getString(R.string.text_no_accessibility_permission);
}
AccessibilityServiceUtils.goToAccessibilitySetting(context);
throw new ScriptStopException(errorMessage);
}
}
public AccessibilityInfoProvider getInfoProvider() {
return mAccessibilityInfoProvider;
}
public ScriptEngineService getScriptEngineService() {
return mScriptEngineService;
}
}