Fix and improve root rocording

This commit is contained in:
hyb1996
2017-05-05 00:35:45 +08:00
parent 7473d7c6a5
commit 163f38760e
80 changed files with 1386 additions and 1017 deletions

View File

@@ -38,6 +38,17 @@ android {
output.outputFile = new File(file.parent, file.name.replace(".apk", "-" + defaultConfig.versionName + ".apk"))
}
}
packagingOptions {
pickFirst 'org/mozilla/javascript/tools/debugger/build.xml'
pickFirst 'org/mozilla/javascript/tools/debugger/test.js'
pickFirst 'org/mozilla/javascript/tools/idswitch/README'
pickFirst 'org/mozilla/javascript/NativeString.java.orig'
pickFirst 'org/mozilla/javascript/Node.java.orig'
pickFirst 'org/mozilla/javascript/resources/Messages_fr.properties'
pickFirst 'org/mozilla/javascript/resources/Messages.properties'
pickFirst 'org/mozilla/javascript/*.java.orig'
pickFirst 'org/mozilla/javascript/tools/resources/*.properties'
}
}
repositories {
@@ -47,7 +58,6 @@ repositories {
}
dependencies {
compile fileTree(include: ['*.jar', '*.so'], dir: 'libs')
testCompile 'junit:junit:4.12'
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
@@ -62,7 +72,6 @@ dependencies {
compile 'com.github.atlassian:commonmark-java:commonmark-parent-0.9.0'
compile 'moe.feng:AlipayZeroSdk:1.1'
compile 'com.jraska:console:0.4.3'
compile 'com.jraska:console-timber-tree:0.4.3'
compile 'com.heinrichreimersoftware:android-issue-reporter:1.3.1'
compile 'de.codecrafters.tableview:tableview:2.5.0'
compile group: "pl.openrnd.android", name: "multi-level-listview", version: "1.0.1"
@@ -72,7 +81,7 @@ dependencies {
compile 'com.ashokvarma.android:bottom-navigation-bar:1.4.1'
compile 'com.yqritc:recyclerview-flexibledivider:1.4.0'
compile 'me.zhanghai.android.materialprogressbar:library:1.3.0'
compile group:'com.twofortyfouram', name:'android-plugin-client-sdk-for-locale', version:'[4.0.2, 5.0['
compile group: 'com.twofortyfouram', name: 'android-plugin-client-sdk-for-locale', version: '[4.0.2, 5.0['
compile 'com.android.volley:volley:1.0.0'
compile 'com.github.hyb1996:EnhancedFloaty:0.15'
compile 'com.flurry.android:analytics:7.0.0@aar'

View File

@@ -6,7 +6,7 @@
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
<uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"/>
<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.SYSTEM_ALERT_WINDOW"/>
@@ -23,6 +23,7 @@
tools:replace="android:label, android:icon, android:allowBackup">
<activity
android:name=".ui.main.MainActivity"
android:hardwareAccelerated="true"
android:label="@string/_app_name"
android:launchMode="singleTask"
android:theme="@style/AppTheme.FullScreen">
@@ -68,7 +69,9 @@
android:resource="@xml/provider_paths"/>
</provider>
<activity android:name=".ui.edit.EditActivity"/>
<activity android:name=".ui.edit.EditActivity" android:multiprocess="true">
</activity>
<activity android:name=".ui.help.DocumentationActivity"/>
<activity android:name=".ui.help.HelpCatalogueActivity"/>
<activity android:name=".ui.settings.AboutActivity"/>

View File

@@ -0,0 +1 @@
__importClass__(com.stardust.scriptdroid.autojs.Shell);

View File

@@ -16,10 +16,10 @@ public interface OnActivityResultDelegate {
void onActivityResult(int requestCode, int resultCode, Intent data);
interface DelegateHost {
Intermediary getDelegateManger();
Mediator getDelegateManger();
}
class Intermediary implements OnActivityResultDelegate {
class Mediator implements OnActivityResultDelegate {
private SparseArray<OnActivityResultDelegate> mSpecialDelegate = new SparseArray<>();
private List<OnActivityResultDelegate> mDelegates = new ArrayList<>();

View File

@@ -78,6 +78,13 @@ public class Pref {
return def().getString(getString(R.string.key_stop_record_trigger), null);
}
public static boolean hasRecordTrigger(){
String startTrigger = getStartRecordTrigger();
String stopTrigger = getStartRecordTrigger();
return startTrigger != null && !startTrigger.equals("NONE")
&& stopTrigger != null && !startTrigger.equals("NONE");
}
public static boolean enableAccessibilityServiceByRoot() {
return def().getBoolean(getString(R.string.key_enable_accessibility_service_by_root), false);
}

View File

@@ -13,7 +13,7 @@ import com.stardust.automator.simple_action.SimpleActionPerformHost;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.Pref;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.scripts.StorageScriptProvider;
import com.stardust.scriptdroid.script.StorageScriptProvider;
import com.stardust.scriptdroid.ui.console.StardustConsole;
import com.stardust.util.Supplier;
import com.stardust.util.UiHandler;
@@ -22,7 +22,7 @@ import com.stardust.scriptdroid.layout_inspector.LayoutInspector;
import com.stardust.scriptdroid.record.accessibility.AccessibilityActionRecorder;
import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
import com.stardust.scriptdroid.tool.AccessibilityServiceTool;
import com.stardust.scriptdroid.ui.console.TimberConsole;
import com.stardust.scriptdroid.ui.console.JraskaConsole;
import com.stardust.view.accessibility.AccessibilityServiceUtils;
@@ -58,7 +58,7 @@ public class AutoJs implements AccessibilityBridge {
manager.setRequirePath(StorageScriptProvider.DEFAULT_DIRECTORY_PATH);
mScriptEngineService = new ScriptEngineServiceBuilder()
.uiHandler(mUiHandler)
.globalConsole(new TimberConsole())
.globalConsole(new JraskaConsole())
.engineManger(manager)
.runtime(new Supplier<ScriptRuntime>() {
@@ -83,6 +83,10 @@ public class AutoJs implements AccessibilityBridge {
return mAccessibilityActionRecorder;
}
public UiHandler getUiHandler() {
return mUiHandler;
}
public LayoutInspector getLayoutInspector() {
return mLayoutInspector;
}

View File

@@ -1,15 +1,11 @@
package com.stardust.scriptdroid.autojs;
import com.flurry.android.FlurryAgent;
import com.stardust.autojs.ScriptEngineService;
import com.stardust.autojs.execution.ScriptExecution;
import com.stardust.autojs.execution.ScriptExecutionListener;
import com.stardust.autojs.runtime.ScriptInterruptedException;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.R;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* Created by Stardust on 2017/5/3.
*/
@@ -29,8 +25,11 @@ public class ScriptExecutionGlobalListener implements ScriptExecutionListener {
}
private void onFinish(ScriptExecution execution) {
long millis = System.currentTimeMillis() - (long) execution.getEngine().getTag(ENGINE_TAG_START_TIME);
execution.getRuntime().console.verbose(App.getApp().getString(R.string.text_execution_finished), execution.getSource().toString(), (double) millis / 1000);
Long millis = (Long) execution.getEngine().getTag(ENGINE_TAG_START_TIME);
if (millis == null)
return;
double seconds = (System.currentTimeMillis() - millis) / 1000.0;
execution.getRuntime().console.verbose(App.getApp().getString(R.string.text_execution_finished), execution.getSource().toString(), seconds);
}
@Override

View File

@@ -0,0 +1,191 @@
package com.stardust.scriptdroid.autojs;
import android.content.Context;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.util.Log;
import com.stardust.autojs.runtime.ScriptInterruptedException;
import com.stardust.autojs.runtime.api.AbstractShell;
import com.stardust.pio.UncheckedIOException;
import com.stardust.scriptdroid.App;
import java.io.IOException;
import jackpal.androidterm.ShellTermSession;
import jackpal.androidterm.emulatorview.TermSession;
import jackpal.androidterm.util.TermSettings;
/**
* Created by Stardust on 2017/4/24.
*/
public class Shell extends AbstractShell implements AutoCloseable {
public interface OutputListener {
void onNewOutput(String str);
}
private static final String TAG = "Shell";
private TermSession mTermSession;
private RuntimeException mInitException;
private final Object mInitLock = new Object();
private final Object mExitLock = new Object();
private boolean mInitialized = false;
private boolean mWaitingExit = false;
private OutputListener mOutputListener;
public Shell() {
super();
}
public Shell(boolean root) {
super(root);
}
@Override
protected void init(String initialCommand) {
init(initialCommand, App.getApp(), AutoJs.getInstance().getUiHandler());
}
private void init(final String initialCommand, final Context context, Handler uiHandler) {
uiHandler.post(new Runnable() {
@Override
public void run() {
TermSettings settings = new TermSettings(context.getResources(), PreferenceManager.getDefaultSharedPreferences(context));
try {
mTermSession = new MyShellTermSession(settings, initialCommand);
mTermSession.initializeEmulator(40, 40);
} catch (IOException e) {
mInitException = new UncheckedIOException(e);
}
}
});
}
public void exec(String command) {
ensureInitialized();
mTermSession.write(command + "\n");
}
public void setOutputListener(OutputListener outputListener) {
mOutputListener = outputListener;
}
private void ensureInitialized() {
if (mTermSession == null) {
checkInitException();
waitInitialization();
if (mTermSession == null) {
checkInitException();
throw new IllegalStateException();
}
}
}
private void checkInitException() {
if (mInitException != null) {
throw mInitException;
}
}
private void waitInitialization() {
if (mInitialized)
throw new IllegalStateException("already initialized");
synchronized (mInitLock) {
try {
mInitLock.wait();
} catch (InterruptedException e) {
exit();
throw new ScriptInterruptedException();
}
}
}
@Override
public void exit() {
mTermSession.finish();
}
@Override
public void exitAndWaitFor() {
execExitAndWait();
if (!isRoot()) {
return;
}
execExitAndWait();
}
private void execExitAndWait() {
synchronized (mExitLock) {
mWaitingExit = true;
exec("exit");
try {
mExitLock.wait();
} catch (InterruptedException e) {
exit();
throw new ScriptInterruptedException();
}
}
}
@Override
public void close() {
exit();
}
private class MyShellTermSession extends ShellTermSession {
public MyShellTermSession(TermSettings settings, String initialCommand) throws IOException {
super(settings, initialCommand);
}
@Override
protected void processInput(byte[] data, int offset, int count) {
String output = new String(data, offset, count);
Log.d(TAG, output);
if(mOutputListener != null){
mOutputListener.onNewOutput(output);
}
if (mInitialized && !mWaitingExit) {
return;
}
String[] lines = new String(data, offset, count).split("\n");
for (String line : lines) {
if (!mInitialized && line.endsWith(" # ")) {
notifyInitialized();
return;
}
if (mWaitingExit && line.endsWith(" $ ")) {
notifyExit();
return;
}
}
}
private void notifyExit() {
synchronized (mExitLock) {
mWaitingExit = false;
mExitLock.notify();
}
}
private void notifyInitialized() {
mInitialized = true;
synchronized (mInitLock) {
mInitLock.notifyAll();
}
}
@Override
protected void onProcessExit() {
super.onProcessExit();
synchronized (mExitLock) {
mWaitingExit = false;
mExitLock.notify();
}
}
}
}

View File

@@ -18,6 +18,7 @@ import com.stardust.scriptdroid.external.floating_window.menu.HoverMenuService;
import com.stardust.scriptdroid.record.Recorder;
import com.stardust.scriptdroid.record.accessibility.AccessibilityActionRecorder;
import com.stardust.scriptdroid.record.inputevent.InputEventConverter;
import com.stardust.scriptdroid.record.inputevent.KeyObserver;
import com.stardust.scriptdroid.record.inputevent.TouchRecorder;
import com.stardust.scriptdroid.ui.main.MainActivity;
import com.stardust.util.MessageEvent;
@@ -35,7 +36,7 @@ import io.mattcarroll.hover.NavigatorContent;
* Created by Stardust on 2017/3/12.
*/
public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStateChangedListener {
public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStateChangedListener, KeyObserver.KeyListener {
private View mView;
@ViewBinding.Id(R.id.sw_recorded_by_root)
@@ -57,6 +58,8 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
private Recorder mRecorder;
private Context mContext;
private KeyObserver mKeyObserver;
private VolumeChangeObserver.OnVolumeChangeListener mOnVolumeChangeListener = new VolumeChangeObserver.OnVolumeChangeListener() {
@Override
public void onVolumeChange() {
@@ -74,8 +77,13 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
mContext = context;
mView = View.inflate(context, R.layout.floating_window_record, null);
ViewBinder.bind(this);
EventBus.getDefault().register(this);
HoverMenuService.getEventBus().register(this);
App.getApp().getVolumeChangeObserver().addOnVolumeChangeListener(mOnVolumeChangeListener);
if (Pref.hasRecordTrigger()) {
mKeyObserver = new KeyObserver();
mKeyObserver.startListening();
mKeyObserver.setKeyListener(this);
}
}
@NonNull
@@ -158,10 +166,18 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
@Subscribe
public void onMessageEvent(MessageEvent event) {
if (event.message.equals(HoverMenuService.MESSAGE_MENU_EXPANDING)) {
pauseRecord();
if (mRecorder != null && mRecorder.getState() == Recorder.STATE_RECORDING)
pauseRecord();
} else if (event.message.equals(HoverMenuService.MESSAGE_MENU_EXIT)) {
EventBus.getDefault().unregister(this);
App.getApp().getVolumeChangeObserver().removeOnVolumeChangeListener(mOnVolumeChangeListener);
onMenuExit();
}
}
public void onMenuExit() {
HoverMenuService.getEventBus().unregister(this);
App.getApp().getVolumeChangeObserver().removeOnVolumeChangeListener(mOnVolumeChangeListener);
if (mKeyObserver != null) {
mKeyObserver.stopListening();
}
}
@@ -172,13 +188,6 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
}
}
@Subscribe
public void onTouchRecorderStateChanged(InputEventConverter.RecordStateChangeEvent event) {
if (!event.isRecording()) {
stopRecord();
}
}
@Override
public void onStart() {
Toast.makeText(mContext, R.string.text_start_record, Toast.LENGTH_SHORT).show();
@@ -198,4 +207,20 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
public void onResume() {
}
@Override
public void onKeyDown(String keyName) {
if (keyName.equals(Pref.getStopRecordTrigger())) {
if (mRecorder != null && mRecorder.getState() == Recorder.STATE_RECORDING && mRecorder.getState() == Recorder.STATE_PAUSED)
stopRecord();
} else if (keyName.equals(Pref.getStartRecordTrigger())) {
if (mRecorder == null)
startRecord();
}
}
@Override
public void onKeyUp(String keyName) {
}
}

View File

@@ -11,8 +11,9 @@ import com.stardust.autojs.script.FileScriptSource;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.scriptdroid.external.floating_window.menu.HoverMenuService;
import com.stardust.scriptdroid.scripts.ScriptFile;
import com.stardust.scriptdroid.scripts.StorageScriptProvider;
import com.stardust.scriptdroid.script.ScriptFile;
import com.stardust.scriptdroid.script.Scripts;
import com.stardust.scriptdroid.script.StorageScriptProvider;
import com.stardust.scriptdroid.ui.edit.EditActivity;
import com.stardust.scriptdroid.ui.main.script_list.ScriptAndFolderListRecyclerView;
import com.stardust.scriptdroid.ui.main.script_list.ScriptListWithProgressBarView;
@@ -53,7 +54,7 @@ public class ScriptListNavigatorContent implements NavigatorContent {
@Override
public void onClick(ScriptFile file, int position) {
AutoJs.getInstance().getScriptEngineService().execute(new FileScriptSource(file));
Scripts.run(file);
HoverMenuService.postEvent(new MessageEvent(HoverMenuService.MESSAGE_COLLAPSE_MENU));
}

View File

@@ -7,13 +7,14 @@ import android.support.annotation.Nullable;
import android.widget.Toast;
import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.scriptdroid.scripts.PathChecker;
import com.stardust.scriptdroid.script.PathChecker;
import com.stardust.autojs.script.FileScriptSource;
import com.stardust.autojs.script.MultiScriptSource;
import com.stardust.autojs.script.ScriptSourceWithInit;
import com.stardust.autojs.script.ScriptSource;
import com.stardust.autojs.script.StringScriptSource;
import com.stardust.scriptdroid.external.CommonUtils;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.script.Scripts;
/**
* Created by Stardust on 2017/2/22.
@@ -40,10 +41,10 @@ public class RunIntentActivity extends Activity {
if (path == null && script != null) {
source = new StringScriptSource(script);
} else if (path != null && new PathChecker(this).checkAndToastError(path)) {
source = new MultiScriptSource(new StringScriptSource(script), new FileScriptSource(path));
source = new ScriptSourceWithInit(new StringScriptSource(script), new FileScriptSource(path));
}
if (source != null) {
AutoJs.getInstance().getScriptEngineService().execute(source);
Scripts.run(source);
}
}

View File

@@ -5,10 +5,11 @@ import android.os.Bundle;
import android.widget.Toast;
import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.scriptdroid.scripts.PathChecker;
import com.stardust.scriptdroid.script.PathChecker;
import com.stardust.autojs.script.FileScriptSource;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.external.CommonUtils;
import com.stardust.scriptdroid.script.ScriptFile;
import com.stardust.scriptdroid.script.Scripts;
/**
* Created by Stardust on 2017/1/23.
@@ -31,7 +32,7 @@ public class ShortcutActivity extends Activity {
private void runScriptFile(String path) {
try {
AutoJs.getInstance().getScriptEngineService().execute(new FileScriptSource(path));
Scripts.run(new ScriptFile(path));
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();

View File

@@ -10,8 +10,8 @@ import android.view.MenuItem;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.external.CommonUtils;
import com.stardust.scriptdroid.scripts.ScriptFile;
import com.stardust.scriptdroid.scripts.StorageScriptProvider;
import com.stardust.scriptdroid.script.ScriptFile;
import com.stardust.scriptdroid.script.StorageScriptProvider;
import com.stardust.scriptdroid.ui.BaseActivity;
import com.stardust.scriptdroid.ui.main.script_list.ScriptAndFolderListRecyclerView;
import com.stardust.scriptdroid.ui.main.script_list.ScriptListWithProgressBarView;

View File

@@ -1,5 +1,7 @@
package com.stardust.scriptdroid.record;
import java.util.Arrays;
/**
* Created by Stardust on 2017/3/16.
*/
@@ -18,27 +20,25 @@ public interface Recorder {
}
OnStateChangedListener NO_OPERATION_LISTENER = new OnStateChangedListener() {
@Override
public void onStart() {
class StateChangeEvent {
private int mOldState;
private int mCurrentState;
public StateChangeEvent(int oldState, int currentState) {
mOldState = oldState;
mCurrentState = currentState;
}
@Override
public void onStop() {
public int getOldState() {
return mOldState;
}
@Override
public void onPause() {
public int getCurrentState() {
return mCurrentState;
}
}
@Override
public void onResume() {
}
};
int STATE_NOT_START = 0;
int STATE_RECORDING = 1;
@@ -59,44 +59,65 @@ public interface Recorder {
void setOnStateChangedListener(OnStateChangedListener onStateChangedListener);
abstract class DefaultIMPL implements Recorder {
abstract class AbstractRecorder implements Recorder {
private static final OnStateChangedListener NO_OPERATION_LISTENER = new OnStateChangedListener() {
@Override
public void onStart() {
}
@Override
public void onStop() {
}
@Override
public void onPause() {
}
@Override
public void onResume() {
}
};
private OnStateChangedListener mOnStateChangedListener = NO_OPERATION_LISTENER;
private final boolean mSync;
private int mState = STATE_NOT_START;
public DefaultIMPL(boolean syncOfState) {
public AbstractRecorder(boolean syncOfState) {
mSync = syncOfState;
}
public DefaultIMPL() {
public AbstractRecorder() {
this(false);
}
public void start() {
checkState(STATE_NOT_START);
ensureIsStateOf(STATE_NOT_START);
setState(STATE_RECORDING);
startImpl();
mOnStateChangedListener.onStart();
}
private void checkState(int... expectedStates) {
private void ensureIsStateOf(int... expectedStates) {
for (int expectedState : expectedStates) {
if (mState == expectedState)
return;
}
throw new IllegalStateException();
throw new IllegalStateException("expected=" + Arrays.toString(expectedStates) + " state=" + mState);
}
protected abstract void startImpl();
public void stop() {
checkState(STATE_RECORDING, STATE_PAUSED);
ensureIsStateOf(STATE_RECORDING, STATE_PAUSED);
setState(STATE_STOPPED);
stopImpl();
mOnStateChangedListener.onStop();
@@ -105,7 +126,7 @@ public interface Recorder {
protected abstract void stopImpl();
public void pause() {
checkState(STATE_RECORDING);
ensureIsStateOf(STATE_RECORDING);
setState(STATE_PAUSED);
pauseImpl();
mOnStateChangedListener.onPause();
@@ -136,7 +157,7 @@ public interface Recorder {
}
public void resume() {
checkState(STATE_PAUSED);
ensureIsStateOf(STATE_PAUSED);
setState(STATE_RECORDING);
resumeImpl();
mOnStateChangedListener.onResume();

View File

@@ -2,12 +2,10 @@ package com.stardust.scriptdroid.record.accessibility;
import android.accessibilityservice.AccessibilityService;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import com.stardust.scriptdroid.record.Recorder;
import com.stardust.view.accessibility.AccessibilityDelegate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
@@ -17,7 +15,7 @@ import java.util.Set;
* Created by Stardust on 2017/2/14.
*/
public class AccessibilityActionRecorder extends Recorder.DefaultIMPL implements AccessibilityDelegate {
public class AccessibilityActionRecorder extends Recorder.AbstractRecorder implements AccessibilityDelegate {
public static class AccessibilityActionRecordEvent {

View File

@@ -1,6 +1,14 @@
package com.stardust.scriptdroid.record.inputevent;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.widget.Toast;
import com.flurry.android.FlurryAgent;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.scriptdroid.record.Recorder;
import org.greenrobot.eventbus.EventBus;
@@ -13,22 +21,6 @@ import java.util.regex.Pattern;
public abstract class InputEventConverter {
public static class RecordStateChangeEvent {
private boolean mIsRecording;
public RecordStateChangeEvent(boolean isRecording) {
this.mIsRecording = isRecording;
}
public boolean isRecording() {
return mIsRecording;
}
}
static class Event {
static final Pattern PATTERN = Pattern.compile("^\\[([^\\]]*)\\]\\s+([^:]*):\\s+([^\\s]*)\\s+([^\\s]*)\\s+([^\\s]*)\\s*$");
@@ -76,47 +68,63 @@ public abstract class InputEventConverter {
}
protected boolean mStarted = false;
protected boolean mConverting = false;
private int mState = Recorder.STATE_NOT_START;
public void parseAndAddEventIfFormatCorrect(String eventStr) {
public void convertEventIfFormatCorrect(String eventStr) {
if(!mConverting)
return;
if(TextUtils.isEmpty(eventStr) || !eventStr.startsWith("["))
return;
Event event = parseEventOrNull(eventStr);
if (event != null) {
addEvent(event);
convertEvent(event);
}
}
public abstract void addEvent(@NonNull Event event);
public abstract void convertEvent(@NonNull Event event);
public String getGetEventCommand() {
return "getevent -t -l";
}
public void start() {
mStarted = true;
mConverting = true;
mState = Recorder.STATE_RECORDING;
}
public void resume(){
mConverting = true;
mState = Recorder.STATE_RECORDING;
}
public void pause() {
mStarted = false;
mConverting = false;
mState = Recorder.STATE_PAUSED;
}
public void stop() {
mStarted = false;
mConverting = false;
mState = Recorder.STATE_STOPPED;
}
public abstract String getCode();
private boolean mFirstEventFormatError = true;
public Event parseEventOrNull(String eventStr) {
try {
return Event.parseEvent(eventStr);
} catch (EventFormatException e) {
e.printStackTrace();
if(mFirstEventFormatError){
Toast.makeText(App.getApp(), R.string.text_record_format_error, Toast.LENGTH_SHORT).show();
mFirstEventFormatError = false;
FlurryAgent.logEvent("EventFormatException:" + e.getMessage());
}
return null;
}
}
public void notifyRecordStopped() {
EventBus.getDefault().post(new RecordStateChangeEvent(false));
}
public void notifyRecordStarted() {
EventBus.getDefault().post(new RecordStateChangeEvent(true));
}
}

View File

@@ -1,11 +1,18 @@
package com.stardust.scriptdroid.record.inputevent;
import android.preference.PreferenceManager;
import android.util.Log;
import com.stardust.pio.UncheckedIOException;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.record.Recorder;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import jackpal.androidterm.ShellTermSession;
import jackpal.androidterm.emulatorview.TermSession;
@@ -15,23 +22,23 @@ import jackpal.androidterm.util.TermSettings;
* Created by Stardust on 2017/3/6.
*/
public abstract class InputEventRecorder extends Recorder.DefaultIMPL {
public class InputEventRecorder extends Recorder.AbstractRecorder {
private static final String TAG = "InputEventRecorder";
private TermSession mTermSession;
private String mGetEventCommand;
protected InputEventConverter mInputEventConverter;
protected InputEventRecorder(String getEventCommand, InputEventConverter inputEventConverter) {
mGetEventCommand = getEventCommand;
protected InputEventRecorder(InputEventConverter inputEventConverter) {
mGetEventCommand = inputEventConverter.getGetEventCommand();
mInputEventConverter = inputEventConverter;
}
public void listen() {
TermSettings settings = new TermSettings(App.getApp().getResources(), PreferenceManager.getDefaultSharedPreferences(App.getApp()));
try {
mTermSession = new MyShellTermSession(settings, "su\r");
mTermSession = new MyShellTermSession(settings, "su");
mTermSession.initializeEmulator(80, 40);
mTermSession.write("su\r");
} catch (IOException e) {
throw new RuntimeException(e);
}
@@ -50,7 +57,7 @@ public abstract class InputEventRecorder extends Recorder.DefaultIMPL {
@Override
protected void resumeImpl() {
mInputEventConverter.start();
mInputEventConverter.resume();
}
@Override
@@ -59,31 +66,79 @@ public abstract class InputEventRecorder extends Recorder.DefaultIMPL {
mInputEventConverter.stop();
}
@Override
public String getCode() {
return mInputEventConverter.getCode();
}
protected abstract void parseAndRecordEvent(String eventStr);
protected void convertEvent(String eventStr) {
mInputEventConverter.convertEventIfFormatCorrect(eventStr);
}
private class MyShellTermSession extends ShellTermSession {
private boolean mGettingEvents = false;
private volatile boolean mGettingEvents = false;
private BufferedReader mBufferedReader;
private OutputStream mOutputStream;
private Thread mReadingThread;
public MyShellTermSession(TermSettings settings, String initialCommand) throws IOException {
super(settings, initialCommand);
PipedInputStream pipedInputStream = new PipedInputStream(8192);
mBufferedReader = new BufferedReader(new InputStreamReader(pipedInputStream));
mOutputStream = new PipedOutputStream(pipedInputStream);
startReadingThread();
}
private void startReadingThread() {
mReadingThread = new Thread(new Runnable() {
@Override
public void run() {
String line;
try {
while (!Thread.currentThread().isInterrupted()
&& (line = mBufferedReader.readLine()) != null){
onNewLine(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
mReadingThread.start();
}
private void onNewLine(String line) {
Log.d(TAG, line);
if (!mGettingEvents && line.endsWith(" $ su")) {
mTermSession.write(mGetEventCommand + "\r");
mGettingEvents = true;
} else if (mGettingEvents) {
convertEvent(line);
}
}
@Override
protected void processInput(byte[] data, int offset, int count) {
String[] lines = new String(data, offset, count).split("\n");
for (String line : lines) {
System.out.println(line);
if (!mGettingEvents && line.endsWith("data # ")) {
mTermSession.write(mGetEventCommand + "\r");
mGettingEvents = true;
} else if (mGettingEvents) {
parseAndRecordEvent(line);
}
try {
mOutputStream.write(data, offset, count);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
@Override
public void finish() {
super.finish();
mReadingThread.interrupt();
try {
mBufferedReader.close();
mOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
appendToEmulator(data, offset, count);
}
}
}

View File

@@ -86,7 +86,7 @@ public class InputEventToJsConverter extends InputEventConverter {
}
private void appendCodeIfNotStopped(Event event) {
if (!mStarted)
if (!mConverting)
return;
long interval = (long) (1000 * (event.time - mTouchTime));
mCode.append("sh.Swipe(")
@@ -115,20 +115,12 @@ public class InputEventToJsConverter extends InputEventConverter {
if (event.code.equals("BTN_TOUCH")) {
mTouchDown = event.value.equals("DOWN");
if (!mTouchDown && mSwipe) {
if (mStarted)
if (mConverting)
mCode.append("sh.Tap(").append(mLastTouchPoint.x).append(", ").append(mLastTouchPoint.y).append(");\n");
mSwipe = false;
}
} else if (event.value.equals("UP")) {
if (!mStarted && event.code.equals(mStartTriggerKey)) {
mStarted = true;
notifyRecordStarted();
} else if (mStarted && event.code.equals(mStopTriggerKey)) {
mStarted = false;
notifyRecordStopped();
} else {
appendKeyPressCode(event);
}
}
}
@@ -141,7 +133,6 @@ public class InputEventToJsConverter extends InputEventConverter {
}
private EventHandler mEventHandler = new TypeRouter();
private String mStartTriggerKey, mStopTriggerKey;
private StringBuilder mCode = new StringBuilder().append("var sh = new Shell(true);\n");
private Point mTouchPoint = new Point(), mLastTouchPoint = new Point();
private boolean mTouchDown = false, mSwipe = false;
@@ -149,7 +140,7 @@ public class InputEventToJsConverter extends InputEventConverter {
@Override
public void addEvent(@NonNull Event event) {
public void convertEvent(@NonNull Event event) {
mEventHandler.handle(event);
}
@@ -163,13 +154,5 @@ public class InputEventToJsConverter extends InputEventConverter {
return mCode.toString();
}
public void setStartTriggerKey(String startTriggerKey) {
mStartTriggerKey = startTriggerKey;
}
public void setStopTriggerKey(String stopTriggerKey) {
mStopTriggerKey = stopTriggerKey;
}
}

View File

@@ -1,33 +0,0 @@
package com.stardust.scriptdroid.record.inputevent;
/**
* Created by Stardust on 2017/3/7.
*/
public class InputEventToJsRecorder extends InputEventRecorder {
private InputEventToJsConverter mInputEventToJsConverter;
public InputEventToJsRecorder() {
super("getevent -t -l", new InputEventToJsConverter());
mInputEventToJsConverter = (InputEventToJsConverter) mInputEventConverter;
}
@Override
protected void parseAndRecordEvent(String eventStr) {
mInputEventConverter.parseAndAddEventIfFormatCorrect(eventStr);
}
@Override
public String getCode() {
return mInputEventConverter.getCode();
}
public void setStartTriggerKey(String startTriggerKey) {
mInputEventToJsConverter.setStartTriggerKey(startTriggerKey);
}
public void setStopTriggerKey(String stopTriggerKey) {
mInputEventToJsConverter.setStopTriggerKey(stopTriggerKey);
}
}

View File

@@ -17,7 +17,7 @@ public class InputEventToSendEventConverter extends InputEventConverter {
private StringBuilder mSendEventCommands = new StringBuilder();
@Override
public void addEvent(@NonNull Event event) {
public void convertEvent(@NonNull Event event) {
if (mLastEventTime == 0) {
mLastEventTime = event.time;
} else if (event.time - mLastEventTime > 0.1) {
@@ -32,6 +32,11 @@ public class InputEventToSendEventConverter extends InputEventConverter {
}
@Override
public String getGetEventCommand() {
return "getevent -t";
}
public String getCode() {
return mSendEventCommands.toString();
}

View File

@@ -0,0 +1,132 @@
package com.stardust.scriptdroid.record.inputevent;
import android.support.annotation.NonNull;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.stardust.util.ScreenMetrics.getScreenHeight;
import static com.stardust.util.ScreenMetrics.getScreenWidth;
/**
* Created by Stardust on 2017/5/3.
*/
public class InputEventToSendEventJsConverter extends InputEventConverter {
private final static Pattern LAST_INT_PATTERN = Pattern.compile("[^0-9]+([0-9]+)$");
private double mLastEventTime;
private StringBuilder mCode = new StringBuilder();
private int mTouchDevice = -1;
private int mLastTouchX = -1;
private int mLastTouchY = -1;
public InputEventToSendEventJsConverter() {
mCode.append("var sh = new Shell(true);\n")
.append("sh.SetScreenScale(").append(getScreenWidth()).append(", ")
.append(getScreenHeight()).append(");\n");
}
@Override
public void convertEvent(@NonNull Event event) {
if (mLastEventTime == 0) {
mLastEventTime = event.time;
} else if (event.time - mLastEventTime > 0.03) {
mCode.append("sleep(").append((long) (1000 * (event.time - mLastEventTime))).append(");\n");
mLastEventTime = event.time;
}
int device = parseDeviceNumber(event.device);
int type = (int) Long.parseLong(event.type, 16);
int code = (int) Long.parseLong(event.code, 16);
int value = (int) Long.parseLong(event.value, 16);
if (type == 3) {
if (code == 53) {
onTouchX(device, value);
return;
}
if (code == 54) {
onTouchY(device, value);
return;
}
}
checkLastTouch();
mCode.append("sh.SendEvent(");
if (device != mTouchDevice) {
mCode.append(device).append(", ");
}
mCode.append(type).append(", ")
.append(code).append(", ")
.append(value).append(");\n");
}
private void checkLastTouch() {
if (mLastTouchX >= 0) {
mCode.append("sh.TouchX(").append(mLastTouchX).append(");\n");
mLastTouchX = -1;
}
if (mLastTouchY >= 0) {
mCode.append("sh.TouchY(").append(mLastTouchY).append(");\n");
mLastTouchY = -1;
}
}
private int parseDeviceNumber(String device) {
Matcher matcher = LAST_INT_PATTERN.matcher(device);
if (matcher.find()) {
String someNumberStr = matcher.group(1);
return Integer.parseInt(someNumberStr);
}
return -1;
}
private void onTouchX(int device, int value) {
if (mTouchDevice == -1) {
setTouchDevice(device);
}
mLastTouchX = value;
}
private void onTouchY(int device, int value) {
if (mTouchDevice == -1) {
setTouchDevice(device);
}
if (mLastTouchX >= 0) {
mCode.append("sh.Touch(")
.append(mLastTouchX).append(", ")
.append(value).append(");\n");
mLastTouchX = -1;
} else {
mLastTouchY = value;
}
}
private void setTouchDevice(int i) {
mCode.append("sh.SetTouchDevice(").append(i).append(");\n");
mTouchDevice = i;
}
@Override
public String getGetEventCommand() {
return "getevent -t";
}
public String getCode() {
return mCode.toString();
}
@Override
public void stop() {
super.stop();
mCode.append("sh.exitAndWaitFor();");
}
private static String hex2dec(String hex) {
try {
return String.valueOf((int) Long.parseLong(hex, 16));
} catch (NumberFormatException e) {
throw new EventFormatException(e);
}
}
}

View File

@@ -1,26 +0,0 @@
package com.stardust.scriptdroid.record.inputevent;
/**
* Created by Stardust on 2017/3/7.
*/
public class InputEventToSendEventRecorder extends InputEventRecorder {
private InputEventToSendEventConverter mEventConverter;
protected InputEventToSendEventRecorder() {
super("getevent -t", new InputEventToSendEventConverter());
}
@Override
protected void parseAndRecordEvent(String eventStr) {
mEventConverter.parseAndAddEventIfFormatCorrect(eventStr);
}
@Override
public String getCode() {
return mEventConverter.getCode();
}
}

View File

@@ -0,0 +1,66 @@
package com.stardust.scriptdroid.record.inputevent;
import android.support.annotation.NonNull;
/**
* Created by Stardust on 2017/5/4.
*/
public class KeyObserver {
public interface KeyListener {
void onKeyDown(String keyName);
void onKeyUp(String keyName);
}
private InputEventRecorder mObserver;
private KeyListener mKeyListener;
public KeyObserver(){
mObserver = new InputEventRecorder(new InputEventConverter() {
@Override
public void convertEvent(@NonNull Event event) {
if(event.value.equalsIgnoreCase("UP")){
notifyKeyUp(event.code);
}
if(event.value.equalsIgnoreCase("DOWN")){
notifyKeyDown(event.code);
}
}
@Override
public String getCode() {
return null;
}
});
}
public void setKeyListener(KeyListener keyListener) {
mKeyListener = keyListener;
}
public void startListening(){
mObserver.listen();
mObserver.start();
}
public void stopListening(){
mObserver.stopImpl();
}
private void notifyKeyDown(String keyName) {
if(mKeyListener != null){
mKeyListener.onKeyDown(keyName);
}
}
private void notifyKeyUp(String keyName) {
if(mKeyListener != null){
mKeyListener.onKeyUp(keyName);
}
}
}

View File

@@ -1,26 +1,32 @@
package com.stardust.scriptdroid.record.inputevent;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.Pref;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.record.Recorder;
/**
* Created by Stardust on 2017/3/16.
*/
public class TouchRecorder extends InputEventToJsRecorder {
public class TouchRecorder extends InputEventRecorder implements KeyObserver.KeyListener {
public TouchRecorder() {
super(new InputEventToSendEventJsConverter());
listen();
setUpTriggers();
}
private void setUpTriggers() {
setStartTriggerKey(Pref.getStartRecordTrigger());
setStopTriggerKey(Pref.getStopRecordTrigger());
@Override
public void stop() {
super.stop();
}
@Override
public void onKeyDown(String keyName) {
}
@Override
public void onKeyUp(String keyName) {
}
}

View File

@@ -1,4 +1,4 @@
package com.stardust.scriptdroid.scripts;
package com.stardust.scriptdroid.script;
import android.app.Activity;
import android.os.Build;

View File

@@ -1,8 +1,7 @@
package com.stardust.scriptdroid.scripts;
package com.stardust.scriptdroid.script;
import android.os.Environment;
import com.android.dex.util.FileUtils;
import com.stardust.pio.PFile;
import java.io.File;

View File

@@ -1,4 +1,4 @@
package com.stardust.scriptdroid.scripts;
package com.stardust.scriptdroid.script;
import java.io.File;

View File

@@ -0,0 +1,113 @@
package com.stardust.scriptdroid.script;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import com.stardust.autojs.execution.ScriptExecution;
import com.stardust.autojs.execution.ScriptExecutionListener;
import com.stardust.autojs.execution.SimpleScriptExecutionListener;
import com.stardust.autojs.runtime.ScriptInterruptedException;
import com.stardust.autojs.script.FileScriptSource;
import com.stardust.autojs.script.ScriptSource;
import com.stardust.autojs.script.ScriptSourceWithInit;
import com.stardust.autojs.script.StringScriptSource;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.BuildConfig;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.scriptdroid.external.CommonUtils;
import com.stardust.scriptdroid.external.shortcut.Shortcut;
import com.stardust.scriptdroid.external.shortcut.ShortcutActivity;
import com.stardust.scriptdroid.script.sample.Sample;
import com.stardust.scriptdroid.ui.edit.EditActivity;
import com.stardust.util.AssetsCache;
import java.io.File;
/**
* Created by Stardust on 2017/5/3.
*/
public class Scripts {
public static final String ACTION_ON_EXECUTION_FINISHED = "Don't leave me alone...";
public static final String EXTRA_EXCEPTION_MESSAGE = "Say something...Eating...17.5.3";
private static final ScriptExecutionListener BROADCAST_SENDER_SCRIPT_EXECUTION_LISTENER = new SimpleScriptExecutionListener() {
@Override
public void onSuccess(ScriptExecution execution, Object result) {
App.getApp().sendBroadcast(new Intent(ACTION_ON_EXECUTION_FINISHED));
}
@Override
public void onException(ScriptExecution execution, Exception e) {
if (ScriptInterruptedException.causedByInterrupted(e)) {
App.getApp().sendBroadcast(new Intent(ACTION_ON_EXECUTION_FINISHED));
} else {
App.getApp().sendBroadcast(new Intent(ACTION_ON_EXECUTION_FINISHED)
.putExtra(EXTRA_EXCEPTION_MESSAGE, e.getMessage()));
}
}
};
private static final String INIT_SCRIPT_PATH = "js/autojs_init.js";
private static ScriptSource initScriptSource;
public static void openByOtherApps(String path) {
Uri uri = Uri.parse("file://" + path);
App.getApp().startActivity(new Intent(Intent.ACTION_VIEW).setDataAndType(uri, "text/plain").addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
public static void openByOtherApps(File file) {
openByOtherApps(file.getPath());
}
public static void createShortcut(ScriptFile scriptFile) {
new Shortcut(App.getApp()).name(scriptFile.getSimplifiedName())
.targetClass(ShortcutActivity.class)
.icon(R.drawable.ic_node_js_black)
.extras(new Intent().putExtra(CommonUtils.EXTRA_KEY_PATH, scriptFile.getPath()))
.send();
}
public static void edit(ScriptFile file) {
EditActivity.editFile(App.getApp(), file.getSimplifiedName(), file.getPath());
}
public static void edit(String path) {
edit(new ScriptFile(path));
}
public static ScriptExecution run(ScriptFile file) {
return run(new FileScriptSource(file));
}
public static ScriptExecution run(ScriptSource source) {
return AutoJs.getInstance().getScriptEngineService().execute(wrappedWithInitSource(source));
}
private static ScriptSource wrappedWithInitSource(ScriptSource source) {
return new ScriptSourceWithInit(getInitScriptSource(), source);
}
public static ScriptExecution runWithBroadcastSender(ScriptSource scriptSource) {
return AutoJs.getInstance().getScriptEngineService().execute(wrappedWithInitSource(scriptSource), BROADCAST_SENDER_SCRIPT_EXECUTION_LISTENER);
}
public static ScriptExecution run(Context context, Sample file) {
ScriptSource source = new StringScriptSource(file.name, AssetsCache.get(context.getAssets(), file.path));
return AutoJs.getInstance().getScriptEngineService().execute(wrappedWithInitSource(source));
}
private static ScriptSource getInitScriptSource() {
if(initScriptSource == null || BuildConfig.DEBUG){
String initScript = AssetsCache.get(App.getApp().getAssets(), INIT_SCRIPT_PATH);
initScriptSource = new StringScriptSource(initScript);
}
return initScriptSource;
}
}

View File

@@ -1,4 +1,4 @@
package com.stardust.scriptdroid.scripts;
package com.stardust.scriptdroid.script;
import android.content.Context;
import android.content.SharedPreferences;

View File

@@ -1,4 +1,4 @@
package com.stardust.scriptdroid.scripts;
package com.stardust.scriptdroid.script;
import android.os.Environment;
@@ -6,7 +6,6 @@ import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.R;
import com.stardust.util.FileSorter;
import com.stardust.util.LimitedHashMap;
import com.stardust.util.MapEntries;
import org.greenrobot.eventbus.EventBus;

View File

@@ -1,4 +1,10 @@
package com.stardust.scriptdroid.scripts.sample;
package com.stardust.scriptdroid.script.sample;
import android.content.Context;
import com.stardust.autojs.script.StringScriptSource;
import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.util.AssetsCache;
import java.io.Serializable;

View File

@@ -1,4 +1,4 @@
package com.stardust.scriptdroid.scripts.sample;
package com.stardust.scriptdroid.script.sample;
import android.content.Context;
import android.content.res.AssetManager;

View File

@@ -1,4 +1,4 @@
package com.stardust.scriptdroid.scripts.sample;
package com.stardust.scriptdroid.script.sample;
import java.util.ArrayList;
import java.util.List;

View File

@@ -4,20 +4,17 @@ import android.accessibilityservice.AccessibilityService;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import com.stardust.scriptdroid.Pref;
import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.R;
import com.stardust.util.Shell;
import com.stardust.autojs.runtime.api.ProcessShell;
import com.stardust.view.accessibility.AccessibilityServiceUtils;
import java.util.Locale;
import static com.stardust.view.accessibility.AccessibilityServiceUtils.isAccessibilityServiceEnabled;
/**
* Created by Stardust on 2017/1/26.
*/
@@ -58,7 +55,7 @@ public class AccessibilityServiceTool {
public static boolean enableAccessibilityServiceByRoot(Class<? extends AccessibilityService> accessibilityService) {
String serviceName = App.getApp().getPackageName() + "/" + accessibilityService.getName();
return TextUtils.isEmpty(Shell.execCommand(String.format(Locale.getDefault(), cmd, serviceName), true).error);
return TextUtils.isEmpty(ProcessShell.exec(String.format(Locale.getDefault(), cmd, serviceName), true).error);
}
public static boolean enableAccessibilityServiceByRootAndWaitFor(long timeOut) {

View File

@@ -76,13 +76,13 @@ public abstract class DrawableSaver {
}
public void select(Activity activity, final OnActivityResultDelegate.Intermediary intermediary) {
new ImageSelector(activity, intermediary, new ImageSelector.ImageSelectorCallback() {
public void select(Activity activity, final OnActivityResultDelegate.Mediator mediator) {
new ImageSelector(activity, mediator, new ImageSelector.ImageSelectorCallback() {
@Override
public void onImageSelected(ImageSelector selector, InputStream inputStream) {
if (inputStream != null)
setDrawable(inputStream);
intermediary.removeDelegate(selector);
mediator.removeDelegate(selector);
}
}).select();
}

View File

@@ -25,8 +25,8 @@ public class ImageSelector implements OnActivityResultDelegate {
private Activity mActivity;
private ImageSelectorCallback mCallback;
public ImageSelector(Activity activity, Intermediary intermediary, ImageSelectorCallback callback) {
intermediary.addDelegate(REQUEST_CODE, this);
public ImageSelector(Activity activity, Mediator mediator, ImageSelectorCallback callback) {
mediator.addDelegate(REQUEST_CODE, this);
mActivity = activity;
mCallback = callback;
}

View File

@@ -1,161 +0,0 @@
package com.stardust.scriptdroid.tool;
import android.content.Context;
import android.preference.PreferenceManager;
import com.stardust.pio.UncheckedIOException;
import com.stardust.scriptdroid.App;
import java.io.IOException;
import jackpal.androidterm.ShellTermSession;
import jackpal.androidterm.emulatorview.TermSession;
import jackpal.androidterm.util.TermSettings;
/**
* Created by Stardust on 2017/4/24.
*/
public class Shell {
private TermSession mTermSession;
private String mOutput;
public Shell(boolean root) {
this(App.getApp(), root ? "su\n" : "sh\n");
}
public Shell(Context context, String initialCommand) {
TermSettings settings = new TermSettings(context.getResources(), PreferenceManager.getDefaultSharedPreferences(context));
try {
mTermSession = new MyShellTermSession(settings, initialCommand);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public String execAndWaitFor(String command) {
mTermSession.write(command + "\n");
mOutput = null;
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
return mOutput;
}
public String execAndWaitFor(String command, int millis) {
mTermSession.write(command + "\n");
mOutput = null;
synchronized (this) {
try {
wait(millis);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
return mOutput;
}
public void exec(String command) {
mTermSession.write(command);
}
public void execute(String command) {
mTermSession.write(command);
}
public void Tap(int x, int y) {
execute("input tap " + x + " " + y);
}
public void Swipe(int x1, int y1, int x2, int y2) {
execute("input swipe " + x1 + " " + y1 + " " + x2 + " " + y2);
}
public void Swipe(int x1, int y1, int x2, int y2, long duration) {
execute("input swipe " + x1 + " " + y1 + " " + x2 + " " + y2 + " " + duration);
}
public void KeyCode(int keyCode) {
execute("input keyevent " + keyCode);
}
public void KeyCode(String keyCode) {
execute("input keyevent " + keyCode);
}
public void Home() {
KeyCode(3);
}
public void Back() {
KeyCode(4);
}
public void Power() {
KeyCode(26);
}
public void Up() {
KeyCode(19);
}
public void Down() {
KeyCode(20);
}
public void Left() {
KeyCode(21);
}
public void Right() {
KeyCode(22);
}
public void OK() {
KeyCode(23);
}
public void VolumeUp() {
KeyCode(24);
}
public void VolumeDown() {
KeyCode(25);
}
public void Menu() {
KeyCode(1);
}
public void Camera() {
KeyCode(27);
}
public void Text(String text) {
execute("input text " + text);
}
private class MyShellTermSession extends ShellTermSession {
public MyShellTermSession(TermSettings settings, String initialCommand) throws IOException {
super(settings, initialCommand);
}
@Override
protected void processInput(byte[] data, int offset, int count) {
mOutput = new String(data, offset, count);
synchronized (Shell.this) {
Shell.this.notifyAll();
}
appendToEmulator(data, offset, count);
}
}
}

View File

@@ -27,7 +27,7 @@ public class ConsoleActivity extends BaseActivity {
private void setUpUI() {
setContentView(R.layout.activity_console);
setToolbarAsBack(getString(R.string.text_console));
setToolbarAsBack(getString(R.string.text_log));
}
@Override

View File

@@ -0,0 +1,83 @@
package com.stardust.scriptdroid.ui.console;
import android.content.Intent;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.util.SparseArray;
import com.jraska.console.Console;
import com.stardust.autojs.runtime.api.AbstractConsole;
import com.stardust.scriptdroid.App;
import com.stardust.util.SparseArrayEntries;
import com.stardust.util.TextUtils;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
/**
* Created by Stardust on 2017/4/2.
*/
public class JraskaConsole extends AbstractConsole {
private static final SparseArray<Integer> COLORS = new SparseArrayEntries<Integer>()
.entry(Log.VERBOSE, 0xff909090)
.entry(Log.DEBUG, 0xdf000000)
.entry(Log.INFO, 0xdf4caf50)
.entry(Log.WARN, 0xff2196f3)
.entry(Log.ERROR, 0xffff534e)
.entry(Log.ASSERT, 0xffff534e)
.sparseArray();
private static final SparseArray<String> TAGS = new SparseArrayEntries<String>()
.entry(Log.VERBOSE, "V")
.entry(Log.DEBUG, "D")
.entry(Log.INFO, "I")
.entry(Log.WARN, "W")
.entry(Log.ERROR, "E")
.entry(Log.ASSERT, "A")
.sparseArray();
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("HH:mm:ss.SSS/", Locale.getDefault());
@Override
public void println(int level, CharSequence charSequence) {
Console.write(getLevelSpannable(level, getTag(level)));
Console.writeLine(getLevelSpannable(level, charSequence));
}
private CharSequence getTag(int level) {
return TextUtils.join("", DATE_FORMAT.format(new Date()), TAGS.get(level), ": ");
}
private SpannableString getLevelSpannable(int level, CharSequence charSequence) {
SpannableString spannable = new SpannableString(charSequence);
spannable.setSpan(new ForegroundColorSpan(COLORS.get(level)), 0, charSequence.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return spannable;
}
@Override
public void clear() {
com.jraska.console.Console.clear();
}
@Override
public void show() {
App.getApp().startActivity(new Intent(App.getApp(), ConsoleActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
@Override
public void hide() {
throw new UnsupportedOperationException();
}
@Override
public void setTitle(CharSequence title) {
}
}

View File

@@ -3,7 +3,7 @@ package com.stardust.scriptdroid.ui.console;
import android.content.Context;
import android.content.Intent;
import com.stardust.autojs.runtime.AbstractConsole;
import com.stardust.autojs.runtime.api.AbstractConsole;
import com.stardust.autojs.runtime.api.Console;
import com.stardust.enhancedfloaty.FloatyService;
import com.stardust.enhancedfloaty.ResizableExpandableFloatyWindow;

View File

@@ -1,68 +0,0 @@
package com.stardust.scriptdroid.ui.console;
import android.content.Intent;
import android.graphics.Color;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import com.jraska.console.Console;
import com.jraska.console.timber.ConsoleTree;
import com.stardust.autojs.runtime.AbstractConsole;
import com.stardust.scriptdroid.App;
import timber.log.Timber;
/**
* Created by Stardust on 2017/4/2.
*/
public class TimberConsole extends AbstractConsole {
static {
Timber.plant(new ConsoleTree.Builder()
.minPriority(Log.VERBOSE)
.verboseColor(0xff909090)
.debugColor(0xdf000000)
.infoColor(0xdf4caf50)
.warnColor(0xff2196f3)
.errorColor(0xffff534e)
.assertColor(0xffff534e)
.build());
}
@Override
public void println(int level, CharSequence charSequence) {
if (level == Log.DEBUG) {
SpannableString spannable = new SpannableString(charSequence);
spannable.setSpan(new ForegroundColorSpan(0xdd000000), 0, charSequence.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
Console.writeLine(spannable);
} else {
Timber.log(level, charSequence.toString());
}
}
@Override
public void clear() {
com.jraska.console.Console.clear();
}
@Override
public void show() {
App.getApp().startActivity(new Intent(App.getApp(), ConsoleActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
@Override
public void hide() {
throw new UnsupportedOperationException();
}
@Override
public void setTitle(CharSequence title) {
}
}

View File

@@ -27,7 +27,8 @@ import com.stardust.autojs.script.JsBeautifier;
import com.stardust.autojs.script.StringScriptSource;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.scriptdroid.scripts.ScriptFile;
import com.stardust.scriptdroid.script.ScriptFile;
import com.stardust.scriptdroid.script.Scripts;
import com.stardust.scriptdroid.tool.JsBeautifierFactory;
import com.stardust.scriptdroid.tool.MaterialDialogFactory;
import com.stardust.scriptdroid.ui.BaseActivity;
@@ -35,7 +36,6 @@ import com.stardust.scriptdroid.ui.edit.completion.InputMethodEnhanceBar;
import com.stardust.scriptdroid.ui.edit.editor920.Editor920Activity;
import com.stardust.scriptdroid.ui.edit.editor920.Editor920Utils;
import com.stardust.scriptdroid.ui.help.HelpCatalogueActivity;
import com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation;
import com.stardust.theme.ThemeColorManager;
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
import com.stardust.util.SparseArrayEntries;
@@ -45,11 +45,6 @@ import com.stardust.widget.ToolbarMenuItem;
import java.io.File;
import timber.log.Timber;
import static com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation.ACTION_ON_RUN_FINISHED;
import static com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation.EXTRA_EXCEPTION_MESSAGE;
/**
* Created by Stardust on 2017/1/29.
*/
@@ -83,6 +78,7 @@ public class EditActivity extends Editor920Activity {
}
}
public static final String EXTRA_CONTENT = "Still Love Eating 17.4.5";
public static void editFile(Context context, String path) {
@@ -109,13 +105,12 @@ public class EditActivity extends Editor920Activity {
private BroadcastReceiver mOnRunFinishedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_ON_RUN_FINISHED)) {
if (intent.getAction().equals(Scripts.ACTION_ON_EXECUTION_FINISHED)) {
mScriptExecution = null;
setMenuStatus(R.id.run, MenuDef.STATUS_NORMAL);
String msg = intent.getStringExtra(EXTRA_EXCEPTION_MESSAGE);
String msg = intent.getStringExtra(Scripts.EXTRA_EXCEPTION_MESSAGE);
if (msg != null) {
Snackbar.make(mView, getString(R.string.text_error) + ": " + msg, Snackbar.LENGTH_LONG).show();
Timber.e(msg);
}
}
}
@@ -131,7 +126,7 @@ public class EditActivity extends Editor920Activity {
handleIntent(getIntent());
setUpUI();
setUpEditor();
registerReceiver(mOnRunFinishedReceiver, new IntentFilter(ACTION_ON_RUN_FINISHED));
registerReceiver(mOnRunFinishedReceiver, new IntentFilter(Scripts.ACTION_ON_EXECUTION_FINISHED));
}
private void handleIntent(Intent intent) {
@@ -212,12 +207,13 @@ public class EditActivity extends Editor920Activity {
Snackbar.make(mView, R.string.text_start_running, Snackbar.LENGTH_SHORT).show();
setMenuStatus(R.id.run, MenuDef.STATUS_DISABLED);
if (mFile != null) {
mScriptExecution = ScriptFileOperation.runOnEditView(new FileScriptSource(mName, mFile));
mScriptExecution = Scripts.runWithBroadcastSender(new FileScriptSource(mName, mFile));
} else {
mScriptExecution = ScriptFileOperation.runOnEditView(new StringScriptSource(mName, mEditorDelegate.getText()));
mScriptExecution = Scripts.runWithBroadcastSender(new StringScriptSource(mName, mEditorDelegate.getText()));
}
}
@ViewBinding.Click(R.id.undo)
private void undo() {
Command command = new Command(Command.CommandEnum.UNDO);
@@ -266,6 +262,9 @@ public class EditActivity extends Editor920Activity {
case R.id.action_console:
showConsole();
return true;
case R.id.action_log:
showLog();
return true;
case R.id.action_help:
HelpCatalogueActivity.showMainCatalogue(this);
return true;
@@ -282,11 +281,13 @@ public class EditActivity extends Editor920Activity {
return super.onOptionsItemSelected(item);
}
private void showLog() {
AutoJs.getInstance().getScriptEngineService().getGlobalConsole().show();
}
private void showConsole() {
if (mScriptExecution != null) {
mScriptExecution.getRuntime().console.show();
} else {
AutoJs.getInstance().getScriptEngineService().getGlobalConsole().show();
}
}
@@ -298,8 +299,7 @@ public class EditActivity extends Editor920Activity {
private void openByOtherApps() {
if (mFile != null)
ScriptFileOperation.openByOtherApps(mFile.getPath());
Scripts.openByOtherApps(mFile);
}
private void beautifyCode() {

View File

@@ -15,16 +15,18 @@ import com.jecelyin.editor.v2.common.Command;
import com.jecelyin.editor.v2.ui.EditorDelegate;
import com.jecelyin.editor.v2.view.EditorView;
import com.jecelyin.editor.v2.view.menu.MenuDef;
import com.stardust.autojs.execution.ScriptExecution;
import com.stardust.autojs.script.StringScriptSource;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.scripts.sample.Sample;
import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.scriptdroid.script.Scripts;
import com.stardust.scriptdroid.script.sample.Sample;
import com.stardust.scriptdroid.ui.BaseActivity;
import com.stardust.scriptdroid.ui.console.ConsoleActivity;
import com.stardust.scriptdroid.ui.edit.editor920.Editor920Activity;
import com.stardust.scriptdroid.ui.edit.editor920.Editor920Utils;
import com.stardust.scriptdroid.ui.help.HelpCatalogueActivity;
import com.stardust.scriptdroid.ui.main.MainActivity;
import com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation;
import com.stardust.theme.ThemeColorManager;
import com.stardust.util.AssetsCache;
import com.stardust.util.SparseArrayEntries;
@@ -32,10 +34,10 @@ import com.stardust.view.ViewBinder;
import com.stardust.view.ViewBinding;
import com.stardust.widget.ToolbarMenuItem;
import timber.log.Timber;
import static com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation.ACTION_ON_RUN_FINISHED;
import static com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation.EXTRA_EXCEPTION_MESSAGE;
import static com.stardust.scriptdroid.script.Scripts.ACTION_ON_EXECUTION_FINISHED;
import static com.stardust.scriptdroid.script.Scripts.EXTRA_EXCEPTION_MESSAGE;
/**
* Created by Stardust on 2017/4/29.
@@ -43,6 +45,7 @@ import static com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation.EXT
public class ViewSampleActivity extends Editor920Activity {
public static void view(Context context, Sample sample) {
context.startActivity(new Intent(context, ViewSampleActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
@@ -51,17 +54,18 @@ public class ViewSampleActivity extends Editor920Activity {
private View mView;
private Sample mSample;
private ScriptExecution mScriptExecution;
private EditorDelegate mEditorDelegate;
private SparseArray<ToolbarMenuItem> mMenuMap;
private BroadcastReceiver mOnRunFinishedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_ON_RUN_FINISHED)) {
if (intent.getAction().equals(ACTION_ON_EXECUTION_FINISHED)) {
mScriptExecution = null;
setMenuStatus(R.id.run, MenuDef.STATUS_NORMAL);
String msg = intent.getStringExtra(EXTRA_EXCEPTION_MESSAGE);
if (msg != null) {
Snackbar.make(mView, getString(R.string.text_error) + ": " + msg, Snackbar.LENGTH_LONG).show();
Timber.e(msg);
}
}
}
@@ -75,7 +79,7 @@ public class ViewSampleActivity extends Editor920Activity {
handleIntent(getIntent());
setUpUI();
setUpEditor();
registerReceiver(mOnRunFinishedReceiver, new IntentFilter(ACTION_ON_RUN_FINISHED));
registerReceiver(mOnRunFinishedReceiver, new IntentFilter(ACTION_ON_EXECUTION_FINISHED));
}
private void handleIntent(Intent intent) {
@@ -107,7 +111,7 @@ public class ViewSampleActivity extends Editor920Activity {
private void run() {
Snackbar.make(mView, R.string.text_start_running, Snackbar.LENGTH_SHORT).show();
setMenuStatus(R.id.run, MenuDef.STATUS_DISABLED);
ScriptFileOperation.runOnEditView(new StringScriptSource(mSample.name, mEditorDelegate.getText()));
mScriptExecution = Scripts.runWithBroadcastSender(new StringScriptSource(mSample.name, mEditorDelegate.getText()));
}
private void initMenuItem() {
@@ -135,7 +139,10 @@ public class ViewSampleActivity extends Editor920Activity {
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_console:
startActivity(new Intent(getContext(), ConsoleActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
showConsole();
return true;
case R.id.action_log:
showLog();
return true;
case R.id.action_help:
HelpCatalogueActivity.showMainCatalogue(this);
@@ -147,6 +154,17 @@ public class ViewSampleActivity extends Editor920Activity {
return super.onOptionsItemSelected(item);
}
private void showLog() {
AutoJs.getInstance().getScriptEngineService().getGlobalConsole().show();
}
private void showConsole() {
if (mScriptExecution != null) {
mScriptExecution.getRuntime().console.show();
}
}
@Override
public void doCommand(Command command) {
mEditorDelegate.doCommand(command);

View File

@@ -29,9 +29,9 @@ import com.stardust.app.NotAskAgainDialog;
import com.stardust.app.OnActivityResultDelegate;
import com.stardust.scriptdroid.BuildConfig;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.scripts.ScriptFile;
import com.stardust.scriptdroid.scripts.StorageScriptProvider;
import com.stardust.scriptdroid.scripts.sample.Sample;
import com.stardust.scriptdroid.script.ScriptFile;
import com.stardust.scriptdroid.script.StorageScriptProvider;
import com.stardust.scriptdroid.script.sample.Sample;
import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
import com.stardust.scriptdroid.tool.AccessibilityServiceTool;
import com.stardust.scriptdroid.tool.DrawableSaver;
@@ -75,7 +75,7 @@ public class MainActivity extends BaseActivity {
private SlidingUpPanel mAddBottomMenuPanel;
private FragmentPagerAdapterBuilder.StoredFragmentPagerAdapter mPagerAdapter;
private OnActivityResultDelegate.Intermediary mActivityResultIntermediary = new OnActivityResultDelegate.Intermediary();
private OnActivityResultDelegate.Mediator mActivityResultMediator = new OnActivityResultDelegate.Mediator();
private DrawableSaver mDrawerHeaderBackgroundSaver, mAppbarBackgroundSaver;
private VersionGuard mVersionGuard;
private Intent mIntentToHandle;
@@ -240,7 +240,7 @@ public class MainActivity extends BaseActivity {
@ViewBinding.Click(R.id.drawer_header_img)
public void selectHeaderImage() {
mDrawerHeaderBackgroundSaver.select(this, mActivityResultIntermediary);
mDrawerHeaderBackgroundSaver.select(this, mActivityResultMediator);
}
@Override
@@ -330,7 +330,7 @@ public class MainActivity extends BaseActivity {
@ViewBinding.Click(R.id.toolbar)
public void OnToolbarClick() {
mAppbarBackgroundSaver.select(this, mActivityResultIntermediary);
mAppbarBackgroundSaver.select(this, mActivityResultMediator);
}
@Subscribe
@@ -343,7 +343,7 @@ public class MainActivity extends BaseActivity {
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
mActivityResultIntermediary.onActivityResult(requestCode, resultCode, data);
mActivityResultMediator.onActivityResult(requestCode, resultCode, data);
}
@Override

View File

@@ -1,84 +0,0 @@
package com.stardust.scriptdroid.ui.main.operation;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import com.stardust.autojs.execution.ScriptExecution;
import com.stardust.autojs.execution.ScriptExecutionListener;
import com.stardust.autojs.execution.SimpleScriptExecutionListener;
import com.stardust.autojs.runtime.ScriptInterruptedException;
import com.stardust.autojs.script.FileScriptSource;
import com.stardust.autojs.script.ScriptSource;
import com.stardust.autojs.script.StringScriptSource;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.scriptdroid.external.CommonUtils;
import com.stardust.scriptdroid.external.shortcut.Shortcut;
import com.stardust.scriptdroid.external.shortcut.ShortcutActivity;
import com.stardust.scriptdroid.scripts.ScriptFile;
import com.stardust.scriptdroid.scripts.sample.Sample;
import com.stardust.scriptdroid.ui.edit.EditActivity;
import com.stardust.util.AssetsCache;
/**
* Created by Stardust on 2017/1/23.
*/
public abstract class ScriptFileOperation {
public static final String ACTION_ON_RUN_FINISHED = "ACTION_ON_RUN_FINISHED";
public static final String EXTRA_EXCEPTION_MESSAGE = "EXTRA_EXCEPTION_MESSAGE";
private static final ScriptExecutionListener RUN_ON_EDIT_VIEW_SCRIPT_EXECUTION_LISTENER = new SimpleScriptExecutionListener() {
@Override
public void onSuccess(ScriptExecution execution, Object result) {
App.getApp().sendBroadcast(new Intent(ACTION_ON_RUN_FINISHED));
}
@Override
public void onException(ScriptExecution execution, Exception e) {
if (ScriptInterruptedException.causedByInterrupted(e)) {
return;
}
App.getApp().sendBroadcast(new Intent(ACTION_ON_RUN_FINISHED)
.putExtra(EXTRA_EXCEPTION_MESSAGE, e.getMessage()));
}
};
public static void openByOtherApps(String path) {
Uri uri = Uri.parse("file://" + path);
App.getApp().startActivity(new Intent(Intent.ACTION_VIEW).setDataAndType(uri, "text/plain").addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
public static void createShortcut(ScriptFile scriptFile) {
new Shortcut(App.getApp()).name(scriptFile.getSimplifiedName())
.targetClass(ShortcutActivity.class)
.icon(R.drawable.ic_node_js_black)
.extras(new Intent().putExtra(CommonUtils.EXTRA_KEY_PATH, scriptFile.getPath()))
.send();
}
public static void edit(ScriptFile file) {
EditActivity.editFile(App.getApp(), file.getSimplifiedName(), file.getPath());
}
public static void run(ScriptFile file) {
AutoJs.getInstance().getScriptEngineService().execute(new FileScriptSource(file));
}
public static void run(Context context, Sample file) {
AutoJs.getInstance().getScriptEngineService().execute(new StringScriptSource(file.name, AssetsCache.get(context.getAssets(), file.path)));
}
public static ScriptExecution runOnEditView(ScriptSource scriptSource) {
return AutoJs.getInstance().getScriptEngineService().execute(scriptSource, RUN_ON_EDIT_VIEW_SCRIPT_EXECUTION_LISTENER);
}
}

View File

@@ -2,7 +2,6 @@ package com.stardust.scriptdroid.ui.main.sample_list;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -10,13 +9,11 @@ import android.view.ViewGroup;
import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.app.Fragment;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.scripts.sample.Sample;
import com.stardust.scriptdroid.scripts.sample.SampleFileManager;
import com.stardust.scriptdroid.script.Scripts;
import com.stardust.scriptdroid.script.sample.Sample;
import com.stardust.scriptdroid.script.sample.SampleFileManager;
import com.stardust.scriptdroid.ui.edit.ViewSampleActivity;
import com.stardust.scriptdroid.ui.main.MainActivity;
import com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation;
import java.io.IOException;
/**
* Created by Stardust on 2017/3/13.
@@ -59,7 +56,7 @@ public class SampleScriptListFragment extends Fragment {
@Override
public void onSelection(MaterialDialog dialog, View itemView, int position, CharSequence text) {
if (position == 0) {
ScriptFileOperation.run(getActivity(), sample);
Scripts.run(getActivity(), sample);
} else {
copySampleToMyScripts(sample);
}

View File

@@ -3,7 +3,6 @@ package com.stardust.scriptdroid.ui.main.sample_list;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.LayoutInflater;
@@ -17,7 +16,7 @@ import com.bignerdranch.expandablerecyclerview.ExpandableRecyclerAdapter;
import com.bignerdranch.expandablerecyclerview.ParentViewHolder;
import com.bignerdranch.expandablerecyclerview.model.Parent;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.scripts.sample.Sample;
import com.stardust.scriptdroid.script.sample.Sample;
import com.stardust.widget.LevelBeamView;
import java.util.ArrayList;
@@ -87,9 +86,9 @@ public class SampleScriptListRecyclerView extends RecyclerView {
mOnItemClickListener = onItemClickListener;
}
public void setSamples(List<com.stardust.scriptdroid.scripts.sample.SampleGroup> samples) {
public void setSamples(List<com.stardust.scriptdroid.script.sample.SampleGroup> samples) {
mSampleGroups.clear();
for (com.stardust.scriptdroid.scripts.sample.SampleGroup sampleGroup : samples) {
for (com.stardust.scriptdroid.script.sample.SampleGroup sampleGroup : samples) {
mSampleGroups.add(new SampleGroup(sampleGroup));
}
mAdapter = new Adapter(mSampleGroups);
@@ -103,9 +102,9 @@ public class SampleScriptListRecyclerView extends RecyclerView {
private class SampleGroup implements Parent<Sample> {
private com.stardust.scriptdroid.scripts.sample.SampleGroup mSampleGroup;
private com.stardust.scriptdroid.script.sample.SampleGroup mSampleGroup;
SampleGroup(com.stardust.scriptdroid.scripts.sample.SampleGroup sampleGroup) {
SampleGroup(com.stardust.scriptdroid.script.sample.SampleGroup sampleGroup) {
mSampleGroup = sampleGroup;
}

View File

@@ -5,7 +5,6 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.text.InputType;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -14,12 +13,12 @@ import android.widget.EditText;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.app.Fragment;
import com.stardust.scriptdroid.scripts.ScriptFile;
import com.stardust.scriptdroid.script.ScriptFile;
import com.stardust.pio.PFile;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.scripts.StorageScriptProvider;
import com.stardust.scriptdroid.script.Scripts;
import com.stardust.scriptdroid.script.StorageScriptProvider;
import com.stardust.scriptdroid.ui.edit.EditActivity;
import com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation;
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
import com.stardust.view.ViewBinder;
import com.stardust.view.ViewBinding;
@@ -142,7 +141,7 @@ public class MyScriptListFragment extends Fragment {
}
}
notifyScriptFileChanged();
ScriptFileOperation.edit(new ScriptFile(path));
Scripts.edit(path);
} else {
Snackbar.make(getView(), R.string.text_create_fail, Snackbar.LENGTH_LONG).show();
}
@@ -255,7 +254,7 @@ public class MyScriptListFragment extends Fragment {
@ViewBinding.Click(R.id.open_by_other_apps)
private void openByOtherApps() {
dismissDialogs();
ScriptFileOperation.openByOtherApps(mSelectedScriptFile.getPath());
Scripts.openByOtherApps(mSelectedScriptFile);
onScriptFileOperated();
}
@@ -272,7 +271,7 @@ public class MyScriptListFragment extends Fragment {
@ViewBinding.Click(R.id.create_shortcut)
private void createShortcut() {
dismissDialogs();
ScriptFileOperation.createShortcut(mSelectedScriptFile);
Scripts.createShortcut(mSelectedScriptFile);
Snackbar.make(getView(), R.string.text_already_create, Snackbar.LENGTH_SHORT).show();
onScriptFileOperated();
}

View File

@@ -10,17 +10,14 @@ import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.workground.WrapContentLinearLayoutManager;
import com.stardust.autojs.script.FileScriptSource;
import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.scriptdroid.scripts.ScriptFile;
import com.stardust.scriptdroid.script.ScriptFile;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.scripts.StorageScriptProvider;
import com.stardust.scriptdroid.ui.main.operation.ScriptFileOperation;
import com.stardust.scriptdroid.script.Scripts;
import com.stardust.scriptdroid.script.StorageScriptProvider;
import com.stardust.widget.ViewHolderMutableAdapter;
import com.stardust.widget.ViewHolderSupplier;
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
@@ -111,7 +108,7 @@ public class ScriptAndFolderListRecyclerView extends RecyclerView {
public void onClick(View v) {
int position = getChildViewHolder((View) v.getParent()).getAdapterPosition();
ScriptFile file = mAdapter.getScriptFileAt(position);
ScriptFileOperation.run(file);
Scripts.run(file);
}
};
private final ViewHolderSupplier<ViewHolder> mDefaultViewHolderSupplier = new ViewHolderSupplier<ViewHolder>() {

View File

@@ -4,8 +4,8 @@ import android.content.Context;
import android.support.annotation.NonNull;
import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.scriptdroid.scripts.ScriptFile;
import com.stardust.scriptdroid.scripts.StorageScriptProvider;
import com.stardust.scriptdroid.script.ScriptFile;
import com.stardust.scriptdroid.script.StorageScriptProvider;
/**
* Created by Stardust on 2017/4/3.

View File

@@ -13,8 +13,8 @@ import android.view.View;
import android.widget.FrameLayout;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.scripts.ScriptFile;
import com.stardust.scriptdroid.scripts.StorageScriptProvider;
import com.stardust.scriptdroid.script.ScriptFile;
import com.stardust.scriptdroid.script.StorageScriptProvider;
/**
* Created by Stardust on 2017/4/3.

View File

@@ -16,7 +16,7 @@ import android.widget.Toast;
import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.scriptdroid.BuildConfig;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.scripts.StorageScriptProvider;
import com.stardust.scriptdroid.script.StorageScriptProvider;
import com.stardust.scriptdroid.tool.IntentTool;
import com.stardust.scriptdroid.tool.UpdateChecker;
import com.stardust.util.DownloadTask;

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_width="304dp"
android:layout_height="match_parent"
android:background="@android:color/white"
android:clickable="true"

View File

@@ -23,7 +23,7 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/text_console"
android:text="@string/text_log"
android:textColor="@android:color/primary_text_light"/>
</LinearLayout>

View File

@@ -20,6 +20,12 @@
android:title="@string/text_force_stop"
app:showAsAction="never"/>
<item
android:id="@+id/action_log"
android:orderInCategory="280"
android:title="@string/text_log"
app:showAsAction="never"/>
<item
android:id="@+id/action_help"
android:orderInCategory="300"

View File

@@ -4,10 +4,16 @@
<item
android:id="@+id/action_console"
android:orderInCategory="200"
android:orderInCategory="100"
android:title="@string/text_console"
app:showAsAction="never"/>
<item
android:id="@+id/action_log"
android:orderInCategory="200"
android:title="@string/text_log"
app:showAsAction="never"/>
<item
android:id="@+id/action_help"
android:orderInCategory="300"

View File

@@ -12,13 +12,13 @@
<string name="text_please_input_name">请输入名称</string>
<string name="text_name">名称</string>
<string name="text_go_to_setting">去设置</string>
<string name="explain_accessibility_permission">软件需要打开\"自动操作服务\"才能运行,请在随后的设置中选择\"AutoJs\"并开启服务。\n您也可以稍后在侧拉菜单中设置。</string>
<string name="explain_accessibility_permission">软件需要打开\"无障碍服务\"才能运行,请在随后的设置中选择\"AutoJs\"并开启服务。\n您也可以稍后在侧拉菜单中设置。</string>
<string name="text_cancel">取消</string>
<string name="text_path_is_empty">路径为空</string>
<string name="text_file_not_exists">文件不存在</string>
<string name="text_no_file_rw_permission">无文件读写权限</string>
<string name="action_test">内嵌920测试</string>
<string name="text_no_accessibility_permission">自动操作服务未启动,脚本已停止运行</string>
<string name="text_no_accessibility_permission">无障碍服务未启动,脚本已停止运行</string>
<string name="text_drawer_close">关闭侧拉菜单</string>
<string name="text_drawer_open">打开侧拉菜单</string>
<string name="text_undo">撤销</string>
@@ -31,7 +31,7 @@
<string name="text_exit_directly">直接退出</string>
<string name="text_setting">设置</string>
<string name="text_exit">退出</string>
<string name="text_auto_operate_service">自动操作服务</string>
<string name="text_auto_operate_service">无障碍服务</string>
<string name="text_syntax_and_api">帮助</string>
<string name="text_close_all_running_scripts">关闭所有正在运行的脚本</string>
<string name="text_about">关于</string>
@@ -83,7 +83,7 @@
<string name="text_choose_email_app">请选择邮件应用</string>
<string name="text_assist_clip">点击定位剪贴板</string>
<string name="text_script_stopped">脚本已停止</string>
<string name="assist_mode_notice">\"点击区域辅助服务\"是在要点击的区域不是文本时使用的,参见\"帮助\"。\"点击区域辅助服务\"只有在\"自动操作服务\"开启时才有效。</string>
<string name="assist_mode_notice">\"点击区域辅助服务\"是在要点击的区域不是文本时使用的,参见\"帮助\"。\"点击区域辅助服务\"只有在\"无障碍服务\"开启时才有效。</string>
<string name="text_please_choose">请选择</string>
<string name="text_crash">崩溃了o(≧口≦)o</string>
<string name="crash_feedback">点击\"退出\"退出程序(ಥ _ ಥ)或者提交错误报告或者复制调试信息反馈给开发者(≧∇≦)ノ</string>
@@ -94,6 +94,7 @@
<string name="text_fail">失败</string>
<string name="text_clear">清空</string>
<string name="text_console">控制台</string>
<string name="text_log">日志</string>
<string name="text_sample_wechat_scan">微信扫一扫</string>
<string name="text_report_bug">提交错误报告</string>
<string name="text_bug_report">Bug Report</string>
@@ -112,7 +113,7 @@
<string name="text_recorded">录制结束</string>
<string name="text_copy_to_clip">复制到剪贴板</string>
<string name="text_file_write_fail">文件写入失败</string>
<string name="text_need_enable_accessibility_service_to_record">需要打开\"自动操作服务“才能录制脚本</string>
<string name="text_need_enable_accessibility_service_to_record">需要打开\"无障碍服务“才能录制脚本</string>
<string name="text_join_qq_group">加入QQ交流群</string>
<string name="text_copied">已复制到剪贴板</string>
<string name="text_close">关闭</string>
@@ -127,10 +128,10 @@
<string name="text_file_exists">文件已存在</string>
<string name="text_accessibility_service">无障碍服务</string>
<string name="text_enable_accessibility_service_by_root">通过Root权限自动启用服务</string>
<string name="text_auto_operate_service_enabled_but_not_running">自动操作服务已启用但并未运行,这可能是安卓的BUG,您可能需要重启手机</string>
<string name="text_auto_operate_service_enabled_but_not_running">无障碍服务已启用但并未运行,这可能是安卓的BUG,您可能需要重启手机</string>
<string name="key_enable_accessibility_service_by_root">key_enable_accessibility_service_by_root</string>
<string name="text_enable_accessibility_service_by_root_timeout">使用Root权限启动自动操作服务超时</string>
<string name="summary_enable_accessibility_service_by_root">开启后运行脚本会使用Root权限自动开启自动操作服务</string>
<string name="text_enable_accessibility_service_by_root_timeout">使用Root权限启动无障碍服务超时</string>
<string name="summary_enable_accessibility_service_by_root">开启后运行脚本会使用Root权限自动开启无障碍服务</string>
<string name="text_appearance">外观</string>
<string name="text_theme_color">主题色</string>
<string name="text_select_image">选择图片</string>
@@ -218,6 +219,7 @@
<string name="text_layout_inspector_is_dumping">布局分析中,请稍后点击</string>
<string name="text_force_stop">强制停止</string>
<string name="text_execution_finished" formatted="false">\n------------\n[%s]运行结束,用时%f秒</string>
<string name="text_record_format_error">录制格式错误</string>
<string-array name="record_control_keys">
<item>无</item>

View File

@@ -20,18 +20,14 @@ android {
}
}
packagingOptions {
exclude 'org/mozilla/javascript/tools/debugger/build.xml'
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:25.3.0'
compile 'com.github.hyb1996:node-android-lib:1.0.14'
compile 'org.greenrobot:eventbus:3.0.0'
compile project(path: ':common')

View File

@@ -1,11 +1,11 @@
if(__engine_name__ == "rhino"){
__importClassOld__ = importClass;
__importClass__ = importClass;
var importClass = function(pack){
if(typeof(pack) == "string"){
__importClassOld__(Packages[pack]);
__importClass__(Packages[pack]);
}else{
__importClassOld__(pack);
__importClass__(pack);
}
}
var loadJar = function(path){
@@ -183,23 +183,23 @@ var setClip = function(text){
var Tap = function(x, y){
__runtime__.shellExecNotReturnResultWithRoot("input tap " + x + " " + y);
__runtime__.shellExecAsync("input tap " + x + " " + y);
}
var Swipe = function(x1, y1, x2, y2, duration){
if(arguments.length == 5){
__runtime__.shellExecNotReturnResultWithRoot("input swipe " + x1 + " " + y1 + " " + x2 + " " + y2 + " " + duration);
__runtime__.shellExecAsync("input swipe " + x1 + " " + y1 + " " + x2 + " " + y2 + " " + duration);
}else{
__runtime__.shellExecNotReturnResultWithRoot("input swipe " + x1 + " " + y1 + " " + x2 + " " + y2);
__runtime__.shellExecAsync("input swipe " + x1 + " " + y1 + " " + x2 + " " + y2);
}
}
var Screencap = function(path){
__runtime__.shellExecNotReturnResultWithRoot("screencap -p " + path);
__runtime__.shellExecAsync("screencap -p " + path);
}
var KeyCode = function(keyCode){
__runtime__.shellExecNotReturnResultWithRoot("input keyevent " + keyCode);
__runtime__.shellExecAsync("input keyevent " + keyCode);
}
var Home = function(){
@@ -251,7 +251,7 @@ var Camera = function(){
}
var Text = function(text){
__runtime__.shellExecNotReturnResultWithRoot("input text " + text);
__runtime__.shellExecAsync("input text " + text);
}
var selector = function(){
@@ -299,8 +299,6 @@ var open = function(path, mode, encoding, bufferSize){
}
//__importClassOld__(com.stardust.autojs.runtime.api.SlowShell);
var newInjectableWebClient = function(){
return new com.stardust.autojs.runtime.api.InjectableWebClient(org.mozilla.javascript.Context.getCurrentContext(), __this__);
}
@@ -308,11 +306,3 @@ var newInjectableWebClient = function(){
var newInjectableWebView = function(activity){
return new com.stardust.autojs.runtime.api.InjectableWebView(activity, org.mozilla.javascript.Context.getCurrentContext(), __this__);
}
/*
importClass("com.stardust.script__runtime__.service.AccessibilityDelegate");
var addAccessibilityDelegate = function(delegate){
__runtime__.addAccessibilityDelegate(delegate);
}
*/

View File

@@ -147,10 +147,9 @@ public class ScriptEngineService {
@Subscribe
public void onScriptExecution(ScriptExecutionEvent event) {
if (event.getCode() == ScriptExecutionEvent.ON_START) {
mGlobalConsole.verbose(DateFormat.getTimeInstance().format(new Date()) + " " + mContext.getString(R.string.text_start_running) + " " + event.getMessage());
mGlobalConsole.verbose(mContext.getString(R.string.text_start_running) + "[" + event.getMessage() + "]");
} else if (event.getCode() == ScriptExecutionEvent.ON_EXCEPTION) {
mUiHandler.toast(mContext.getString(R.string.text_error) + ": " + event.getMessage());
mGlobalConsole.error(event.getMessage());
}
}

View File

@@ -0,0 +1,70 @@
package com.stardust.autojs.runtime;
import com.stardust.autojs.engine.JavaScriptEngine;
import com.stardust.autojs.runtime.api.AbstractShell;
import com.stardust.autojs.runtime.api.AppUtils;
import com.stardust.autojs.runtime.api.Console;
import com.stardust.autojs.runtime.api.UiSelector;
import com.stardust.autojs.runtime.simple_action.SimpleActionAutomator;
import com.stardust.view.accessibility.AccessibilityInfoProvider;
/**
* Created by Stardust on 2017/5/4.
*/
public abstract class AbstractScriptRuntime {
@JavascriptField
public AppUtils app;
@JavascriptField
public Console console;
@JavascriptField
public SimpleActionAutomator automator;
@JavascriptField
public AccessibilityInfoProvider info;
public AbstractScriptRuntime(AppUtils app, Console console, AccessibilityBridge bridge) {
this.app = app;
this.console = console;
this.automator = new SimpleActionAutomator(bridge, this);
this.info = bridge.getInfoProvider();
}
public AbstractScriptRuntime() {
}
@JavascriptInterface
public abstract void toast(final String text);
@JavascriptInterface
public abstract void sleep(long millis);
@JavascriptInterface
public abstract void setClip(final String text);
@JavascriptInterface
public abstract void shellExecAsync(String cmd);
@JavascriptInterface
public abstract AbstractShell.Result shell(String cmd, int root);
@JavascriptInterface
public abstract UiSelector selector(JavaScriptEngine engine);
@JavascriptInterface
public abstract boolean isStopped();
@JavascriptInterface
public abstract void requiresApi(int i);
@JavascriptInterface
public abstract void loadJar(String path);
@JavascriptInterface
public abstract void stop();
public abstract void ensureAccessibilityServiceEnabled();
}

View File

@@ -6,17 +6,14 @@ import com.stardust.autojs.R;
import com.stardust.autojs.engine.JavaScriptEngine;
import com.stardust.autojs.rhino_android.AndroidClassLoader;
import com.stardust.autojs.runtime.api.AbstractShell;
import com.stardust.autojs.runtime.api.SlowShell;
import com.stardust.autojs.runtime.simple_action.SimpleActionAutomator;
import com.stardust.autojs.runtime.api.AppUtils;
import com.stardust.autojs.runtime.api.Console;
import com.stardust.autojs.runtime.api.UiSelector;
import com.stardust.pio.UncheckedIOException;
import com.stardust.util.ClipboardUtil;
import com.stardust.autojs.runtime.api.ProcessShell;
import com.stardust.util.SdkVersionUtil;
import com.stardust.util.Shell;
import com.stardust.util.UiHandler;
import com.stardust.view.accessibility.AccessibilityInfoProvider;
import org.mozilla.javascript.ContextFactory;
@@ -28,42 +25,25 @@ import java.io.IOException;
* Created by Stardust on 2017/1/27.
*/
public class ScriptRuntime {
public class ScriptRuntime extends AbstractScriptRuntime {
private static final String TAG = "ScriptRuntime";
private UiHandler mUiHandler;
private AccessibilityBridge mAccessibilityBridge;
@JavascriptField
public AppUtils app;
@JavascriptField
public Console console;
@JavascriptField
public SimpleActionAutomator automator;
@JavascriptField
public AccessibilityInfoProvider info;
private AbstractShell mRootShell;
public ScriptRuntime(UiHandler uiHandler, Console console, AccessibilityBridge accessibilityBridge) {
super(new AppUtils(uiHandler.getContext()), console, accessibilityBridge);
mAccessibilityBridge = accessibilityBridge;
mUiHandler = uiHandler;
app = new AppUtils(uiHandler.getContext());
info = accessibilityBridge.getInfoProvider();
this.console = console;
automator = new SimpleActionAutomator(accessibilityBridge, this);
}
@JavascriptInterface
public void toast(final String text) {
mUiHandler.toast(text);
}
@JavascriptInterface
public void sleep(long millis) {
try {
Thread.sleep(millis);
@@ -72,7 +52,6 @@ public class ScriptRuntime {
}
}
@JavascriptInterface
public void setClip(final String text) {
mUiHandler.post(new Runnable() {
@Override
@@ -82,38 +61,31 @@ public class ScriptRuntime {
});
}
@JavascriptInterface
public void shellExecNotReturnResultWithRoot(String cmd) {
public void shellExecAsync(String cmd) {
if (mRootShell == null) {
mRootShell = new SlowShell(true);
mRootShell = new ProcessShell(true);
}
mRootShell.exec(cmd);
}
@JavascriptInterface
public Shell.CommandResult shell(String cmd, int root) {
return Shell.execCommand(cmd, root != 0);
public AbstractShell.Result shell(String cmd, int root) {
return ProcessShell.exec(cmd, root != 0);
}
@JavascriptInterface
public UiSelector selector(JavaScriptEngine engine) {
return new UiSelector(mAccessibilityBridge);
}
@JavascriptInterface
public boolean isStopped() {
return Thread.currentThread().isInterrupted();
}
@JavascriptInterface
public void requiresApi(int i) {
if (Build.VERSION.SDK_INT < i) {
throw new ScriptStopException(mUiHandler.getContext().getString(R.string.text_requires_sdk_version_to_run_the_script) + SdkVersionUtil.sdkIntToString(i));
}
}
@JavascriptInterface
public void loadJar(String path) {
try {
((AndroidClassLoader) ContextFactory.getGlobal().getApplicationClassLoader()).loadJar(new File(path));
@@ -122,7 +94,6 @@ public class ScriptRuntime {
}
}
@JavascriptInterface
public void stop() {
Thread.interrupted();
}

View File

@@ -1,8 +1,9 @@
package com.stardust.autojs.runtime;
package com.stardust.autojs.runtime.api;
import android.support.annotation.Nullable;
import android.util.Log;
import com.stardust.autojs.runtime.ScriptStopException;
import com.stardust.autojs.runtime.api.Console;
/**

View File

@@ -1,23 +1,110 @@
package com.stardust.autojs.runtime.api;
import android.text.TextUtils;
import com.stardust.util.ScreenMetrics;
import java.util.Arrays;
/**
* Created by Stardust on 2017/4/24.
*/
public abstract class AbstractShell {
public static class Result {
public int code = -1;
public String error;
public String result;
@Override
public String toString() {
return "ShellResult{" +
"code=" + code +
", error='" + error + '\'' +
", result='" + result + '\'' +
'}';
}
}
private static final String COMMAND_SU = "su";
private static final String COMMAND_SH = "sh";
static final String COMMAND_EXIT = "exit\n";
static final String COMMAND_LINE_END = "\n";
private int mTouchDevice;
private int mScreenHeight, mScreenWidth;
private boolean mRoot;
public AbstractShell() {
this(false);
}
public AbstractShell(boolean root) {
init(root ? "su" : "sh");
mRoot = root;
init(root ? COMMAND_SU: COMMAND_SH);
}
public boolean isRoot() {
return mRoot;
}
protected abstract void init(String initialCommand);
public abstract void exec(String command);
public abstract void exit();
public void SetTouchDevice(int touchDevice) {
mTouchDevice = touchDevice;
}
public void SendEvent(int type, int code, int value){
SendEvent(mTouchDevice, type, code, value);
}
public void SendEvent(int device, int type, int code, int value){
exec(TextUtils.join("", new Object[]{"sendevent /dev/input/event", device, " ", type, " ", code, " ", value}));
}
public void SetScreenScale(int width, int height){
mScreenWidth = width;
mScreenHeight = height;
}
public void Touch(int x, int y){
TouchX(x);
TouchY(y);
}
public void TouchX(int x) {
SendEvent(mTouchDevice, 3, 53, scaleX(x));
}
private int scaleX(int x) {
int screenWidth = ScreenMetrics.getScreenWidth();
if(screenWidth == mScreenWidth){
return x;
}
return x * screenWidth / mScreenWidth;
}
public void TouchY(int y) {
SendEvent(mTouchDevice, 3, 54, scaleY(y));
}
private int scaleY(int y) {
int screenHeight = ScreenMetrics.getScreenHeight();
if(screenHeight == mScreenHeight){
return y;
}
return y * screenHeight / mScreenHeight;
}
public void KeyCode(int keyCode) {
exec("input keyevent " + keyCode);
}
@@ -77,4 +164,6 @@ public abstract class AbstractShell {
public void Text(String text) {
exec("input text " + text);
}
public abstract void exitAndWaitFor();
}

View File

@@ -0,0 +1,176 @@
package com.stardust.autojs.runtime.api;
import com.stardust.pio.UncheckedIOException;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* Created by Stardust on 2017/1/20.
* <p>
* 来自网络~~
*/
public class ProcessShell extends AbstractShell implements AutoCloseable {
private static final String TAG = "ProcessShell";
private Process mProcess;
private DataOutputStream mCommandOutputStream;
private BufferedReader mSucceedReader;
private BufferedReader mErrorReader;
private StringBuilder mSucceedOutput = new StringBuilder();
private StringBuilder mErrorOutput = new StringBuilder();
public ProcessShell() {
}
public ProcessShell(boolean root) {
super(root);
}
@Override
protected void init(String initialCommand) {
try {
mProcess = new ProcessBuilder(initialCommand).redirectErrorStream(true).start();
mCommandOutputStream = new DataOutputStream(mProcess.getOutputStream());
mSucceedReader = new BufferedReader(new InputStreamReader(mProcess.getInputStream()));
mErrorReader = new BufferedReader(new InputStreamReader(mProcess.getErrorStream()));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
@Override
public void exec(String command) {
try {
mCommandOutputStream.writeBytes(command);
if (!command.endsWith(COMMAND_LINE_END)) {
mCommandOutputStream.writeBytes(COMMAND_LINE_END);
}
mCommandOutputStream.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void exit() {
if(mProcess != null) {
mProcess.destroy();
mProcess = null;
}
if(mSucceedReader != null){
try{
mSucceedReader.close();
}catch (IOException ignored){
}
mSucceedReader = null;
}
if(mErrorReader != null){
try{
mErrorReader.close();
}catch (IOException ignored){
}
mErrorReader = null;
}
}
@Override
public void close() {
exit();
}
@Override
public void exitAndWaitFor() {
exec(COMMAND_EXIT);
waitFor();
exit();
}
public int waitFor() {
try {
return mProcess.waitFor();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
public ProcessShell readAll() {
return readSucceedOutput().readErrorOutput();
}
public ProcessShell readSucceedOutput() {
try {
while (mSucceedReader.ready()) {
String line = mSucceedReader.readLine();
mSucceedOutput.append(line).append("\n");
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
return this;
}
public ProcessShell readErrorOutput() {
String line;
try {
while ((line = mErrorReader.readLine()) != null) {
mErrorOutput.append(line).append("\n");
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
return this;
}
public StringBuilder getSucceedOutput() {
return mSucceedOutput;
}
public StringBuilder getErrorOutput() {
return mErrorOutput;
}
public Process getProcess() {
return mProcess;
}
public BufferedReader getSucceedReader() {
return mSucceedReader;
}
public BufferedReader getErrorReader() {
return mErrorReader;
}
public static Result exec(String command, boolean isRoot) {
String[] commands = command.split("\n");
return exec(commands, isRoot);
}
public static Result exec(String[] commands, boolean isRoot) {
try(ProcessShell shell = new ProcessShell(isRoot)){
for(String command : commands){
shell.exec(command);
}
shell.exec(COMMAND_EXIT);
Result result = new Result();
result.code = shell.waitFor();
shell.readAll();
result.error = shell.getErrorOutput().toString();
result.result = shell.getSucceedOutput().toString();
shell.exit();
return result;
}
}
}

View File

@@ -1,28 +0,0 @@
package com.stardust.autojs.runtime.api;
import com.stardust.util.Shell;
/**
* Created by Stardust on 2017/3/7.
*/
public class SlowShell extends AbstractShell {
private Shell mShell;
public SlowShell(boolean root) {
super(root);
}
@Override
protected void init(String initialCommand) {
mShell = new Shell(initialCommand);
}
@Override
public void exec(String command) {
mShell.execute(command);
}
}

View File

@@ -8,6 +8,7 @@ import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import com.stardust.autojs.runtime.AbstractScriptRuntime;
import com.stardust.autojs.runtime.AccessibilityBridge;
import com.stardust.autojs.runtime.JavascriptInterface;
import com.stardust.autojs.runtime.ScriptRuntime;
@@ -45,9 +46,9 @@ public class SimpleActionAutomator {
}
private AccessibilityBridge mAccessibilityBridge;
private ScriptRuntime mScriptRuntime;
private AbstractScriptRuntime mScriptRuntime;
public SimpleActionAutomator(AccessibilityBridge accessibilityBridge, ScriptRuntime scriptRuntime) {
public SimpleActionAutomator(AccessibilityBridge accessibilityBridge, AbstractScriptRuntime scriptRuntime) {
mAccessibilityBridge = accessibilityBridge;
mScriptRuntime = scriptRuntime;
}

View File

@@ -1,33 +0,0 @@
package com.stardust.autojs.script;
/**
* Created by Stardust on 2017/4/2.
*/
public class MultiScriptSource extends ScriptSource {
private String mScript;
private FileScriptSource mFileScriptSource;
public MultiScriptSource(StringScriptSource stringScriptSource, FileScriptSource fileScriptSource) {
super(fileScriptSource.getName());
mFileScriptSource = fileScriptSource;
StringBuilder stringBuilder = new StringBuilder();
if (stringScriptSource.getScript() != null)
stringBuilder.append(stringScriptSource.getScript()).append("\n");
stringBuilder.append(fileScriptSource.getScript());
mScript = stringBuilder.toString();
}
@Override
public String getScript() {
return mScript;
}
@Override
public String toString() {
return mFileScriptSource.toString();
}
}

View File

@@ -0,0 +1,33 @@
package com.stardust.autojs.script;
/**
* Created by Stardust on 2017/4/2.
*/
public class ScriptSourceWithInit extends ScriptSource {
private String mScript;
private ScriptSource mMainScriptSource;
public ScriptSourceWithInit(ScriptSource initScriptSource, ScriptSource mainScriptSource) {
super(mainScriptSource.getName());
mMainScriptSource = mainScriptSource;
StringBuilder stringBuilder = new StringBuilder();
if (initScriptSource.getScript() != null)
stringBuilder.append(initScriptSource.getScript()).append("\n");
stringBuilder.append(mainScriptSource.getScript());
mScript = stringBuilder.toString();
}
@Override
public String getScript() {
return mScript;
}
@Override
public String toString() {
return mMainScriptSource.toString();
}
}

View File

@@ -22,11 +22,9 @@ android {
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.2.0'
testCompile 'junit:junit:4.12'
compile project(path: ':common')
}

View File

@@ -22,7 +22,6 @@ android {
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})

View File

@@ -2,15 +2,9 @@ package com.stardust.util;
import android.app.Activity;
import android.content.res.AssetManager;
import android.support.v4.app.FragmentActivity;
import com.stardust.pio.PFile;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* Created by Stardust on 2017/3/14.
*/

View File

@@ -1,264 +0,0 @@
package com.stardust.util;
import android.util.Log;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* Created by Stardust on 2017/1/20.
* <p>
* 来自网络~~
*/
public class Shell {
private static final String TAG = "Shell";
private final static String COMMAND_SU = "su";
private final static String COMMAND_SH = "sh";
private final static String COMMAND_EXIT = "exit\n";
private final static String COMMAND_LINE_END = "\n";
private Process mProcess;
private DataOutputStream mCommandOutputStream;
private BufferedReader mSucceedReader;
private BufferedReader mErrorReader;
private StringBuilder mSucceedOutput = new StringBuilder();
private StringBuilder mErrorOutput = new StringBuilder();
public Shell() {
this(false);
}
public Shell(boolean root) {
this(root ? COMMAND_SU : COMMAND_SH);
}
public Shell(String initialCommand) {
try {
mProcess = new ProcessBuilder(initialCommand).redirectErrorStream(true).start();
mCommandOutputStream = new DataOutputStream(mProcess.getOutputStream());
mSucceedReader = new BufferedReader(new InputStreamReader(mProcess.getInputStream()));
mErrorReader = new BufferedReader(new InputStreamReader(mProcess.getErrorStream()));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public Shell execute(String command) {
try {
mCommandOutputStream.writeBytes(command);
if (!command.endsWith(COMMAND_LINE_END)) {
mCommandOutputStream.writeBytes(COMMAND_LINE_END);
}
mCommandOutputStream.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
return this;
}
public Shell exitAndWaitFor() {
exit();
try {
mProcess.waitFor();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return this;
}
public Shell readAll() {
return readSucceedOutput().readErrorOutput();
}
public Shell readSucceedOutput() {
try {
while (mSucceedReader.ready()) {
String line = mSucceedReader.readLine();
mSucceedOutput.append(line).append("\n");
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return this;
}
public Shell readErrorOutput() {
String line;
try {
while ((line = mErrorReader.readLine()) != null) {
mErrorOutput.append(line).append("\n");
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return this;
}
public StringBuilder getSucceedOutput() {
return mSucceedOutput;
}
public StringBuilder getErrorOutput() {
return mErrorOutput;
}
public Shell exit() {
execute(COMMAND_EXIT);
return this;
}
public Shell destroy() {
mProcess.destroy();
return this;
}
public Process getProcess() {
return mProcess;
}
public BufferedReader getSucceedReader() {
return mSucceedReader;
}
public BufferedReader getErrorReader() {
return mErrorReader;
}
public int waitFor() {
try {
return mProcess.waitFor();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
/**
* Command执行结果
*
* @author Mountain
*/
public static class CommandResult {
public int code = -1;
public String error;
public String result;
@Override
public String toString() {
return "ShellResult{" +
"code=" + code +
", error='" + error + '\'' +
", result='" + result + '\'' +
'}';
}
}
/**
* 执行命令—单条
*
* @param command
* @param isRoot
* @return
*/
public static CommandResult execCommand(String command, boolean isRoot) {
String[] commands = command.split("\n");
return execCommand(commands, isRoot);
}
/**
* 执行命令-多条
*
* @param commands
* @param isRoot
* @return
*/
public static CommandResult execCommand(String[] commands, boolean isRoot) {
CommandResult commandResult = new CommandResult();
if (commands == null || commands.length == 0) return commandResult;
Process process = null;
DataOutputStream os = null;
BufferedReader successResult = null;
BufferedReader errorResult = null;
StringBuilder successMsg = null;
StringBuilder errorMsg = null;
try {
process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH);
os = new DataOutputStream(process.getOutputStream());
for (String command : commands) {
if (command != null) {
os.write(command.getBytes());
os.writeBytes(COMMAND_LINE_END);
os.flush();
}
}
os.writeBytes(COMMAND_EXIT);
os.flush();
commandResult.code = process.waitFor();
//获取错误信息
successMsg = new StringBuilder();
errorMsg = new StringBuilder();
successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String s;
while ((s = successResult.readLine()) != null) successMsg.append(s);
while ((s = errorResult.readLine()) != null) errorMsg.append(s);
commandResult.result = successMsg.toString();
commandResult.error = errorMsg.toString();
Log.i(TAG, commandResult.toString());
} catch (Exception e) {
String errmsg = e.getMessage();
if (errmsg != null) {
Log.e(TAG, errmsg);
} else {
e.printStackTrace();
}
} finally {
try {
if (os != null) os.close();
if (successResult != null) successResult.close();
if (errorResult != null) errorResult.close();
} catch (IOException e) {
String errmsg = e.getMessage();
if (errmsg != null) {
Log.e(TAG, errmsg);
} else {
e.printStackTrace();
}
}
if (process != null) process.destroy();
}
return commandResult;
}
public static Process exec(String[] commands, boolean isRoot) {
try {
Process process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH);
DataOutputStream os = new DataOutputStream(process.getOutputStream());
for (String command : commands) {
if (command != null) {
os.write(command.getBytes());
os.writeBytes(COMMAND_LINE_END);
os.flush();
}
}
os.writeBytes(COMMAND_EXIT);
os.flush();
os.close();
return process;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static Process exec(String command, boolean isRoot) {
return exec(command.split("\n"), isRoot);
}
}

View File

@@ -0,0 +1,12 @@
package com.stardust.util;
/**
* Created by Stardust on 2017/5/3.
*/
public class TextUtils {
public static String join(CharSequence delimiter, Object... tokens){
return android.text.TextUtils.join(delimiter, tokens);
}
}