Kill Android Activity if webview is loading - android

Would like to ask if there's a way to kill / move to another activity in Android if the webview is loading for too long, say example 5 seconds.

you can use
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if(isStillLoading())
//move to the next activity
}
},3000);
you have to impliment the method isStillLoading

You can listen the progress of page loading using WebClient -
private boolean loadingFinished;
mWebView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String urlNewString) {
return false;
}
#Override
public void onPageStarted(WebView view, String url, Bitmap facIcon) {
loadingFinished = false;
//SHOW LOADING IF IT ISNT ALREADY VISIBLE
}
#Override
public void onPageFinished(WebView view, String url) {
loadingFinished = true;
}
});
User Handler to check if the webview is loaded or not after 5 seconds -
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// Will get executed after 5 seconds
if(!loadingFinished)
//move to the next activity
}
},5000); //5000 miliseconds.. i.e. 5 seconds

Related

Android: TimeOut on WebViewClient

I am trying to implement a TimeOut error handling on a webview. But unfortunately I am doing something wrong, which is causing me huge headaches. Currently I am using a TimerTask. To check the progress of a webpage for 10 seconds. The idea is if the page takes more than 10 seconds to load, the app should display a custom "no I-net" view.
Here is my code so far:
webView.setWebViewClient(new WebViewClient() {
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
if (mNoInternetConnectionView.getVisibility() == View.VISIBLE) {
mNoInternetConnectionView.setVisibility(View.GONE);
}
mTimer = new Timer();
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (webView.getProgress() < 100) {
handleInternetProblems();
}
}
});
}
};
mTimer.schedule(timerTask, 10000, 1);
}
#Override
public void onPageFinished(WebView view, String url) {
cancelTimer();
if (!internetError && webView.getVisibility() != View.VISIBLE) {
webView.setVisibility(View.VISIBLE);
}
}
#SuppressWarnings("deprecation")
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return mCheckoutUrlHandler.handleUrl(webView, url);
}
#TargetApi(Build.VERSION_CODES.N)
#Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
return true;
}
#Override
public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {
//handle ssl error
}
#Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
handleInternetProblems();
}
});
And here are my handleInternetProblems() and my cancelTimer():
private void handleInternetProblems() {
internetError = true;
webView.setVisibility(View.GONE);
mNoInternetConnectionView.setVisibility(View.VISIBLE);
mKLLoadingAnimation.hide();
cancelTimer();
}
private void cancelTimer() {
if (mTimer != null) {
mTimer.cancel();
mTimer.purge();
mTimer = null;
}
}
The problem is that if I click on an URL on the webview and I try to load another webpage I get mNoInternetConnectionView and I can see that handleInternetProblems() is called multiple times inside TimerTask. What am I doing wrong? How can I prevent this from happening?

Android WebView issue on override url loading

I’m trying to override url loading when clicking on a link on an app WebView.
The page loads but the WebView will keep it’s last scroll position and content size.
Is there some parameter I forgot to set on the WebView to reset the content size and the scroll position on next load?
Here’s how I’m using it:
#SuppressLint("SetJavaScriptEnabled")
#AfterViews
protected void afterViews() {
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new WebClient());
webView.setWebChromeClient(new ChromeClient());
webView.loadUrl(url);
}
public class WebClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
boolean isValidEmail = url.startsWith("mailto:") && Patterns.EMAIL_ADDRESS.matcher(url.substring("mailto:".length())).matches();
boolean isValidPhone = url.startsWith("tel:") && Patterns.PHONE.matcher(url.substring("tel:".length())).matches();
if (url.startsWith("about:")) {
return super.shouldOverrideUrlLoading(view, url);
}
if (isValidEmail) {
Intent sendIntent = new Intent(Intent.ACTION_SENDTO, Uri.parse(url));
startActivity(Intent.createChooser(sendIntent, ""));
} else {
if (isValidPhone) {
Intent dialIntent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
startActivity(Intent.createChooser(dialIntent, ""));
} else {
WebViewActivity.this.setPageTitle(url);
webView.loadUrl(url);
}
}
return true;
}
#Override
public void onPageFinished(WebView view, String url) {
//..
}
}
public class ChromeClient extends WebChromeClient {
#Override
public void onProgressChanged(WebView view, int progress) {
//...
}
}
Thanks.
Did you try to set scroll position in onPageFinished?
#Override
public void onPageFinished(WebView view, String url) {
// other code...
view.scrollTo(0,0);
}
That should set WebView content back to top, and not on old scroll position
Edit 1:
Sometimes if the page loads for a long time this won't work properly, so we must wait for page to get fully loaded:
#Override
public void onPageFinished(WebView view, String url) {
view.postDelayed(new Runnable() {
#Override
public void run() {
webView.scrollTo(0, 0);
}
// Delay the scrollTo to make it work
}, 300);
}
Please note that webView this time is not the WebView from the method onPageFinished, but the WebView fetched from the layout (same one as in afterViews() method).
#Bojan Kopanja, my sincere apologies for misleading.
It turns out I had the webview inside a pull to refresh listener with a scrollview and removing that got rid of the problem.
Thanks for your help nevertheless.

