fix(autojs): ui.emitter.emit() may make app crash if callback throws exception

add(sample): 界面模板一.js
This commit is contained in:
hyb1996 2018-06-03 11:57:49 +08:00
parent 35a5abed6a
commit 7036fa994e
4 changed files with 128 additions and 12 deletions

View File

@ -0,0 +1,89 @@
"ui";
var color = "#009688";
ui.layout(
<drawer id="drawer">
<vertical>
<appbar>
<toolbar id="toolbar" title="示例"/>
<tabs id="tabs"/>
</appbar>
<viewpager id="viewpager">
<frame>
<text text="第一页内容" textColor="black" textSize="16sp"/>
</frame>
<frame>
<text text="第二页内容" textColor="red" textSize="16sp"/>
</frame>
<frame>
<text text="第三页内容" textColor="green" textSize="16sp"/>
</frame>
</viewpager>
</vertical>
<vertical layout_gravity="left" bg="#ffffff" w="280">
<img w="280" h="200" scaleType="fitXY" src="http://images.shejidaren.com/wp-content/uploads/2014/10/023746fki.jpg"/>
<list id="menu">
<horizontal bg="?selectableItemBackground" w="*">
<img w="50" h="50" padding="16" src="{{this.icon}}" tint="{{color}}"/>
<text textColor="black" textSize="15sp" text="{{this.title}}" layout_gravity="center"/>
</horizontal>
</list>
</vertical>
</drawer>
);
//创建选项菜单(右上角)
ui.emitter.on("create_options_menu", menu=>{
menu.add("设置");
menu.add("关于");
});
//监听选项菜单点击
ui.emitter.on("options_item_selected", (e, item)=>{
switch(item.getTitle()){
case "设置":
toast("还没有设置");
break;
case "关于":
alert("关于", "Auto.js界面模板 v1.0.0");
break;
}
e.consumed = true;
});
activity.setSupportActionBar(ui.toolbar);
//设置滑动页面的标题
ui.viewpager.setTitles(["标签一", "标签二", "标签三"]);
//让滑动页面和标签栏联动
ui.tabs.setupWithViewPager(ui.viewpager);
//让工具栏左上角可以打开侧拉菜单
ui.toolbar.setupWithDrawer(ui.drawer);
ui.menu.setDataSource([
{
title: "选项一",
icon: "@drawable/ic_android_black_48dp"
},
{
title: "选项二",
icon: "@drawable/ic_settings_black_48dp"
},
{
title: "选项三",
icon: "@drawable/ic_favorite_black_48dp"
},
{
title: "退出",
icon: "@drawable/ic_exit_to_app_black_48dp"
}
]);
ui.menu.on("item_click", item => {
switch(item.title){
case "退出":
ui.finish();
break;
}
})

View File

