add: apk builder plugin support; fix: inrt AutoJs.ensureServiceEnabled

This commit is contained in:
hyb1996
2017-11-29 16:07:52 +08:00
parent 028c5c91f4
commit 6dfd35683a
20 changed files with 393 additions and 388 deletions

3
.idea/modules.xml generated
View File

@@ -2,7 +2,8 @@
<project version="4"> <project version="4">
<component name="ProjectModuleManager"> <component name="ProjectModuleManager">
<modules> <modules>
<module fileurl="file://$PROJECT_DIR$/Auto.js.iml" filepath="$PROJECT_DIR$/Auto.js.iml" /> <module fileurl="file://E:\YiBin\AndroidStudioProjects\NoRootScriptDroid\Auto.js.iml" filepath="E:\YiBin\AndroidStudioProjects\NoRootScriptDroid\Auto.js.iml" />
<module fileurl="file://$PROJECT_DIR$/NoRootScriptDroid.iml" filepath="$PROJECT_DIR$/NoRootScriptDroid.iml" />
<module fileurl="file://C:\Users\Stardust\Documents\AndroidProjects\Auto.js\NoRootScriptDroid.iml" filepath="C:\Users\Stardust\Documents\AndroidProjects\Auto.js\NoRootScriptDroid.iml" /> <module fileurl="file://C:\Users\Stardust\Documents\AndroidProjects\Auto.js\NoRootScriptDroid.iml" filepath="C:\Users\Stardust\Documents\AndroidProjects\Auto.js\NoRootScriptDroid.iml" />
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" /> <module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
<module fileurl="file://$PROJECT_DIR$/autojs/autojs.iml" filepath="$PROJECT_DIR$/autojs/autojs.iml" /> <module fileurl="file://$PROJECT_DIR$/autojs/autojs.iml" filepath="$PROJECT_DIR$/autojs/autojs.iml" />

View File

