PhoneGapとAndroidを使用しています。外部サーバーに.htmlファイルとjsファイルがあります。次のコードを使用すると、外部.htmlファイルが読み込まれ、すべてが正常に機能します。
this.setIntegerProperty("loadUrlTimeoutValue", 60000);
this.loadUrl("http://www.myserver.com");
ただし、WebView
を介して作業する場合、loadURLTimeoutValue
にWebView
を設定できないようです。
private WebView webView;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
webView = (WebView) findViewById(R.id.webview);
webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
webView.loadUrl("http://www.myserver.com");
}
これは機能しません。 WebView
にタイムアウト値を設定するにはどうすればよいですか?
これは、説明されている動作をシミュレートする回避策です。 WebViewClient
を使用して、onPageStarted
メソッドをオーバーライドできます。
public class MyWebViewClient extends WebViewClient {
boolean timeout;
public MyWebViewClient() {
timeout = true;
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
new Thread(new Runnable() {
@Override
public void run() {
timeout = true;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(timeout) {
// do what you want
}
}
}).start();
}
@Override
public void onPageFinished(WebView view, String url) {
timeout = false;
}
}
タイムアウトの場合、たとえばエラーページを読み込むことができます...
WebViewClient
をWebView
に追加するには、次のようにします。
webView.setWebViewClient(new MyWebViewClient());
これを使用して、WebViewのタイムアウトを設定しました。
public class MyWebViewClient extends WebViewClient {
boolean timeout = true;
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
Runnable run = new Runnable() {
public void run() {
if(timeout) {
// do what you want
showAlert("Connection Timed out", "Whoops! Something went wrong. Please try again later.");
}
}
};
Handler myHandler = new Handler(Looper.myLooper());
myHandler.postDelayed(run, 5000);
}
@Override
public void onPageFinished(WebView view, String url) {
timeout = false;
}
}
デフォルトのタイムアウトを変更する正しい方法は、config.xmlファイルで<preference />
タグを使用することです。次に例を示します。
<preference name="loglevel" value="DEBUG" />
<preference name="loadUrlTimeoutValue" value="60000" />
<preference name="errorUrl" value="file:///Android_asset/www/connection_error.html" />
その他の設定オプションについては、 Android Configuration を参照してください。
WebView mWebView = findViewById(R.id.web_view);
mWebView.setWebViewClient(new WebViewClient() {
private volatile boolean timeout;
private volatile String timeoutOnPageStartedURL;
private volatile String timeoutCurrentURL;
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
timeout = true;
timeoutOnPageStartedURL = url;
timeoutCurrentURL = view.getUrl();
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (timeout) {
view.post(new Runnable() {
@Override
public void run() {
String currentURL = view.getUrl();
if ((timeoutOnPageStartedURL.hashCode() == currentURL.hashCode()) ||
(timeoutCurrentURL.hashCode() == currentURL.hashCode())) {
// do what you want with UI
}
}
});
}
}
}).start();
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
timeout = false;
}
});
Phonegap APIを取得するために必要なCordovaWebViewを拡張する場合は、次を使用できます。
this.getIntent().putExtra("loadUrlTimeoutValue", 60000);
内部的に、CordovaWebViewは前回の投稿で提案されたものと同様のタイムアウトメカニズムを実装しています(デフォルトのタイムアウト= 2000)。
これは文書化されたインターフェースではないので、将来壊れる可能性があることに注意してください。
Threadクラスを使用すると、run関数からWebViewを呼び出すのが面倒で、WebViewが作成されて別のスレッドで使用されるため、例外が発生します。これをAsyncTaskで実行します。この例では、タイムアウトに達した場合にAsyncTaskを使用してエラーファイルをWebViewにロードします。ページが適切にロードされたら、AsyncTaskをキャンセルします。 onPostExecute
はUIスレッドで実行されるため、WebViewと対話するスレッドセーフの問題はありません。
private class CustomWebViewClient extends WebViewClient {
boolean mPageLoaded;
final int mTimeoutLength = 20000;
WebView mView;
TimeoutCheck timeoutCheckTask;
public CustomWebViewClient()
{
super();
mPageLoaded = false;
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
mView = view;
timeoutCheckTask = new TimeoutCheck();
timeoutCheckTask.execute(null,null);
}
public void onPageFinished(WebView view, String url) {
mPageLoaded = true;
timeoutCheckTask.cancel(true);
}
private class TimeoutCheck extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... params) {
long count = 0;
while (count < mTimeoutLength)
{
try
{
Thread.sleep( 1000 );
}
catch ( InterruptedException e )
{
e.printStackTrace();
}
// Escape early if cancel() is called
if (isCancelled()) break;
count += 1000;
}
return null;
}
protected void onPostExecute(Void result) {
if(!mPageLoaded) {
mbLoadedErrFile = true;
//load error file into the webview
mView.loadUrl("file:///Android_asset/url_err_timeout.html");
}
}
}