Access Meta Data from android WebView - android

How to access Meta Data of a HTML page loaded into a WebView in Android?
I search for hours stackoverflow.com and google and I coudn't find any answer.
I only could get url and title by this code:
webView.getTitle();
webView.getUrl();
Dose is it imposible and webview not support it?

Don't open the URL in the WebView.
First. open an HttpURLConnection to the URL. Read the output from the server and you can scan through the server response to find your meta data.
As you are reading the server output, write the data into a buffer, then use loadData instead of loadUrl to display the buffered data in the WebView

You can solve the problem by this easy 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);
}
}

If its your own web page then you can pass the meta description or any text to your app using the below code:
public class WebAppInterface {
#JavascriptInterface
public void setDesc(String desc) {
mDescription = desc;
}
}
Then add JS interface to WebView:
webView.addJavascriptInterface(new WebAppInterface(), "Android");
Finally, add the following code in your webpage:
<script type="text/javascript">
Android.setDesc("Your meta tag desc here");
</script>
Read more at https://developer.android.com/guide/webapps/webview.html

Related

WebView not posting/loading correctly

I have this piece of WebView code which should login to a website and then load a certain page of that website.
webView = (WebView) findViewById(R.id.recording_web_view);
Bundle b = getIntent().getExtras();
String filename = b.getString("filename");
SettingsManager setman = SettingsManager.getInstance(getBaseContext());
//Login to webinterface before we can watch the recording
String postData = "username=" + setman.getUserName() + "&password=" + setman.getPassword();
//This is the section of code that fixes redirects to external apps
webView.setWebViewClient(new WebViewClient(){
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url){
return false;
}
});
//Post login to get session
webView.postUrl("http://" + setman.getIp() + "/login", EncodingUtils.getBytes(postData, "BASE64"));
//Load actual recording
webView.loadUrl("http://" + setman.getIp() + "/movies/" + filename);
And when I run this I just get the login page, and the server says it received no postdata. However, when I remove the loadUrl line it does receive the login data and load the page after the login.
Can anyone tell me what I am doing wrong? Thanks
Try use in WebViewClient:
#Override
public void onPageFinished( WebView view, String url)
{
view.loadUrl( "http://" + setman.getIp() + "/movies/" + filename);
}
Also you can check error of request:
#Override
public void onReceivedError( WebView view, int errorCode, String description, String failingUrl)
Enable the the JavaScript
webView.getSettings().setJavaScriptEnabled(
true);

Android: Viewing pdf in Webview using GoogleDocs

I am trying to open pdf links in my webview using Google Docs. The Webview initially accepts the url but in log cat i notice that at some point the url changes to "about:blank" and in the end it load only a blank page.
I have also overriden onPageStarted and onPageFinished methods and noticed that when shouldOvverideUrlLoading is called the second time by the WebView it changes the url to "about:blank"
Any thoughts on why this happens?
#Override
public boolean shouldOverrideUrlLoading(String url) {
getView().loadWebview(url);
}
#Override
public void loadWebview(String url) {
String pdfSuffix = ".pdf";
String googleDocsUrl = "http://docs.google.com/viewer?url=" + url;
if (url.endsWith(pdfSuffix)) {
Logger.i(LOG_TAG, "pdf loadwebview: url= " + googleDocsUrl);
mView.loadUrl(googleDocsUrl);
} else {
Logger.i(LOG_TAG, "loadwebview: url= " + url);
mView.loadUrl(url);
}
}

How to capture http post data from Android WebView [duplicate]