android webview progress: any good solution?

I want to have a busy indicator of some sort when pages are loading. My indicator will be full-screen like a splash screen. This is because the android webview blanks the page to white before it starts loading, unlike a normal browser.
A simple solution might be suggested. for example, set loading true in onPageStarted() and set false in onPageFinished().
#Override
public void onPageFinished(WebView view, String url) {
setLoading(false);
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
setLoading(true);
}
the problem with this is that the website i'm loading results in multiple start / finished cycles for a single click. maybe this is redirects, or iframes. i'm not sure ... but the result is that the "busy" indicator flashes on and off disturbingly.
Considering that, another ideas is to keep a count of pages loading- incrementing in onPageStarted() and decrementing in onPageFinished(). something like this,
private int loadingCount = 0;
#Override
public void onPageFinished(WebView view, String url) {
loadingCount--;
if (loadingCount == 0) {
setLoading(false);
}
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
if (loadingCount == 0) {
setLoading(true);
}
loadingCount++;
}
I'm running into this problem: page started / page finished are not matched. I'm not sure why exactly, but I think it might have to do w/ redirects.
Any ideas?
Try this:
private boolean loadingFinished = true, redirect = false;
public class myWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String urlNewString) {
if (!loadingFinished) {
redirect = true;
}
loadingFinished = false;
view.setVisibility(View.VISIBLE);
view.loadUrl(urlNewString);
return true;
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
setTitle(url);
loadingFinished = false;
progressDialog = new ProgressDialog(FacebookWebView.this);
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.setMessage(" Loading...");
progressDialog.setCancelable(true);
progressDialog.show();
}
#Override
public void onPageFinished(WebView view, String url) {
if (!redirect) {
loadingFinished = true;
}
if (loadingFinished && !redirect) {
if (progressDialog.isShowing()){
progressDialog.dismiss();
}
//finish();
} else {
redirect = false;
}
}
I'm not exactly sure, but this should solve your problem with redirects. In the case of several frames on the same page, probably counting in onPageFinished till the number of frames, and then dismiss "busy dialog", should be a solution.

progressBar and refresh webview combination android

