fix: app crash when ui script throws exception

This commit is contained in:
hyb1996
2017-11-07 12:56:19 +08:00
parent 7c1decdc04
commit d3c60049b7
8 changed files with 77 additions and 16 deletions

View File

@@ -10,7 +10,9 @@ module.exports = function(__runtime__, scope){
ui.setContentView = function(view){
ui.view = view;
ui.__view_cache__ = {};
activity.setContentView(view);
ui.run(function(){
activity.setContentView(view);
});
}
ui.id = function(id){
@@ -43,12 +45,16 @@ module.exports = function(__runtime__, scope){
color = android.graphics.Color.parseColor(color);
}
if(android.os.Build.VERSION.SDK_INT >= 21){
activity.getWindow().setStatusBarColor(color);
ui.run(function(){
activity.getWindow().setStatusBarColor(color);
});
}
}
ui.finish = function(){
activity.finish();
ui.run(function(){
activity.finish();
});
}
ui.findViewByStringId = function(view, id){
@@ -97,5 +103,7 @@ module.exports = function(__runtime__, scope){
return ui[name];
}
};
return proxy;
}

View File

@@ -11,6 +11,9 @@ import com.stardust.autojs.core.ui.widget.JsFrameLayout;
import com.stardust.autojs.core.ui.xml.XmlConverter;
import com.stardust.util.MapEntries;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
/**
@@ -54,7 +57,6 @@ public class ConvertLayoutInflater implements JsLayoutInflater {
@Override
public View inflate(Context context, String xml) {
try {
String androidLayoutXml = XmlConverter.convertToAndroidLayout(xml);
JsFrameLayout root = new JsFrameLayout(context);

View File

@@ -16,6 +16,12 @@ import com.stardust.util.Callback;
public class LoopBasedJavaScriptEngine extends RhinoJavaScriptEngine {
public interface ExecuteCallback {
void onResult(Object r);
void onException(Exception e);
}
private Handler mHandler;
private boolean mLooping = false;
@@ -30,15 +36,21 @@ public class LoopBasedJavaScriptEngine extends RhinoJavaScriptEngine {
}
public void execute(final ScriptSource source, final Callback<Object> callback) {
Runnable r = new Runnable() {
@Override
public void run() {
public void execute(final ScriptSource source, final ExecuteCallback callback) {
Runnable r = () -> {
try {
Object o = LoopBasedJavaScriptEngine.super.execute((JavaScriptSource) source);
if (callback != null)
callback.call(o);
callback.onResult(o);
} catch (Exception e) {
if (callback == null) {
throw e;
} else {
callback.onException(e);
}
}
};
mHandler.post(r);
if (!mLooping && Looper.myLooper() != Looper.getMainLooper()) {
@@ -56,7 +68,9 @@ public class LoopBasedJavaScriptEngine extends RhinoJavaScriptEngine {
@Override
public synchronized void destroy() {
Loopers.quitForThread(getThread());
Thread thread = getThread();
if (thread != null)
Loopers.quitForThread(thread);
super.destroy();
}

View File

@@ -13,6 +13,7 @@ import com.stardust.automator.UiObjectCollection;
import com.stardust.pio.PFiles;
import com.stardust.pio.UncheckedIOException;
import org.mozilla.javascript.Callable;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.ContextFactory;
import org.mozilla.javascript.ImporterTopLevel;
@@ -43,6 +44,7 @@ import java.util.Locale;
public class RhinoJavaScriptEngine extends JavaScriptEngine {
private static final String LOG_TAG = "RhinoJavaScriptEngine";
private static ThreadLocal<Thread.UncaughtExceptionHandler> mExceptionHandlerThreadLocal = new ThreadLocal<>();
private static int contextCount = 0;
private static StringScriptSource sInitScript;
@@ -163,13 +165,17 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine {
return context;
}
public static void setUncaghtExceptionHandler(Thread.UncaughtExceptionHandler handler) {
mExceptionHandlerThreadLocal.set(handler);
}
private class WrapFactory extends org.mozilla.javascript.WrapFactory {
@Override
public Object wrap(Context cx, Scriptable scope, Object obj, Class<?> staticType) {
if (staticType == String.class) {
return getRuntime().bridges.toString(obj);
}
if (staticType == UiObjectCollection.class ) {
if (staticType == UiObjectCollection.class) {
return getRuntime().bridges.toArray(obj);
}
@@ -196,6 +202,21 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine {
cx.setInstructionObserverThreshold(10000);
return cx;
}
@Override
protected Object doTopCall(Callable callable, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
Thread.UncaughtExceptionHandler exceptionHandler = mExceptionHandlerThreadLocal.get();
if (exceptionHandler == null)
return super.doTopCall(callable, cx, scope, thisObj, args);
else {
try {
return super.doTopCall(callable, cx, scope, thisObj, args);
} catch (Exception e) {
exceptionHandler.uncaughtException(Thread.currentThread(), e);
return null;
}
}
}
}

View File

@@ -5,16 +5,20 @@ import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
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.script.JavaScriptSource;
import com.stardust.autojs.script.ScriptSource;
import com.stardust.lang.ThreadCompat;
import com.stardust.util.IntentExtras;
/**
* Created by Stardust on 2017/2/5.
*/
public class ScriptExecuteActivity extends AppCompatActivity {
public class ScriptExecuteActivity extends AppCompatActivity implements Thread.UncaughtExceptionHandler {
private static final String EXTRA_EXECUTION = ScriptExecuteActivity.class.getName() + ".execution";
@@ -47,6 +51,7 @@ public class ScriptExecuteActivity extends AppCompatActivity {
mScriptSource = mScriptExecution.getSource();
mScriptEngine = mScriptExecution.getEngine();
mExecutionListener = mScriptExecution.getListener();
RhinoJavaScriptEngine.setUncaghtExceptionHandler(this);
runScript();
}
@@ -60,6 +65,7 @@ public class ScriptExecuteActivity extends AppCompatActivity {
}
}
@SuppressWarnings("unchecked")
private void doExecution() {
mScriptEngine.setTag(ScriptEngine.TAG_SOURCE, mScriptSource);
mExecutionListener.onStart(mScriptExecution);
@@ -86,6 +92,12 @@ public class ScriptExecuteActivity extends AppCompatActivity {
mScriptExecution = null;
}
@Override
public void uncaughtException(Thread t, Throwable e) {
mExecutionListener.onException(mScriptExecution, (Exception) e);
super.finish();
}
private static class ActivityScriptExecution extends ScriptExecution.AbstractScriptExecution {
private ScriptEngine mScriptEngine;

View File

@@ -50,4 +50,5 @@ public class AndroidContextFactory extends ShellContextFactory {
return cx;
}
}

View File

@@ -51,4 +51,6 @@ public class UI extends ProxyObject {
}
}