Android挂起异常



我的应用程序是一个混合的html5+JS+android,运行在webview中,通过JS接口与Andorid进行大量通信。

我收到一些报告说,在某些设备上,它在2秒钟后就失败了。我添加了ACRA,这样我就可以得到报告,但我什么都没得到。

所以我试着自己测试它,为了引发一个异常,我在Javascript接口的函数中添加了一段代码,该函数是用html中的按钮触发的,它可以操作主线程的视图。这引发了一个异常:只有创建视图层次结构的原始线程才能接触其视图现在应用程序启动,当我点击按钮时,它异常退出,ACRA发送报告。

然后我把操作代码放在JS接口的一个函数中,该函数在应用程序启动后立即调用。现在应用程序在一秒钟后关闭。但是ACRA没有发送任何错误。即使是ExceptionHandler也没有捕捉到它,而是捕捉到了第一个案例。

这是第二个场景的日志:

59): Starting input on non-focused client com.android.internal.view.IInputMethodClient$Stub$Proxy@43f8d990 (uid=10019 pid=329)
12-15 01:18:07.047: WARN/dalvikvm(409): JNI WARNING: JNI method called with exception raised
12-15 01:18:07.047: WARN/dalvikvm(409): in Landroid/webkit/BrowserFrame;.stringByEvaluatingJavaScriptFromString (Ljava/lang/String;)Ljava/lang/String; (NewString)
12-15 01:18:07.057: WARN/dalvikvm(409): Pending exception is:
12-15 01:18:07.057: INFO/dalvikvm(409): Landroid/view/ViewRoot$CalledFromWrongThreadException;: Only the original thread that created a view hierarchy can touch its views

我不知道这个挂起的异常是什么?我在网上找不到任何东西。我想知道为什么ACRA或异常处理程序没有抓住它?

class JavaScriptInterface
{
MyActivity parent;
JavaScriptInterface(MyActivity parent)
{
this.parent = parent;
}
public void immediatelyCalled() 
// Webview load index.html in oncreate of activity and js inside html calls this function immediately
{
parent.textview1.setText("test"); 
// raise an exception which ACRA or Exception Handler dont catch
// Problem is here
}
public void buttonCalled() 
// This is called when a button is tapped in html
{
parent.textview1.setText("test"); 
// raise an exception which Exception Handler and ACRA catch
}
}

这是我的活动:

public class MyActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
class MyExceptionHandler implements Thread.UncaughtExceptionHandler
{
@Override
public void uncaughtException(Thread thread, Throwable throwable)
{
Log.d("ExceptionHandler", "Caught exception: " + throwable.getClass().getName() + ": " + throwable.getMessage());
}
}
MyExceptionHandler handler = new MyExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(handler);

this.wv = (WebView) findViewById(R.id.webview);
this.wv.addJavascriptInterface(new JavaScriptInterface(this), "android");
this.ws = this.wv.getSettings();
this.ws.setJavaScriptEnabled(true);
this.wv.loadUrl("file:///android_asset/index.html");
}
}

这是index.html:的一部分

<script type="text/javascript">
android.immediatelyCalled();
</scritp>
<button onclick="android.buttonCalled()"></button>

在AVD 2.2和Xperai Arc 4.0.3上测试,两者都是相同的

我认为方法immediatelyCalled()是在另一个线程中调用的,而不是您正在创建的"MyActivity parent"(UI线程,您的应用程序主线程)。因此,您分配给ui线程的未捕获异常处理程序与运行javascript代码的进程无关,无法捕获在setText(访问属于另一个线程的视图)处发生的异常。

我认为,如果将parent.textview1.setText("test")括起来,当然可以发现异常;在一个尝试-接球块中。如果您以这种方式修改setText调用,您应该能够避免异常:

parent.textView1.post(new Runnable() {
public void run() {
parent.textview1.setText("test");
}
});

您必须将父参数标记为final。不幸的是,我这里没有eclipse要测试,而且已经很晚了:)祝你好运

最新更新