I've problem with adding Javscript BEFORE page starts to load. I tried to do something like this:
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
browser.loadUrl("javascript:alert(window.prepended = 'abc - "+url+"');");
}
Or:
#Override
public void onLoadResource(WebView view, String url) {
super.onLoadResource(view, url);
browser.loadUrl("javascript:alert(window.prepended = 'abc - "+url+"');");
}
But after first time (when I click Reload) I'm getting undefined in JS:
<script type="text/javascript">
alert(window.prepended);
setTimeout("alert('Timeout: '+window.prepended)", 2000);
</script>
Reload
Edit:
Finally I used onProgressChanged function from WebChromeClient :)
Try something like this in onPageStarted() method:
/*
* This call injects JavaScript into the page replacing the page
* content
*/
webView.loadUrl(injectJavaScriptIntoErrorPage());
/**
* Method used to inject custom JavaScript code into HTML page.
*
* #return String of JavaScript function Called in onReceivedError method
* for myWebClient
*/
protected String injectJavaScriptIntoErrorPage() {
String errorPage = "javascript:(function() { "
+ "document.getElementsByTagName('style')[0].innerHTML = ' "
+ " body { margin:auto;width:500px;text-align:center; }"
+ " p { font-size:20px; }'; "
+ "document.getElementsByTagName('body')[0].innerHTML = ' "
+ " <img src=\"file:///android_asset/custom_error.png\"/>"
+ " <p>Venter på nettet.</p>" + "';})()";
return errorPage;
}
The method above modifies the current page and it will display an custom error page instead of the default one.
I was calling this in on onReceivedError(), but you can you use it in onPageStarted() and add your custom javascript function.
This is just to give you an idea on how you can manipulate the current page.
Best regards.
Related
I used this code and working but it first loads with website header and then afterward loads without header.
What is wrong in this code? What to modify so that only one screen loads, i.e, without website header?
webSettings.setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient()
{
#Override
public void onPageFinished(WebView view, String url)
{
webView.loadUrl("javascript:(function() { " +
"var head = document.getElementsByTagName('header')[0];"
+ "head.parentNode.removeChild(head);" +
"})()");
webView.loadUrl("javascript:(function() { " +
"var head = document.getElementsByTagName('footer')[0];"
+ "head.parentNode.removeChild(head);" +
"})()");
}
});
webView.loadUrl("https://www.google.com");
I resolved by putting this code in OnLoadResource() method instead of OnPageFinished() and using evaluateJavascript:
override fun onLoadResource(view: WebView?, url: String?) {
webView.evaluateJavascript("javascript:(function() { " +
"var head = document.getElementsByTagName('footer')[0];"
+ "head.parentNode.removeChild(head);" +
"})()", {});
}
I'm trying to develop android app using webview and JavaScriptInterface like this.
private static final String ENTRY_URL = "https://www.google.com";
mWebView.setWebViewClient(new WebViewClient() {
...
#Override
public void onPageFinished(WebView view, String url) {
if (url.equals(ENTRY_URL)) {
String keyword = "tistory";
String script = "javascript:function afterLoad() {"
+ "document.getElementById('keyword').value = '" + keyword + "';"
+ "document.forms[0].setAttribute('onsubmit', 'window.Zeany.justDoIt(elements[0].value); return true;');"
+ "};"
+ "afterLoad();";
view.loadUrl(script);
}
}
}
when I call method (mwebview.load("https://www.google.com")), I want to load only html file. Beacuse of Download Speed
I need only html, not css,png. when download all resources, webview load speed is too slow.
I really want to get only html. How to I achieve this goal?
Using this code you should be able to do that.
WebSettings settings = webview.getSettings();
settings.setBlockNetworkLoads(true);
settings.setBlockNetworkImage(true);
settings.setJavaScriptEnabled(false);
I am using an android WebView and I want to load webpage on my android device but display only some parts of webpage, not the whole page.
Is this possible?
I think what you want to do is remove some content from your HTML page and then display it in the WebView. This is possible via javascript so just before you display the page add some javascript code that will remove the elements you don't want.
LIKE
final WebView mWebView = (WebView) findViewById(R.id.mWebViewId);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url)
{
mWebView.loadUrl("javascript:(function() { " +
"document.getElementById('tableid')[0].style.display='none'; " +
"})()");
}
});
mWebView.loadUrl(youUrl);
Just replace document.getElementsByTagName('tableid') with document.getElementsByTagName('theElementYouWantToRemove') for every element and you're set. Original solution can be found at Display a part of the webpage on the webview android
for those who still looking for a solution:
WebView webView = findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url)
{
mWebView.loadUrl("javascript:(function() { " +
"document.getElementsByClassName('className1')[0].remove();
document.getElementsByClassName('className2')[0].remove();
document.getElementsByClassName('className3')[0].remove();" +
"})()");
}
});
webView.loadUrl(url);
In Kotlin in this way:
view.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView, url: String) {
view.loadUrl(
"javascript:(function() { " +
"var head = document.getElementsByClassName('header')[0].style.display='true'; " +
"var head = document.getElementsByClassName('art-bnr')[0].style.display='none'; " +
"var head = document.getElementsByClassName('container-box')[0].style.display='none'; " +
"var head = document.getElementsByClassName('blog-sidebar')[0].style.display='none'; " +
"var head = document.getElementsByClassName('footer-container')[0].style.display='none'; " +
"})()"
) } }
view.loadUrl(url)
I am making an application which uses Android WebView. This application displays page title and page description of the URL that is loaded. As a sample I am using following url
http://in.news.yahoo.com/ca-chief-slams-racist-comments-over-fawad-ahmeds-071749766.html?.tsrc=yahoo
Getting page title is easy
public void onPageFinished (WebView view, String url) {
String title = view.getTitle();
}
If you do a view source of the above url in Chrome, this title is fetched from
<title>CA chief slams `racist` comments over Fawad Ahmed's `beer-branded kit` refusal - Yahoo! News India</title>
Now, I need to get meta name "description", so as to show page description, which is as given below
<meta name="description" lang="en-IN" content="'CA chief slams `racist` comments over Fawad Ahmed's `beer-branded kit` refusal' on Yahoo! News India. Islamabad, Sept 5 (ANI): Cricket Australia (CA) chief James Sutherland has slammed 'racist comments' aimed at Pakistan-born Australian leg-spinner Fawad Ahmed following his refusal to wear a kit displaying the logo of beer brand VB due to 'religious reasons'."/>
Android web view doesn't have an API to get description from meta tag "description".
How is it possible to get meta tags from document element?
You can solve the problem by this way:
private class JsInterface {
#JavascriptInterface
#SuppressWarnings("unused")
public void processHTML(String content) {
//handle content
}
}
mWebView.addJavascriptInterface(new JsInterface(), "CC_FUND");
mWebView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
mWebView.loadUrl("javascript:window.CC_FUND.processHTML( (function (){var metas = document.getElementsByTagName('meta'); \n" +
"\n" +
" for (var i=0; i<metas.length; i++) { \n" +
" if (metas[i].getAttribute(\"name\") == \"description\") { \n" +
" return metas[i].getAttribute(\"content\"); \n" +
" } \n" +
" } \n" +
"\n" +
" return \"\";})() );");
super.onPageFinished(view, url);
}
}
I think what you are looking for is String.contains("meta name=\"description\"").
That would be the easiest method anyway. You could probably piece together a result from the code in how to get html content from a webview?
Another way would be to use the WebView.addJavascriptInterface() to insert the code from murala's answer, but I'm not sure how you would retrieve the result. Use my first idea.
Kotlin code:
if you use evaluateJavascript then not need to define javascriptInterface.
call evaluateJavascript then use ValueCallback<String> resultCallback callback value.
webview.evaluateJavascript(
"""
function getOGPImageUrl(){
var metas = document.getElementsByTagName('meta');
for (var i=0; i<metas.length; i++) {
if (metas[i].getAttribute("property") == "og:image") {
return metas[i].getAttribute("content");
}
}
return "";
};
getOGPImageUrl();
""".trimIndent()) {
// this is ValueCallback block
Logger.d("getOGPImageUrl: $it")
}
document.getElementsByName("title"); returns a set of elements not a single element so within a cycle you could use element.tagName to get the tag
basicly
document.getElementsByName("title")[0].tagName should work
(or)
Just use something like :
var author = $('meta[name=author]').attr("content");
I am try to show epub book in android pad. I can parse the html and css, in order to show the book's content and format, perhaps the book include pictures, It seems that I have two option:
use Webview.
Write a customer view, so that it can render html/css --- it seems a very complicated task.
Which is the good way? If I have to use WebView, how about the page break logic, since webview parse one html file in one page, I can not find the page break in webview.
I have developed a native epub player for android and ios
Code I shared here is part of my product source code, copying and pasting of it will not work for you. Consider it as reference.
I have used webview in android and uiwebview in ios making custom view and parsing html/css is almost like developing a new rendering engine (i.e browser).Its a tedious and complex.
Briefly I give you the steps I have followed for android
Create a custom webview
load url and write call back clients (WebViewClient,WebChromeClient)
after webview load do pagination using below method
Code:
private class MyWebClient extends WebViewClient
{
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
#Override
public void onPageFinished(WebView view, String url)
{
super.onPageFinished(view, url);
final MyWebView myWebView = (MyWebView) view;
String varMySheet = "var mySheet = document.styleSheets[0];";
String addCSSRule = "function addCSSRule(selector, newRule) {"
+ "ruleIndex = mySheet.cssRules.length;"
+ "mySheet.insertRule(selector + '{' + newRule + ';}', ruleIndex);"
+ "}";
String insertRule1 = "addCSSRule('html', 'padding: 0px; height: "
+ (myWebView.getMeasuredHeight()/getContext().getResources().getDisplayMetrics().density )
+ "px; -webkit-column-gap: 0px; -webkit-column-width: "
+ myWebView.getMeasuredWidth() + "px;')";
myWebView.loadUrl("javascript:" + varMySheet);
myWebView.loadUrl("javascript:" + addCSSRule);
myWebView.loadUrl("javascript:" + insertRule1);
}
}
private class MyWebChromeClient extends WebChromeClient
{
#Override
public void onProgressChanged(WebView view, int newProgress)
{
super.onProgressChanged(view, newProgress);
// GlobalConstants.ENABLE_WEB_VIEW_TOUCH = false;
if(newProgress == 100)
{
postDelayed(new Runnable()
{
#Override
public void run()
{
calculateNoOfPages();
}
},300);
}
}
}
private void calculateNoOfPages()
{
if(getMeasuredWidth() != 0)
{
int newPageCount = computeHorizontalScrollRange()/getMeasuredWidth();
}
}
Inject jquery.js into webview:
private void addJQueryJS()
{
String path = "file:///android_asset/JSLibraries/jquery.min.js";
String data = "{\"MethodName\":\"onJQueryJSLoaded\",\"MethodArguments\":{}}";
String callBackToNative = " jsInterface.callNativeMethod('jstoobjc:"+data+"');";
String script = "function includeJSFile()"
+"{"
+"function loadScript(url, callback)"
+"{"
+"var script = document.createElement('script');"
+"script.type = 'text/javascript';"
+"script.onload = function () {"
+"callback();"
+"};"
+"script.src = url;"
+"if(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0])"
+"{"
+"(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(script);"
+"}"
+"else { callback(); }"
+"}"
+"loadScript('"+path+"', function ()"
+"{"
+callBackToNative
+"});"
+"} ; includeJSFile();";
loadUrl("javascript: "+script);
}
wrap all words into spans - used for highlighting text and navigating to a page.
there would be 3 webviews - current page ,next page and previous page.You should set offset to webview scroll according to page count of that chapter.
lets say one .html file has content of 3 pages - previous webview is first page,current webview is second page,next webview is third page but all webviews loaded the same url.But their content offset is different.
write you own page swiping logic instead of using viewpager.Just pass the current page to the adapter then adapter will return you the next page and previous page.by some calculations.
Code:
#Override
public PageView getPreviousView(PageView oldPage)
{
MyWebView oldWebView = ((PageView)oldPage).getWebView();
int chapterIndex = oldWebView.getData().getIndexOfChapter();
int pageIndex = oldWebView.getData().getIndexOfPage();
int pageCount = oldWebView.getData().getChapterVO().getPageCount();
pageIndex--;
if(pageIndex < 0)
{
pageIndex = 0;
chapterIndex--;
if(chapterIndex<0)
{
//return the same page
chapterIndex = 0;
return null;
}
else
{
//previous chapter last page
PageView pageView = new PageView(oldPage.getContext(),_mViewPager);
MyWebView webView= pageView.getWebView();
PageVO data = new PageVO();
data.setChapterVO(_chaptersColl.get(chapterIndex));
data.setIndexOfChapter(chapterIndex);
data.setIndexOfPage(-2);
webView.setData(data);
return pageView;
}
}
else if(pageIndex <= pageCount-1)
{
//same chapter previous page
PageView pageView = new PageView(oldPage.getContext(),_mViewPager);
MyWebView webView= pageView.getWebView();
PageVO data = new PageVO();
data.setChapterVO(_chaptersColl.get(chapterIndex));
data.setIndexOfChapter(chapterIndex);
data.setIndexOfPage(pageIndex);
webView.setData(data);
return pageView;
}
return oldPage;
}
#Override
public PageView getNextView(PageView oldPage)
{
MyWebView oldWebView = ((PageView)oldPage).getWebView();
int chapterIndex = oldWebView.getData().getIndexOfChapter();
int pageIndex = oldWebView.getData().getIndexOfPage();
int pageCount = oldWebView.getData().getChapterVO().getPageCount();
pageIndex++;
if(pageIndex>=pageCount)
{
pageIndex=0;
chapterIndex++;
if(chapterIndex>=_chaptersColl.size())
{
//end of the chapters and pages so return the same page
chapterIndex--;
return null;
}
else
{
//next chapter first page
PageView pageView = new PageView(oldPage.getContext(),_mViewPager);
MyWebView webView= pageView.getWebView();
PageVO data = new PageVO();
data.setChapterVO(_chaptersColl.get(chapterIndex));
data.setIndexOfChapter(chapterIndex);
data.setIndexOfPage(pageIndex);
webView.setData(data);
return pageView;
}
}
else
{
//next page in same chapter
PageView pageView = new PageView(oldPage.getContext(),_mViewPager);
MyWebView webView= pageView.getWebView();
PageVO data = new PageVO();
data.setChapterVO(_chaptersColl.get(chapterIndex));
data.setIndexOfChapter(chapterIndex);
data.setIndexOfPage(pageIndex);
//data.setPageCount(pageCount);
webView.setData(data);
return pageView;
}
}
No need to use any third party libs .Just need to spend good amount of time to write every thing your own.
Nice One, But in Question... :-)
I don't think any Page Break logic for android webview is available, As per your concern WebView is the good choice to display .epub file (You can add many functionality like, highlight, search, bookmark etc..). And If you found that one then what about if device size is changed. What I am doing is, I just display WebPage in webview and disable scroll, Then I can find the max height of webview, and device screen size (Height and width), Now I have put two buttons for next and previous pages, which just scroll page according to height of device size..
Something easy.. Try this if you want to... (This is my personal opinion may be I am wrong on this)
There's this javascript library that takes care of the pagination issue
http://monocle.inventivelabs.com.au/
This project uses it in android
https://github.com/sharathpuranik/chaek-android
Grab the sourcecode and take a look.