Add statics:
This commit is contained in:
@@ -3,13 +3,13 @@ def AAVersion = '4.2.0'
|
|||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 25
|
compileSdkVersion 25
|
||||||
buildToolsVersion "25.0.1"
|
buildToolsVersion "25.0.2"
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.stardust.scriptdroid"
|
applicationId "com.stardust.scriptdroid"
|
||||||
minSdkVersion 19
|
minSdkVersion 19
|
||||||
targetSdkVersion 23
|
targetSdkVersion 23
|
||||||
versionCode 119
|
versionCode 120
|
||||||
versionName "2.0.8 Beta"
|
versionName "2.0.9 Beta"
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
}
|
}
|
||||||
@@ -49,6 +49,9 @@ android {
|
|||||||
pickFirst 'org/mozilla/javascript/*.java.orig'
|
pickFirst 'org/mozilla/javascript/*.java.orig'
|
||||||
pickFirst 'org/mozilla/javascript/tools/resources/*.properties'
|
pickFirst 'org/mozilla/javascript/tools/resources/*.properties'
|
||||||
}
|
}
|
||||||
|
configurations.all {
|
||||||
|
resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.1'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
@@ -58,13 +61,16 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
|
||||||
|
exclude group: 'com.android.support', module: 'support-annotations'
|
||||||
|
})
|
||||||
testCompile 'junit:junit:4.12'
|
testCompile 'junit:junit:4.12'
|
||||||
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5'
|
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5'
|
||||||
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
|
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
|
||||||
testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
|
testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
|
||||||
annotationProcessor "org.androidannotations:androidannotations:$AAVersion"
|
annotationProcessor 'com.pushtorefresh.storio:sqlite-annotations-processor:1.12.3'
|
||||||
compile "org.androidannotations:androidannotations-api:$AAVersion"
|
compile 'com.pushtorefresh.storio:sqlite-annotations:1.12.3'
|
||||||
compile 'com.android.support:appcompat-v7:25.1.0'
|
compile 'com.android.support:appcompat-v7:25.3.0'
|
||||||
compile 'com.android.support:design:25.1.0'
|
compile 'com.android.support:design:25.1.0'
|
||||||
compile 'com.github.hyb1996:MutableTheme:0.2.2'
|
compile 'com.github.hyb1996:MutableTheme:0.2.2'
|
||||||
compile 'com.afollestad.material-dialogs:core:0.9.2.3'
|
compile 'com.afollestad.material-dialogs:core:0.9.2.3'
|
||||||
@@ -85,6 +91,7 @@ dependencies {
|
|||||||
compile 'com.android.volley:volley:1.0.0'
|
compile 'com.android.volley:volley:1.0.0'
|
||||||
compile 'com.github.hyb1996:EnhancedFloaty:0.15'
|
compile 'com.github.hyb1996:EnhancedFloaty:0.15'
|
||||||
compile 'com.flurry.android:analytics:7.0.0@aar'
|
compile 'com.flurry.android:analytics:7.0.0@aar'
|
||||||
|
compile 'com.pushtorefresh.storio:sqlite:1.12.3'
|
||||||
compile 'com.android.support:multidex:1.0.1'
|
compile 'com.android.support:multidex:1.0.1'
|
||||||
compile(name: 'libtermexec-release', ext: 'aar')
|
compile(name: 'libtermexec-release', ext: 'aar')
|
||||||
compile(name: 'emulatorview-release', ext: 'aar')
|
compile(name: 'emulatorview-release', ext: 'aar')
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
package com.stardust.scriptdroid.statics;
|
||||||
|
|
||||||
|
import android.support.test.InstrumentationRegistry;
|
||||||
|
|
||||||
|
import com.stardust.autojs.script.FileScriptSource;
|
||||||
|
import com.stardust.autojs.script.ScriptSource;
|
||||||
|
import com.stardust.autojs.script.StringScriptSource;
|
||||||
|
import com.stardust.util.MapEntries;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Stardust on 2017/5/5.
|
||||||
|
*/
|
||||||
|
public class SQLiteStaticsStorageTest {
|
||||||
|
|
||||||
|
|
||||||
|
private SQLiteStaticsStorage mStorage;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
mStorage = new SQLiteStaticsStorage(InstrumentationRegistry.getTargetContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void record() throws Exception {
|
||||||
|
testOneRecord();
|
||||||
|
testTwoRecord();
|
||||||
|
testRepeatedRecord();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOneRecord() {
|
||||||
|
mStorage.clear();
|
||||||
|
mStorage.record(new StringScriptSource("Name", "Script"));
|
||||||
|
assertEquals(mStorage.getAll(), new MapEntries<String, String>()
|
||||||
|
.entry("Name.js", "1")
|
||||||
|
.map());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTwoRecord() {
|
||||||
|
mStorage.clear();
|
||||||
|
mStorage.record(new StringScriptSource("Name", "Script"));
|
||||||
|
mStorage.record(new FileScriptSource("/test/test.js"));
|
||||||
|
assertEquals(mStorage.getAll(), new MapEntries<String, String>()
|
||||||
|
.entry("Name.js", "1")
|
||||||
|
.entry("/test/test.js", "1")
|
||||||
|
.map());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRepeatedRecord() {
|
||||||
|
mStorage.clear();
|
||||||
|
mStorage.record(new FileScriptSource("/test/test.js"));
|
||||||
|
mStorage.record(new StringScriptSource("Name", "Script"));
|
||||||
|
mStorage.record(new FileScriptSource("/test/test.js"));
|
||||||
|
mStorage.record(new FileScriptSource("/test/test.js"));
|
||||||
|
assertEquals(mStorage.getAll(), new MapEntries<String, String>()
|
||||||
|
.entry("Name.js", "1")
|
||||||
|
.entry("/test/test.js", "3")
|
||||||
|
.map());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getMax() throws Exception {
|
||||||
|
mStorage.clear();
|
||||||
|
put(new FileScriptSource("/test/test.js"), 50);
|
||||||
|
put(new StringScriptSource("Name4", "Script"), 10);
|
||||||
|
put(new StringScriptSource("Name5", "Script"), 5);
|
||||||
|
put(new StringScriptSource("Name6", "Script"), 4);
|
||||||
|
put(new StringScriptSource("Name7", "Script"), 3);
|
||||||
|
put(new StringScriptSource("Name8", "Script"), 1);
|
||||||
|
put(new StringScriptSource("Name9", "Script"), 1);
|
||||||
|
put(new StringScriptSource("Name3", "Script"), 20);
|
||||||
|
put(new StringScriptSource("Name1", "Script"), 100);
|
||||||
|
assertEquals(mStorage.getMax(5), new MapEntries<String, String>()
|
||||||
|
.entry("Name1.js", "100")
|
||||||
|
.entry("/test/test.js", "50")
|
||||||
|
.entry("Name3.js", "20")
|
||||||
|
.entry("Name4.js", "10")
|
||||||
|
.entry("Name5.js", "5")
|
||||||
|
.map());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void put(ScriptSource source, int times) {
|
||||||
|
for (int i = 0; i < times; i++) {
|
||||||
|
mStorage.record(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ import com.stardust.app.SimpleActivityLifecycleCallbacks;
|
|||||||
import com.stardust.app.VolumeChangeObserver;
|
import com.stardust.app.VolumeChangeObserver;
|
||||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||||
import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
|
import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
|
||||||
|
import com.stardust.scriptdroid.statics.ScriptStatics;
|
||||||
import com.stardust.scriptdroid.tool.CrashHandler;
|
import com.stardust.scriptdroid.tool.CrashHandler;
|
||||||
import com.stardust.scriptdroid.tool.JsBeautifierFactory;
|
import com.stardust.scriptdroid.tool.JsBeautifierFactory;
|
||||||
import com.stardust.scriptdroid.ui.error.ErrorReportActivity;
|
import com.stardust.scriptdroid.ui.error.ErrorReportActivity;
|
||||||
@@ -49,9 +50,7 @@ public class App extends MultiDexApplication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setUpStaticsTool() {
|
private void setUpStaticsTool() {
|
||||||
new FlurryAgent.Builder()
|
ScriptStatics.init(this);
|
||||||
.withLogEnabled(true)
|
|
||||||
.build(this, "D42MH48ZN4PJC5TKNYZD");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -91,7 +90,6 @@ public class App extends MultiDexApplication {
|
|||||||
@Override
|
@Override
|
||||||
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
|
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
|
||||||
super.onActivityCreated(activity, savedInstanceState);
|
super.onActivityCreated(activity, savedInstanceState);
|
||||||
FlurryAgent.logEvent(activity.getClass().getSimpleName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.stardust.autojs.execution.ScriptExecution;
|
|||||||
import com.stardust.autojs.execution.ScriptExecutionListener;
|
import com.stardust.autojs.execution.ScriptExecutionListener;
|
||||||
import com.stardust.scriptdroid.App;
|
import com.stardust.scriptdroid.App;
|
||||||
import com.stardust.scriptdroid.R;
|
import com.stardust.scriptdroid.R;
|
||||||
|
import com.stardust.scriptdroid.statics.ScriptStatics;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Stardust on 2017/5/3.
|
* Created by Stardust on 2017/5/3.
|
||||||
@@ -16,7 +17,7 @@ public class ScriptExecutionGlobalListener implements ScriptExecutionListener {
|
|||||||
@Override
|
@Override
|
||||||
public void onStart(ScriptExecution execution) {
|
public void onStart(ScriptExecution execution) {
|
||||||
execution.getEngine().setTag(ENGINE_TAG_START_TIME, System.currentTimeMillis());
|
execution.getEngine().setTag(ENGINE_TAG_START_TIME, System.currentTimeMillis());
|
||||||
FlurryAgent.logEvent("EXEC:" + execution.getSource().toString());
|
ScriptStatics.recordScript(execution.getSource());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -7,10 +7,16 @@ import android.util.Log;
|
|||||||
|
|
||||||
import com.stardust.autojs.runtime.ScriptInterruptedException;
|
import com.stardust.autojs.runtime.ScriptInterruptedException;
|
||||||
import com.stardust.autojs.runtime.api.AbstractShell;
|
import com.stardust.autojs.runtime.api.AbstractShell;
|
||||||
|
import com.stardust.lang.ThreadCompat;
|
||||||
import com.stardust.pio.UncheckedIOException;
|
import com.stardust.pio.UncheckedIOException;
|
||||||
import com.stardust.scriptdroid.App;
|
import com.stardust.scriptdroid.App;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
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.ShellTermSession;
|
||||||
import jackpal.androidterm.emulatorview.TermSession;
|
import jackpal.androidterm.emulatorview.TermSession;
|
||||||
@@ -22,19 +28,23 @@ import jackpal.androidterm.util.TermSettings;
|
|||||||
|
|
||||||
public class Shell extends AbstractShell implements AutoCloseable {
|
public class Shell extends AbstractShell implements AutoCloseable {
|
||||||
|
|
||||||
public interface OutputListener {
|
public interface Callback {
|
||||||
void onNewOutput(String str);
|
void onNewLine(String str);
|
||||||
|
|
||||||
|
void onInitialized();
|
||||||
|
|
||||||
|
void onInterrupted(InterruptedException e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String TAG = "Shell";
|
private static final String TAG = "Shell";
|
||||||
|
|
||||||
private TermSession mTermSession;
|
private TermSession mTermSession;
|
||||||
private RuntimeException mInitException;
|
|
||||||
private final Object mInitLock = new Object();
|
private final Object mInitLock = new Object();
|
||||||
private final Object mExitLock = new Object();
|
private final Object mExitLock = new Object();
|
||||||
private boolean mInitialized = false;
|
private volatile RuntimeException mInitException;
|
||||||
private boolean mWaitingExit = false;
|
private volatile boolean mInitialized = false;
|
||||||
private OutputListener mOutputListener;
|
private volatile boolean mWaitingExit = false;
|
||||||
|
private Callback mCallback;
|
||||||
|
|
||||||
public Shell() {
|
public Shell() {
|
||||||
super();
|
super();
|
||||||
@@ -69,8 +79,12 @@ public class Shell extends AbstractShell implements AutoCloseable {
|
|||||||
mTermSession.write(command + "\n");
|
mTermSession.write(command + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOutputListener(OutputListener outputListener) {
|
public void setCallback(Callback callback) {
|
||||||
mOutputListener = outputListener;
|
mCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInitialized() {
|
||||||
|
return mInitialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensureInitialized() {
|
private void ensureInitialized() {
|
||||||
@@ -97,9 +111,17 @@ public class Shell extends AbstractShell implements AutoCloseable {
|
|||||||
try {
|
try {
|
||||||
mInitLock.wait();
|
mInitLock.wait();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
|
onInterrupted(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onInterrupted(InterruptedException e) {
|
||||||
|
if (mCallback == null) {
|
||||||
exit();
|
exit();
|
||||||
throw new ScriptInterruptedException();
|
throw new ScriptInterruptedException();
|
||||||
}
|
} else {
|
||||||
|
mCallback.onInterrupted(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,8 +146,7 @@ public class Shell extends AbstractShell implements AutoCloseable {
|
|||||||
try {
|
try {
|
||||||
mExitLock.wait();
|
mExitLock.wait();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
exit();
|
onInterrupted(e);
|
||||||
throw new ScriptInterruptedException();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,31 +158,65 @@ public class Shell extends AbstractShell implements AutoCloseable {
|
|||||||
|
|
||||||
private class MyShellTermSession extends ShellTermSession {
|
private class MyShellTermSession extends ShellTermSession {
|
||||||
|
|
||||||
|
private BufferedReader mBufferedReader;
|
||||||
|
private OutputStream mOutputStream;
|
||||||
|
private Thread mReadingThread;
|
||||||
|
|
||||||
public MyShellTermSession(TermSettings settings, String initialCommand) throws IOException {
|
public MyShellTermSession(TermSettings settings, String initialCommand) throws IOException {
|
||||||
super(settings, initialCommand);
|
super(settings, initialCommand);
|
||||||
|
PipedInputStream pipedInputStream = new PipedInputStream(8192);
|
||||||
|
mBufferedReader = new BufferedReader(new InputStreamReader(pipedInputStream));
|
||||||
|
mOutputStream = new PipedOutputStream(pipedInputStream);
|
||||||
|
startReadingThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void startReadingThread() {
|
||||||
|
mReadingThread = new ThreadCompat(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
protected void processInput(byte[] data, int offset, int count) {
|
public void run() {
|
||||||
String output = new String(data, offset, count);
|
String line;
|
||||||
Log.d(TAG, output);
|
try {
|
||||||
if(mOutputListener != null){
|
while (!Thread.currentThread().isInterrupted()
|
||||||
mOutputListener.onNewOutput(output);
|
&& (line = mBufferedReader.readLine()) != null) {
|
||||||
|
onNewLine(line);
|
||||||
}
|
}
|
||||||
if (mInitialized && !mWaitingExit) {
|
} catch (IOException e) {
|
||||||
return;
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
String[] lines = new String(data, offset, count).split("\n");
|
}
|
||||||
for (String line : lines) {
|
});
|
||||||
if (!mInitialized && line.endsWith(" # ")) {
|
mReadingThread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onNewLine(String line) {
|
||||||
|
Log.d(TAG, line);
|
||||||
|
if (mInitialized) {
|
||||||
|
if (mCallback != null) {
|
||||||
|
mCallback.onNewLine(line);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isRoot() && line.endsWith(" $ su")) {
|
||||||
notifyInitialized();
|
notifyInitialized();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mWaitingExit && line.endsWith(" $ ")) {
|
if (!isRoot() && line.endsWith(" $ ")) {
|
||||||
notifyExit();
|
notifyInitialized();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (mWaitingExit && line.endsWith(" exit")) {
|
||||||
|
notifyExit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processInput(byte[] data, int offset, int count) {
|
||||||
|
try {
|
||||||
|
mOutputStream.write(data, offset, count);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new UncheckedIOException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyExit() {
|
private void notifyExit() {
|
||||||
@@ -176,6 +231,9 @@ public class Shell extends AbstractShell implements AutoCloseable {
|
|||||||
synchronized (mInitLock) {
|
synchronized (mInitLock) {
|
||||||
mInitLock.notifyAll();
|
mInitLock.notifyAll();
|
||||||
}
|
}
|
||||||
|
if (mCallback != null) {
|
||||||
|
mCallback.onInitialized();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -186,6 +244,18 @@ public class Shell extends AbstractShell implements AutoCloseable {
|
|||||||
mExitLock.notify();
|
mExitLock.notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finish() {
|
||||||
|
super.finish();
|
||||||
|
mReadingThread.interrupt();
|
||||||
|
try {
|
||||||
|
mBufferedReader.close();
|
||||||
|
mOutputStream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
|
|||||||
if (Pref.isRecordVolumeControlEnable()) {
|
if (Pref.isRecordVolumeControlEnable()) {
|
||||||
if (mRecorder == null) {
|
if (mRecorder == null) {
|
||||||
startRecord();
|
startRecord();
|
||||||
} else if (mRecorder.getState() == Recorder.STATE_RECORDING) {
|
} else if (alreadyStartedRecord()) {
|
||||||
stopRecord();
|
stopRecord();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -211,7 +211,7 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
|
|||||||
@Override
|
@Override
|
||||||
public void onKeyDown(String keyName) {
|
public void onKeyDown(String keyName) {
|
||||||
if (keyName.equals(Pref.getStopRecordTrigger())) {
|
if (keyName.equals(Pref.getStopRecordTrigger())) {
|
||||||
if (mRecorder != null && mRecorder.getState() == Recorder.STATE_RECORDING && mRecorder.getState() == Recorder.STATE_PAUSED)
|
if (alreadyStartedRecord())
|
||||||
stopRecord();
|
stopRecord();
|
||||||
} else if (keyName.equals(Pref.getStartRecordTrigger())) {
|
} else if (keyName.equals(Pref.getStartRecordTrigger())) {
|
||||||
if (mRecorder == null)
|
if (mRecorder == null)
|
||||||
@@ -219,6 +219,10 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean alreadyStartedRecord() {
|
||||||
|
return mRecorder != null && mRecorder.getState() == Recorder.STATE_RECORDING && mRecorder.getState() == Recorder.STATE_PAUSED;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onKeyUp(String keyName) {
|
public void onKeyUp(String keyName) {
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.stardust.scriptdroid.App;
|
|||||||
import com.stardust.scriptdroid.R;
|
import com.stardust.scriptdroid.R;
|
||||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||||
import com.stardust.scriptdroid.record.Recorder;
|
import com.stardust.scriptdroid.record.Recorder;
|
||||||
|
import com.stardust.util.MapEntries;
|
||||||
|
|
||||||
import org.greenrobot.eventbus.EventBus;
|
import org.greenrobot.eventbus.EventBus;
|
||||||
|
|
||||||
@@ -121,7 +122,9 @@ public abstract class InputEventConverter {
|
|||||||
if (mFirstEventFormatError) {
|
if (mFirstEventFormatError) {
|
||||||
Toast.makeText(App.getApp(), R.string.text_record_format_error, Toast.LENGTH_SHORT).show();
|
Toast.makeText(App.getApp(), R.string.text_record_format_error, Toast.LENGTH_SHORT).show();
|
||||||
mFirstEventFormatError = false;
|
mFirstEventFormatError = false;
|
||||||
FlurryAgent.logEvent("EventFormatException:" + e.getMessage());
|
FlurryAgent.logEvent("EventFormatException", new MapEntries<String, String>()
|
||||||
|
.entry("message", e.getMessage())
|
||||||
|
.map());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import android.util.Log;
|
|||||||
|
|
||||||
import com.stardust.pio.UncheckedIOException;
|
import com.stardust.pio.UncheckedIOException;
|
||||||
import com.stardust.scriptdroid.App;
|
import com.stardust.scriptdroid.App;
|
||||||
|
import com.stardust.scriptdroid.autojs.Shell;
|
||||||
import com.stardust.scriptdroid.record.Recorder;
|
import com.stardust.scriptdroid.record.Recorder;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
@@ -25,24 +26,36 @@ import jackpal.androidterm.util.TermSettings;
|
|||||||
public class InputEventRecorder extends Recorder.AbstractRecorder {
|
public class InputEventRecorder extends Recorder.AbstractRecorder {
|
||||||
|
|
||||||
private static final String TAG = "InputEventRecorder";
|
private static final String TAG = "InputEventRecorder";
|
||||||
private TermSession mTermSession;
|
|
||||||
private String mGetEventCommand;
|
private String mGetEventCommand;
|
||||||
|
private Shell mShell;
|
||||||
protected InputEventConverter mInputEventConverter;
|
protected InputEventConverter mInputEventConverter;
|
||||||
|
|
||||||
|
|
||||||
protected InputEventRecorder(InputEventConverter inputEventConverter) {
|
protected InputEventRecorder(InputEventConverter inputEventConverter) {
|
||||||
mGetEventCommand = inputEventConverter.getGetEventCommand();
|
mGetEventCommand = inputEventConverter.getGetEventCommand();
|
||||||
mInputEventConverter = inputEventConverter;
|
mInputEventConverter = inputEventConverter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void listen() {
|
public void listen() {
|
||||||
TermSettings settings = new TermSettings(App.getApp().getResources(), PreferenceManager.getDefaultSharedPreferences(App.getApp()));
|
mShell = new Shell(true);
|
||||||
try {
|
mShell.setCallback(new Shell.Callback() {
|
||||||
mTermSession = new MyShellTermSession(settings, "su");
|
@Override
|
||||||
mTermSession.initializeEmulator(80, 40);
|
public void onNewLine(String str) {
|
||||||
} catch (IOException e) {
|
if (mShell.isInitialized()) {
|
||||||
throw new RuntimeException(e);
|
convertEvent(str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInitialized() {
|
||||||
|
mShell.exec(mGetEventCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInterrupted(InterruptedException e) {
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -62,7 +75,7 @@ public class InputEventRecorder extends Recorder.AbstractRecorder {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void stopImpl() {
|
protected void stopImpl() {
|
||||||
mTermSession.finish();
|
mShell.exit();
|
||||||
mInputEventConverter.stop();
|
mInputEventConverter.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,70 +88,4 @@ public class InputEventRecorder extends Recorder.AbstractRecorder {
|
|||||||
mInputEventConverter.convertEventIfFormatCorrect(eventStr);
|
mInputEventConverter.convertEventIfFormatCorrect(eventStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MyShellTermSession extends ShellTermSession {
|
|
||||||
|
|
||||||
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) {
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
package com.stardust.scriptdroid.record.inputevent;
|
package com.stardust.scriptdroid.record.inputevent;
|
||||||
|
|
||||||
import com.stardust.scriptdroid.Pref;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Stardust on 2017/3/16.
|
* Created by Stardust on 2017/3/16.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class TouchRecorder extends InputEventRecorder implements KeyObserver.KeyListener {
|
public class TouchRecorder extends InputEventRecorder {
|
||||||
|
|
||||||
public TouchRecorder() {
|
public TouchRecorder() {
|
||||||
super(new InputEventToSendEventJsConverter());
|
super(new InputEventToSendEventJsConverter());
|
||||||
@@ -19,14 +17,4 @@ public class TouchRecorder extends InputEventRecorder implements KeyObserver.Key
|
|||||||
super.stop();
|
super.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onKeyDown(String keyName) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onKeyUp(String keyName) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,140 @@
|
|||||||
|
package com.stardust.scriptdroid.statics;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
|
||||||
|
import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping;
|
||||||
|
import com.pushtorefresh.storio.sqlite.StorIOSQLite;
|
||||||
|
import com.pushtorefresh.storio.sqlite.impl.DefaultStorIOSQLite;
|
||||||
|
import com.pushtorefresh.storio.sqlite.queries.DeleteQuery;
|
||||||
|
import com.pushtorefresh.storio.sqlite.queries.Query;
|
||||||
|
import com.stardust.autojs.script.ScriptSource;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Stardust on 2017/5/5.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class SQLiteStaticsStorage implements ScriptStaticsStorage {
|
||||||
|
|
||||||
|
private static final int VERSION = 1;
|
||||||
|
private static final String DATABASE_NAME = "Ever.db";
|
||||||
|
static final String TABLE_NAME = "FinalEating";
|
||||||
|
|
||||||
|
private StorIOSQLite mStorIOSQLite;
|
||||||
|
|
||||||
|
public SQLiteStaticsStorage(Context context) {
|
||||||
|
mStorIOSQLite = DefaultStorIOSQLite.builder()
|
||||||
|
.sqliteOpenHelper(new SQLiteOpenHelper(context))
|
||||||
|
.addTypeMapping(ScriptStaticsRecord.class, new ScriptStaticsRecordSQLiteTypeMapping())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void record(ScriptSource source) {
|
||||||
|
int times = getTimes(source) + 1;
|
||||||
|
mStorIOSQLite.put()
|
||||||
|
.object(new ScriptStaticsRecord(source.toString(), times))
|
||||||
|
.prepare()
|
||||||
|
.executeAsBlocking();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTimes(ScriptSource source) {
|
||||||
|
ScriptStaticsRecord record = mStorIOSQLite.get()
|
||||||
|
.object(ScriptStaticsRecord.class)
|
||||||
|
.withQuery(Query.builder()
|
||||||
|
.table(TABLE_NAME)
|
||||||
|
.where("name = ?")
|
||||||
|
.whereArgs(source.toString())
|
||||||
|
.build())
|
||||||
|
.prepare()
|
||||||
|
.executeAsBlocking();
|
||||||
|
if (record != null) {
|
||||||
|
return record.times;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getAll() {
|
||||||
|
List<ScriptStaticsRecord> records = mStorIOSQLite.get()
|
||||||
|
.listOfObjects(ScriptStaticsRecord.class)
|
||||||
|
.withQuery(Query.builder()
|
||||||
|
.table(TABLE_NAME)
|
||||||
|
.orderBy("times")
|
||||||
|
.build())
|
||||||
|
.prepare()
|
||||||
|
.executeAsBlocking();
|
||||||
|
return toMap(records);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String> toMap(List<ScriptStaticsRecord> records) {
|
||||||
|
Map<String, String> map = new HashMap<>();
|
||||||
|
for (ScriptStaticsRecord record : records) {
|
||||||
|
map.put(record.name, String.valueOf(record.times));
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getMax(int size) {
|
||||||
|
List<ScriptStaticsRecord> records = mStorIOSQLite.get()
|
||||||
|
.listOfObjects(ScriptStaticsRecord.class)
|
||||||
|
.withQuery(Query.builder()
|
||||||
|
.table(TABLE_NAME)
|
||||||
|
.orderBy("times DESC")
|
||||||
|
.limit(size)
|
||||||
|
.build())
|
||||||
|
.prepare()
|
||||||
|
.executeAsBlocking();
|
||||||
|
return toMap(records);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
mStorIOSQLite.delete()
|
||||||
|
.byQuery(DeleteQuery.builder()
|
||||||
|
.table(TABLE_NAME)
|
||||||
|
.build())
|
||||||
|
.prepare()
|
||||||
|
.executeAsBlocking();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
try {
|
||||||
|
mStorIOSQLite.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SQLiteOpenHelper extends android.database.sqlite.SQLiteOpenHelper {
|
||||||
|
|
||||||
|
|
||||||
|
SQLiteOpenHelper(Context context) {
|
||||||
|
super(context, DATABASE_NAME, null, VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(SQLiteDatabase db) {
|
||||||
|
db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + "(\n"
|
||||||
|
+ "name TEXT NOT NULL PRIMARY KEY, "
|
||||||
|
+ "times INTEGER"
|
||||||
|
+ ");");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package com.stardust.scriptdroid.statics;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.text.format.DateUtils;
|
||||||
|
|
||||||
|
import com.flurry.android.FlurryAgent;
|
||||||
|
import com.stardust.autojs.script.ScriptSource;
|
||||||
|
import com.stardust.scriptdroid.BuildConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Stardust on 2017/5/5.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ScriptStatics {
|
||||||
|
|
||||||
|
|
||||||
|
private static final String KEY_MILLIS = "Sorry, I should have left";
|
||||||
|
private static ScriptStaticsStorage storage;
|
||||||
|
private static SharedPreferences preferences;
|
||||||
|
|
||||||
|
public static void init(Context context) {
|
||||||
|
storage = new SQLiteStaticsStorage(context);
|
||||||
|
new FlurryAgent.Builder()
|
||||||
|
.withLogEnabled(BuildConfig.DEBUG)
|
||||||
|
.build(context, "D42MH48ZN4PJC5TKNYZD");
|
||||||
|
preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void recordScript(ScriptSource source) {
|
||||||
|
storage.record(source);
|
||||||
|
sendStaticsIfNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void sendStaticsIfNeeded() {
|
||||||
|
long millis = preferences.getLong(KEY_MILLIS, 0);
|
||||||
|
if (!DateUtils.isToday(millis)) {
|
||||||
|
preferences.edit().putLong(KEY_MILLIS, System.currentTimeMillis()).apply();
|
||||||
|
FlurryAgent.logEvent("ScriptStatics", storage.getMax(10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void finalize() throws Throwable {
|
||||||
|
super.finalize();
|
||||||
|
storage.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.stardust.scriptdroid.statics;
|
||||||
|
|
||||||
|
import com.pushtorefresh.storio.sqlite.annotations.StorIOSQLiteColumn;
|
||||||
|
import com.pushtorefresh.storio.sqlite.annotations.StorIOSQLiteCreator;
|
||||||
|
import com.pushtorefresh.storio.sqlite.annotations.StorIOSQLiteType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Stardust on 2017/5/5.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@StorIOSQLiteType(table = SQLiteStaticsStorage.TABLE_NAME)
|
||||||
|
|
||||||
|
public class ScriptStaticsRecord {
|
||||||
|
|
||||||
|
@StorIOSQLiteColumn(name = "name", key = true)
|
||||||
|
public String name;
|
||||||
|
|
||||||
|
@StorIOSQLiteColumn(name = "times")
|
||||||
|
public int times;
|
||||||
|
|
||||||
|
public ScriptStaticsRecord(String name, int times) {
|
||||||
|
this.name = name;
|
||||||
|
this.times = times;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScriptStaticsRecord() {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.stardust.scriptdroid.statics;
|
||||||
|
|
||||||
|
import com.stardust.autojs.script.ScriptSource;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Stardust on 2017/5/5.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface ScriptStaticsStorage {
|
||||||
|
|
||||||
|
void record(ScriptSource source);
|
||||||
|
|
||||||
|
Map<String, String> getAll();
|
||||||
|
|
||||||
|
Map<String, String> getMax(int size);
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
void close();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user