I need to know how does the shouldinterceptrequest
work. I don't know how to create and handle this method to read and replace the CSS link. Thank you!
2 Answers
Well, the short answer is that it works quite similar to shouldOverrideUrlLoading(WebView view, String url)
, as illustrated in the WebView tutorial.
To get you started, see the code below. You simply override the shouldInterceptRequest(WebView view, String url)
method of your WebViewClient. Obviously you don't have to do that inline, but for the sake of compactness that's what I did:
WebView webview = (WebView) findViewById(R.id.webview);
webview.setWebViewClient(new WebViewClient() {
@Override
public WebResourceResponse shouldInterceptRequest (final WebView view, String url) {
if (url.contains(".css")) {
return getCssWebResourceResponseFromAsset();
} else {
return super.shouldInterceptRequest(view, url);
}
}
/**
* Return WebResourceResponse with CSS markup from a String.
*/
@SuppressWarnings("deprecation")
private WebResourceResponse getCssWebResourceResponseFromString() {
return getUtf8EncodedCssWebResourceResponse(new ByteArrayInputStream("body { background-color: #F781F3; }".getBytes()));
}
/**
* Return WebResourceResponse with CSS markup from an asset (e.g. "assets/style.css").
*/
private WebResourceResponse getCssWebResourceResponseFromAsset() {
try {
return getUtf8EncodedCssWebResourceResponse(getAssets().open("style.css"));
} catch (IOException e) {
return null;
}
}
/**
* Return WebResourceResponse with CSS markup from a raw resource (e.g. "raw/style.css").
*/
private WebResourceResponse getCssWebResourceResponseFromRawResource() {
return getUtf8EncodedCssWebResourceResponse(getResources().openRawResource(R.raw.style));
}
private WebResourceResponse getUtf8EncodedCssWebResourceResponse(InputStream data) {
return new WebResourceResponse("text/css", "UTF-8", data);
}
});
webview.loadUrl("http://stackoverflow.com");
Catch the loading of the css file and return your own WebResourceResponse
containing the data you want to load in stead.
Do note that this method requires API level 11.
If you want to do something similar for Android 2.x, you might want to try using the earlier mentioned shouldOverrideUrlLoading(WebView view, String url)
to avoid loading the page, fetch it manually, replace the reference to the css file with your own, and finally call loadData(String data, String mimeType, String encoding)
(or loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl)
) on the WebView, passing in the manipulated html content as a string.
Before:
After:
-
So how ho do I replace the css link in my aspx file with a local one and put in the return webresourceresponse. – androdio Nov 26 '11 at 19:14
-
Well, you don't actually replace the css link in the aspx file, but whenever the referenced css file is loaded, you intercept it and in stead return your own css content. I extended the code in my answer with an example. I haven't actually tried it, but looking at the documentation it should be somewhat like that. Note that in stead of using a string with the css markup, you could also load a file from the SD card or resources and pass that along as InputStream. – MH. Nov 26 '11 at 20:14
-
I tried something like this to read css from a local file: InputStream im = null; File file = new File("file:///android_asset/android.css"); try { im = new FileInputStream(file); } catch (FileNotFoundException e) {} Unfortunately it does not load the data of the file. Thank you so much for your help! – androdio Nov 27 '11 at 11:07
-
Sorry for getting back this late - it's been hectic at work. I tidied up the code a bit and added a bunch of examples that illustrate how to use the `shouldInterceptRequest` method. Using these, I had no problems at all to catch SO's css file and in stead load up my own containing nothing more than a nice pink background. See added screenshots :) I suggest you breakpoint your own code and retry loading your asset as illustrated in my example above. – MH. Dec 02 '11 at 06:50
-
MH thanks a lot. my local css works now perfect with the shouldinterceptmethod. But now I struggle with appending html tags specific javascript(combination of css and jquery) to the webview. Do you have any idea? Thank you – androdio Dec 05 '11 at 22:03
-
You could potentially inject bit 'n pieces of Javascript as outlined [here](http://lexandera.com/2009/01/injecting-javascript-into-a-webview/). However, if your plan is to make a lot of modifications to a document, I'd say it's better practice to fetch up the source apriori, modify it whatever way you want (preferably using one of the many HTML/XML parsers 'out there') and finally feed it to the WebView. That's the only way you'll have full control over the document's source... – MH. Dec 06 '11 at 06:29
-
Is there any possibility to get the code from the page loaded in webview. to parse seems to much for me. i just want to do some style modifications. – androdio Dec 06 '11 at 18:28
-
There is no convenience method to get the source code of the page loaded. There is a [workaround](http://stackoverflow.com/questions/2376471/how-do-i-get-the-web-page-contents-from-a-webview) using the same approach as linked in my previous comment, but the downside is it'll effectively make the webview load twice for a single page (although it's rendered only the second time). This may be sufficient for your specific case, although I don't really see the benefits over first fetching the page, manipulating it and then load it up in the webview. Totally up to you. – MH. Dec 07 '11 at 04:58
-
hi,I had try to use shouldOverrideUrlLoading to replace the url, the it can't work at 2.3 – atian25 Jun 05 '13 at 06:51
-
@atian25: Yes, `shouldInterceptRequest()` wasn't available until API level 11 (Honeycomb, Android 3.0). The best next thing on older platforms is `shouldOverrideUrlLoading()`, as already mentioned in my answer. – MH. Jun 05 '13 at 09:01
-
@MH. yes, I had try, but the `shouldOverrideUrlLoading()` don't trigger. – atian25 Jun 06 '13 at 01:52
-
I dont recommend using `StringBufferInputStream` anymore, its deprecated and it produces bad results. Do `InputStream is = new ByteArrayInputStream(string.getBytes());` instead – AAlferez May 02 '14 at 17:32
this might be also interesting for you. It reads files from specific folders and if a request is incoming with this filename it uses the file from the asset folder and not that from web.
//get list of files of specific asset folder
private ArrayList listAssetFiles(String path) {
List myArrayList = new ArrayList();
String [] list;
try {
list = getAssets().list(path);
for(String f1 : list){
myArrayList.add(f1);
}
} catch (IOException e) {
e.printStackTrace();
}
return (ArrayList) myArrayList;
}
//get mime type by url
public String getMimeType(String url) {
String type = null;
String extension = MimeTypeMap.getFileExtensionFromUrl(url);
if (extension != null) {
if (extension.equals("js")) {
return "text/javascript";
}
else if (extension.equals("woff")) {
return "application/font-woff";
}
else if (extension.equals("woff2")) {
return "application/font-woff2";
}
else if (extension.equals("ttf")) {
return "application/x-font-ttf";
}
else if (extension.equals("eot")) {
return "application/vnd.ms-fontobject";
}
else if (extension.equals("svg")) {
return "image/svg+xml";
}
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}
return type;
}
//return webresourceresponse
public WebResourceResponse loadFilesFromAssetFolder (String folder, String url) {
List myArrayList = listAssetFiles(folder);
for (Object str : myArrayList) {
if (url.contains((CharSequence) str)) {
try {
Log.i(TAG2, "File:" + str);
Log.i(TAG2, "MIME:" + getMimeType(url));
return new WebResourceResponse(getMimeType(url), "UTF-8", getAssets().open(String.valueOf(folder+"/" + str)));
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
//@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@SuppressLint("NewApi")
@Override
public WebResourceResponse shouldInterceptRequest(final WebView view, String url) {
//Log.i(TAG2, "SHOULD OVERRIDE INIT");
//String url = webResourceRequest.getUrl().toString();
String extension = MimeTypeMap.getFileExtensionFromUrl(url);
//I have some folders for files with the same extension
if (extension.equals("css") || extension.equals("js") || extension.equals("img")) {
return loadFilesFromAssetFolder(extension, url);
}
//more possible extensions for font folder
if (extension.equals("woff") || extension.equals("woff2") || extension.equals("ttf") || extension.equals("svg") || extension.equals("eot")) {
return loadFilesFromAssetFolder("font", url);
}
return null;
}

- 2,892
- 1
- 33
- 32
-
shouldInterceptRequest is deprecated and if use new method then got " must not be null" error. – Md Imran Choudhury Aug 25 '18 at 03:47
-
nice solution but its better u put complete code ... webview.setWebViewClient(new WebViewClient() {... – Eyni Kave Sep 13 '22 at 21:23