@ -20,6 +20,9 @@ bridges.call = function (func, target, args) {
*/
function wrap(value){
if(value == null || value == undefined){
return value;
}
if(!(typeof(value) == 'object' && value.getClass && util.isFunction(value.getClass))){
return value;
}

View File

@ -5,7 +5,9 @@ import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
@ -13,13 +15,18 @@ import android.view.MotionEvent;
import com.stardust.autojs.core.eventloop.EventEmitter;
import com.stardust.autojs.core.eventloop.SimpleEvent;
import com.stardust.autojs.core.ui.inflater.inflaters.Exceptions;
import com.stardust.autojs.engine.JavaScriptEngine;
import com.stardust.autojs.engine.LoopBasedJavaScriptEngine;
import com.stardust.autojs.engine.ScriptEngine;
import com.stardust.autojs.engine.ScriptEngineManager;
import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.autojs.runtime.api.UI;
import com.stardust.autojs.script.ScriptSource;
import com.stardust.util.IntentExtras;
import org.mozilla.javascript.NativeObject;
/**
* Created by Stardust on 2017/2/5.
*/
@ -34,6 +41,7 @@ public class ScriptExecuteActivity extends AppCompatActivity {
private ScriptSource mScriptSource;
private ActivityScriptExecution mScriptExecution;
private IntentExtras mIntentExtras;
private ScriptRuntime mRuntime;
private EventEmitter mEventEmitter;
@ -62,7 +70,8 @@ public class ScriptExecuteActivity extends AppCompatActivity {
mScriptSource = mScriptExecution.getSource();
mScriptEngine = mScriptExecution.createEngine(this);
mExecutionListener = mScriptExecution.getListener();
mEventEmitter = new EventEmitter(((JavaScriptEngine) mScriptEngine).getRuntime().bridges);
mRuntime = ((JavaScriptEngine) mScriptEngine).getRuntime();
mEventEmitter = new EventEmitter(mRuntime.bridges);
runScript();
}
@ -153,7 +162,7 @@ public class ScriptExecuteActivity extends AppCompatActivity {
@Override
public void onBackPressed() {
SimpleEvent event = new SimpleEvent();
mEventEmitter.emit("back_pressed", event);
emit("back_pressed", event);
if (!event.consumed) {
super.onBackPressed();
}
@ -161,14 +170,14 @@ public class ScriptExecuteActivity extends AppCompatActivity {
@Override
protected void onPause() {
mEventEmitter.emit("pause");
emit("pause");
super.onPause();
}
@Override
protected void onResume() {
super.onResume();
mEventEmitter.emit("resume");
emit("resume");
}
@Override
@ -179,19 +188,19 @@ public class ScriptExecuteActivity extends AppCompatActivity {
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mEventEmitter.emit("restore_instance_state", savedInstanceState);
emit("restore_instance_state", savedInstanceState);
}
@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
mEventEmitter.emit("save_instance_state", outState, outPersistentState);
emit("save_instance_state", outState, outPersistentState);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
SimpleEvent e = new SimpleEvent();
mEventEmitter.emit("key_down", keyCode, event, e);
emit("key_down", keyCode, event, e);
return e.consumed || super.onKeyDown(keyCode, event);
}
@ -199,29 +208,41 @@ public class ScriptExecuteActivity extends AppCompatActivity {
@Override
public boolean onGenericMotionEvent(MotionEvent event) {
SimpleEvent e = new SimpleEvent();
mEventEmitter.emit("generic_motion_event", event, e);
emit("generic_motion_event", event, e);
return super.onGenericMotionEvent(event);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
mEventEmitter.emit("activity_result", requestCode, resultCode, data);
emit("activity_result", requestCode, resultCode, data);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
mEventEmitter.emit("create_options_menu", menu);
emit("create_options_menu", menu);
return menu.size() > 0;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
SimpleEvent e = new SimpleEvent();
mEventEmitter.emit("options_item_selected", e, item);
emit("options_item_selected", e, item);
return e.consumed || super.onOptionsItemSelected(item);
}
public void emit(String event, Object... args) {
try {
mEventEmitter.emit(event, (Object[]) args);
} catch (Exception e) {
mRuntime.exit(e);
}
}
public void setSupportActionBar(@Nullable NativeObject toolbar) {
super.setSupportActionBar(UI.unwrapJsViewObject(toolbar, Toolbar.class));
}
private static class ActivityScriptExecution extends ScriptExecution.AbstractScriptExecution {
private ScriptEngine mScriptEngine;

View File

@ -2,6 +2,7 @@ package com.stardust.autojs.runtime.api;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.view.View;
import com.stardust.autojs.core.graphics.ScriptCanvasView;
@ -55,7 +56,9 @@ public class UI extends ProxyObject {
}
@SuppressWarnings("unchecked")
public static <V extends View> V unwrapJsViewObject(NativeObject object, Class<V> c) {
public static <V extends View> V unwrapJsViewObject(@Nullable NativeObject object, Class<V> c) {
if (object == null)
return null;
if (!object.containsKey("__javaObject__")) {
throw new ClassCastException("object " + object + " cannot be cast to " + c.getName());
}