265 lines
9.5 KiB
Java
265 lines
9.5 KiB
Java
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 androidx.annotation.Nullable;
|
|
import androidx.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.GlobalConsole;
|
|
import com.stardust.autojs.core.console.ConsoleImpl;
|
|
import com.stardust.autojs.core.image.capture.ScreenCaptureRequestActivity;
|
|
import com.stardust.autojs.core.image.capture.ScreenCaptureRequester;
|
|
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.ScriptEngineManager;
|
|
import com.stardust.autojs.rhino.InterruptibleAndroidContextFactory;
|
|
import com.stardust.autojs.runtime.ScriptRuntime;
|
|
import com.stardust.autojs.runtime.accessibility.AccessibilityConfig;
|
|
import com.stardust.autojs.runtime.api.AppUtils;
|
|
import com.stardust.autojs.script.AutoFileSource;
|
|
import com.stardust.autojs.script.JavaScriptSource;
|
|
import com.stardust.util.ResourceMonitor;
|
|
import com.stardust.util.ScreenMetrics;
|
|
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.mozilla.javascript.ContextFactory;
|
|
import org.mozilla.javascript.WrappedException;
|
|
|
|
import java.io.File;
|
|
|
|
/**
|
|
* 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;
|
|
private final Context mContext;
|
|
private final Application mApplication;
|
|
private final UiHandler mUiHandler;
|
|
private final AppUtils mAppUtils;
|
|
private final AccessibilityInfoProvider mAccessibilityInfoProvider;
|
|
private final ScreenCaptureRequester mScreenCaptureRequester = new ScreenCaptureRequesterImpl();
|
|
private final ScriptEngineService mScriptEngineService;
|
|
private final GlobalConsole mGlobalConsole;
|
|
|
|
|
|
protected AutoJs(final Application application) {
|
|
mContext = application.getApplicationContext();
|
|
mApplication = application;
|
|
mLayoutInspector = new LayoutInspector(mContext);
|
|
mUiHandler = new UiHandler(mContext);
|
|
mAppUtils = createAppUtils(mContext);
|
|
mGlobalConsole = createGlobalConsole();
|
|
mNotificationObserver = new AccessibilityNotificationObserver(mContext);
|
|
mAccessibilityInfoProvider = new AccessibilityInfoProvider(mContext);
|
|
mScriptEngineService = buildScriptEngineService();
|
|
ScriptEngineService.setInstance(mScriptEngineService);
|
|
init();
|
|
}
|
|
|
|
protected AppUtils createAppUtils(Context context) {
|
|
return new AppUtils(mContext);
|
|
}
|
|
|
|
protected GlobalConsole createGlobalConsole() {
|
|
return new GlobalConsole(mUiHandler);
|
|
}
|
|
|
|
protected void init() {
|
|
addAccessibilityServiceDelegates();
|
|
registerActivityLifecycleCallbacks();
|
|
ResourceMonitor.setExceptionCreator(resource -> {
|
|
Exception exception;
|
|
if (org.mozilla.javascript.Context.getCurrentContext() != null) {
|
|
exception = new WrappedException(new ResourceMonitor.UnclosedResourceException(resource));
|
|
} else {
|
|
exception = new ResourceMonitor.UnclosedResourceException(resource);
|
|
}
|
|
exception.fillInStackTrace();
|
|
return exception;
|
|
});
|
|
ResourceMonitor.setUnclosedResourceDetectedHandler(detectedException -> mGlobalConsole.error(detectedException));
|
|
}
|
|
|
|
public abstract void ensureAccessibilityServiceEnabled();
|
|
|
|
protected Application getApplication() {
|
|
return mApplication;
|
|
}
|
|
|
|
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(createRuntime());
|
|
return engine;
|
|
});
|
|
initContextFactory();
|
|
mScriptEngineManager.registerEngine(AutoFileSource.ENGINE, () -> new RootAutomatorEngine(mContext));
|
|
|
|
}
|
|
|
|
protected void initContextFactory() {
|
|
ContextFactory.initGlobal(new InterruptibleAndroidContextFactory(new File(mContext.getCacheDir(), "classes")));
|
|
}
|
|
|
|
protected ScriptRuntime createRuntime() {
|
|
return new ScriptRuntime.Builder()
|
|
.setConsole(new ConsoleImpl(mUiHandler, mGlobalConsole))
|
|
.setScreenCaptureRequester(mScreenCaptureRequester)
|
|
.setAccessibilityBridge(new AccessibilityBridgeImpl(mUiHandler))
|
|
.setUiHandler(mUiHandler)
|
|
.setAppUtils(mAppUtils)
|
|
.setEngineService(mScriptEngineService)
|
|
.setShellSupplier(() -> new Shell(mContext, true)).build();
|
|
}
|
|
|
|
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.Companion.addDelegate(100, mAccessibilityInfoProvider);
|
|
AccessibilityService.Companion.addDelegate(200, mNotificationObserver);
|
|
AccessibilityService.Companion.addDelegate(300, mAccessibilityActionRecorder);
|
|
}
|
|
|
|
public AccessibilityActionRecorder getAccessibilityActionRecorder() {
|
|
return mAccessibilityActionRecorder;
|
|
}
|
|
|
|
public AppUtils getAppUtils() {
|
|
return mAppUtils;
|
|
}
|
|
|
|
public UiHandler getUiHandler() {
|
|
return mUiHandler;
|
|
}
|
|
|
|
public LayoutInspector getLayoutInspector() {
|
|
return mLayoutInspector;
|
|
}
|
|
|
|
public GlobalConsole getGlobalConsole() {
|
|
return mGlobalConsole;
|
|
}
|
|
|
|
public ScriptEngineService getScriptEngineService() {
|
|
return mScriptEngineService;
|
|
}
|
|
|
|
public AccessibilityInfoProvider getInfoProvider() {
|
|
return mAccessibilityInfoProvider;
|
|
}
|
|
|
|
|
|
public abstract void waitForAccessibilityServiceEnabled();
|
|
|
|
protected AccessibilityConfig createAccessibilityConfig() {
|
|
return new AccessibilityConfig();
|
|
}
|
|
|
|
private class AccessibilityBridgeImpl extends AccessibilityBridge {
|
|
|
|
public AccessibilityBridgeImpl(UiHandler uiHandler) {
|
|
super(mContext, createAccessibilityConfig(), uiHandler);
|
|
}
|
|
|
|
@Override
|
|
public void ensureServiceEnabled() {
|
|
AutoJs.this.ensureAccessibilityServiceEnabled();
|
|
}
|
|
|
|
@Override
|
|
public void waitForServiceEnabled() {
|
|
AutoJs.this.waitForAccessibilityServiceEnabled();
|
|
}
|
|
|
|
@Nullable
|
|
@Override
|
|
public AccessibilityService getService() {
|
|
return AccessibilityService.Companion.getInstance();
|
|
}
|
|
|
|
@Override
|
|
public AccessibilityInfoProvider getInfoProvider() {
|
|
return mAccessibilityInfoProvider;
|
|
}
|
|
|
|
@Override
|
|
public AccessibilityNotificationObserver getNotificationObserver() {
|
|
return mNotificationObserver;
|
|
}
|
|
|
|
}
|
|
|
|
private class ScreenCaptureRequesterImpl extends ScreenCaptureRequester.AbstractScreenCaptureRequester {
|
|
|
|
@Override
|
|
public void setOnActivityResultCallback(Callback callback) {
|
|
super.setOnActivityResultCallback((result, data) -> {
|
|
mResult = data;
|
|
callback.onRequestResult(result, data);
|
|
});
|
|
}
|
|
|
|
@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);
|
|
}
|
|
}
|
|
}
|
|
}
|