Android WebViewClient / WebViewAssetLoader implementation error - android

I am trying to load a webpage in asset folder and app's local storage using the webasset loader using the code provided by google.
final WebViewAssetLoader assetLoader = new WebViewAssetLoader.Builder()
.addPathHandler("/assets/", new WebViewAssetLoader.AssetsPathHandler(this))
.build();
myWebView = (WebView) findViewById(R.id.webview);
myWebView.setWebViewClient(new WebViewClient() {
#Override
#RequiresApi(21)
public WebResourceResponse shouldInterceptRequest(WebView view,
WebResourceRequest request) {
return assetLoader.shouldInterceptRequest(request.getUrl());
}
//This gives the error: shouldInterceptRequest(WebView, WebResourceRequest)' is already
defined in 'Anonymous class derived from android.webkit.WebViewClient
#Override
#SuppressWarnings("deprecation") // for API < 21
public WebResourceResponse shouldInterceptRequest(WebView view,
WebResourceRequest request) {
return assetLoader.shouldInterceptRequest(Uri.parse(request));
//This gives an error for the request variable. It says : Required type: String and
Provided: WebResourceRequest. When I cast it as a string type, it
gives an error similar to first error.
}
});
Can someone please guide me here? What am i doing wrong here, i am using the exact code given by google. Any tutorial on using this class?

The snippet you found in the documentation is wrong, and I have already opened an issue for it.
The problem is that the second method's signature, which refers to a deprecated implementation, should instead be:
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
Use this and it'll compile (and work) as expected.

Related

WebSetting allowFileAccessFromFileURLs is Deprecated in API Level 30

I wanted to use webSetting allowFileAccessFromFileURLs in WebView but the setter is deprecated. how should I set this parameter.
Apparently you should be using WebViewAssetLoader now. Reference here.
Add an implementation "androidx.webkit:webkit:x.x.x" to your build.gradle file replacing x.x.x with the current version (1.3.0 is the most recent one as of the date of this post).
And load it like this in wherever you're setting your WebView (Activity, Fragment, etc):
final WebViewAssetLoader assetLoader = new WebViewAssetLoader.Builder()
.addPathHandler("/assets/", new AssetsPathHandler(this))
.addPathHandler("/res/", new ResourcesPathHandler(this))
.build();
webView.setWebViewClient(new WebViewClient() {
#Override
public WebResourceResponse shouldInterceptRequest(WebView view,
WebResourceRequest request) {
return assetLoader.shouldInterceptRequest(request.getUrl());
}
});
// Assets are hosted under http(s)://appassets.androidplatform.net/assets/... .
// If the application's assets are in the "main/assets" folder this will read the file
// from "main/assets/www/index.html" and load it as if it were hosted on:
// https://appassets.androidplatform.net/assets/www/index.html
webview.loadUrl("https://appassets.androidplatform.net/assets/www/index.html");

If WEB_URL site fails to load in the webview, how to move to another URL - Android

