- * Licensed under the MIT License: - *
- * 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: - *
- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *
- * 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 {
private static final String LOG_TAG = "DynamicLayoutInflater";
diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/CanvasViewAttrSetter.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/CanvasViewAttrSetter.java
new file mode 100644
index 00000000..bfe27d58
--- /dev/null
+++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/CanvasViewAttrSetter.java
@@ -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 {
Object getTag(String key);
+ String cwd();
+
+ void uncaughtException(Exception throwable);
+
+ Exception getUncaughtException();
+
+
/**
* @hide
*/
@@ -60,11 +67,12 @@ public interface ScriptEngine {
private Map {
throw new SecurityException("setOnDestroyListener can be called only once");
mOnDestroyListener = onDestroyListener;
}
+
+ @Override
+ public void uncaughtException(Exception throwable) {
+ mUncaughtException = throwable;
+ forceStop();
+ }
+
+ @Override
+ public Exception getUncaughtException() {
+ return mUncaughtException;
+ }
}
}
diff --git a/autojs/src/main/java/com/stardust/autojs/engine/ScriptEngineProxy.java b/autojs/src/main/java/com/stardust/autojs/engine/ScriptEngineProxy.java
new file mode 100644
index 00000000..a295662b
--- /dev/null
+++ b/autojs/src/main/java/com/stardust/autojs/engine/ScriptEngineProxy.java
@@ -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 implements ScriptEngine {
+
+ private final ScriptEngine mScriptEngine;
+
+ public ScriptEngineProxy(ScriptEngine 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();
+ }
+}
diff --git a/autojs/src/main/java/com/stardust/autojs/execution/LoopedBasedJavaScriptExecution.java b/autojs/src/main/java/com/stardust/autojs/execution/LoopedBasedJavaScriptExecution.java
index 4e643022..dc8f4894 100644
--- a/autojs/src/main/java/com/stardust/autojs/execution/LoopedBasedJavaScriptExecution.java
+++ b/autojs/src/main/java/com/stardust/autojs/execution/LoopedBasedJavaScriptExecution.java
@@ -23,10 +23,6 @@ public class LoopedBasedJavaScriptExecution extends RunnableScriptExecution {
long delay = getConfig().delay;
sleep(delay);
final LoopBasedJavaScriptEngine javaScriptEngine = (LoopBasedJavaScriptEngine) engine;
- javaScriptEngine.setUncaughtExceptionHandler((t, e) -> {
- javaScriptEngine.forceStop();
- getListener().onException(this, (Exception) e);
- });
final long interval = getConfig().interval;
javaScriptEngine.getRuntime().loopers.setMainLooperQuitHandler(new Loopers.LooperQuitHandler() {
long times = getConfig().loopTimes == 0 ? Integer.MAX_VALUE : getConfig().loopTimes;
diff --git a/autojs/src/main/java/com/stardust/autojs/execution/ScriptExecuteActivity.java b/autojs/src/main/java/com/stardust/autojs/execution/ScriptExecuteActivity.java
index 9e8e43e7..ca5187e2 100644
--- a/autojs/src/main/java/com/stardust/autojs/execution/ScriptExecuteActivity.java
+++ b/autojs/src/main/java/com/stardust/autojs/execution/ScriptExecuteActivity.java
@@ -1,5 +1,6 @@
package com.stardust.autojs.execution;
+import android.app.Activity;
import android.content.Context;
import android.content.Intent;
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.ScriptEngine;
import com.stardust.autojs.engine.ScriptEngineManager;
+import com.stardust.autojs.engine.ScriptEngineProxy;
import com.stardust.autojs.script.ScriptSource;
import com.stardust.util.IntentExtras;
@@ -16,7 +18,7 @@ import com.stardust.util.IntentExtras;
* 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";
@@ -24,7 +26,8 @@ public class ScriptExecuteActivity extends AppCompatActivity implements Thread.U
private ScriptEngine mScriptEngine;
private ScriptExecutionListener mExecutionListener;
private ScriptSource mScriptSource;
- private ScriptExecution mScriptExecution;
+ private ActivityScriptExecution mScriptExecution;
+ private IntentExtras mIntentExtras;
public static ActivityScriptExecution execute(Context context, ScriptEngineManager manager, ScriptExecutionTask task) {
ActivityScriptExecution execution = new ActivityScriptExecution(manager, task);
@@ -37,22 +40,34 @@ public class ScriptExecuteActivity extends AppCompatActivity implements Thread.U
return execution;
}
+ // FIXME: 2018/3/16 如果Activity被回收则得不到改进
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- IntentExtras extras = IntentExtras.fromIntent(getIntent());
- if (extras.get(EXTRA_EXECUTION) == null) {
+ mIntentExtras = readIntentExtras(savedInstanceState);
+ if (mIntentExtras == null || mIntentExtras.get(EXTRA_EXECUTION) == null) {
finish();
return;
}
- mScriptExecution = extras.get(EXTRA_EXECUTION);
+ mScriptExecution = mIntentExtras.get(EXTRA_EXECUTION);
mScriptSource = mScriptExecution.getSource();
- mScriptEngine = mScriptExecution.getEngine();
+ mScriptEngine = mScriptExecution.createEngine(this);
mExecutionListener = mScriptExecution.getListener();
- ((RhinoJavaScriptEngine) mScriptEngine).setUncaughtExceptionHandler((t, e) -> onException((Exception) e));
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() {
try {
prepare();
@@ -93,7 +108,12 @@ public class ScriptExecuteActivity extends AppCompatActivity implements Thread.U
@Override
public void finish() {
- mExecutionListener.onSuccess(mScriptExecution, mResult);
+ Exception exception = mScriptEngine.getUncaughtException();
+ if (exception != null) {
+ onException(exception);
+ } else {
+ mExecutionListener.onSuccess(mScriptExecution, mResult);
+ }
super.finish();
}
@@ -106,8 +126,12 @@ public class ScriptExecuteActivity extends AppCompatActivity implements Thread.U
}
@Override
- public void uncaughtException(Thread t, Throwable e) {
- onException((Exception) e);
+ protected void onSaveInstanceState(Bundle outState) {
+ 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 {
@@ -120,12 +144,23 @@ public class ScriptExecuteActivity extends AppCompatActivity implements Thread.U
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
public ScriptEngine getEngine() {
- if (mScriptEngine == null) {
- mScriptEngine = mScriptEngineManager.createEngineOfSourceOrThrow(getSource());
- }
return mScriptEngine;
}
diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/ScriptRuntime.java b/autojs/src/main/java/com/stardust/autojs/runtime/ScriptRuntime.java
index f70a3ed3..9dadf40f 100644
--- a/autojs/src/main/java/com/stardust/autojs/runtime/ScriptRuntime.java
+++ b/autojs/src/main/java/com/stardust/autojs/runtime/ScriptRuntime.java
@@ -9,6 +9,7 @@ import com.stardust.autojs.ScriptEngineService;
import com.stardust.autojs.annotation.ScriptVariable;
import com.stardust.autojs.core.accessibility.AccessibilityBridge;
import com.stardust.autojs.core.image.Colors;
+import com.stardust.autojs.engine.JavaScriptEngine;
import com.stardust.autojs.engine.RhinoJavaScriptEngine;
import com.stardust.autojs.engine.ScriptEngine;
import com.stardust.autojs.rhino.AndroidClassLoader;
@@ -321,22 +322,10 @@ public class ScriptRuntime {
}
}
- public void exit(Object obj) throws Throwable {
- mThread.interrupt();
- if (!(obj instanceof Throwable)) {
- console.error(obj);
- return;
- }
- Throwable e = (Exception) obj;
+ public void exit(Exception e) {
+ engines.myEngine().uncaughtException(e);
if (Looper.myLooper() != Looper.getMainLooper()) {
- throw e;
- } else {
- Thread.UncaughtExceptionHandler handler = ((RhinoJavaScriptEngine) engines.myEngine()).getUncaughtExceptionHandler();
- if (handler != null) {
- handler.uncaughtException(Thread.currentThread(), e);
- } else {
- console.error(e);
- }
+ throw new ScriptException(e);
}
}
diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/Files.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/Files.java
index 0f71e23e..0cf659d5 100644
--- a/autojs/src/main/java/com/stardust/autojs/runtime/api/Files.java
+++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/Files.java
@@ -39,7 +39,7 @@ public class Files {
}
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) {
diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/UI.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/UI.java
index eb937e78..06dfaaff 100644
--- a/autojs/src/main/java/com/stardust/autojs/runtime/api/UI.java
+++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/UI.java
@@ -3,10 +3,12 @@ package com.stardust.autojs.runtime.api;
import android.content.Context;
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.JsLayoutInflater;
import com.stardust.autojs.core.ui.inflater.DynamicLayoutInflater;
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.widget.JsImageView;
import com.stardust.autojs.rhino.ProxyObject;
@@ -38,6 +40,8 @@ public class UI extends ProxyObject {
DynamicLayoutInflater inflater = new DynamicLayoutInflater(mValueParser);
inflater.registerViewAttrSetter(JsImageView.class.getName(),
new JsImageViewAttrSetter(mValueParser));
+ inflater.registerViewAttrSetter(ScriptCanvasView.class.getName(),
+ new CanvasViewAttrSetter(mValueParser, runtime));
mJsLayoutInflater = new ConvertLayoutInflater(inflater);
mProperties.put("layoutInflater", mJsLayoutInflater);
}
diff --git a/common/src/main/java/com/stardust/util/DeveloperUtils.java b/common/src/main/java/com/stardust/util/DeveloperUtils.java
index 2b62cf85..e9267caa 100644
--- a/common/src/main/java/com/stardust/util/DeveloperUtils.java
+++ b/common/src/main/java/com/stardust/util/DeveloperUtils.java
@@ -167,10 +167,10 @@ public class DeveloperUtils {
a.finish();
return;
}
- long[] crc = readCrc(a.getString(crcRes));
- if (!checkDexFile(a, crc)) {
- a.finish();
- }
+ //long[] crc = readCrc(a.getString(crcRes));
+ //if (!checkDexFile(a, crc)) {
+ //a.finish();
+ //}
}
});
diff --git a/common/src/main/java/com/stardust/util/IntentExtras.java b/common/src/main/java/com/stardust/util/IntentExtras.java
index 7f987804..5c680857 100644
--- a/common/src/main/java/com/stardust/util/IntentExtras.java
+++ b/common/src/main/java/com/stardust/util/IntentExtras.java
@@ -14,8 +14,9 @@ import java.util.concurrent.atomic.AtomicInteger;
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 final String EXTRA_ID = "com.stardust.util.IntentExtras.id";
private static SparseArray