EDIT:
I am using a ProgressBar for a Webview that works fine. Now I want to refresh my Webview, which also works. When I am trying to combine them, the Spinner doesn't end at all. This is my code:
private final Runnable m_Runnable = new Runnable()
{
public void run()
{
//Toast.makeText(WebcamsScreen.this,"in runnable",Toast.LENGTH_SHORT).show();
doRefreshingStuff(id);
WebcamsScreen.this.mHandler.postDelayed(m_Runnable, 20000);
}
};
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//initialitions
doRefreshingStuff(id);
this.mHandler = new Handler();
this.mHandler.postDelayed(m_Runnable,20000);
doRefreshingStuff(id);
}
public void doRefreshingStuff(String id){
setContentView(R.layout.web4);
webView7 = (WebView) findViewById(R.id.web_4_1);
webView7.getSettings().setJavaScriptEnabled(true);
webView7.getSettings().setJavaScriptEnabled(true);
progressBar = ProgressDialog.show(WebcamsScreen.this, "example", "...");
url="my url";
webView7.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view, String url1) {
view.loadUrl(url1);
return true;
}
public void onPageFinished(WebView view, String url1) {
if (progressBar.isShowing()) {
progressBar.dismiss();
}
}
});
webView7.loadUrl(url);
what must I change?
It looks like you are refreshing your WebView every 20 seconds and popping up a new progress dialog when you do. Your code assumes that the old progress dialog has already been dismissed. If it hasn't, then the progress dialog just became orphaned and will remain on display forever. You can probably fix this by inserting this code:
if (progressBar != null && progressBar.isShowing()) {
progressBar.dismiss();
}
just before the line progressBar = ....
But I wouldn't fix your code that way. You are doing a huge amount of work that you don't need to do. (For instance, you don't need to reload the same content view.) Here's my revised version:
private final Runnable m_Runnable = new Runnable() {
public void run() {
doRefreshingStuff(id);
mHandler.postDelayed(m_Runnable, 20000);
}
};
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//initialitions
setContentView(R.layout.web4);
webView7 = (WebView) findViewById(R.id.web_4_1);
webView7.getSettings().setJavaScriptEnabled(true);
webView7.getSettings().setJavaScriptEnabled(true);
webView7.setWebViewClient(new WebViewClient() {
public void onPageStarted(WebView view, String url, Bitmap favicon) {
if (!mProgressBar.isShowing()) {
mProgressBar.show();
}
}
public void onPageFinished(WebView view, String url1) {
if (mProgressBar.isShowing()) {
mProgressBar.dismiss();
}
}
});
mProgressBar = new ProgressDialog(this);
mProgressBar.setTitle("example");
mProgressBar.setMessage("...");
mHandler = new Handler();
}
protected void onResume() {
super.onResume();
mHandler.post(m_Runnable);
}
protected void onPause() {
super.onPause();
mHandler.removeCallbacks(m_Runnable);
}
public void doRefreshingStuff(String id) {
url="my url";
webView7.loadUrl(url);
}
Note that I moved the starting of the page loading loop to onResume() and kill the looping in onPause(). You may want slightly different logic, but you should definitely stop looping somehow when your activity pauses or finishes.

Set loadURLTImeOutValue on WebView

I'm working with PhoneGap and Android and have my .html and js files on an external server. When I use the following code, the app loads my external .html files and everything works fine:
this.setIntegerProperty("loadUrlTimeoutValue", 60000);
this.loadUrl("http://www.myserver.com");
However, when work via a WebView I can't seem to set the loadURLTimeoutValue for 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");
}
This doesn't work. How can I set the timeout value on the WebView?
This is a workaround to simulate the described behavior. You can use a WebViewClient, and override the onPageStarted method:
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;
}
}
If timeout, you can load, for example, an error page...
To add the WebViewClient to you WebView, just do this:
webView.setWebViewClient(new MyWebViewClient());
I used this to set a time out for my 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;
}
}
The correct way to change the default timeout is using tag <preference /> in config.xml file, for example:
<preference name="loglevel" value="DEBUG" />
<preference name="loadUrlTimeoutValue" value="60000" />
<preference name="errorUrl" value="file:///android_asset/www/connection_error.html" />
For more preference options, refer to Android Configuration.
If you extend CordovaWebView, which you should in order to get the phonegap API, you can just use the following:
this.getIntent().putExtra("loadUrlTimeoutValue", 60000);
Internally, CordovaWebView implements a timeout mechanism similar to the ones proposed in the previous post (default timeout = 2000).
Mind that this is not a documented interface, so it might break in the future.
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;
}
});
The use of Thread class bothers me calling the WebView from the run function will lead to an exception as the WebView is created and used in another thread.
I would perform this with an AsyncTask.
In this example, I use an AsyncTask to load an error file into the WebView if the timeout was reached. If the page loads properly I cancel the AsyncTask.
The onPostExecute runs in the UI thread so there is no thread safety problem to interact with the 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");
}
}
}

Categories

Resources