If WEB_URL site fails to load in the webview, how to move to another URL - Android
There's something I don't know when building an Android app.
The URL private final static String WEB_URL = "https://a.html"; ` is received as a URL and displayed in the webview.
private final static String WEB_URL = "https://a.html";
If this URL doesn't exist
private final static String WEB_URL1 = "https://b.html";
private final static String WEB_URL2 = "https://c.html";
private final static String WEB_URL3 = "https://d.html";
If the WEB_URL site fails to load in the webview due to a problem,
Load the web view with WEB_URL1
If it is not WEB_URL1, I want to automatically load the webview to WEB_URL2 and WEB_URL3.enter code here
I would like to know the code or example for this.
Thank you for teaching me.
Thank you.
You could handle this by override onReceivedError method in WebViewClient like so:
#Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error){
view.loadUrl(WEB_URL2);
}

Dynamically changing css values in a webview without reloading (Android)

I have a WebView based app to which I want to add a 'night-mode'.
My first instinct was to just have the program render the right CSS values each time depending on whether night-mode was on or not, and it works great, but it means that the page has to be reloaded each time the mode is toggled.
Is there any way I can change the css values retro-actively without having to reload the page?
You could inject code into your page's DOM. So you could for example have a reset stylesheet, and then inject a day or night mode class with javascript into the dom as required like this:
public class WebClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
#Override
public void onPageFinished(WebView view, String url)
{
view.loadUrl("javascript:document.getElementById(id).style.property=new style");
}
}
HTH

Issue with loading local javascript files inside a webview

I had with an issue that has plagued me for days. It turned out that it was an Android glitch and has been submitted, confirmed, and hopefully will be fixed in a future release. Now I have found a solution that works for me, and will provide it below, however the solution is not perfect as it involves editing the phone gap source. Mainly my question is if someone can find a better solution to this issue.
The Bug:
There is a glitch when you attempt to load a page inside of a WebView on Android 3.0+. The glitch is that if that page references any local javascript files, you cannot append query data to the url. Basically
This works:
<script type="text/javascript" src="StaticJS.js"></script>
This does not work:
<script type="text/javascript" src="StaticJS.js?var=val"></script>
Why the hell would anyone want to do this since the file obviously can't do anything with the query vals? Well for me I have a phonegap application that loads a settings file via JSONP, however if a settings file is not specified it defaults to a local file. So yeah, the file can't process the query data but it would be nice to use the same file format and loading structure.
Solution 1 (Non-PhoneGap)
So there is an easy solution to this if the target android platform is 11(Honeycomb) or higher. (As long as you are careful and do not use any method that do not exists in any lower API levels this code will run on <11 apis, but you will still have to set 11 as your target)
Basically you add a WebViewClient to the WebView that utilizes the shouldInterceptRequest method to intercept the loading of local js files with query data attached.
import java.io.IOException;
import java.io.InputStream;
import android.content.res.AssetManager;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class PatchingWebViewClient extends WebViewClient{
AssetManager am;
public PatchingWebViewClient(AssetManager am){
this.am = am;
}
#Override
public WebResourceResponse shouldInterceptRequest (WebView view, String url){
if(url.indexOf("file:///android_asset") == 0 && url.contains("?")){
String filePath = url.substring(22, url.length());
filePath = filePath.substring(0, filePath.indexOf("?"));
try {
InputStream is = am.open(filePath);
WebResourceResponse wr = new WebResourceResponse("text/javascript", "UTF-8", is);
return wr;
} catch (IOException e) {
return null;
}
}else{
return null;
}
}
}
To set the WebViewClient, your code would look something like this:
import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;
public class CanWeBreakAWebViewActivity extends Activity {
WebView mWebView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mWebView = (WebView) findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebViewClient(new PatchingWebViewClient(this.getAssets()));
mWebView.loadUrl("file:///android_asset/index.html");
}
}
Solution 2 (PhoneGap)
Now for Phonegap I don't have a clean solution. My solution is to go and download the Phonegap source and edit the CordovaWebViewClient by adding the following method:
#Override
public WebResourceResponse shouldInterceptRequest (WebView view, String url){
if(url.indexOf("file:///android_asset") == 0 && url.contains("?")){
String filePath = url.substring(22, url.length());
filePath = filePath.substring(0, filePath.indexOf("?"));
try {
InputStream is = ctx.getAssets().open(filePath);
WebResourceResponse wr = new WebResourceResponse("text/javascript", "Cp1252", is);
return wr;
} catch (IOException e) {
return null;
}
}else{
return null;
}
}
Solution 3 (Non-Existent)
This solution would hopefully be some easy to include class or tweak to the main activity so that you can use phone gap but could just use a .jar file of the code, making upgrades easier.
Thanks for this post, you clued me in to the latest solution which is simply to use IceCreamCordovaWebViewClient.
#Override
public void init() {
super.init(webView, new IceCreamCordovaWebViewClient(this, webView), new CordovaChromeClient(this, webView));
}
Query data is appended to javascript files (and other file types like css) to prevent browser caching. The query data is useless to the file but the browser treats it as new because the location is changed (in the eyes of the browser) and it loads a fresh copy.
I'm glad you found an answer to your problem, just thought I'd give my input as to why people use this method.

Load HTML file into WebView

I have a local html page along with several other resources pointed by it (css files and Javascript libraries) that I would like to load into a WebView . How could this be achieved ?
Perhaps not the best way to procede but I'm still experimenting.
The easiest way would probably be to put your web resources into the assets folder then call:
webView.loadUrl("file:///android_asset/filename.html");
For Complete Communication between Java and Webview See This
Update: The assets folder is usually the following folder:
<project>/src/main/assets
This can be changed in the asset folder configuration setting in your <app>.iml file as:
<option name=”ASSETS_FOLDER_RELATIVE_PATH” value=”/src/main/assets” />
See Article Where to place the assets folder in Android Studio
probably this sample could help:
WebView lWebView = (WebView)findViewById(R.id.webView);
File lFile = new File(Environment.getExternalStorageDirectory() + "<FOLDER_PATH_TO_FILE>/<FILE_NAME>");
lWebView.loadUrl("file:///" + lFile.getAbsolutePath());
In this case, using WebView#loadDataWithBaseUrl() is better than WebView#loadUrl()!
webView.loadDataWithBaseURL(url,
data,
"text/html",
"utf-8",
null);
url: url/path String pointing to the directory all your JavaScript files and html links have their origin. If null, it's about:blank.
data: String containing your hmtl file, read with BufferedReader for example
More info: WebView.loadDataWithBaseURL(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
The Accepted Answer is not working for me, This is what works for me
WebSettings webSetting = webView.getSettings();
webSetting.setBuiltInZoomControls(true);
webView1.setWebViewClient(new WebViewClient());
webView.loadUrl("file:///android_asset/index.html");
XML Layout File:
<WebView android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/webView"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".activities.Bani9">
</WebView>
Java Code:
public class Bani9 extends AppCompatActivity {
WebView webView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bani9);
webView = findViewById(R.id.webView);
WebSettings webSetting = webView.getSettings();
webSetting.setBuiltInZoomControls(true);
webView.setWebViewClient(new WebViewClient());
webView.loadUrl("file:///android_asset/punjabi/bani9.html");
}
}
Make sure you set file path accurately.
From the official guide https://developer.android.com/develop/ui/views/layout/webapps/load-local-content :
Store the HTML as an asset in app/src/main/assets/
Use WebViewAssetLoader to load the asset. Construct it in your onCreate() as follows:
final WebViewAssetLoader assetLoader = new WebViewAssetLoader.Builder()
.addPathHandler("/assets/", new WebViewAssetLoader.AssetsPathHandler(this))
.addPathHandler("/res/", new WebViewAssetLoader.ResourcesPathHandler(this))
.build();
Subclass WebViewClient to wrap WebViewAssetLoader:
private static class LocalContentWebViewClient extends WebViewClientCompat {
private final WebViewAssetLoader mAssetLoader;
LocalContentWebViewClient(WebViewAssetLoader assetLoader) {
mAssetLoader = assetLoader;
}
#Override
#RequiresApi(21)
public WebResourceResponse shouldInterceptRequest(WebView view,
WebResourceRequest request) {
return mAssetLoader.shouldInterceptRequest(request.getUrl());
}
#Override
#SuppressWarnings("deprecation") // to support API < 21
public WebResourceResponse shouldInterceptRequest(WebView view,
String url) {
return mAssetLoader.shouldInterceptRequest(Uri.parse(url));
}
}
This basically passes the request URL to WebViewAssetLoader to load web content from an asset.
Use assetLoader from (2) to construct WebViewClient from (3), and set it in your WebView. Your index.html can be loaded by using https and the default domain appassets.androidplatform.net:
mWebView.setWebViewClient(new LocalContentWebViewClient(assetLoader));
mWebView.loadUrl("https://appassets.androidplatform.net/assets/index.html");
Note that loading local files using web-like URLs instead of file:// is desirable as it is compatible with the Same-Origin policy.

Categories

Resources