2

私のアプリはハイブリッド html5 + JS + android であり、webview で実行され、JS インターフェイスを介して Andorid と多くの通信を行います。

一部のデバイスで 2 秒後に失敗するという報告がありました。レポートを取得できるようにACRAを追加しましたが、何も取得できませんでした。

だから私はそれを自分でテストしようとしました。例外を発生させるために、HTMLのボタンでトリガーされたJavascriptインターフェースの関数でメインスレッドのビューを操作するコードを追加します。これにより例外が発生します。ビュー階層を作成した元のスレッドのみがそのビューにアクセスできます。アプリが起動し、ボタンをタップすると例外で終了し、ACRA がレポートを送信します。

そして、アプリ起動直後に呼び出されるJSインターフェースの関数に操作コードを入れます。1秒後にアプリが閉じられるようになりました。しかし、ACRA はエラーを送信しません。ExceptionHandler でさえそれをキャッチしませんでしたが、最初のケースをキャッチしました。

これは 2 番目のシナリオのログです。

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 や Exception Handler がそれをキャッチしないのはなぜでしょうか?

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 でテスト済み、どちらも同じ

4

1 に答える 1

2

メソッド immediatelyCalled() は、「MyActivity 親」(UI スレッド、アプリのメイン スレッド) を作成しているスレッドとは別のスレッドで呼び出されていると思います。そのため、ui スレッドに割り当てられ、javascript コードを実行しているプロセスとは関係のないキャッチされていない例外ハンドラーは、setText (別のスレッドに属するビューへのアクセス) で発生するこの例外をキャッチできません。

parent.textview1.setText("test"); を囲むと、もちろん例外をキャッチできると思います。try catch ブロックで。次のように setText 呼び出しを変更すると、例外を回避できるはずです。

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

親パラメーターを最終としてマークする必要があります。残念ながら、ここにはテストする日食がなく、すでに遅いです:)頑張ってください!

于 2012-12-14T23:31:03.507 に答える