I've started to write an app which provides the user with an HTML form via a WebView. As the form is not under my control, the data filled in may be sent as either GET or POST request. My app is required to capture the transported form data, that is, get a hold on what was entered into the form fields.
Using an adequate callback from WebViewClient such as onPageLoaded(), it is easy to capture form data from a GET request. However, I cannot find any appropriate method to allow the same for POSTed data, i.e., be able to access the HTTP POST message body containing the form data. Am I missing a relevant callback here or is there simply no way to accomplish the specified goal with the given API (even the latest level 8)?
Assuming it wasn't possible, I considered overriding and extending parts of android.webkit in order to introduce a new callback hook that is passed the POST body somehow. That way, my app could be shipped with a customized browser/WebViewClient that fulfills the desired feature. However, I couldn't find any good spot to start with in the code and would be glad for any hints in this regards (in case the approach looks promising at all).
Thanks in advance!
As indicated in my own comment to the original question, the JavaScript injection approach works. Basically, what you need to do is add some piece of JavaScript code to the DOM onsubmit event, have it parse the form's fields, and return the result back to a Java-registered function.
Code example:
public class MyBrowser extends Activity {
private final String jsInjectCode =
"function parseForm(event) {" +
" var form = this;" +
" // make sure form points to the surrounding form object if a custom button was used" +
" if (this.tagName.toLowerCase() != 'form')" +
" form = this.form;" +
" var data = '';" +
" if (!form.method) form.method = 'get';" +
" data += 'method=' + form.method;" +
" data += '&action=' + form.action;" +
" var inputs = document.forms[0].getElementsByTagName('input');" +
" for (var i = 0; i < inputs.length; i++) {" +
" var field = inputs[i];" +
" if (field.type != 'submit' && field.type != 'reset' && field.type != 'button')" +
" data += '&' + field.name + '=' + field.value;" +
" }" +
" HTMLOUT.processFormData(data);" +
"}" +
"" +
"for (var form_idx = 0; form_idx < document.forms.length; ++form_idx)" +
" document.forms[form_idx].addEventListener('submit', parseForm, false);" +
"var inputs = document.getElementsByTagName('input');" +
"for (var i = 0; i < inputs.length; i++) {" +
" if (inputs[i].getAttribute('type') == 'button')" +
" inputs[i].addEventListener('click', parseForm, false);" +
"}" +
"";
class JavaScriptInterface {
#JavascriptInterface
public void processFormData(String formData) {
//added annotation for API > 17 to make it work
<do whatever you need to do with the form data>
}
}
onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.browser);
WebView browser = (WebView)findViewById(R.id.browser_window);
browser.getSettings().setJavaScriptEnabled(true);
browser.addJavascriptInterface(new JavaScriptInterface(), "HTMLOUT");
browser.setWebViewClient(new 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:(function() { " +
MyBrowser.jsInjectCode + "})()");
}
}
Informally, what this does is inject the custom JavaScript code (as a onsubmit handler) whenever a page finishes loading. On submission of a form, Javascript will parse the form data and pass it back to Java land through the JavaScriptInterface object.
In order to parse form fields, the Javascript code adds form onsubmit and button onclick handlers. The former can handle canonical form submissions through a regular submit button while the latter deals with custom submit buttons, i.e., buttons that do some additional Javascript magic before calling form.submit().
Please be aware that the Javascript code may not be perfect: There might be other methods to submit a form that my injected code may not be able to catch. However, I'm convinced that the injected code can be updated to deal with such possibilities.
The provided answer gives error so I decided to make a simpler implementation which also featured well structured JavaScript (meaning JS is in a file):
In your assets folder create a file called inject.js with following code inside:
document.getElementsByTagName('form')[0].onsubmit = function () {
var objPWD, objAccount, objSave;
var str = '';
var inputs = document.getElementsByTagName('input');
for (var i = 0; i < inputs.length; i++) {
if (inputs[i].name.toLowerCase() === 'username') {
objAccount = inputs[i];
} else if (inputs[i].name.toLowerCase() === 'password') {
objPWD = inputs[i];
} else if (inputs[i].name.toLowerCase() === 'rememberlogin') {
objSave = inputs[i];
}
}
if(objAccount != null) {
str += objAccount.value;
}
if(objPWD != null) {
str += ' , ' + objPWD.value;
}
if(objSave != null) {
str += ' , ' + objSave.value;
}
window.AndroidInterface.processHTML(str);
return true;
};
This is the javascript code we'll use for injections, you can switch out the if statements as you see fit and use types instead or names.The callback to Android is this line: window.AndroidInterface.processHTML(str);
Then your Activity/fragment should look like this:
public class MainActivity extends ActionBarActivity {
class JavaScriptInterface {
#JavascriptInterface
public void processHTML(String formData) {
Log.d("AWESOME_TAG", "form data: " + formData);
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WebView webView = new WebView(this);
this.setContentView(webView);
// enable javascript
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webView.addJavascriptInterface(new JavaScriptInterface(), "AndroidInterface");
// catch events
webView.setWebViewClient(new WebViewClient(){
#Override
public void onPageFinished(WebView view, String url) {
try {
view.loadUrl("javascript:" + buildInjection());
} catch (IOException e) {
e.printStackTrace();
}
}
});
webView.loadUrl("http://someurl.com");
}
private String buildInjection() throws IOException {
StringBuilder buf = new StringBuilder();
InputStream inject = getAssets().open("inject.js");// file from assets
BufferedReader in = new BufferedReader(new InputStreamReader(inject, "UTF-8"));
String str;
while ((str = in.readLine()) != null) {
buf.append(str);
}
in.close();
return buf.toString();
}

How to embed a custom font to Android app (WebView)

I want to embed a custom font into my android app. I don't use TextView so such tutorials as this one (How to use custom font with TextView) do not help.
In my case, the content is taken from the SQLite database and shown on the screen using WebView. I don't either use bundled HTML files so this tutorial (How to use custom font with WebView) does not solve my problem, either.
FIY, here is my code:
public void initWebview()
{
WebSettings settings = wvContent.getSettings();
settings.setDefaultTextEncodingName("utf-8");
setContentView(R.layout.content);
wvContent = (WebView) findViewById(R.id.wvContent);
wvContent.setBackgroundColor(Color.argb(250, 250, 250, 250));
wvContent.getSettings().setSupportZoom(true);
wvContent.getSettings().setBuiltInZoomControls(true);
wvContent.setInitialScale(100);
wvContent.setWebViewClient(new WebViewClient()
{
public void onPageFinished(WebView view, String url)
{
if (pd != null)
{
pd.dismiss();
pd = null;
}
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
Log.i(CONTENT_TAG,"WebView link clicked; url = " + url);
try
{
String arrUrlPart[] = url.split("://");
if (arrUrlPart[0].equals("entry"))
{
String content = getContentByWord(arrUrlPart[1]);
showContent(content);
}
else if (arrUrlPart[0].equals("http"))
{
try {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
} catch (Exception ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
}
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
return true;
}
});
}
The font stored in assets/fonts seems to be embedded into the app, and my questions are:
How can I programmatically do to "force" my app to use this font?
Are there any solutions to my problem?
Thank you very much.
From the comments in this reply, a possible solution seems to be to use loadDataWithBaseURL while providing the assets folder as the base url, i.e.
LoadData() does not work, but
webView.loadDataWithBaseURL("file:///android_asset/",... works fine.
Then also font file reference as "/fonts/MyFont.otf" should work. –
JaakL Dec 1 '11 at 16:59
I assume bundling your font is not a problem, right?
[Edit] To clarify my answer, I've composed a little example. In the code below, I've put the Quicksand_Dash.otf in assets/fonts, and twitter_logo.png straight into assets. The HTML is simply a string constant, but you'd retrieve it from your SQLLite database. The essence is really just to use loadDataWithBaseURL()....
package oh.jolly.webview;
import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;
public class WebviewTestActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
WebView webView = (WebView) findViewById(R.id.webview);
webView.loadDataWithBaseURL("file:///android_asset/", PAGE_HTML, "text/html", "UTF-8", "null" );
}
private final static String PAGE_HTML =
"<html>\n" +
" <style type=\"text/css\"> \n" +
" #font-face { \n" +
" font-family: MyFont; \n" +
" src: url(\"file:///android_asset/fonts/Quicksand_Dash.otf\") \n" +
" } \n" +
" body { \n" +
" font-family: MyFont; \n" +
" font-size: medium; \n" +
" text-align: justify; \n" +
" } \n" +
" </style> \n" +
" <body>\n" +
" I've got a sinking feeling...<br>\n" +
" <img src=\"file:///android_asset/twitter_logo.png\" />\n" +
" </body>\n" +
"</html>";
}
Please check below links ... i think its useful
How to change font face of Webview in Android?
How to use custom font with WebView
Set your custom font on html header and set your content in html body. so all content display as per your embed font in webview...

is it possible to access HTML form data POSTed through a WebView?

I've started to write an app which provides the user with an HTML form via a WebView. As the form is not under my control, the data filled in may be sent as either GET or POST request. My app is required to capture the transported form data, that is, get a hold on what was entered into the form fields.
Using an adequate callback from WebViewClient such as onPageLoaded(), it is easy to capture form data from a GET request. However, I cannot find any appropriate method to allow the same for POSTed data, i.e., be able to access the HTTP POST message body containing the form data. Am I missing a relevant callback here or is there simply no way to accomplish the specified goal with the given API (even the latest level 8)?
Assuming it wasn't possible, I considered overriding and extending parts of android.webkit in order to introduce a new callback hook that is passed the POST body somehow. That way, my app could be shipped with a customized browser/WebViewClient that fulfills the desired feature. However, I couldn't find any good spot to start with in the code and would be glad for any hints in this regards (in case the approach looks promising at all).
Thanks in advance!
As indicated in my own comment to the original question, the JavaScript injection approach works. Basically, what you need to do is add some piece of JavaScript code to the DOM onsubmit event, have it parse the form's fields, and return the result back to a Java-registered function.
Code example:
public class MyBrowser extends Activity {
private final String jsInjectCode =
"function parseForm(event) {" +
" var form = this;" +
" // make sure form points to the surrounding form object if a custom button was used" +
" if (this.tagName.toLowerCase() != 'form')" +
" form = this.form;" +
" var data = '';" +
" if (!form.method) form.method = 'get';" +
" data += 'method=' + form.method;" +
" data += '&action=' + form.action;" +
" var inputs = document.forms[0].getElementsByTagName('input');" +
" for (var i = 0; i < inputs.length; i++) {" +
" var field = inputs[i];" +
" if (field.type != 'submit' && field.type != 'reset' && field.type != 'button')" +
" data += '&' + field.name + '=' + field.value;" +
" }" +
" HTMLOUT.processFormData(data);" +
"}" +
"" +
"for (var form_idx = 0; form_idx < document.forms.length; ++form_idx)" +
" document.forms[form_idx].addEventListener('submit', parseForm, false);" +
"var inputs = document.getElementsByTagName('input');" +
"for (var i = 0; i < inputs.length; i++) {" +
" if (inputs[i].getAttribute('type') == 'button')" +
" inputs[i].addEventListener('click', parseForm, false);" +
"}" +
"";
class JavaScriptInterface {
#JavascriptInterface
public void processFormData(String formData) {
//added annotation for API > 17 to make it work
<do whatever you need to do with the form data>
}
}
onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.browser);
WebView browser = (WebView)findViewById(R.id.browser_window);
browser.getSettings().setJavaScriptEnabled(true);
browser.addJavascriptInterface(new JavaScriptInterface(), "HTMLOUT");
browser.setWebViewClient(new 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:(function() { " +
MyBrowser.jsInjectCode + "})()");
}
}
Informally, what this does is inject the custom JavaScript code (as a onsubmit handler) whenever a page finishes loading. On submission of a form, Javascript will parse the form data and pass it back to Java land through the JavaScriptInterface object.
In order to parse form fields, the Javascript code adds form onsubmit and button onclick handlers. The former can handle canonical form submissions through a regular submit button while the latter deals with custom submit buttons, i.e., buttons that do some additional Javascript magic before calling form.submit().
Please be aware that the Javascript code may not be perfect: There might be other methods to submit a form that my injected code may not be able to catch. However, I'm convinced that the injected code can be updated to deal with such possibilities.
The provided answer gives error so I decided to make a simpler implementation which also featured well structured JavaScript (meaning JS is in a file):
In your assets folder create a file called inject.js with following code inside:
document.getElementsByTagName('form')[0].onsubmit = function () {
var objPWD, objAccount, objSave;
var str = '';
var inputs = document.getElementsByTagName('input');
for (var i = 0; i < inputs.length; i++) {
if (inputs[i].name.toLowerCase() === 'username') {
objAccount = inputs[i];
} else if (inputs[i].name.toLowerCase() === 'password') {
objPWD = inputs[i];
} else if (inputs[i].name.toLowerCase() === 'rememberlogin') {
objSave = inputs[i];
}
}
if(objAccount != null) {
str += objAccount.value;
}
if(objPWD != null) {
str += ' , ' + objPWD.value;
}
if(objSave != null) {
str += ' , ' + objSave.value;
}
window.AndroidInterface.processHTML(str);
return true;
};
This is the javascript code we'll use for injections, you can switch out the if statements as you see fit and use types instead or names.The callback to Android is this line: window.AndroidInterface.processHTML(str);
Then your Activity/fragment should look like this:
public class MainActivity extends ActionBarActivity {
class JavaScriptInterface {
#JavascriptInterface
public void processHTML(String formData) {
Log.d("AWESOME_TAG", "form data: " + formData);
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WebView webView = new WebView(this);
this.setContentView(webView);
// enable javascript
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webView.addJavascriptInterface(new JavaScriptInterface(), "AndroidInterface");
// catch events
webView.setWebViewClient(new WebViewClient(){
#Override
public void onPageFinished(WebView view, String url) {
try {
view.loadUrl("javascript:" + buildInjection());
} catch (IOException e) {
e.printStackTrace();
}
}
});
webView.loadUrl("http://someurl.com");
}
private String buildInjection() throws IOException {
StringBuilder buf = new StringBuilder();
InputStream inject = getAssets().open("inject.js");// file from assets
BufferedReader in = new BufferedReader(new InputStreamReader(inject, "UTF-8"));
String str;
while ((str = in.readLine()) != null) {
buf.append(str);
}
in.close();
return buf.toString();
}

Categories

Resources