Android WebView cache AJAX response for offline - android

Is there a way to cache the AJAX responses received in the WebView to be cached for offline use?
I have cached the page and all its resources using some of the webveiw settings and most importnant:
ConnectivityManager cm = (ConnectivityManager) getActivity().getSystemService(Activity.CONNECTIVITY_SERVICE);
if (cm.getActiveNetworkInfo() == null || !cm.getActiveNetworkInfo().isConnected()) {
wvContent.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
} else {
wvContent.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
}
But in my client's page, that I cached, there are some AJAX calls which responses I want co cache for offline use? Is there a way to achieve that?

In order to achieve this you have to implement two things.
1) a way to catch the Ajax response and cache it.
2) a way to serve the cached result on an ajax request.
Part #1
You can use a JavascriptInterface and jQuery to catch the AJAX response. Look here for an example how to use the JavascriptInterface. After that you can cache the response
Part #2 (or 1 & 2)
You can serve the cached content using the shouldInterceptRequest method of WebViewClient. Look here for an example. In the example you can combine the #part 1 and make a network call to fetch the Ajax response manually.
Here is an example you can work with.
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
Log.i(TAG,"shouldInterceptRequest path:"+request.getUrl().getPath());
WebResourceResponse returnResponse = null;
if (request.getUrl().getPath().startsWith("/cart")) { // only interested in /cart requests
returnResponse = super.shouldInterceptRequest(view, request);
Log.i(TAG,"cart AJAX call - doing okRequest");
Request okRequest = new Request.Builder()
.url(request.getUrl().toString())
.post(null)
.build();
try {
Response okResponse = app.getOkHttpClient().newCall(okRequest).execute();
if (okResponse!=null) {
int statusCode = okResponse.code();
String encoding = "UTF-8";
String mimeType = "application/json";
String reasonPhrase = "OK";
Map<String,String> responseHeaders = new HashMap<String,String>();
if (okResponse.headers()!=null) {
if (okResponse.headers().size()>0) {
for (int i = 0; i < okResponse.headers().size(); i++) {
String key = okResponse.headers().name(i);
String value = okResponse.headers().value(i);
responseHeaders.put(key, value);
if (key.toLowerCase().contains("x-cart-itemcount")) {
Log.i(TAG,"setting cart item count");
app.setCartItemsCount(Integer.parseInt(value));
}
}
}
}
InputStream data = new ByteArrayInputStream(okResponse.body().string().getBytes(StandardCharsets.UTF_8));
Log.i(TAG, "okResponse code:" + okResponse.code());
returnResponse = new WebResourceResponse(mimeType,encoding,statusCode,reasonPhrase,responseHeaders,data);
} else {
Log.w(TAG,"okResponse fail");
}
} catch (IOException e) {
e.printStackTrace();
}
}
return returnResponse;
}

Related

Android WebView sometimes doesn't send request headers on initial page load

I have a webview activity that loads a URL with a few custom request headers in its onCreate() method. The requirement is to pass the custom headers with the initial URL request. On a few devices, the webview stops sending the headers after the webview activity has been launched a few times.
For example, I have a HomeActivity which launches a WebViewActivity. After launching the WebViewActivity and navigating back to HomeActivity a few times, the WebViewActivity stops sending the custom request headers and this behaviour doesn't change unless I clear the application's data.
I have confirmed this behaviour using a MITM tool. The implementation is as follows:
#Override
protected void onCreate(Bundle savedInstanceState) {
Map<String, String> map = new HashMap<>();
map.put("header1", "header1_value");
map.put("header2", "header2_value");
map.put("header3", "header3_value");
map.put("header4", "header4_value");
webView.loadUrl("https://www.example.com/mypath", map);
}
The above snippet executes unconditionally on every activity launch. However, the headers are not present in the actual request made by the webview. Also, the page being requested is a 303 redirect.
If your minimum API target is level 21, you can use the shouldInterceptRequest else you can use this
With each interception, you will need to take the url, make this request yourself, and return the content stream:
Then:
WebViewClient wvc = new WebViewClient() {
#Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
try {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
httpGet.setHeader("header1", "header1_value");
httpGet.setHeader("header2", "header2_value");
httpGet.setHeader("header3", "header3_value");
httpGet.setHeader("header4", "header4_value");
HttpResponse httpReponse = client.execute(httpGet);
Header contentType = httpReponse.getEntity().getContentType();
Header encoding = httpReponse.getEntity().getContentEncoding();
InputStream responseInputStream = httpReponse.getEntity().getContent();
String contentTypeValue = null;
String encodingValue = null;
if (contentType != null) {
contentTypeValue = contentType.getValue();
}
if (encoding != null) {
encodingValue = encoding.getValue();
}
return new WebResourceResponse(contentTypeValue, encodingValue, responseInputStream);
} catch (ClientProtocolException e) {
//return null to tell WebView we failed to fetch it WebView should try again.
return null;
} catch (IOException e) {
//return null to tell WebView we failed to fetch it WebView should try again.
return null;
}
}
}
//Where wv is your webview
wv.setWebViewClient(wvc);
Based on this question