@@ -8,8 +8,8 @@ android {
applicationId "com.stardust.scriptdroid" applicationId "com.stardust.scriptdroid"
minSdkVersion 17 minSdkVersion 17
targetSdkVersion 23 targetSdkVersion 23
versionCode 224 versionCode 226
versionName "3.0.0 Alpha2" versionName "3.0.0 Alpha26"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true multiDexEnabled true
ndk { ndk {
@@ -83,8 +83,6 @@ dependencies {
compile('com.afollestad.material-dialogs:core:0.9.2.3', { compile('com.afollestad.material-dialogs:core:0.9.2.3', {
exclude group: 'com.android.support' exclude group: 'com.android.support'
}) })
// Gson
compile 'com.google.code.gson:gson:2.8.0'
// Common Markdown // Common Markdown
compile 'com.github.atlassian:commonmark-java:commonmark-parent-0.9.0' compile 'com.github.atlassian:commonmark-java:commonmark-parent-0.9.0'
// AlipayZeroSdk // AlipayZeroSdk

View File

@@ -0,0 +1,9 @@
var url = "www.baidu.com";
var res = http.get(url);
if(res.statusCode == 200){
toast("请求成功");
console.show();
log(res.body.string());
}else{
toast("请求失败:" + res.statusMessage);
}

View File

@@ -1,6 +1,7 @@
package com.stardust.scriptdroid.autojs; package com.stardust.scriptdroid.autojs;
import android.app.Activity; import android.app.Activity;
import android.app.Application;
import android.content.Context; import android.content.Context;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
@@ -52,7 +53,7 @@ import org.opencv.android.OpenCVLoader;
* Created by Stardust on 2017/4/2. * Created by Stardust on 2017/4/2.
*/ */
public class AutoJs { public class AutoJs extends com.stardust.autojs.AutoJs {
private static AutoJs instance; private static AutoJs instance;
@@ -64,24 +65,15 @@ public class AutoJs {
instance = new AutoJs(context); instance = new AutoJs(context);
} }
private final AccessibilityActionRecorder mAccessibilityActionRecorder = new AccessibilityActionRecorder();
private final AccessibilityNotificationObserver mNotificationObserver;
private ScriptEngineManager mScriptEngineManager;
private final LayoutInspector mLayoutInspector = new LayoutInspector();
private final Context mContext;
private final UiHandler mUiHandler;
private final AppUtils mAppUtils;
private final AccessibilityInfoProvider mAccessibilityInfoProvider;
private final ScreenCaptureRequester mScreenCaptureRequester = new ScreenCaptureRequesterImpl();
private final ScriptEngineService mScriptEngineService;
private final Console mGlobalConsole;
private AutoJs(final Context context) { private AutoJs(final Context context) {
mContext = context; super(context);
mUiHandler = new UiHandler(context); getScriptEngineService().registerGlobalScriptExecutionListener(new ScriptExecutionGlobalListener());
mAppUtils = new AppUtils(context); }
mGlobalConsole = new GlobalStardustConsole(mUiHandler) {
@Override
protected Console createGlobalConsole() {
return new GlobalStardustConsole(getUiHandler()) {
@Override @Override
public String println(int level, CharSequence charSequence) { public String println(int level, CharSequence charSequence) {
String log = super.println(level, charSequence); String log = super.println(level, charSequence);
@@ -89,172 +81,33 @@ public class AutoJs {
return log; return log;
} }
}; };
mNotificationObserver = new AccessibilityNotificationObserver(context);
mAccessibilityInfoProvider = new AccessibilityInfoProvider(context.getPackageManager());
mScriptEngineService = buildScriptEngineService();
addAccessibilityServiceDelegates();
mScriptEngineService.registerGlobalScriptExecutionListener(new ScriptExecutionGlobalListener());
registerActivityLifecycleCallbacks();
InputEventObserver.initGlobal(context);
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_13, context, new BaseLoaderCallback(context) {
});
}
private ScriptEngineService buildScriptEngineService() {
initScriptEngineManager();
return new ScriptEngineServiceBuilder()
.uiHandler(mUiHandler)
.globalConsole(mGlobalConsole)
.engineManger(mScriptEngineManager)
.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)
.setEngineService(mScriptEngineService)
.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() {
App.getApp().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 void addAccessibilityServiceDelegates() {
AccessibilityService.addDelegate(100, mAccessibilityInfoProvider);
AccessibilityService.addDelegate(200, mNotificationObserver);
AccessibilityService.addDelegate(300, mAccessibilityActionRecorder);
}
public AccessibilityActionRecorder getAccessibilityActionRecorder() {
return mAccessibilityActionRecorder;
}
public AppUtils getAppUtils() {
return mAppUtils;
}
public UiHandler getUiHandler() {
return mUiHandler;
}
public LayoutInspector getLayoutInspector() {
return mLayoutInspector;
}
public Console getGlobalConsole() {
return mGlobalConsole;
}
public ScriptEngineService getScriptEngineService() {
return mScriptEngineService;
}
public AccessibilityInfoProvider getInfoProvider() {
return mAccessibilityInfoProvider;
} }
public void ensureAccessibilityServiceEnabled() { public void ensureAccessibilityServiceEnabled() {
if (AccessibilityService.getInstance() == null) { if (AccessibilityService.getInstance() != null) {
String errorMessage = null; return;
if (AccessibilityServiceTool.isAccessibilityServiceEnabled(App.getApp())) { }
errorMessage = App.getApp().getString(R.string.text_auto_operate_service_enabled_but_not_running); String errorMessage = null;
} else { if (AccessibilityServiceTool.isAccessibilityServiceEnabled(App.getApp())) {
if (Pref.enableAccessibilityServiceByRoot()) { errorMessage = App.getApp().getString(R.string.text_auto_operate_service_enabled_but_not_running);
if (!AccessibilityServiceTool.enableAccessibilityServiceByRootAndWaitFor(2000)) { } else {
errorMessage = App.getApp().getString(R.string.text_enable_accessibility_service_by_root_timeout); if (Pref.enableAccessibilityServiceByRoot()) {
} if (!AccessibilityServiceTool.enableAccessibilityServiceByRootAndWaitFor(2000)) {
} else { errorMessage = App.getApp().getString(R.string.text_enable_accessibility_service_by_root_timeout);
errorMessage = App.getApp().getString(R.string.text_no_accessibility_permission);
} }
}
if (errorMessage != null) {
AccessibilityServiceTool.goToAccessibilitySetting();
throw new ScriptException(errorMessage);
}
}
}
private class AccessibilityBridgeImpl extends AccessibilityBridge {
@Override
public void ensureServiceEnabled() {
AutoJs.this.ensureAccessibilityServiceEnabled();
}
@Nullable
@Override
public AccessibilityService getService() {
return AccessibilityService.getInstance();
}
@Override
public AccessibilityInfoProvider getInfoProvider() {
return mAccessibilityInfoProvider;
}
@Override
public AccessibilityNotificationObserver getNotificationObserver() {
return mNotificationObserver;
}
}
private class ScreenCaptureRequesterImpl extends 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 { } else {
ScreenCaptureRequestActivity.request(mContext, mCallback); errorMessage = App.getApp().getString(R.string.text_no_accessibility_permission);
} }
} }
if (errorMessage != null) {
AccessibilityServiceTool.goToAccessibilitySetting();
throw new ScriptException(errorMessage);
}
} }
@Override
protected Application getApplication() {
return App.getApp();
}
} }

View File

@@ -0,0 +1,36 @@
package com.stardust.scriptdroid.build;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import com.stardust.pio.UncheckedIOException;
import com.stardust.util.DeveloperUtils;
import java.io.IOException;
import java.io.InputStream;
/**
* Created by Stardust on 2017/11/29.
*/
public class ApkBuilderPluginHelper {
private static final String PLUGIN_PACKAGE_NAME = "org.autojs.apkbuilderplugin";
private static final String TEMPLATE_APK_PATH = "template.apk";
public static boolean checkPlugin(Context context) {
return DeveloperUtils.checkSignature(context, PLUGIN_PACKAGE_NAME);
}
public static InputStream openTemplateApk(Context context) {
try {
return context.getPackageManager().getResourcesForApplication(PLUGIN_PACKAGE_NAME)
.getAssets().open(TEMPLATE_APK_PATH);
} catch (IOException e) {
throw new UncheckedIOException(e);
} catch (PackageManager.NameNotFoundException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -26,7 +26,7 @@ import io.reactivex.subjects.PublishSubject;
/** /**
* Created by Stardust on 2017/11/27. * Created by Stardust on 2017/11/27.
*/ */
//TODO rx
public class TimedTaskManager { public class TimedTaskManager {
@@ -75,23 +75,6 @@ public class TimedTaskManager {
} }
} }
private Flowable<TimedTask> getTaskById(int id) {
return RXSQLite.rx(SQLite.select()
.from(TimedTask.class)
.where(TimedTask_Table.id.is(id)))
.queryStreamResults()
.subscribeOn(Schedulers.io());
}
private Completable removeTask(int id) {
return RXSQLite.rx(SQLite.delete(TimedTaskDatabase.class)
.where(TimedTask_Table.id.is(id)))
.execute()
.subscribeOn(Schedulers.io());
}
public void cancelTask(TimedTask timedTask) { public void cancelTask(TimedTask timedTask) {
TimedTaskScheduler.cancel(mContext, timedTask); TimedTaskScheduler.cancel(mContext, timedTask);
mTimedTaskModelAdapter.delete(timedTask); mTimedTaskModelAdapter.delete(timedTask);

View File

@@ -1,17 +1,22 @@
package com.stardust.scriptdroid.ui.build; package com.stardust.scriptdroid.ui.build;
import android.content.Intent; import android.content.Intent;
import android.support.annotation.NonNull;
import android.util.Log; import android.util.Log;
import android.widget.EditText; import android.widget.EditText;
import android.widget.Toast; import android.widget.Toast;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog; import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.autojs.build.AutoJsApkBuilder; import com.stardust.scriptdroid.autojs.build.AutoJsApkBuilder;
import com.stardust.scriptdroid.build.ApkBuilderPluginHelper;
import com.stardust.scriptdroid.network.download.DownloadManager;
import com.stardust.scriptdroid.storage.file.StorageFileProvider; import com.stardust.scriptdroid.storage.file.StorageFileProvider;
import com.stardust.scriptdroid.model.script.ScriptFile; import com.stardust.scriptdroid.model.script.ScriptFile;
import com.stardust.scriptdroid.ui.BaseActivity; import com.stardust.scriptdroid.ui.BaseActivity;
import com.stardust.scriptdroid.ui.filechooser.FileChooserDialogBuilder; import com.stardust.scriptdroid.ui.filechooser.FileChooserDialogBuilder;
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
import com.stardust.util.IntentUtil; import com.stardust.util.IntentUtil;
import org.androidannotations.annotations.AfterViews; import org.androidannotations.annotations.AfterViews;
@@ -20,6 +25,7 @@ import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.ViewById; import org.androidannotations.annotations.ViewById;
import java.io.File; import java.io.File;
import java.io.InputStream;
import io.reactivex.Observable; import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
@@ -61,9 +67,28 @@ public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.Prog
if (sourcePath != null) { if (sourcePath != null) {
setupWithSourceFile(new ScriptFile(sourcePath)); setupWithSourceFile(new ScriptFile(sourcePath));
} }
showPluginDownloadDialogIfNeeded();
} }
private void showPluginDownloadDialogIfNeeded() {
if (ApkBuilderPluginHelper.checkPlugin(this)) {
return;
}
new ThemeColorMaterialDialogBuilder(this)
.content(R.string.no_apk_builder_plugin)
.positiveText(R.string.ok)
.negativeText(R.string.text_exit)
.onPositive((dialog, which) -> downloadPlugin())
.onNegative((dialog, which) -> finish())
.show();
}
private void downloadPlugin() {
// TODO: 2017/11/29
}
private void setupWithSourceFile(ScriptFile file) { private void setupWithSourceFile(ScriptFile file) {
mSourcePath.setText(file.getPath()); mSourcePath.setText(file.getPath());
mOutputPath.setText(file.getParent()); mOutputPath.setText(file.getParent());
@@ -102,6 +127,14 @@ public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.Prog
@Click(R.id.fab) @Click(R.id.fab)
void buildApk() { void buildApk() {
if (!ApkBuilderPluginHelper.checkPlugin(this)) {
Toast.makeText(this, R.string.text_apk_builder_plugin_unavailable, Toast.LENGTH_SHORT).show();
return;
}
doBuildingApk();
}
private void doBuildingApk() {
String jsPath = mSourcePath.getText().toString(); String jsPath = mSourcePath.getText().toString();
String versionName = mVersionName.getText().toString(); String versionName = mVersionName.getText().toString();
int versionCode = Integer.parseInt(mVersionCode.getText().toString()); int versionCode = Integer.parseInt(mVersionCode.getText().toString());
@@ -110,20 +143,21 @@ public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.Prog
File outApk = new File(mOutputPath.getText().toString(), File outApk = new File(mOutputPath.getText().toString(),
String.format("%s_v%s.apk", appName, versionName)); String.format("%s_v%s.apk", appName, versionName));
showProgressDialog(); showProgressDialog();
Observable.fromCallable(() -> Observable.fromCallable(() -> {
new AutoJsApkBuilder(getAssets().open("template.apk"), outApk, tmpDir.getPath()) InputStream templateApk = ApkBuilderPluginHelper.openTemplateApk(BuildActivity.this);
.setProgressCallback(BuildActivity.this) return new AutoJsApkBuilder(templateApk, outApk, tmpDir.getPath())
.prepare() .setProgressCallback(BuildActivity.this)
.withConfig(new AutoJsApkBuilder.AppConfig(appName, versionName, versionCode, jsPath)) .prepare()
.build() .withConfig(new AutoJsApkBuilder.AppConfig(appName, versionName, versionCode, jsPath))
.sign() .build()
.cleanWorkspace() .sign()
.cleanWorkspace();
}
) )
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(apkBuilder -> onBuildSuccessful(outApk), .subscribe(apkBuilder -> onBuildSuccessful(outApk),
this::onBuildFailed); this::onBuildFailed);
} }
private void showProgressDialog() { private void showProgressDialog() {

View File

@@ -330,4 +330,6 @@
<string name="text_day6"></string> <string name="text_day6"></string>
<string name="text_day7"></string> <string name="text_day7"></string>
<string name="text_weekly_task_should_check_day_of_week">至少选择一周中的一天</string> <string name="text_weekly_task_should_check_day_of_week">至少选择一周中的一天</string>
<string name="no_apk_builder_plugin">没有安装打包插件,是否立即下载?</string>
<string name="text_apk_builder_plugin_unavailable">打包插件不可用</string>
</resources> </resources>

View File

@@ -52,6 +52,8 @@ dependencies {
compile 'com.android.support:appcompat-v7:25.4.0' compile 'com.android.support:appcompat-v7:25.4.0'
compile 'com.github.hyb1996:EnhancedFloaty:0.17' compile 'com.github.hyb1996:EnhancedFloaty:0.17'
compile 'com.github.hyb1996:OpenCvLib:2.4.13.4-imgproc' compile 'com.github.hyb1996:OpenCvLib:2.4.13.4-imgproc'
// Gson
compile 'com.google.code.gson:gson:2.8.0'
// Terminal emulator // Terminal emulator
compile(name: 'libtermexec-release', ext: 'aar') compile(name: 'libtermexec-release', ext: 'aar')
compile(name: 'emulatorview-release', ext: 'aar') compile(name: 'emulatorview-release', ext: 'aar')

View File

@@ -0,0 +1,217 @@
package com.stardust.autojs;
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.autojs.core.accessibility.AccessibilityBridge;
import com.stardust.autojs.core.console.GlobalStardustConsole;
import com.stardust.autojs.core.console.StardustConsole;
import com.stardust.autojs.core.image.ScreenCaptureRequestActivity;
import com.stardust.autojs.core.image.ScreenCaptureRequester;
import com.stardust.autojs.core.inputevent.InputEventObserver;
import com.stardust.autojs.core.record.accessibility.AccessibilityActionRecorder;
import com.stardust.autojs.core.util.Shell;
import com.stardust.autojs.engine.LoopBasedJavaScriptEngine;
import com.stardust.autojs.engine.RootAutomatorEngine;
import com.stardust.autojs.engine.ScriptEngine;
import com.stardust.autojs.engine.ScriptEngineManager;
import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.autojs.runtime.api.AppUtils;
import com.stardust.autojs.runtime.api.Console;
import com.stardust.autojs.runtime.exception.ScriptException;
import com.stardust.autojs.script.AutoFileSource;
import com.stardust.autojs.script.JavaScriptSource;
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.AccessibilityNotificationObserver;
import com.stardust.view.accessibility.AccessibilityService;
import com.stardust.view.accessibility.LayoutInspector;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.OpenCVLoader;
/**
* Created by Stardust on 2017/11/29.
*/
public abstract class AutoJs {
private final AccessibilityActionRecorder mAccessibilityActionRecorder = new AccessibilityActionRecorder();
private final AccessibilityNotificationObserver mNotificationObserver;
private ScriptEngineManager mScriptEngineManager;
private final LayoutInspector mLayoutInspector = new LayoutInspector();
private final Context mContext;
private final UiHandler mUiHandler;
private final AppUtils mAppUtils;
private final AccessibilityInfoProvider mAccessibilityInfoProvider;
private final ScreenCaptureRequester mScreenCaptureRequester = new ScreenCaptureRequesterImpl();
private final ScriptEngineService mScriptEngineService;
private final Console mGlobalConsole;
protected AutoJs(final Context context) {
mContext = context;
mUiHandler = new UiHandler(context);
mAppUtils = new AppUtils(context);
mGlobalConsole = createGlobalConsole();
mNotificationObserver = new AccessibilityNotificationObserver(context);
mAccessibilityInfoProvider = new AccessibilityInfoProvider(context.getPackageManager());
mScriptEngineService = buildScriptEngineService();
init();
}
protected Console createGlobalConsole() {
return new GlobalStardustConsole(mUiHandler);
}
protected void init() {
addAccessibilityServiceDelegates();
registerActivityLifecycleCallbacks();
InputEventObserver.initGlobal(mContext);
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_13, mContext, new BaseLoaderCallback(mContext) {
});
}
public abstract void ensureAccessibilityServiceEnabled();
protected abstract Application getApplication();
protected ScriptEngineService buildScriptEngineService() {
initScriptEngineManager();
return new ScriptEngineServiceBuilder()
.uiHandler(mUiHandler)
.globalConsole(mGlobalConsole)
.engineManger(mScriptEngineManager)
.build();
}
protected void initScriptEngineManager() {
mScriptEngineManager = new ScriptEngineManager(mContext);
mScriptEngineManager.registerEngine(JavaScriptSource.ENGINE, () -> {
LoopBasedJavaScriptEngine engine = new LoopBasedJavaScriptEngine(mContext);
engine.setRuntime(new ScriptRuntime.Builder()
.setConsole(new StardustConsole(mUiHandler, mGlobalConsole))
.setScreenCaptureRequester(mScreenCaptureRequester)
.setAccessibilityBridge(new AccessibilityBridgeImpl())
.setUiHandler(mUiHandler)
.setAppUtils(mAppUtils)
.setEngineService(mScriptEngineService)
.setShellSupplier(() -> new Shell(mContext, true)).build());
return engine;
});
mScriptEngineManager.registerEngine(AutoFileSource.ENGINE, new Supplier<ScriptEngine>() {
@Override
public ScriptEngine get() {
return new RootAutomatorEngine(mContext);
}
});
}
protected void registerActivityLifecycleCallbacks() {
getApplication().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 void addAccessibilityServiceDelegates() {
AccessibilityService.addDelegate(100, mAccessibilityInfoProvider);
AccessibilityService.addDelegate(200, mNotificationObserver);
AccessibilityService.addDelegate(300, mAccessibilityActionRecorder);
}
public AccessibilityActionRecorder getAccessibilityActionRecorder() {
return mAccessibilityActionRecorder;
}
public AppUtils getAppUtils() {
return mAppUtils;
}
public UiHandler getUiHandler() {
return mUiHandler;
}
public LayoutInspector getLayoutInspector() {
return mLayoutInspector;
}
public Console getGlobalConsole() {
return mGlobalConsole;
}
public ScriptEngineService getScriptEngineService() {
return mScriptEngineService;
}
public AccessibilityInfoProvider getInfoProvider() {
return mAccessibilityInfoProvider;
}
private class AccessibilityBridgeImpl extends AccessibilityBridge {
@Override
public void ensureServiceEnabled() {
AutoJs.this.ensureAccessibilityServiceEnabled();
}
@Nullable
@Override
public AccessibilityService getService() {
return AccessibilityService.getInstance();
}
@Override
public AccessibilityInfoProvider getInfoProvider() {
return mAccessibilityInfoProvider;
}
@Override
public AccessibilityNotificationObserver getNotificationObserver() {
return mNotificationObserver;
}
}
private class ScreenCaptureRequesterImpl extends 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(mContext, mCallback);
}
}
}
}

View File

@@ -3,7 +3,6 @@ package com.stardust.autojs.engine;
import android.util.Log; import android.util.Log;
import com.stardust.autojs.BuildConfig; import com.stardust.autojs.BuildConfig;
import com.stardust.autojs.core.accessibility.UiCollection;
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.exception.ScriptInterruptedException; import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
@@ -17,21 +16,14 @@ import org.mozilla.javascript.Callable;
import org.mozilla.javascript.Context; import org.mozilla.javascript.Context;
import org.mozilla.javascript.ContextFactory; import org.mozilla.javascript.ContextFactory;
import org.mozilla.javascript.ImporterTopLevel; import org.mozilla.javascript.ImporterTopLevel;
import org.mozilla.javascript.NativeArray;
import org.mozilla.javascript.ScriptRuntime;
import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject; import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.TopLevel;
import org.mozilla.javascript.WrapFactory;
import org.mozilla.javascript.commonjs.module.RequireBuilder; import org.mozilla.javascript.commonjs.module.RequireBuilder;
import org.mozilla.javascript.commonjs.module.provider.SoftCachingModuleScriptProvider; import org.mozilla.javascript.commonjs.module.provider.SoftCachingModuleScriptProvider;
import org.mozilla.javascript.tools.debugger.Dim;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.URI; import java.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -44,7 +36,7 @@ import java.util.Locale;
public class RhinoJavaScriptEngine extends JavaScriptEngine { public class RhinoJavaScriptEngine extends JavaScriptEngine {
private static final String LOG_TAG = "RhinoJavaScriptEngine"; private static final String LOG_TAG = "RhinoJavaScriptEngine";
private static ThreadLocal<Thread.UncaughtExceptionHandler> mExceptionHandlerThreadLocal = new ThreadLocal<>(); private static ThreadLocal<Thread.UncaughtExceptionHandler> sExceptionHandlerThreadLocal = new ThreadLocal<>();
private static int contextCount = 0; private static int contextCount = 0;
private static StringScriptSource sInitScript; private static StringScriptSource sInitScript;
@@ -165,8 +157,8 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine {
return context; return context;
} }
public static void setUncaghtExceptionHandler(Thread.UncaughtExceptionHandler handler) { public static void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler handler) {
mExceptionHandlerThreadLocal.set(handler); sExceptionHandlerThreadLocal.set(handler);
} }
private class WrapFactory extends org.mozilla.javascript.WrapFactory { private class WrapFactory extends org.mozilla.javascript.WrapFactory {
@@ -205,7 +197,7 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine {
@Override @Override
protected Object doTopCall(Callable callable, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { protected Object doTopCall(Callable callable, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
Thread.UncaughtExceptionHandler exceptionHandler = mExceptionHandlerThreadLocal.get(); Thread.UncaughtExceptionHandler exceptionHandler = sExceptionHandlerThreadLocal.get();
if (exceptionHandler == null) if (exceptionHandler == null)
return super.doTopCall(callable, cx, scope, thisObj, args); return super.doTopCall(callable, cx, scope, thisObj, args);
else { else {

View File

@@ -40,7 +40,6 @@ public class LoopedBasedJavaScriptExecution extends RunnableScriptExecution {
return false; return false;
} }
javaScriptEngine.getRuntime().loopers.setLooperQuitHandler(null); javaScriptEngine.getRuntime().loopers.setLooperQuitHandler(null);
getListener().onSuccess(LoopedBasedJavaScriptExecution.this, null);
return true; return true;
} }
}); });

View File

@@ -9,9 +9,7 @@ import com.stardust.autojs.engine.LoopBasedJavaScriptEngine;
import com.stardust.autojs.engine.RhinoJavaScriptEngine; 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.engine.ScriptEngineManager;
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.util.IntentExtras; import com.stardust.util.IntentExtras;
/** /**
@@ -51,7 +49,7 @@ public class ScriptExecuteActivity extends AppCompatActivity implements Thread.U
mScriptSource = mScriptExecution.getSource(); mScriptSource = mScriptExecution.getSource();
mScriptEngine = mScriptExecution.getEngine(); mScriptEngine = mScriptExecution.getEngine();
mExecutionListener = mScriptExecution.getListener(); mExecutionListener = mScriptExecution.getListener();
RhinoJavaScriptEngine.setUncaghtExceptionHandler(this); RhinoJavaScriptEngine.setUncaughtExceptionHandler(this);
runScript(); runScript();
} }

View File

@@ -179,7 +179,7 @@ public class ScriptRuntime {
if (loopers != null) if (loopers != null)
throw new IllegalStateException("already initialized"); throw new IllegalStateException("already initialized");
timers = new Timers(bridges); timers = new Timers(bridges);
loopers = new Loopers(timers); loopers = new Loopers(this);
events = new Events(mUiHandler.getContext(), accessibilityBridge, bridges, loopers); events = new Events(mUiHandler.getContext(), accessibilityBridge, bridges, loopers);
} }

View File

@@ -3,6 +3,7 @@ package com.stardust.autojs.runtime.api;
import android.os.Looper; import android.os.Looper;
import android.os.MessageQueue; import android.os.MessageQueue;
import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.autojs.runtime.exception.ScriptInterruptedException; import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
import com.stardust.lang.ThreadCompat; import com.stardust.lang.ThreadCompat;
@@ -22,10 +23,12 @@ public class Loopers {
private volatile Looper mServantLooper; private volatile Looper mServantLooper;
private static volatile ConcurrentHashMap<Thread, Looper> sLoopers = new ConcurrentHashMap<>(); private static volatile ConcurrentHashMap<Thread, Looper> sLoopers = new ConcurrentHashMap<>();
private Timers mTimers; private Timers mTimers;
private ScriptRuntime mScriptRuntime;
private LooperQuitHandler mLooperQuitHandler; private LooperQuitHandler mLooperQuitHandler;
public Loopers(Timers timers) { public Loopers(ScriptRuntime runtime) {
mTimers = timers; mTimers = runtime.timers;
mScriptRuntime = runtime;
if (Looper.myLooper() == Looper.getMainLooper()) { if (Looper.myLooper() == Looper.getMainLooper()) {
waitWhenIdle = true; waitWhenIdle = true;
} }
@@ -35,6 +38,7 @@ public class Loopers {
Looper l = Looper.myLooper(); Looper l = Looper.myLooper();
if (l != null && shouldQuitLooper()) { if (l != null && shouldQuitLooper()) {
if (mLooperQuitHandler != null && mLooperQuitHandler.shouldQuit()) { if (mLooperQuitHandler != null && mLooperQuitHandler.shouldQuit()) {
mScriptRuntime.events.emit("exit");
l.quit(); l.quit();
} }
} }

View File

@@ -27,9 +27,10 @@ public class DeveloperUtils {
return PACKAGE_NAME.equals(runningPackage); return PACKAGE_NAME.equals(runningPackage);
} }
public static String getSignature(Context context) { @Nullable
public static String getSignature(Context context, String packageName) {
try { try {
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES); PackageInfo packageInfo = context.getPackageManager().getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
Signature[] signatures = packageInfo.signatures; Signature[] signatures = packageInfo.signatures;
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
for (Signature signature : signatures) { for (Signature signature : signatures) {
@@ -47,7 +48,12 @@ public class DeveloperUtils {
* 为了开源社区的发展,请善用源码:-) * 为了开源社区的发展,请善用源码:-)
*/ */
public static boolean checkSignature(Context context) { public static boolean checkSignature(Context context) {
return SIGNATURE.equals(getSignature(context)); return SIGNATURE.equals(getSignature(context, context.getPackageName()));
} }
public static boolean checkSignature(Context context, String packageName) {
return SIGNATURE.equals(getSignature(context, packageName));
}
} }

View File

@@ -6,6 +6,7 @@
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<application <application
android:name=".App" android:name=".App"

View File

@@ -8,6 +8,7 @@ import android.os.Bundle;
import com.stardust.auojs.inrt.rt.AutoJs; import com.stardust.auojs.inrt.rt.AutoJs;
import com.stardust.autojs.core.console.ConsoleView; import com.stardust.autojs.core.console.ConsoleView;
import com.stardust.autojs.core.console.StardustConsole;
import com.stardust.autojs.script.StringScriptSource; import com.stardust.autojs.script.StringScriptSource;
import com.stardust.pio.PFiles; import com.stardust.pio.PFiles;
@@ -34,7 +35,7 @@ public class MainActivity extends AppCompatActivity {
private void setupView() { private void setupView() {
ConsoleView consoleView = new ConsoleView(this); ConsoleView consoleView = new ConsoleView(this);
consoleView.setConsole(AutoJs.getInstance().getGlobalConsole()); consoleView.setConsole((StardustConsole) AutoJs.getInstance().getGlobalConsole());
setContentView(consoleView); setContentView(consoleView);
} }

View File

@@ -39,8 +39,9 @@ public class AccessibilityServiceTool {
public static boolean enableAccessibilityServiceByRootAndWaitFor(Context context, long timeOut) { public static boolean enableAccessibilityServiceByRootAndWaitFor(Context context, long timeOut) {
if (enableAccessibilityServiceByRoot(context, com.stardust.view.accessibility.AccessibilityService.class)) { if (enableAccessibilityServiceByRoot(context, com.stardust.view.accessibility.AccessibilityService.class)) {
com.stardust.view.accessibility.AccessibilityService.waitForEnabled(timeOut); com.stardust.view.accessibility.AccessibilityService.waitForEnabled(timeOut);
return true;
} }
return true; return false;
} }
public static void goToAccessibilitySetting() { public static void goToAccessibilitySetting() {

View File

@@ -1,6 +1,7 @@
package com.stardust.auojs.inrt.rt; package com.stardust.auojs.inrt.rt;
import android.app.Activity; import android.app.Activity;
import android.app.Application;
import android.content.Context; import android.content.Context;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
@@ -40,15 +41,17 @@ import com.stardust.view.accessibility.AccessibilityService;
import com.stardust.view.accessibility.AccessibilityServiceUtils; import com.stardust.view.accessibility.AccessibilityServiceUtils;
import com.stardust.view.accessibility.NotificationListener; import com.stardust.view.accessibility.NotificationListener;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.OpenCVLoader;
/** /**
* Created by Stardust on 2017/4/2. * Created by Stardust on 2017/4/2.
*/ */
public class AutoJs { public class AutoJs extends com.stardust.autojs.AutoJs {
private static AutoJs instance; private static AutoJs instance;
private Class<? extends android.accessibilityservice.AccessibilityService> sAccessibilityServiceClass = AccessibilityService.class;
public static AutoJs getInstance() { public static AutoJs getInstance() {
return instance; return instance;
@@ -58,166 +61,31 @@ public class AutoJs {
instance = new AutoJs(context); instance = new AutoJs(context);
} }
private final AccessibilityActionRecorder mAccessibilityActionRecorder = new AccessibilityActionRecorder(); private AutoJs(Context context) {
private final AccessibilityNotificationObserver mNotificationObserver; super(context);
private ScriptEngineManager mScriptEngineManager;
private final Context mContext;
private final UiHandler mUiHandler;
private final AppUtils mAppUtils;
private final AccessibilityInfoProvider mAccessibilityInfoProvider;
private final ScreenCaptureRequester mScreenCaptureRequester = new ScreenCaptureRequesterImpl();
private final ScriptEngineService mScriptEngineService;
private final StardustConsole mGlobalConsole;
private AutoJs(final Context context) {
mContext = context;
mUiHandler = new UiHandler(context);
mAppUtils = new AppUtils(context);
mGlobalConsole = new GlobalStardustConsole(mUiHandler);
mNotificationObserver = new AccessibilityNotificationObserver(context);
mAccessibilityInfoProvider = new AccessibilityInfoProvider(context.getPackageManager());
mScriptEngineService = buildScriptEngineService();
addAccessibilityServiceDelegates();
registerActivityLifecycleCallbacks();
InputEventObserver.initGlobal(context);
}
public StardustConsole getGlobalConsole() {
return mGlobalConsole;
}
private ScriptEngineService buildScriptEngineService() {
initScriptEngineManager();
return new ScriptEngineServiceBuilder()
.uiHandler(mUiHandler)
.globalConsole(mGlobalConsole)
.engineManger(mScriptEngineManager)
.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)
.setEngineService(mScriptEngineService)
.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() {
App.getApp().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 void addAccessibilityServiceDelegates() {
AccessibilityService.addDelegate(100, mAccessibilityInfoProvider);
AccessibilityService.addDelegate(200, mNotificationObserver);
AccessibilityService.addDelegate(300, mAccessibilityActionRecorder);
}
public ScriptEngineService getScriptEngineService() {
return mScriptEngineService;
} }
@Override
public void ensureAccessibilityServiceEnabled() { public void ensureAccessibilityServiceEnabled() {
if (AccessibilityService.getInstance() == null) { if (AccessibilityService.getInstance() != null) {
String errorMessage = getErrorMessage(); return;
}
String errorMessage = null;
if (AccessibilityServiceUtils.isAccessibilityServiceEnabled(getApplication(), AccessibilityService.class)) {
errorMessage = App.getApp().getString(R.string.text_auto_operate_service_enabled_but_not_running);
} else {
if (!AccessibilityServiceTool.enableAccessibilityServiceByRootAndWaitFor(getApplication(), 2000)) {
errorMessage = App.getApp().getString(R.string.text_no_accessibility_permission);
}
}
if (errorMessage != null) {
AccessibilityServiceTool.goToAccessibilitySetting(); AccessibilityServiceTool.goToAccessibilitySetting();
throw new ScriptException(errorMessage); throw new ScriptException(errorMessage);
} }
} }
private String getErrorMessage() { @Override
if (AccessibilityServiceUtils.isAccessibilityServiceEnabled(App.getApp(), sAccessibilityServiceClass)) { protected Application getApplication() {
return App.getApp().getString(R.string.text_auto_operate_service_enabled_but_not_running); return App.getApp();
} else {
if (true) {
if (!AccessibilityServiceTool.enableAccessibilityServiceByRootAndWaitFor(App.getApp(), 2000)) {
return App.getApp().getString(R.string.text_enable_accessibility_service_by_root_timeout);
}
}
}
return App.getApp().getString(R.string.text_no_accessibility_permission);
}
private class AccessibilityBridgeImpl extends AccessibilityBridge {
@Override
public void ensureServiceEnabled() {
AutoJs.this.ensureAccessibilityServiceEnabled();
}
@Nullable
@Override
public AccessibilityService getService() {
return AccessibilityService.getInstance();
}
@Override
public AccessibilityInfoProvider getInfoProvider() {
return mAccessibilityInfoProvider;
}
@Override
public AccessibilityNotificationObserver getNotificationObserver() {
return mNotificationObserver;
}
}
private class ScreenCaptureRequesterImpl extends 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(mContext, mCallback);
}
}
} }
} }