Last active
March 22, 2022 09:17
-
-
Save museofwater/6373048 to your computer and use it in GitHub Desktop.
Android code snippet showing how to handle timeouts and server errors cleanly in a web view
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class AsyncMultiplayerSetupActivity extends Activity { | |
private static final String TAG = AsyncMultiplayerSetupActivity.class.getName(); | |
public static final String UTF_8 = "UTF-8"; | |
private WebView wvSignin; | |
private String url = "http://localhost:9000/signin"; | |
private ProgressDialog progressLoadUrl; | |
private SigninWebViewClient webViewClient; | |
public void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
Intent intent = getIntent(); | |
registerUser(url); | |
} | |
private void registerUser(String url) { | |
webViewClient = new SigninWebViewClient(getResources().getInteger(R.integer.timeout)); | |
setContentView(R.layout.setup); | |
wvSignin = (WebView)findViewById(R.id.wvSignin); | |
wvSignin.getSettings().setJavaScriptEnabled(true); | |
wvSignin.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); | |
wvSignin.setWebViewClient(webViewClient); | |
loadUrl(url); | |
} | |
private void loadUrl(String url) { | |
if (!NetworkUtil.checkNetwork(this)) { | |
setSigninFailureResult(); | |
} | |
// Show progress | |
progressLoadUrl = | |
ProgressDialog.show(this, getString(R.string.CONNECTING_TITLE), | |
getString(R.string.CONNECTING_MSG)); | |
webViewClient.prepareToLoadUrl(); | |
wvSignin.loadUrl(url); | |
} | |
private void setSigninFailureResult() { | |
setResult(getResources().getInteger(R.integer.RESPONSE_FAILED_CODE)); | |
finish(); | |
} | |
private void setSigninResult() { | |
setResult(getResources().getInteger(R.integer.RESPONSE_OK_CODE)); | |
} | |
private class SigninWebViewClient extends WebViewClient { | |
/** | |
* Timeout for page load in seconds | |
*/ | |
private int timeout; | |
private String urlLoading; | |
boolean pageLoaded = false; | |
// Flag to instruct the client to ignore callbacks after an error | |
boolean hasError = false; | |
private Handler timeoutHandler; | |
private AlertDialog alertDialog; | |
private SigninWebViewClient(int timeout) { | |
this.timeout = timeout; | |
timeoutHandler = new Handler(); | |
} | |
// Called by activity before requesting load of a url | |
private void prepareToLoadUrl() { | |
this.hasError = false; | |
this.pageLoaded = true; | |
this.urlLoading = null; | |
} | |
@Override | |
public void onPageStarted(WebView view, String url, Bitmap favicon) { | |
if (hasError) { | |
return; | |
} | |
urlLoading = url; | |
// timeout has expired if this flag is still set when the message is handled | |
pageLoaded = false; | |
Runnable run = new Runnable() { | |
public void run() { | |
// Do nothing if we already have an error | |
if (hasError) { | |
return; | |
} | |
// Dismiss any current alerts and progress | |
dismissProgress(); | |
dismissErrorAlert(); | |
if (!pageLoaded) { | |
showTimeoutAlert(); | |
} | |
} | |
}; | |
timeoutHandler.postDelayed(run, this.timeout*1000); | |
} | |
@Override | |
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { | |
// Ignore future callbacks because the page load has failed | |
hasError = true; | |
dismissProgress(); | |
showServerErrorAlert(); | |
} | |
@Override | |
public void onPageFinished(WebView view, String url) { | |
if (hasError) { | |
return; | |
} | |
pageLoaded = true; | |
dismissProgress(); | |
dismissErrorAlert(); | |
urlLoading = null; | |
// Do whatever processing you need to on page load here | |
} | |
private void showTimeoutAlert() { | |
showErrorAlert(R.string.TIMEOUT_TITLE, R.string.TIMEOUT_MSG); | |
} | |
private void showServerErrorAlert() { | |
showErrorAlert(R.string.SERVER_ERROR_TITLE,R.string.SERVER_ERROR_MSG); | |
} | |
private void showErrorAlert(int titleResource, int messageResource) { | |
AlertDialog.Builder builder = new AlertDialog.Builder(AsyncMultiplayerSetupActivity.this); | |
// Add the buttons | |
builder.setTitle(titleResource) | |
.setMessage(messageResource) | |
.setPositiveButton(R.string.RETRY, new DialogInterface.OnClickListener() { | |
public void onClick(DialogInterface dialog, int id) { | |
// Try to load url again | |
loadUrl(urlLoading); | |
dialog.dismiss(); | |
} | |
}); | |
builder.setNegativeButton(R.string.CANCEL, new DialogInterface.OnClickListener() { | |
public void onClick(DialogInterface dialog, int id) { | |
// User cancelled the dialog | |
setSigninFailureResult(); | |
dialog.cancel(); | |
} | |
}); | |
// Create the AlertDialog | |
alertDialog = builder.create(); | |
alertDialog.show(); | |
} | |
private void dismissProgress() { | |
if (progressLoadUrl != null && progressLoadUrl.isShowing()) { | |
progressLoadUrl.dismiss(); | |
} | |
} | |
private void dismissErrorAlert() { | |
if (alertDialog != null && alertDialog.isShowing()) { | |
alertDialog.dismiss(); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment