Android Webview not loading javascript injected images - javascript

I have the following application:
From start the webview is created and will load a local (to the app) HTML file.
This local HTML file contains some javascript that is able to update the HTML when data parsed to it.
Only when i parse data to it the images will not load, however a am able to see the HTML change and see the correct img tags appear with the correct URL's. I tested the javascript and the data that i send to it in the browser and it works.
My app:
private static final String URL = "file:///android_asset/overview.html";
private WebView wView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//Set settings
wView = (WebView) findViewById(R.id.webView);
wView.getSettings().setJavaScriptEnabled(true);
wView.getSettings().setUseWideViewPort(true);
wView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
wView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
//TMP DEBUDDING
wView.setWebContentsDebuggingEnabled(true);
//Create interface called "AppBridge" for JavaScript
wView.addJavascriptInterface(new WebAppInterface(this), "AppBridge");
wView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
view.loadUrl("javascript:testInject('Hello World');");
view.loadUrl("javascript:updateOverview(SOME DATA);");
}
#Override
public void onLoadResource (WebView view, String url) {
Log.v(TAG, "Webview load Resouce " + url);
}
});
wView.setWebChromeClient(new WebChromeClient() {
#Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
Log.d(TAG, message);
return true;
}
});
wView.loadUrl(URL);
Does anyone have an idea what is prohibiting the webview from loading my injected html images.
---- UPDATE ----
Some extra testing, when adding the img tag manually to the html the image is loaded and then when adding it again trough javascript it is shown. But only the same image is show all others are still not loaded.

After about 8 hours of testing , debugging and head bashing. I found the solution.
Inspired by the following article http://artemzin.com/blog/android-webview-io/
By overriding shouldInterceptRequest the WebView wil load the images.
wView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
view.loadUrl("javascript:testInject('Hello World');");
view.loadUrl("javascript:updateOverview("SOME DATA");
}
#Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
return super.shouldInterceptRequest(view, request);
}
});

Related

Is there a way to have an webview on android where I can inject css before the page is loading?

I need to have a webview where I inject CSS to a webpage before it is loaded so that the injected css is applied to the loading page itself. On iOS webviews this is a native feature, but as far as I know, there is no feature like that in the android native webview.
I tried using flutters inAppWebview for that, but according to their doc at https://inappwebview.dev/docs/javascript/user-scripts/ they can't provide that feature because of the same reason and therefore the behavior isn't guaranteed.
Is there some alternative webview out there that provides this kind of feature?
You can modify or stylish web pages with your own custom CSS style sheet in Android web-view. To do that, we have just a CSS file and a few lines of code needed.
like~
#Override
public void onPageFinished(String URL, WebView view) {
super.onPageFinished(view, URL);
// Inject CSS when page is done loading
injectCSS();
});
// Load a web
webl.loadUrl("https://www.example.com");
}
// Inject CSS method: read style.css from assets folder
// Append stylesheet to document head
private void injectCSS() {
try {
InputStream inputStream = getAssets().open("black.css");
byte[] buffer = new byte[inputStream.available()];
inputStream.read(buffer);
inputStream.close();
String encoded = Base64.encodeToString(buffer, Base64.NO_WRAP);
webl.loadUrl("javascript:(function() {" +
"var parent = document.getElementsByTagName('head').item(0);" +
"var style = document.createElement('style');" +
"style.type = 'text/css';" +
// Tell the browser to BASE64-decode the string into your script !!!
"style.innerHTML = window.atob('" + encoded + "');" +
"parent.appendChild(style)" +
"})()");
} catch (Exception e) {
e.printStackTrace();
};
Hope it will helpful
reference - https://www.programmersought.com/article/54381014286/
You can add your CSS code in the public void onLoadResource(WebView view, String url) method then it will be applied before the page load is finished.
It will help you to prevent users to sees the actual webpage before your CSS gets applied.
below is the full code
webView.setWebViewClient(new MyWebViewClient());
String url = getString(R.string.blogURL);
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl(url);
WebViewClient class code
private class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
#Override
public void onPageFinished(WebView view, String url) {
//if in the website used any javascript to interact with CSS then also add in this method, otherwise remove it from this method.
view.loadUrl("javascript:(function() { " +
"var h1 = document.getElementById('et_mobile_nav_menu').style.visibility='hidden'; " +
"})()");
}
#Override
public void onLoadResource(WebView view, String url) {
super.onLoadResource(view, url);
view.loadUrl("javascript:(function() { " +
"var h1 = document.getElementById('et_mobile_nav_menu').style.visibility='hidden'; " +
"})()");
}
#Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
Toast.makeText(BlogActivity.this, "Something is wrong while loading blog. Please try again", Toast.LENGTH_SHORT).show();
}
}
hope it will help someone

add data to webview html input in android

i have a webview, am trying to load a webpage as shown in figure attached below, there is a dropdown and two inputs in need to get it loaded by filling these values given by us in android webview
I have tried this code but its not working
final String sectionName = getIntent().getStringExtra("sectionName");
final String consumerNumber = getIntent().getStringExtra("consumerNumber");
final String billNumber = getIntent().getStringExtra("billNumber");
this.web = (WebView) findViewById(R.id.web);
this.web.loadUrl(Constants.Payment_URL);
this.web.getSettings().setJavaScriptEnabled(true);
this.web.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
Log.e("TAG", "sectionName:" + sectionName);
view.loadUrl("javascript:$($(\"#sectionCode option\")[" + sectionName + "]).prop('selected','selected');$('#ConsumerNo').val('" + consumerNumber + "');$('#billNo').val('" + billNumber + "');");
}
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
});
I need the web view get loaded with those values given in programenter image description here
Yes you can do that with the help of javascript.
You can inject javascript into your webview in many ways.
I would advice you to use JavaSCript injector library. You can find it here.
https://github.com/henrychuangtw/WebView-Javascript-Inject

Get all the DOM with webview

Im trying to get the html response in my webview, (yes I know that I can do the same without webview).
On my page finished I have this code:
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
view.loadUrl("javascript:window.HTMLOUT.showHTML('<html>'+document.getElementsByTagName(\"*\")+'</html>');");
The response:
<html>[object HTMLCollection]</html>
If I try this:
view.loadUrl("javascript:window.HTMLOUT.showHTML('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>');");
Then this is the response:
<html><head></head><body></body></html>
Any idea?

How to download APK file with its extension from a web view?

I created an app with a web view. This web view opens a page with a lot of links to download APKs. The download process goes smoothly, BUT the downloaded apk file doesn't get its original name and extension.
This is my code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tech_news);
techView = (WebView) findViewById(R.id.tech_webView);
techView.getSettings().setJavaScriptEnabled(true);
techView.loadUrl("http://egy-tech-droid.blogspot.com.eg/2015/08/blog-post.html");
// This will handle downloading. It requires Gingerbread, though
final DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
// This is where downloaded files will be written, using the package
// name isn't required
// but it's a good way to communicate who owns the directory
final File destinationDir = new File(Environment.getExternalStorageDirectory(), getPackageName());
if (!destinationDir.exists()) {
destinationDir.mkdir(); // Don't forget to make the directory if
// it's not there
}
techView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
techView.setDownloadListener(new DownloadListener() {
public void onDownloadStart(String url, String userAgent, String contentDisposition,
String mimetype, long contentLength) {
Request request = new Request(Uri.parse(url));
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, contentDisposition);
DownloadManager dm = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
dm.enqueue(request);
Toast.makeText(getApplicationContext(), "downloading",
// To notify the user that the file
// is being downloaded.
Toast.LENGTH_LONG).show();
}
});
return true;
}
});
}
I want the downloaded file to get its original name and extension, so when the user opens the file later from a file explorer the system recognizes that file as an an apk, not just an unknown file.

Javascript is not working in webView when Loaded from asset folder but working from both http server & localhost

I am trying to load offline version of python documentation into an webview from assetfolder. The offline docs work perfectly in my pc web browser in offline but not working properly in webview (something like jquery is missing).
#SuppressLint("SetJavaScriptEnabled")
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView webView = (WebView) findViewById(R.id.wrapper);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebChromeClient(new WebChromeClient());
webView.loadUrl("file:///android_asset/python/index.html");
}
}
And this error message is shown when I tried to load the home page or navigate to any page.
09-24 01:03:02.789: E/Web Console(479): ReferenceError: Can't find variable: $ at file:///android_asset/python/index.html:164
And the above error is for a Jquery code snippet ( I think this for that the jquery library isn't loading)
<script type="text/javascript">$('#searchbox').show(0);</script>
But when I load those pages from my local server localhost or http server, this is working perfectly. What did I miss?
Edit
Showing nothing in the webView. After using loadDataWithBaseURL:
#SuppressLint("SetJavaScriptEnabled")
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView webView = (WebView) findViewById(R.id.wrapper);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebChromeClient(new WebChromeClient());
AssetManager assetManager = getAssets();
String htmlPage = null;
InputStream input;
try {
input = assetManager.open("python/index.html");
int size = input.available();
byte[] buffer = new byte[size];
input.read(buffer);
input.close();
// byte buffer into a string
htmlPage = new String(buffer);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
webView.loadDataWithBaseURL("file:///android_asset/", htmlPage, "text/html", "utf-8", "");
}
}
Your html page should be having reference to
<script type="text/javascript" src="http://code.jquery.com/jquery-1.6.4.min.js">
</script>
Since you say the docs should load offline the jquery js is not being loaded. You could probably bundle jquery along with your application and reference it locally like this
<script src="file:///android_asset/js/jquery-1.8.2.min.js"></script>
Also include
<script src="file:///android_asset/js/jquery.mobile-1.3.2.min.js"></script>
You might also have to load your html page using loadDataWithBaseURL as seen below instead of loadUrl.
AssetManager assetManager = getAssets();
String htmlPage=null;
InputStream input;
try {
input = assetManager.open("python/index.html");
int size = input.available();
byte[] buffer = new byte[size];
input.read(buffer);
input.close();
// byte buffer into a string
htmlPage = new String(buffer);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
webView.loadDataWithBaseURL("file:///android_asset/", htmlPage, "text/html", "utf-8", "");
Note: jquery-1.8.2.min.js and jquery.mobile-1.3.2.min.js files should be present in your assets folder.
Hope this helps.
The problem was - I extracted those web files from a phonegap app's asset folder; those had some additional files ad different structure. That's why it was not working in Android naive environment !

Categories

Resources