WebViewを使用して、アプリのアクティビティの1つにインターネットコンテンツを表示します。
問題は、ユーザーがこのアクティビティを終了すると、WebViewのスレッドが実行を継続することです。
問題のあるスレッドは次のとおりです。
_Thread [<17> WebViewCoreThread] (Running)
Thread [<25> CookieSyncManager] (Running)
Thread [<19> http0] (Running)
Thread [<29> http1] (Running)
Thread [<31> http2] (Running)
Thread [<33> http3] (Running)
_
これらの各スレッドを一時停止し、実行中の処理を確認します。
_Thread [<17> WebViewCoreThread] (Suspended)
Object.wait(long, int) line: not available [native method]
MessageQueue(Object).wait() line: 288
MessageQueue.next() line: 148
Looper.loop() line: 110
WebViewCore$WebCoreThread.run() line: 471
Thread.run() line: 1060
Thread [<25> CookieSyncManager] (Suspended)
Object.wait(long, int) line: not available [native method]
MessageQueue(Object).wait(long) line: 326
MessageQueue.next() line: 144
Looper.loop() line: 110
CookieSyncManager(WebSyncManager).run() line: 90
Thread.run() line: 1060
Thread [<19> http0] (Suspended)
Object.wait(long, int) line: not available [native method]
RequestQueue(Object).wait() line: 288
ConnectionThread.run() line: 93
_
これらの各スレッドのLooper
に終了を指示するにはどうすればよいのでしょうか。
アクティビティのwebView.destroy()
メソッドでonPause()
を呼び出してみましたが、影響はありませんでした。
webViewでWebページを開くための呼び出しを無効にすると(webView.loadUrl(...)
)、これらのスレッドは当然開始されないため、アクティビティを終了した後もオンのままになりません。
WebView
のスレッドを、アクティビティを終了した後に停止させる方法に関するアイデアはありますか?
WebビューでonPause/onResumeを呼び出すことにより、これらのスレッドを停止/再開できるはずです。
ただし、これらは非表示になっているため、リフレクションを使用して行う必要があります。次のコードは私のために働きました:
Class.forName("Android.webkit.WebView").getMethod("onPause", (Class[]) null).invoke(webView, (Object[]) null);
ここで、webViewはWebViewのインスタンスです。
こちらもご覧ください: http://code.google.com/p/Android/issues/detail?id=10282
私の解決策は、拡張されたwebviewクラスで(Android 2.2、andriod 2.3、Android 3.1)でテスト済み):
private boolean is_gone = false;
public void onWindowVisibilityChanged(int visibility) {
super.onWindowVisibilityChanged(visibility);
if (visibility == View.GONE) {
try {
WebView.class.getMethod("onPause").invoke(this); //stop flash
} catch (Exception e) {}
this.pauseTimers();
this.is_gone = true;
} else if (visibility == View.VISIBLE) {
try {
WebView.class.getMethod("onResume").invoke(this); //resume flash
} catch (Exception e) {}
this.resumeTimers();
this.is_gone = false;
}
}
public void onDetachedFromWindow() { //this will be trigger when back key pressed, not when home key pressed
if (this.is_gone) {
try {
this.destroy();
} catch (Exception e) {}
}
}
仕事をするクリーンで簡単なソリューション:
@Override
public void onPause() {
super.onPause();
webView.onPause();
webView.pauseTimers(); //careful with this! Pauses all layout, parsing, and JavaScript timers for all WebViews.
}
@Override
public void onResume() {
super.onResume();
webView.onResume();
webView.resumeTimers();
}
@Override
public void onDestroy() {
super.onDestroy();
parentViewGroup.removeAllViews(); //the viewgroup the webview is attached to
webView.loadUrl("about:blank");
webView.stopLoading();
webView.setWebChromeClient(null);
webView.setWebViewClient(null);
webView.destroy();
webView = null;
}
このandev.orgスレッドを見てください( WebViewCoreThread problem )。
応答を参照してください... Re:WebViewCoreThread problem-Postby potatoho
2)フラッシュを一時停止するには、非表示メソッドWebView.onPause()/ WebView.onResume()を呼び出す必要があります。
3)WebViewCoreThreadを一時停止するには、WebView.pauseTimers()/ WebView.resumeTimers()を使用します。
OnPause/onResumeをスキップしましたが、webView.pauseTimers()
とwebView.resumeTimers()
を実装し、少なくともCPUブリードを停止しました。
CookieSyncManager.getInstance().stopSync()
/startSync
もonPause/onResumeに追加しました。
WebView.destroy()はどうですか?ファンキーなリフレクションコールをせずに、私や物事を片付けているようです。
これらの情報のおかげで、電話のロックボタンを押すと、webViewのswfでサウンドを一時停止する問題が発生しました。ロック解除ボタンを押すと、onPauseとonResumeはまだswfを再生しますが、アクティビティはまだ表示されません。 webViewでswfサウンドの再生を一時停止および再開する場合は、これらをonWindowFocusChangedに配置します。
@Override
public void onWindowFocusChanged(boolean hasFocus) {
gameView = (WebView) findViewById(R.id.gameView);
// TODO Auto-generated method stub
if (hasFocus) {
try {
Class.forName("Android.webkit.WebView")
.getMethod("onResume", (Class[]) null)
.invoke(gameView, (Object[]) null);
} catch (Exception e) {
}
gameView.resumeTimers();
gameView.loadUrl("javascript:setflashfocus()");
} else {
try {
Class.forName("Android.webkit.WebView")
.getMethod("onPause", (Class[]) null)
.invoke(gameView, (Object[]) null);
} catch (Exception e) {
}
gameView.pauseTimers();
}
super.onWindowFocusChanged(hasFocus);
}
実際、webView.destroy(), onPause(), clear**()
を使用しても、Webcoreとその関連スレッドを停止することはできません。
実際には、理想的な方法は、WebViewが存在するアクティビティを独立したプロセスに設定して、アクティビティが終了するとWebcoreを含むすべてのスレッドが破棄されるようにすることです。
それが私が採用した方法です。多分それはあなたにも役立ちます。
上記の解決策は、Samsung Galaxy SでAndroid 2.3.3。
webview.loadUrl("file:///Android_asset/nonexistent.html");
存在しないhtmlファイルをロードするようにwebviewを強制しています。これは、webviewにクリーンアップを強制するようです。
WebViewのメモリをクリアするには、WebViewのonDestroyを呼び出す必要がありました。私はフラッシュをロードしていましたが、WebViewでこのアクティビティに戻ると、アプリが強制終了していました。 Flashは、使用するたびにWebViewを破壊しなければ、生き生きと食べます。
メソッドを定義します。
_ private void hiddenWebViewMethod(String state){
if( webView != null ){
try {
Method method = WebView.class.getMethod(state);
method.invoke(webView);
} catch (Exception e) {
Log.e("TAG", "Exception: " + e.toString());
webView.loadData("", "text/html", "utf-8");
}
}
}
_
次に、hiddenWebViewMethod("onPause");
を呼び出してロードを停止し、hiddenWebViewMethod("onResume");
を呼び出して再開します。