Getting around X-Frame-Options DENY in an Android WebView

I am attempting to implement a technique similar to the one describe in this question.
I have an android application (Ionic built on top of Cordova) that runs in a webview. Basically what I want to do is load a page into an iframe and perform some work on this page. Many website uses the X-Frame-Options: DENY header to disallow their content from being loaded in an iFrame. In a chrome extension you can get around this by intercepting the webrequest and removing that header.
I've overridden the shouldInterceptRequest function here: https://developer.android.com/reference/android/webkit/WebViewClient.html
// Handle API until level 21
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
try {
WebResourceResponse cordovaResponse = super.shouldInterceptRequest(view, request);
if(cordovaResponse != null) {
return cordovaResponse;
}
String url = request.getUrl().toString();
HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection();
urlConnection.connect();
//view.loadUrl(url, getCustomHeaders());
WebResourceResponse response = new WebResourceResponse(urlConnection.getContentType(),
urlConnection.getContentEncoding(),
urlConnection.getInputStream());
Map<String, String> headers = response.getResponseHeaders();
if(headers != null){
response.setResponseHeaders(removeXOriginHeaders(headers));
}
return response;
} catch(MalformedURLException e) {
e.printStackTrace();
return null;
}
catch (IOException e) {
e.printStackTrace();
return null;
}
}`
but when the headers for all requests are received using the above method they are null and when the content is put into the iframe, it doesn't result in a fully formed Document.
The chrome debugger provides this message: Resource interpreted as Document but transferred with MIME type text/html;charset=UTF-8:
It's like the page content is fetched using xhr and then stuck inside a single element of the Document as opposed to loading as it normally would when using an iframe (all scripts run to execution, subsequent ajax requests fired etc).
Is there anyway to get the page content to load in the iframe after having removed that single header?
I was able to solve my problem by using the OkHttpClient found here: http://square.github.io/okhttp/ instead of the java URLConnection
// Handle API until level 21
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
try {
WebResourceResponse cordovaResponse = super.shouldInterceptRequest(view, request);
if(cordovaResponse != null) {
return cordovaResponse;
}
String url = request.getUrl().toString();
OkHttpClient httpClient = new OkHttpClient();
Request okRequest = new Request.Builder()
.url(url)
.build();
Response response = httpClient.newCall(okRequest).execute();
Response modifiedResponse = response.newBuilder()
.removeHeader("x-frame-options")
.removeHeader("frame-options")
.build();
return new WebResourceResponse("text/html",
modifiedResponse.header("content-encoding", "utf-8"),
modifiedResponse.body().byteStream()
);
} catch(MalformedURLException e) {
e.printStackTrace();
return null;
}
catch (IOException e) {
e.printStackTrace();
return null;
}
}

Spring Android POST no return type application/octet-stream in ResponseEntity

I am working with a Node.js server running Express 3.0.
During one part in my application I POST json to a URI to purchase a powerup at /api/transactions/powerup. This has several return options.
I will either receive a 201 meaning that the transaction was valid, a 404 that the request was not valid due to insufficient funds. My problem is that if I want to tell the android client whether it was successful based only on the headers that are in the ResponseEntity.
There is no json that is passed back to the client because the HTTP codes can tell me if it was successful. Does anyone know how to do this?
PowerupPurchase purchase = new PowerupPurchase();
purchase.setPowerId(params[0]);
final String url = getString(R.string.external_api_url) + "/transactions/powers?apiKey="+mCurrentUser.getApiKey();
Log.i(TAG,url);
// create the headers
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
requestHeaders.setAcceptEncoding(ContentCodingType.GZIP);
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
// Create the Json that will be exchanged
HttpEntity<?> requestEntity = new HttpEntity<PowerupPurchase>(purchase, requestHeaders);
// Create a new RestTemplate instance
RestTemplate restTemplate = new RestTemplate();
MappingJacksonHttpMessageConverter converter = new MappingJacksonHttpMessageConverter();
List<MediaType> mediaList = new LinkedList<MediaType>();
mediaList.add(new MediaType("application","octet-stream",Charset.forName("UTF-8")));
converter.setSupportedMediaTypes(mediaList);
restTemplate.getMessageConverters().add(converter);
try {
// Make the network request
ResponseEntity<?> response = restTemplate.postForEntity(url, requestEntity, Object.class);
// HOW DO I GET THE HEADERS??
response.getHeaders()
400's seem to always throw errors in Spring Android is there anyway that I can simply look at the http header and not worry about a return object map to?
DefaultResponseErrorHandler used by RestTemplate throws exceptions for all 400 and 500 series HTTP Status responses. One option is to use a custom ResponseErrorHandler with your RestTemplate request that won't throw exceptions. You can modify your request to use the custom handler and then check for the expected status codes:
// set the custom error handler
restTemplate.setErrorHandler(new CustomErrorHandler());
// make the request
ResponseEntity<Void> response = restTemplate.postForEntity(url, requestEntity, null);
// check status code
HttpStatus statusCode = response.getStatusCode();
if (statusCode == HttpStatus.CREATED) {
// handle success
} else if (statusCode == HttpStatus.NOT_FOUND) {
// handle error
}
Here is an example of an "empty" implementation that won't throw any exceptions:
class CustomErrorHandler implements ResponseErrorHandler {
#Override
public void handleError(ClientHttpResponse response) throws IOException {
}
#Override
public boolean hasError(ClientHttpResponse response) throws IOException {
return false;
}
}
Because the server might return other status codes, it's probably a good idea to look for the expected status codes and not throw exceptions for those particular ones. But it simply depends on what your needs are. This example extends the default handler used by RestTemplate and checks for the expected status codes:
class CustomErrorHandler extends DefaultResponseErrorHandler {
#Override
public void handleError(ClientHttpResponse response) throws IOException {
// check for expected status codes
if (isExpected(response.getStatusCode())) {
return;
}
super.handleError(response);
}
#Override
public boolean hasError(ClientHttpResponse response) throws IOException {
// check for expected status codes
if (isExpected(response.getStatusCode())) {
return false;
}
return super.hasError(response);
}
private boolean isExpected(HttpStatus statusCode) {
return (statusCode == HttpStatus.CREATED || statusCode == HttpStatus.NOT_FOUND);
}
}
Surely you can use the exception as failed?
boolean success;
try{
ResponseEntity<?> response = restTemplate.postForEntity(url, requestEntity, Object.class);
int result = response.getHeaders().getStatus()...
success = result >= 200 && result < 300;
}catch(Exception e){
success = false;
}

Intercept POST requests in a WebView

I'm developping an Android application filtering the requests (with a white list) and using a custom SSLSocketFactory. For this, I've developed a custom WebViewClient and I have overridden the shouldInterceptRequest method. I can filter and use my SocketFactory with the GET requests but I can't intercept the POST requests.
So, is there a way to intercept the POST requests in a WebView ?
Here is the code of the shouldInterceptRequest method :
public final WebResourceResponse shouldInterceptRequest(WebView view, String urlStr) {
URI uri = URI.create(urlStr);
String scheme = uri.getScheme();
// If scheme not http(s), let the default webview manage it
if(!"http".equals(scheme) && !"https".equals(scheme)) {
return null;
}
URL url = uri.toURL();
if(doCancelRequest(url)) {
// Empty response
Log.d(TAG, "URL filtered: " + url);
return new WebResourceResponse("text/plain", "UTF-8", new EmptyInputStream());
} else {
Log.d(TAG, "URL: " + url);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("User-Agent", mSettings.getUserAgentString());
// Configure connections
configureConnection(conn);
String mimeType = conn.getContentType();
String encoding = conn.getContentEncoding();
if(mimeType != null && mimeType.contains(CONTENT_TYPE_SPLIT)) {
String[] split = mimeType.split(CONTENT_TYPE_SPLIT);
mimeType = split[0];
Matcher matcher = CONTENT_TYPE_PATTERN.matcher(split[1]);
if(matcher.find()) {
encoding = matcher.group(1);
}
}
InputStream is = conn.getInputStream();
return new WebResourceResponse(mimeType, encoding, is);
}
}
I was facing the same issue a few days ago.
So I built a library that solves it:
https://github.com/KonstantinSchubert/request_data_webviewclient
It is a WebViewClient with a custom WebResourceRequest that contains the POST/PUT/... payload of XMLHttpRequest requests.
It only works for these though - not for forms and other kind of request sources.
The hack works, basically, by injecting a script into the HTML that intercepts XMLHttpRequest calls. It records the post/put/... content and sends it to an android.webkit.JavascriptInterface. There, the request is stashed until the shouldInterceptRequest method is called by Android ...
I have created a library that aims to capture all data of all HTTP requests sent from Android WebViews.
Using this library, you can easily implement sending POST, or any other requests. Here's your code adapted to work with the library:
#Nullable
#Override
public final WebResourceResponse shouldInterceptRequest(WebView view, WebViewRequest request) {
URI uri = URI.create(request.getUrl());
String scheme = uri.getScheme();
// If scheme not http(s), let the default webview manage it
if(!"http".equals(scheme) && !"https".equals(scheme)) {
return null;
}
URL url = uri.toURL();
if(doCancelRequest(url)) {
// Empty response
Log.d(TAG, "URL filtered: " + url);
return new WebResourceResponse("text/plain", "UTF-8", new EmptyInputStream());
} else {
Log.d(TAG, "URL: " + url);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// Set request method
conn.setRequestMethod(request.getMethod());
// Set request headers
for (Map.Entry<String, String> header : request.getHeaders().entrySet()) {
conn.setRequestProperty(header.getKey(), header.getValue());
}
// Set request body, if it's present
if (!request.getBody().isEmpty()) {
OutputStream os = conn.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
osw.write(request.getBody());
osw.flush();
osw.close();
os.close(); //don't forget to close the OutputStream
}
conn.connect();
String mimeType = conn.getContentType();
String encoding = conn.getContentEncoding();
if(mimeType != null && mimeType.contains(CONTENT_TYPE_SPLIT)) {
String[] split = mimeType.split(CONTENT_TYPE_SPLIT);
mimeType = split[0];
Matcher matcher = CONTENT_TYPE_PATTERN.matcher(split[1]);
if(matcher.find()) {
encoding = matcher.group(1);
}
}
InputStream is = conn.getInputStream();
return new WebResourceResponse(mimeType, encoding, is);
}
}
I have one of my answers on above thread http://code.google.com/p/android/issues/detail?id=9122
Please see comment#31
Some of the caveats of my solution I see are:
Putting a dependency on xmlhttprequest prototype which has different implementation for different webkits.
Security issue in sending data for post requests in URL. But I guess you can solve that through some encryption mechanism.
URL length issue for some of the browsers if you big data to post
Apart from that, I found this github repo which seems to be solving this problem in another hacky way. I looked into the code but didn't get time to implement and test it. But worth giving a try.
The easiest way I found to do this is to just use the JQuery Ajax Event Handlers with a Javascript Interface.
You have to setup the Javascript Interface, but once you do just have it match the signature of the handler you're interested in.
To get the payload, just find the payload variable name put it in the interface.
Here's the Javascript:
$( document ).ajaxSend(function( event, request, settings ) {
var eventJSON= JSON.stringify(event);
var requestJSON = JSON.stringify(request);
var settingsJSON = JSON.stringify(settings);
var payloadJSON = JSON.stringify(payload);
myJSInterface.passData(eventJSON,requestJSON,settingsJSON,payloadJSON);
});
Here's the Kotlin class
class yourJSInterface() {
lateinit var event: String
lateinit var request: String
lateinit var settings: String
lateinit var payload: String
#JavascriptInterface
fun passData(eventJSON:String, responseJSON:String, settingsJSON:String,payloadJSON:String){
event = eventJSON
response= responseJSON
settings= settingsJSON
payload= payloadJSON
}
}
The registration in the onPageStarted override for WebViewClient
webView.addJavascriptInterface(yourJSInterface,"myJSInterface")
Finally the JS injection into the WebView in the OnPageFinished override
webView.evaluateJavascript("javascript:" + getString(R.string.js_from_above),null)
I registered the interface in onPageStarted because otherwise, the javascript file in onPageFinished won't recognize your interface.
There's a simpler solution: send the parameters by GET in the ajax call and transform them to POST in shouldInterceptRequest
you can get input value before submit
https://github.com/henrychuangtw/WebView-Javascript-Inject
Step 1 : create a class which called by javascript
class MyJavaScriptInterface
{
#JavascriptInterface
public void processHTML(String html)
{
//called by javascript
}
}
Step 2 : register interface for javascript
webview1.getSettings().setJavaScriptEnabled(true);
webview1.addJavascriptInterface(new MyJavaScriptInterface(), "MYOBJECT");
Step 3 : inject javascript to page
webview1.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
StringBuilder sb = new StringBuilder();
sb.append("document.getElementsByTagName('form')[0].onsubmit = function () {");
sb.append("var objPWD, objAccount;var str = '';");
sb.append("var inputs = document.getElementsByTagName('input');");
sb.append("for (var i = 0; i < inputs.length; i++) {");
sb.append("if (inputs[i].type.toLowerCase() === 'password') {objPWD = inputs[i];}");
sb.append("else if (inputs[i].name.toLowerCase() === 'email') {objAccount = inputs[i];}");
sb.append("}");
sb.append("if (objAccount != null) {str += objAccount.value;}");
sb.append("if (objPWD != null) { str += ' , ' + objPWD.value;}");
sb.append("window.MYOBJECT.processHTML(str);");
sb.append("return true;");
sb.append("};");
view.loadUrl("javascript:" + sb.toString());
}
});
Use GET instead of POST.
Known issue:
http://code.google.com/p/android/issues/detail?id=9122
Was answered here as well:
Android - how to intercept a form POST in android WebViewClient on API level 4

Access the http response headers in a WebView?

Is there a way to view the http response headers in an Activity once a web page has been loaded in a WebView? Seems like this should be possible, but I can't find any methods that expose the headers.
Neither WebView nor WebViewClient provide methods to do that, Though, you can try to implement that manually. You can do something like this:
private WebView webview;
public void onCreate(Bundle icicle){
// bla bla bla
// here you initialize your webview
webview = new WebView(this);
webview.setWebViewClient(new YourWebClient());
}
// this will be the webclient that will manage the webview
private class YourWebClient extends WebViewClient{
// you want to catch when an URL is going to be loaded
public boolean shouldOverrideUrlLoading (WebView view, String urlConection){
// here you will use the url to access the headers.
// in this case, the Content-Length one
URL url;
URLConnection conexion;
try {
url = new URL(urlConection);
conexion = url.openConnection();
conexion.setConnectTimeout(3000);
conexion.connect();
// get the size of the file which is in the header of the request
int size = conexion.getContentLength();
}
// and here, if you want, you can load the page normally
String htmlContent = "";
HttpGet httpGet = new HttpGet(urlConection);
// this receives the response
HttpResponse response;
try {
response = httpClient.execute(httpGet);
if (response.getStatusLine().getStatusCode() == 200) {
// la conexion fue establecida, obtener el contenido
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream inputStream = entity.getContent();
htmlContent = convertToString(inputStream);
}
}
} catch (Exception e) {}
webview.loadData(htmlContent, "text/html", "utf-8");
return true;
}
public String convertToString(InputStream inputStream){
StringBuffer string = new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
try {
while ((line = reader.readLine()) != null) {
string.append(linea + "\n");
}
} catch (IOException e) {}
return string.toString();
}
}
I can't test it right now, but that's basically what you could do (it's very crazy though :).
inspired by Cristian answer I needed to intercept AJAX calls webview is doing, where I needed to intercept response headers to get some information (cart item count in e-commerce app), which I needed to leverage in app. As the app is using okhttp I've ended up doing this and it's working:
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
Log.i(TAG,"shouldInterceptRequest path:"+request.getUrl().getPath());
WebResourceResponse returnResponse = null;
if (request.getUrl().getPath().startsWith("/cart")) { // only interested in /cart requests
returnResponse = super.shouldInterceptRequest(view, request);
Log.i(TAG,"cart AJAX call - doing okRequest");
Request okRequest = new Request.Builder()
.url(request.getUrl().toString())
.post(null)
.build();
try {
Response okResponse = app.getOkHttpClient().newCall(okRequest).execute();
if (okResponse!=null) {
int statusCode = okResponse.code();
String encoding = "UTF-8";
String mimeType = "application/json";
String reasonPhrase = "OK";
Map<String,String> responseHeaders = new HashMap<String,String>();
if (okResponse.headers()!=null) {
if (okResponse.headers().size()>0) {
for (int i = 0; i < okResponse.headers().size(); i++) {
String key = okResponse.headers().name(i);
String value = okResponse.headers().value(i);
responseHeaders.put(key, value);
if (key.toLowerCase().contains("x-cart-itemcount")) {
Log.i(TAG,"setting cart item count");
app.setCartItemsCount(Integer.parseInt(value));
}
}
}
}
InputStream data = new ByteArrayInputStream(okResponse.body().string().getBytes(StandardCharsets.UTF_8));
Log.i(TAG, "okResponse code:" + okResponse.code());
returnResponse = new WebResourceResponse(mimeType,encoding,statusCode,reasonPhrase,responseHeaders,data);
} else {
Log.w(TAG,"okResponse fail");
}
} catch (IOException e) {
e.printStackTrace();
}
}
return returnResponse;
}
I hope this may be helpful to others and if somebody has a suggestions for improvement I would be grateful. Unfortunately it's compatible only with LOLLIPOP and higher as from this version you can access/return headers using WebResourceRequest, which was needed for my case.
You should be able to control all your headers by skipping loadUrl and writing your own loadPage using Java's HttpURLConnection. Then view the headers, do your thing, and use the webview's loadData to display the response.
There is an alternative solution if you're targeting at least Kit-Kat, even though this wouldn't show the headers in the Activity but rather in Chrome. You can simply follow this short guide on how to remotely debug Webviews.
The 2 key points are, first, to enable WebView debugging in you app
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
And then open chrome://inspect in a Chrome tab in a computer. Once you connect your phone via USB to the computer, you will see your app's WebView in the list of debuggable devices
you can use OkHttp:
private fun handleRequestViaOkHttp(url: String) {
var httpClient = OkHttpClient()
thread {
try {
val request = Request.Builder().url(url).build()
print("Request: $request")
val response = httpClient.newCall(request).execute()
println("Response: " + response.headers().toString())
} catch (e: Exception) {}
}
}
you should call it inside this method:
override fun shouldInterceptRequest(view: WebView?, request: WebResourceRequest?): WebResourceResponse? {
handleRequestViaOkHttp(webViewUrl.value.toString())
return super.shouldInterceptRequest(view, request)
}
As the accepted answer will only work with HttpGet, here is a trick thet currently I'm using (at this time it seems to work)
In onPageFinished handler, if there is an error, the title of the page will be like "ERROR_NUM - ERROR_DESCRIPTION", like "500 - Internal Server Error", so all I do is to get title from webview in the function, and then check the title.
view.getTitle()

Categories

Resources