just to save works

This commit is contained in:
hyb1996 committed 2018-03-17 14:34:59 +08:00
1 parent 976e78e07d
commit c5e3050732
26 files changed
+500 -209

No files matched your search

+2 -2
View File
@@ -8,8 +8,8 @@ android {
applicationId "com.stardust.scriptdroid" applicationId "com.stardust.scriptdroid"
minSdkVersion 17 minSdkVersion 17
targetSdkVersion 23 targetSdkVersion 23
versionCode 256 versionCode 257
versionName "3.1.0 Beta" versionName "3.1.1 Alpha"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true multiDexEnabled true
ndk { ndk {
@@ -0,0 +1,24 @@
"ui";
ui.layout(
<frame>
<canvas id="graphic" w="*" h="*"/>
</frame>
);
var f = function(x){
return x * x + 3 * x - 4;
}
var paint = new Paint();
paint.setStrokeWidth(2);
var start = -5;
var end = 5;
ui.graphic.on("draw", function(canvas){
var w = canvas.getWidth();
for (var i = 0; i < w; i++) {
var x = (end - start) / w * i + start;
var y = f(x);
canvas.drawPoint(x, y, paint);
}
});
@@ -96,14 +96,15 @@ public class JavaScriptHighlighter implements SimpleTextWatcher.AfterTextChanged
TokenStream ts = new TokenStream(null, sourceString, 0); TokenStream ts = new TokenStream(null, sourceString, 0);
HighlightTokens highlightTokens = new HighlightTokens(sourceString); HighlightTokens highlightTokens = new HighlightTokens(sourceString);
int token; int token;
int color = mTheme.getColorForToken(Token.NAME);
while ((token = ts.getToken()) != Token.EOF) { while ((token = ts.getToken()) != Token.EOF) {
if (mRunningHighlighterId.get() != id) if (mRunningHighlighterId.get() != id)
return; return;
int color = mTheme.getColorForToken(token); color = mTheme.getColorForToken(token);
highlightTokens.addToken(ts.getTokenBeg(), ts.getTokenEnd(), color); highlightTokens.addToken(ts.getTokenBeg(), ts.getTokenEnd(), color);
} }
if (highlightTokens.getCharCount() < sourceString.length()) { if (highlightTokens.getCharCount() < sourceString.length()) {
highlightTokens.addToken(highlightTokens.getCharCount(), sourceString.length(), mTheme.getColorForToken(Token.NAME)); highlightTokens.addToken(highlightTokens.getCharCount(), sourceString.length(), color);
} }
mCodeEditText.updateHighlightTokens(highlightTokens); mCodeEditText.updateHighlightTokens(highlightTokens);
} }
@@ -76,9 +76,10 @@ public class AboutActivity extends BaseActivity {
@Click(R.id.icon) @Click(R.id.icon)
void lol() { void lol() {
mLolClickCount++; mLolClickCount++;
Toast.makeText(this, R.string.text_lll, Toast.LENGTH_LONG).show(); //Toast.makeText(this, R.string.text_lll, Toast.LENGTH_LONG).show();
if (mLolClickCount >= 5) { if (mLolClickCount >= 5) {
crashTest(); //crashTest();
showEasterEgg();
} }
} }
@@ -92,11 +93,8 @@ public class AboutActivity extends BaseActivity {
new ThemeColorMaterialDialogBuilder(this) new ThemeColorMaterialDialogBuilder(this)
.title("Crash Test") .title("Crash Test")
.positiveText("Crash") .positiveText("Crash")
.onPositive(new MaterialDialog.SingleButtonCallback() { .onPositive((dialog, which) -> {
@Override throw new RuntimeException("Crash Test");
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
throw new RuntimeException("Crash Test");
}
}).show(); }).show();
} }
@@ -1,106 +0,0 @@
package com.stardust.scriptdroid.ui.settings;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.stardust.theme.ThemeColorManagerCompat;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Stardust on 2017/5/10.
*/
public class PaintView extends View {
private List<Path> mPaths = new ArrayList<>();
private Path mCurrentPath;
private Paint mPaint;
public PaintView(Context context) {
super(context);
init();
}
public PaintView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public PaintView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public PaintView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setColor(ThemeColorManagerCompat.getColorPrimary());
mPaint.setAntiAlias(true);
mPaint.setStrokeWidth(5);
setWillNotDraw(false);
setClickable(true);
setBackgroundColor(Color.TRANSPARENT);
}
@Override
protected void onDraw(Canvas canvas) {
for (Path path : mPaths) {
canvas.drawPath(path, mPaint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getY();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
onTouchDown(x, y);
return true;
case MotionEvent.ACTION_MOVE:
onTouchMove(x, y);
return true;
case MotionEvent.ACTION_UP:
onTouchUp(x, y);
return true;
}
return super.onTouchEvent(event);
}
private void onTouchDown(float x, float y) {
if (mCurrentPath != null) {
mCurrentPath.close();
mPaths.add(mCurrentPath);
invalidate();
}
mCurrentPath = new Path();
mCurrentPath.moveTo(x, y);
}
private void onTouchMove(float x, float y) {
mCurrentPath.moveTo(x, y);
}
private void onTouchUp(float x, float y) {
mCurrentPath.close();
mPaths.add(mCurrentPath);
mCurrentPath = null;
invalidate();
}
}
@@ -0,0 +1,88 @@
package com.stardust.scriptdroid.ui.settings;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by Stardust on 2018/3/16.
*/
public class TestSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private volatile boolean mDrawing = true;
private static final String LOG_TAG = "TestSurfaceView";
private ExecutorService mDrawingThreadPool;
public TestSurfaceView(Context context) {
super(context);
init();
}
public TestSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public TestSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
getHolder().addCallback(this);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
performDraw();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
private void performDraw() {
if (mDrawingThreadPool == null)
mDrawingThreadPool = Executors.newCachedThreadPool();
mDrawingThreadPool.execute(() -> {
SurfaceHolder holder = getHolder();
while (mDrawing) {
Canvas canvas = holder.lockCanvas();
canvas.drawColor(Color.RED);
holder.unlockCanvasAndPost(canvas);
}
Log.d(LOG_TAG, "drawing thread: mRunning = false");
});
}
@Override
protected void onWindowVisibilityChanged(int visibility) {
if (visibility == VISIBLE) {
if (mDrawingThreadPool != null) {
mDrawing = true;
performDraw();
}
} else {
mDrawing = false;
}
super.onWindowVisibilityChanged(visibility);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d(LOG_TAG, "surfaceDestroyed: mRunning = true");
mDrawing = false;
Log.d(LOG_TAG, "surfaceDestroyed: mRunning = false");
mDrawingThreadPool.shutdown();
mDrawingThreadPool = null;
}
}
+1 -8
View File
@@ -3,14 +3,7 @@
android:layout_width="600dp" android:layout_width="600dp"
android:layout_height="600dp"> android:layout_height="600dp">
<ImageView <com.stardust.scriptdroid.ui.settings.TestSurfaceView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:padding="200dp"
android:src="@drawable/ic_android_eat_js"/>
<com.stardust.scriptdroid.ui.settings.PaintView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"/> android:layout_height="match_parent"/>
+1
View File
@@ -13,6 +13,7 @@
> >
<activity <activity
android:name=".execution.ScriptExecuteActivity" android:name=".execution.ScriptExecuteActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:theme="@style/AppTheme"/> android:theme="@style/AppTheme"/>
+4 -1
View File
@@ -96,12 +96,15 @@ runtime.init();
importClass(android.view.KeyEvent); importClass(android.view.KeyEvent);
importClass(com.stardust.autojs.core.util.Shell); importClass(com.stardust.autojs.core.util.Shell);
importClass(android.graphics.Paint);
//重定向require以便支持相对路径 //重定向require以便支持相对路径
(function(){ (function(){
var __require__ = require; var __require__ = require;
global.require = function(path){ global.require = function(path){
path = files.path(path); if(!path.startsWith("http://") && !path.startsWith("https://")){
path = files.path(path);
}
return __require__(path); return __require__(path);
}; };
})(); })();
@@ -110,6 +110,10 @@ public class EventEmitter {
mBridges = bridges; mBridges = bridges;
} }
protected void setTimer(Timer timer) {
mTimer = timer;
}
public EventEmitter once(String eventName, Object listener) { public EventEmitter once(String eventName, Object listener) {
getListeners(eventName).add(listener, true); getListeners(eventName).add(listener, true);
return this; return this;
@@ -0,0 +1,148 @@
package com.stardust.autojs.core.graphics;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import com.stardust.autojs.core.eventloop.EventEmitter;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by Stardust on 2018/3/16.
*/
@SuppressLint("ViewConstructor")
public class ScriptCanvasView extends SurfaceView implements SurfaceHolder.Callback {
private static final String LOG_TAG = "ScriptCanvasView";
private volatile boolean mDrawing = true;
private EventEmitter mEventEmitter;
private final SurfaceHolder mHolder;
private ExecutorService mDrawingThreadPool;
public ScriptCanvasView(Context context, EventEmitter eventEmitter) {
super(context);
mEventEmitter = eventEmitter;
mHolder = getHolder();
init();
}
private void init() {
mHolder.addCallback(this);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
performDraw();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
private void performDraw() {
if (mDrawingThreadPool == null)
mDrawingThreadPool = Executors.newCachedThreadPool();
mDrawingThreadPool.execute(() -> {
SurfaceHolder holder = getHolder();
while (mDrawing) {
Canvas canvas = holder.lockCanvas();
canvas.drawColor(Color.WHITE);
emit("draw", canvas, this);
holder.unlockCanvasAndPost(canvas);
}
Log.d(LOG_TAG, "drawing thread: mRunning = false");
});
}
@Override
protected void onWindowVisibilityChanged(int visibility) {
if (visibility == VISIBLE) {
if (mDrawingThreadPool != null) {
mDrawing = true;
performDraw();
}
} else {
mDrawing = false;
}
super.onWindowVisibilityChanged(visibility);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d(LOG_TAG, "surfaceDestroyed: mRunning = true");
mDrawing = false;
Log.d(LOG_TAG, "surfaceDestroyed: mRunning = false");
mDrawingThreadPool.shutdown();
mDrawingThreadPool = null;
}
public EventEmitter once(String eventName, Object listener) {
return mEventEmitter.once(eventName, listener);
}
public EventEmitter on(String eventName, Object listener) {
return mEventEmitter.on(eventName, listener);
}
public EventEmitter addListener(String eventName, Object listener) {
return mEventEmitter.addListener(eventName, listener);
}
public boolean emit(String eventName, Object... args) {
return mEventEmitter.emit(eventName, args);
}
public String[] eventNames() {
return mEventEmitter.eventNames();
}
public int listenerCount(String eventName) {
return mEventEmitter.listenerCount(eventName);
}
public Object[] listeners(String eventName) {
return mEventEmitter.listeners(eventName);
}
public EventEmitter prependListener(String eventName, Object listener) {
return mEventEmitter.prependListener(eventName, listener);
}
public EventEmitter prependOnceListener(String eventName, Object listener) {
return mEventEmitter.prependOnceListener(eventName, listener);
}
public EventEmitter removeAllListeners() {
return mEventEmitter.removeAllListeners();
}
public EventEmitter removeAllListeners(String eventName) {
return mEventEmitter.removeAllListeners(eventName);
}
public EventEmitter removeListener(String eventName, Object listener) {
return mEventEmitter.removeListener(eventName, listener);
}
public EventEmitter setMaxListeners(int n) {
return mEventEmitter.setMaxListeners(n);
}
public int getMaxListeners() {
return mEventEmitter.getMaxListeners();
}
public static int defaultMaxListeners() {
return EventEmitter.defaultMaxListeners();
}
}
@@ -24,7 +24,7 @@ public class LooperHelper {
public static void quitForThread(Thread thread) { public static void quitForThread(Thread thread) {
Looper looper = sLoopers.remove(thread); Looper looper = sLoopers.remove(thread);
if (looper != null) if (looper != null && looper != Looper.getMainLooper())
looper.quit(); looper.quit();
} }
} }
@@ -87,7 +87,7 @@ public class TimerThread extends ThreadCompat {
return getTimer().setTimeout(callback, delay, args); return getTimer().setTimeout(callback, delay, args);
} }
private Timer getTimer() { public Timer getTimer() {
if (mTimer == null) { if (mTimer == null) {
throw new IllegalStateException("thread is not alive"); throw new IllegalStateException("thread is not alive");
} }
@@ -49,30 +49,7 @@ import java.util.Map;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
/**
* Copyright Nicholas White 2015.
* Source: https://github.com/nickwah/DynamicLayoutInflator
* <p>
* Licensed under the MIT License:
* <p>
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* <p>
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* <p>
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
public class DynamicLayoutInflater { public class DynamicLayoutInflater {
private static final String LOG_TAG = "DynamicLayoutInflater"; private static final String LOG_TAG = "DynamicLayoutInflater";
@@ -0,0 +1,32 @@
package com.stardust.autojs.core.ui.inflater.attrsetter;
import android.content.Context;
import android.support.annotation.Nullable;
import com.stardust.autojs.core.eventloop.EventEmitter;
import com.stardust.autojs.core.graphics.ScriptCanvasView;
import com.stardust.autojs.core.ui.inflater.ValueParser;
import com.stardust.autojs.core.ui.inflater.ViewCreator;
import com.stardust.autojs.runtime.ScriptRuntime;
import java.util.Map;
/**
* Created by Stardust on 2018/3/16.
*/
public class CanvasViewAttrSetter extends BaseViewAttrSetter<ScriptCanvasView> {
private ScriptRuntime mScriptRuntime;
public CanvasViewAttrSetter(ValueParser valueParser, ScriptRuntime runtime) {
super(valueParser);
mScriptRuntime = runtime;
}
@Nullable
@Override
public ViewCreator<ScriptCanvasView> getCreator() {
return (context, attrs) -> new ScriptCanvasView(context, new EventEmitter(mScriptRuntime.bridges));
}
}
@@ -12,6 +12,7 @@ import android.widget.SeekBar;
import android.widget.Spinner; import android.widget.Spinner;
import android.widget.TimePicker; import android.widget.TimePicker;
import com.stardust.autojs.core.graphics.ScriptCanvasView;
import com.stardust.autojs.core.ui.widget.JsButton; import com.stardust.autojs.core.ui.widget.JsButton;
import com.stardust.autojs.core.ui.widget.JsEditText; import com.stardust.autojs.core.ui.widget.JsEditText;
import com.stardust.autojs.core.ui.widget.JsFrameLayout; import com.stardust.autojs.core.ui.widget.JsFrameLayout;
@@ -64,6 +65,7 @@ public class XmlConverter {
.map("checkbox", CheckBox.class.getName()) .map("checkbox", CheckBox.class.getName())
.map("scroll", ScrollView.class.getName()) .map("scroll", ScrollView.class.getName())
.map("toolbar", Toolbar.class.getName()) .map("toolbar", Toolbar.class.getName())
.map("canvas", ScriptCanvasView.class.getName())
); );
private static final AttributeHandler ATTRIBUTE_HANDLER = new AttributeHandler.AttrNameRouter() private static final AttributeHandler ATTRIBUTE_HANDLER = new AttributeHandler.AttrNameRouter()
@@ -44,7 +44,6 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine {
private Scriptable mScriptable; private Scriptable mScriptable;
private Thread mThread; private Thread mThread;
private android.content.Context mAndroidContext; private android.content.Context mAndroidContext;
private Thread.UncaughtExceptionHandler mUncaughtExceptionHandler;
public RhinoJavaScriptEngine(android.content.Context context) { public RhinoJavaScriptEngine(android.content.Context context) {
mAndroidContext = context; mAndroidContext = context;
@@ -157,14 +156,6 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine {
context.setWrapFactory(new WrapFactory()); context.setWrapFactory(new WrapFactory());
} }
public void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler uiThreadExceptionHandler) {
mUncaughtExceptionHandler = uiThreadExceptionHandler;
}
public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() {
return mUncaughtExceptionHandler;
}
private class WrapFactory extends org.mozilla.javascript.WrapFactory { private class WrapFactory extends org.mozilla.javascript.WrapFactory {
@Override @Override
@@ -208,7 +199,7 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine {
try { try {
return super.doTopCall(callable, cx, scope, thisObj, args); return super.doTopCall(callable, cx, scope, thisObj, args);
} catch (Exception e) { } catch (Exception e) {
mUncaughtExceptionHandler.uncaughtException(Thread.currentThread(), e); getRuntime().exit(e);
return null; return null;
} }
} }
@@ -40,6 +40,13 @@ public interface ScriptEngine<S extends ScriptSource> {
Object getTag(String key); Object getTag(String key);
String cwd();
void uncaughtException(Exception throwable);
Exception getUncaughtException();
/** /**
* @hide * @hide
*/ */
@@ -60,11 +67,12 @@ public interface ScriptEngine<S extends ScriptSource> {
private Map<String, Object> mTags = new ConcurrentHashMap<>(); private Map<String, Object> mTags = new ConcurrentHashMap<>();
private OnDestroyListener mOnDestroyListener; private OnDestroyListener mOnDestroyListener;
private boolean mDestroyed = false; private boolean mDestroyed = false;
private Exception mUncaughtException;
@Override @Override
public synchronized void setTag(String key, Object value) { public synchronized void setTag(String key, Object value) {
if(value == null) if (value == null)
return; return;
mTags.put(key, value); mTags.put(key, value);
} }
@@ -97,5 +105,16 @@ public interface ScriptEngine<S extends ScriptSource> {
throw new SecurityException("setOnDestroyListener can be called only once"); throw new SecurityException("setOnDestroyListener can be called only once");
mOnDestroyListener = onDestroyListener; mOnDestroyListener = onDestroyListener;
} }
@Override
public void uncaughtException(Exception throwable) {
mUncaughtException = throwable;
forceStop();
}
@Override
public Exception getUncaughtException() {
return mUncaughtException;
}
} }
} }
@@ -0,0 +1,76 @@
package com.stardust.autojs.engine;
import com.stardust.autojs.script.ScriptSource;
/**
* Created by Stardust on 2018/3/17.
*/
public class ScriptEngineProxy<S extends ScriptSource> implements ScriptEngine<S> {
private final ScriptEngine<S> mScriptEngine;
public ScriptEngineProxy(ScriptEngine<S> scriptEngine) {
mScriptEngine = scriptEngine;
}
@Override
public void put(String name, Object value) {
mScriptEngine.put(name, value);
}
@Override
public Object execute(S scriptSource) {
return mScriptEngine.execute(scriptSource);
}
@Override
public void forceStop() {
mScriptEngine.forceStop();
}
@Override
public void destroy() {
mScriptEngine.destroy();
}
@Override
public boolean isDestroyed() {
return mScriptEngine.isDestroyed();
}
@Override
public void setTag(String key, Object value) {
mScriptEngine.setTag(key, value);
}
@Override
public Object getTag(String key) {
return mScriptEngine.getTag(key);
}
@Override
public String cwd() {
return mScriptEngine.cwd();
}
@Override
public void uncaughtException(Exception throwable) {
mScriptEngine.uncaughtException(throwable);
}
@Override
public Exception getUncaughtException() {
return mScriptEngine.getUncaughtException();
}
@Override
public void setOnDestroyListener(OnDestroyListener listener) {
mScriptEngine.setOnDestroyListener(listener);
}
@Override
public void init() {
mScriptEngine.init();
}
}
@@ -23,10 +23,6 @@ public class LoopedBasedJavaScriptExecution extends RunnableScriptExecution {
long delay = getConfig().delay; long delay = getConfig().delay;
sleep(delay); sleep(delay);
final LoopBasedJavaScriptEngine javaScriptEngine = (LoopBasedJavaScriptEngine) engine; final LoopBasedJavaScriptEngine javaScriptEngine = (LoopBasedJavaScriptEngine) engine;
javaScriptEngine.setUncaughtExceptionHandler((t, e) -> {
javaScriptEngine.forceStop();
getListener().onException(this, (Exception) e);
});
final long interval = getConfig().interval; final long interval = getConfig().interval;
javaScriptEngine.getRuntime().loopers.setMainLooperQuitHandler(new Loopers.LooperQuitHandler() { javaScriptEngine.getRuntime().loopers.setMainLooperQuitHandler(new Loopers.LooperQuitHandler() {
long times = getConfig().loopTimes == 0 ? Integer.MAX_VALUE : getConfig().loopTimes; long times = getConfig().loopTimes == 0 ? Integer.MAX_VALUE : getConfig().loopTimes;
@@ -1,5 +1,6 @@
package com.stardust.autojs.execution; package com.stardust.autojs.execution;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
@@ -9,6 +10,7 @@ import com.stardust.autojs.engine.LoopBasedJavaScriptEngine;
import com.stardust.autojs.engine.RhinoJavaScriptEngine; import com.stardust.autojs.engine.RhinoJavaScriptEngine;
import com.stardust.autojs.engine.ScriptEngine; import com.stardust.autojs.engine.ScriptEngine;
import com.stardust.autojs.engine.ScriptEngineManager; import com.stardust.autojs.engine.ScriptEngineManager;
import com.stardust.autojs.engine.ScriptEngineProxy;
import com.stardust.autojs.script.ScriptSource; import com.stardust.autojs.script.ScriptSource;
import com.stardust.util.IntentExtras; import com.stardust.util.IntentExtras;
@@ -16,7 +18,7 @@ import com.stardust.util.IntentExtras;
* Created by Stardust on 2017/2/5. * Created by Stardust on 2017/2/5.
*/ */
public class ScriptExecuteActivity extends AppCompatActivity implements Thread.UncaughtExceptionHandler { public class ScriptExecuteActivity extends AppCompatActivity {
private static final String EXTRA_EXECUTION = ScriptExecuteActivity.class.getName() + ".execution"; private static final String EXTRA_EXECUTION = ScriptExecuteActivity.class.getName() + ".execution";
@@ -24,7 +26,8 @@ public class ScriptExecuteActivity extends AppCompatActivity implements Thread.U
private ScriptEngine mScriptEngine; private ScriptEngine mScriptEngine;
private ScriptExecutionListener mExecutionListener; private ScriptExecutionListener mExecutionListener;
private ScriptSource mScriptSource; private ScriptSource mScriptSource;
private ScriptExecution mScriptExecution; private ActivityScriptExecution mScriptExecution;
private IntentExtras mIntentExtras;
public static ActivityScriptExecution execute(Context context, ScriptEngineManager manager, ScriptExecutionTask task) { public static ActivityScriptExecution execute(Context context, ScriptEngineManager manager, ScriptExecutionTask task) {
ActivityScriptExecution execution = new ActivityScriptExecution(manager, task); ActivityScriptExecution execution = new ActivityScriptExecution(manager, task);
@@ -37,22 +40,34 @@ public class ScriptExecuteActivity extends AppCompatActivity implements Thread.U
return execution; return execution;
} }
// FIXME: 2018/3/16 如果Activity被回收则得不到改进
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
IntentExtras extras = IntentExtras.fromIntent(getIntent()); mIntentExtras = readIntentExtras(savedInstanceState);
if (extras.get(EXTRA_EXECUTION) == null) { if (mIntentExtras == null || mIntentExtras.get(EXTRA_EXECUTION) == null) {
finish(); finish();
return; return;
} }
mScriptExecution = extras.get(EXTRA_EXECUTION); mScriptExecution = mIntentExtras.get(EXTRA_EXECUTION);
mScriptSource = mScriptExecution.getSource(); mScriptSource = mScriptExecution.getSource();
mScriptEngine = mScriptExecution.getEngine(); mScriptEngine = mScriptExecution.createEngine(this);
mExecutionListener = mScriptExecution.getListener(); mExecutionListener = mScriptExecution.getListener();
((RhinoJavaScriptEngine) mScriptEngine).setUncaughtExceptionHandler((t, e) -> onException((Exception) e));
runScript(); runScript();
} }
private IntentExtras readIntentExtras(Bundle savedInstanceState) {
IntentExtras extras = IntentExtras.fromIntent(getIntent());
if (extras == null && savedInstanceState != null) {
int id = savedInstanceState.getInt(IntentExtras.EXTRA_ID, -1);
if (id == -1) {
return null;
}
extras = IntentExtras.fromId(id);
}
return extras;
}
private void runScript() { private void runScript() {
try { try {
prepare(); prepare();
@@ -93,7 +108,12 @@ public class ScriptExecuteActivity extends AppCompatActivity implements Thread.U
@Override @Override
public void finish() { public void finish() {
mExecutionListener.onSuccess(mScriptExecution, mResult); Exception exception = mScriptEngine.getUncaughtException();
if (exception != null) {
onException(exception);
} else {
mExecutionListener.onSuccess(mScriptExecution, mResult);
}
super.finish(); super.finish();
} }
@@ -106,8 +126,12 @@ public class ScriptExecuteActivity extends AppCompatActivity implements Thread.U
} }
@Override @Override
public void uncaughtException(Thread t, Throwable e) { protected void onSaveInstanceState(Bundle outState) {
onException((Exception) e); super.onSaveInstanceState(outState);
if (mIntentExtras == null)
return;
IntentExtras extras = IntentExtras.newExtras().putAll(mIntentExtras);
outState.putInt(IntentExtras.EXTRA_ID, extras.getId());
} }
private static class ActivityScriptExecution extends ScriptExecution.AbstractScriptExecution { private static class ActivityScriptExecution extends ScriptExecution.AbstractScriptExecution {
@@ -120,12 +144,23 @@ public class ScriptExecuteActivity extends AppCompatActivity implements Thread.U
mScriptEngineManager = manager; mScriptEngineManager = manager;
} }
@SuppressWarnings("unchecked")
public ScriptEngine createEngine(Activity activity) {
if (mScriptEngine != null) {
mScriptEngine.forceStop();
}
mScriptEngine = new ScriptEngineProxy(mScriptEngineManager.createEngineOfSourceOrThrow(getSource())) {
@Override
public void forceStop() {
super.forceStop();
activity.finish();
}
};
return mScriptEngine;
}
@Override @Override
public ScriptEngine getEngine() { public ScriptEngine getEngine() {
if (mScriptEngine == null) {
mScriptEngine = mScriptEngineManager.createEngineOfSourceOrThrow(getSource());
}
return mScriptEngine; return mScriptEngine;
} }
@@ -9,6 +9,7 @@ import com.stardust.autojs.ScriptEngineService;
import com.stardust.autojs.annotation.ScriptVariable; import com.stardust.autojs.annotation.ScriptVariable;
import com.stardust.autojs.core.accessibility.AccessibilityBridge; import com.stardust.autojs.core.accessibility.AccessibilityBridge;
import com.stardust.autojs.core.image.Colors; import com.stardust.autojs.core.image.Colors;
import com.stardust.autojs.engine.JavaScriptEngine;
import com.stardust.autojs.engine.RhinoJavaScriptEngine; import com.stardust.autojs.engine.RhinoJavaScriptEngine;
import com.stardust.autojs.engine.ScriptEngine; import com.stardust.autojs.engine.ScriptEngine;
import com.stardust.autojs.rhino.AndroidClassLoader; import com.stardust.autojs.rhino.AndroidClassLoader;
@@ -321,22 +322,10 @@ public class ScriptRuntime {
} }
} }
public void exit(Object obj) throws Throwable { public void exit(Exception e) {
mThread.interrupt(); engines.myEngine().uncaughtException(e);
if (!(obj instanceof Throwable)) {
console.error(obj);
return;
}
Throwable e = (Exception) obj;
if (Looper.myLooper() != Looper.getMainLooper()) { if (Looper.myLooper() != Looper.getMainLooper()) {
throw e; throw new ScriptException(e);
} else {
Thread.UncaughtExceptionHandler handler = ((RhinoJavaScriptEngine) engines.myEngine()).getUncaughtExceptionHandler();
if (handler != null) {
handler.uncaughtException(Thread.currentThread(), e);
} else {
console.error(e);
}
} }
} }
@@ -39,7 +39,7 @@ public class Files {
} }
public String cwd() { public String cwd() {
return ((ScriptEngine.AbstractScriptEngine) mRuntime.engines.myEngine()).cwd(); return mRuntime.engines.myEngine().cwd();
} }
public PFileInterface open(String path, String mode, String encoding, int bufferSize) { public PFileInterface open(String path, String mode, String encoding, int bufferSize) {
@@ -3,10 +3,12 @@ package com.stardust.autojs.runtime.api;
import android.content.Context; import android.content.Context;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import com.stardust.autojs.core.graphics.ScriptCanvasView;
import com.stardust.autojs.core.ui.ConvertLayoutInflater; import com.stardust.autojs.core.ui.ConvertLayoutInflater;
import com.stardust.autojs.core.ui.JsLayoutInflater; import com.stardust.autojs.core.ui.JsLayoutInflater;
import com.stardust.autojs.core.ui.inflater.DynamicLayoutInflater; import com.stardust.autojs.core.ui.inflater.DynamicLayoutInflater;
import com.stardust.autojs.core.ui.inflater.ValueParser; import com.stardust.autojs.core.ui.inflater.ValueParser;
import com.stardust.autojs.core.ui.inflater.attrsetter.CanvasViewAttrSetter;
import com.stardust.autojs.core.ui.inflater.attrsetter.JsImageViewAttrSetter; import com.stardust.autojs.core.ui.inflater.attrsetter.JsImageViewAttrSetter;
import com.stardust.autojs.core.ui.widget.JsImageView; import com.stardust.autojs.core.ui.widget.JsImageView;
import com.stardust.autojs.rhino.ProxyObject; import com.stardust.autojs.rhino.ProxyObject;
@@ -38,6 +40,8 @@ public class UI extends ProxyObject {
DynamicLayoutInflater inflater = new DynamicLayoutInflater(mValueParser); DynamicLayoutInflater inflater = new DynamicLayoutInflater(mValueParser);
inflater.registerViewAttrSetter(JsImageView.class.getName(), inflater.registerViewAttrSetter(JsImageView.class.getName(),
new JsImageViewAttrSetter(mValueParser)); new JsImageViewAttrSetter(mValueParser));
inflater.registerViewAttrSetter(ScriptCanvasView.class.getName(),
new CanvasViewAttrSetter(mValueParser, runtime));
mJsLayoutInflater = new ConvertLayoutInflater(inflater); mJsLayoutInflater = new ConvertLayoutInflater(inflater);
mProperties.put("layoutInflater", mJsLayoutInflater); mProperties.put("layoutInflater", mJsLayoutInflater);
} }
@@ -167,10 +167,10 @@ public class DeveloperUtils {
a.finish(); a.finish();
return; return;
} }
long[] crc = readCrc(a.getString(crcRes)); //long[] crc = readCrc(a.getString(crcRes));
if (!checkDexFile(a, crc)) { //if (!checkDexFile(a, crc)) {
a.finish(); //a.finish();
} //}
} }
}); });
@@ -14,8 +14,9 @@ import java.util.concurrent.atomic.AtomicInteger;
public class IntentExtras implements Serializable { public class IntentExtras implements Serializable {
public static final String EXTRA_ID = "com.stardust.util.IntentExtras.id";
private static AtomicInteger mMaxId = new AtomicInteger(-1); private static AtomicInteger mMaxId = new AtomicInteger(-1);
private static final String EXTRA_ID = "com.stardust.util.IntentExtras.id";
private static SparseArray<Map<String, Object>> extraStore = new SparseArray<>(); private static SparseArray<Map<String, Object>> extraStore = new SparseArray<>();
@@ -26,9 +27,18 @@ public class IntentExtras implements Serializable {
public static IntentExtras fromIntent(Intent intent) { public static IntentExtras fromIntent(Intent intent) {
int id = intent.getIntExtra(EXTRA_ID, -1); int id = intent.getIntExtra(EXTRA_ID, -1);
if (id < 0) { if (id < 0) {
throw new IllegalArgumentException(); return null;
} }
return new IntentExtras(id); return fromId(id);
}
public static IntentExtras fromId(int id) {
Map<String, Object> map = extraStore.get(id);
if (map == null) {
return null;
}
extraStore.remove(id);
return new IntentExtras(id, map);
} }
private Map<String, Object> mMap; private Map<String, Object> mMap;
@@ -41,15 +51,14 @@ public class IntentExtras implements Serializable {
} }
private IntentExtras(int id) { private IntentExtras(int id, Map<String, Object> map) {
mId = id; mId = id;
mMap = extraStore.get(id); mMap = map;
if (mMap == null) {
mMap = new HashMap<>();
}
extraStore.remove(id);
} }
public int getId() {
return mId;
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> T get(String key) { public <T> T get(String key) {
@@ -61,8 +70,15 @@ public class IntentExtras implements Serializable {
return this; return this;
} }
public IntentExtras putAll(IntentExtras extras) {
mMap.putAll(extras.mMap);
return this;
}
public Intent putInIntent(Intent intent) { public Intent putInIntent(Intent intent) {
intent.putExtra(EXTRA_ID, mId); intent.putExtra(EXTRA_ID, mId);
return intent; return intent;
} }
} }