#android #cordova #android-webview
#Android #кордова #android-webview
Вопрос:
Я работаю с PhoneGap и Android, и мои файлы .html и js хранятся на внешнем сервере. Когда я использую следующий код, приложение загружает мои внешние HTML-файлы, и все работает нормально:
this.setIntegerProperty("loadUrlTimeoutValue", 60000);
this.loadUrl("http://www.myserver.com");
Однако, когда я работаю через a WebView
, я не могу установить loadURLTimeoutValue
для a 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
?
Ответ №1:
Это обходной путь для имитации описанного поведения. Вы можете использовать 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());
Комментарии:
1. Если есть тайм-аут, вы можете попробовать добавить некоторые элементы управления внутри
if
инструкции, чтобы проверить, загружена ли страница наполовину2. Возникает проблема, если страница загружается успешно и если вы загружаете другую страницу, когда поток не завершен… Кроме того, ваш конструктор неверен, и вы должны установить время ожидания в true в
onPageStarted
методе!3. как отменить загрузку веб-сайта после его завершения?
4. как справиться, если onPageFinished вызывается несколько раз
5. Это не будет работать для нескольких одновременных вызовов. Один вызов будет мешать другому.
Ответ №2:
Я использовал это, чтобы установить тайм-аут для моего 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;
}
}
Комментарии:
1. что здесь означает «MyHandler»? я попробовал решение до вашего, но код, который я хотел запустить, вызвал исключение, в котором говорилось, что мне нужно запустить свой код в потоке пользовательского интерфейса. Ваше решение использует метод «postDelayed», который теоретически должен запускать код в потоке пользовательского интерфейса, верно? я просто в замешательстве относительно того, что такое «MyHandler» перед «postDelayed»? не могли бы вы дополнить пример кодом MyHandler или простым примером того, как вы определили бы код myhandler.
2. Предположительно, MyHandler инициализируется как new Handler() в основном потоке (UI). Для получения дополнительной информации ознакомьтесь с документацией Android по обработчику и циклу. Из документации неясно, будет ли вызываться onPageFinished() при любых обстоятельствах — например, если возникает ошибка или выполняется вызов WebView.stopLoading() .
3. MyHandler = новый обработчик(Looper.myLooper());
Ответ №3:
Правильный способ изменить время ожидания по умолчанию — использовать tag <preference />
в config.xml файл, например:
<preference name="loglevel" value="DEBUG" />
<preference name="loadUrlTimeoutValue" value="60000" />
<preference name="errorUrl" value="file:///android_asset/www/connection_error.html" />
Дополнительные параметры настроек см. в разделе Конфигурация Android.
Комментарии:
1. Что эквивалентно этим настройкам в Eclipse?
Ответ №4:
Если вы расширяете CordovaWebView, что необходимо для получения phonegap API, вы можете просто использовать следующее:
this.getIntent().putExtra("loadUrlTimeoutValue", 60000);
Внутренне CordovaWebView реализует механизм тайм-аута, аналогичный предложенным в предыдущем сообщении (тайм-аут по умолчанию = 2000).
Имейте в виду, что это не документированный интерфейс, поэтому он может сломаться в будущем.
Ответ №5:
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;
}
});
Комментарии:
1. Это единственное решение, которое сработало для меня, поскольку мне нужно обновить пользовательский интерфейс и загрузить разные URL-адреса из массива строк.
Ответ №6:
Использование класса Thread беспокоит меня, вызов WebView из функции run приведет к исключению, поскольку WebView создается и используется в другом потоке. Я бы выполнил это с помощью AsyncTask. В этом примере я использую AsyncTask для загрузки файла ошибки в WebView, если время ожидания было достигнуто. Если страница загружается правильно, я отменяю AsyncTask. onPostExecute
Выполняется в потоке пользовательского интерфейса, поэтому для взаимодействия с 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");
}
}
}