3

Phonegap を使用して Android WebApp で作業しています。アプリケーションを終了するにはnavigator.app.exitApp、JavaScript コードから呼び出しています。

このメソッドのドキュメント ページを見つけようとしましたが、存在しません。次に、Android 用の Phonegap ソース コードをダウンロードしましたが、このライブラリがネイティブ コードからアプリを終了する場所と方法が見つからず、迷子になりました。時間がないので、自分でテストすることにしました。

私のアプリには単一の DroidGap アクティビティ (singleInstance フラグで起動) だけでなく、サービスとブロードキャスト レシーバーもあります。ユーザーは GUI を閉じることができる必要がありますが、サービスとその他すべてを実行したままにしたいと考えています。だから私がやりたいのは、を呼び出す代わりに、アクティビティだけを終了することSystem.exitです。

ここで奇妙な部分が来ます。これをシミュレーターでテストしたところ、DroidGap アクティビティは希望どおりに閉じているように見え (onDestroy が起動され)、サービスは実行され続けています。しかし、アクティビティが閉じられ、アプリのアイコンがタスク マネージャーに表示されなくなったにもかかわらず、どういうわけか JavaScript タイマーがまだ実行されています。私はこれをトリプルチェックしました。アクティビティがバックグラウンドにあると信じたいのですが、そうではありません.singleInstanceとして起動され、アプリを再度開くと最初のページが表示されます(別のページで閉じられました)。

なぜこれが起こるのですか?finishアクティビティを直接呼び出すプラグインをコーディングする必要がありますか?

前もって感謝します。

4

2 に答える 2

2

私はこれを数時間調査してきたので、ここに私の調査結果を投稿します。

Phonegap アプリだけでなく、すべての Android WebApp で、WebView があるときはいつでも 2 つのスレッドが生成されます:WebViewCoreThreadWebViewWorkerThread. それらは DDMS で表示されます。私は Android のソースを読んでいて、このスレッドの作成をWebViewCore.javaファイルまで追跡しました。明らかに、アプリケーション プロセスごとに 2 つのスレッドのみが開始され、それらはアプリ内のすべての WebView によって共有されます。

私見、画面でビューを使用するという事実は、スレッドの生成が非常に悪い設計であることを意味します。このフィールドがスレッドの開始と同じくらい複雑なことを行う必要がある場合は、代わりに WebViewActivity または WebWiewFragment としてより適切に設計する必要があります。いずれにせよ、スレッドを作成するクラスは、スレッドが不要になったときにスレッドを終了する責任も負う必要があります。残念ながら、そうではありません。

WebView を含むアクティビティが閉じられても、アプリケーション プロセスがまだ実行されている場合 (サービスなどの他のコンポーネントがあるため、または OS がまだそれを強制終了していないため)、これらのスレッドは実行され続けます。コア スレッドは、アプリで設定したタイマーを実行し続けます。アクティビティが再度作成されると、スレッドが再利用されます。

補足として、これにより、アクティビティを表示したままにしなくても、バックグラウンドで JavaScript コードを実行できることに注意してください。

この質問で公開されている通常の WebView のいくつかの回避策を試しました: WebView スレッドは決して停止しません (WebViewCoreThread, CookieSyncManager, http[0-3])

しかし、不明な理由で、Phonegap では機能しません。次のように DroidGap サブクラスをオーバーライドしようとしました。

@Override
public void onDestroy(){
    System.out.println("Activity destroyed");

    if(appView != null){ //This is a protected reference to the `CordovaWebView`, extending `WebView`
        //First attempt
        try {
            Class.forName("android.webkit.WebView").getMethod("onPause", (Class[]) null).invoke(appView, (Object[]) null);
        } catch (Exception e) {             
            e.printStackTrace();
        } 

        //Second attempt
        appView.pauseTimers();          
    }

    super.onDestroy();
}

最後に、アプリを終了する前に、すべてのタイマーが JavaScript コードからキャンセルされるようにしました。ただし、これは Android OS コードで修正されるか、Phonegap でパッチが適用されることが予想されます。これは、最良の場合でも、これらのスレッドは、Web ページが表示されていないときに実際には必要のないリソースを浪費しているためです。そして最悪のシナリオでは、DOM 関連の JavaScript コードの一部がクラッシュする可能性があります。

于 2013-04-09T13:26:39.337 に答える
0

を呼び出す直前に、タイマーを明示的に強制終了する必要がありますnavigator.app.exitApp()。この問題については、こちらでも説明しています。

お役に立てれば...:)

于 2013-04-09T11:23:13.350 に答える