Get JSON from a div in html - android

I have a hidden div which by JavaScript gets filled with json text. I need to find this div and read the json text from it. How can this be done?
<html>
<div id="hiddenJSON">
{
"id":"1234",
"Name":"Jonas",
"Address":"Test Road 5",
"Phone":"1234-1234-1234"
}
</div>
</html>

try below code :-
Pattern p = Pattern.compile(Pattern.quote("<div id=\"hiddenJSON\">") + "(.*?)" + Pattern.quote("</div>"));
Matcher m = p.matcher(text);
while (m.find()) {
System.out.println(m.group(1));
}
But better solution is you have to receive data without html tag so talk with back end person.

It would be best to use a library for this such as JSoup. Check out this question about parsing html code

Here is how i solved this:
result is the response from #JavascriptInterface
WebView Fragment
WebView wv = ...
wv.addJavascriptInterface( this, "android" );
wv.loadUrl( "javascript:android.showHTML(document.getElementById('hiddenJSON').innerHTML);" );
Interface in my WebView Fragment
#JavascriptInterface
public void showHTML( String result ) {
// handle JSON (result)
}
Problem:
I had to get the result from my WebView in order to get the JavaScript to run (filling this hidden div with JSON).

Related

How to set font size and text color in WebView?

I'm developing an Android application in which I have used an HTML file for help contents. I have used a WebView to display the content and every thing is fine.
The problem is that user can change the theme and font size of the application. How can I propagate these properties to the content of WebView? Exactly how can I change the font size and text color in WebView? Is there a simple way to do that or I should create different HTMLfiles or CSSes? How to handle the size units (dp, sp, ...)?
I will appreciate your help with this situation.
loadUrl("javascript:(document.body.style.backgroundColor ='red');");
loadUrl("javascript:(document.body.style.fontSize ='20pt');");loadUrl("javascript:(document.body.style.color ='yellow');");
On your android application, use following code to load a web page with user chosen font size and color:
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.setWebChromeClient(new InredisChromeClient(this));
myWebView.setWebViewClient(new InredisWebViewClient(this));
myWebView.clearCache(true);
myWebView.clearHistory();
myWebView.getSettings().setJavaScriptEnabled(true);
myWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
myWebView.loadUrl("http://demo.com/content.html?font-size=12&fontcolor=blue");
On the content.html page, enable JavaScript and use jQuery and its function as below:
function getCssValue(sCSS)
{
var sPageURL = window.location.search.substring(1);
var sValues = sPageURL.split('&');
for (var i = 0; i < sValues.length; i++)
{
var sPair = sValues[i].split('=');
if (sPair[0] == sCSS)
{
return sPair[1];
}
}
}
$(document).ready(function(){
// Set the Font Size from URL
$('html').css('font-size', getCssValue('font-size'));
});
It is best to do theme activities using CSS and Javascript. However if we want to pass on some settings from Android to the WebView dynamically, it is possible and a solution is to use the JavascriptInterface. Here is one way of doing it:
Firstly, we define a class which will be used as a bridge between the Android app and the WebView for JS interactions.
Here WebInterface is an inner class in the Activity and hence it has direct access to myWebView, which is a WebView instance variable.
public class WebInterface {
private Activity activity;
public WebInterface(Activity activiy) {
this.activity = activiy;
}
#JavascriptInterface
public void changeTheme() {
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
// All of the theme settings could go here, the settings passed on by Android
myWebView.loadUrl("javascript:document.body.style.backgroundColor ='red';");
myWebView.loadUrl("javascript:document.body.style.fontSize ='20pt'");
myWebView.loadUrl("javascript:document.body.style.color ='yellow';");
//OR load your data as shown here http://stackoverflow.com/a/7736654/891092
htmlData = "<link rel=\"stylesheet\" type=\"text/css\" href=\"theme.css\" />" + htmlData;
// lets assume we have /assets/theme.css file
myWebView.loadDataWithBaseURL("file:///android_asset/", htmlData, "text/html", "UTF-8", null);
}
});
}
}
Note that it is very important to run your code in UI Thread otherwise it will not work.
Here is how the Activity registers the WebView with the JavascriptInterface:
myWebView.getSettings().setJavaScriptEnabled(true);
myWebView.addJavascriptInterface(jsInterface, "JSInterface");
In the HTML file, which the user is viewing, a button or widget could be made to change theme by calling code in Android through the bridge:
<input type="button" value="Say hello" onClick="doChangeTest()" />
<script type="text/javascript">
function doChangeTest(){
JSInterface.changeTheme(); // this calls the changeTheme in WebInterface
}
</script>
First you need to define a webView and after that use below method.
lightFont is your font that you should store in asset folder.
color is your text color.
font size : you can change font size.(for example 20px or medium and etc).
at the end you need to use seconde method to show html on webView
First Method:
public static String getStyledFont(String html) {
boolean addBodyStart = !html.toLowerCase().contains("<body>");
boolean addBodyEnd = !html.toLowerCase().contains("</body");
return "<style type=\"text/css\">" +
"#font-face {font-family: CustomFont;" +
"src: url(\"file:///android_asset/lightFont.ttf\")}" +
"body {color: #787878;}"+
"body {font-family: CustomFont;font-size: x-small;}</style>" +
(addBodyStart ? "<body>" : "") + html +(addBodyEnd ? "</body>" : "");
}
Second method:
String htmlText = getStyledFont(yourText);
webView.loadDataWithBaseURL("file:///android_asset/",
htmlText ,
"text/html; charset=UTF-8", null, null);

TagHandler to handle Youtube tag <iframe>?

I'm parsing html using Html.fromHtml(). My problem is that my html text has youtube embeded links (basically <iframe> tags)
So, since Html class does NOT support <iframe> tag, I need to define my own TagHandler to handle it. What I'm trying to do is to convert the <iframe> to a regular <a> tag so that it can be rendered correctly.
//convert this
<iframe src="http://www.youtube.com/embed/xAEdMI2ZE88" frameborder="0" width="560" height="315"></iframe>
//To this
Click to Watch
My problem is that I couldn't find a way to get the src link of the youtube from the <iframe> tag.
Here is my TagHandler's handleTag() method:
#Override
public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) {
if (tag.equals("iframe")) {
if(opening) {
output.append("<a href=");
//How to get YouTube video link and append it?
}
else {
output.append("Click To Watch</a>");
}
}
}
Thanks in advance.
You can also use this regex.
htmlString.replaceAll("<iframe\\s+.*?\\s+src=(\".*?\").*?<\\/iframe>", "<a href=$1>CLICK TO WATCH</a>");
I, for now, took CommonsWare advice and modify the String before passing it to Html.fromHtml.
//Opening tag
Pattern p = Pattern.compile("<iframe src");
Matcher m = p.matcher(htmlString);
while (m.find())
htmlString= m.replaceAll("<a href");
//Closing tag
p = Pattern.compile("frameborder=.*</iframe>");
m = p.matcher(htmlString);
while (m.find())
htmlString= m.replaceAll(">CLICK TO WATCH</a>");

How to pass parameter into HTML file from android

I can show up HTML file content in android webview well.Now how could i pass parameter into HTML file.For ex.my HTML content has an video player
i need to pass dynamic values(URL) into HTML file for playing dynamic video.My HTML file is located on asset folder.How could i do this?
Thanks.
I came upon this problem today, however I needed this to work with UTF-8 encoding, so this was my approach, hopefully it will help someone and clarify some of the previous answers to this question.
HTML:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<h1>%ERR_TITLE%</h1>
<h2>%ERR_DESC%</h2>
</body>
</html>
Java:
String content = IOUtils.toString(getAssets().open("error.html"))
.replaceAll("%ERR_TITLE%", getString(R.string.error_title))
.replaceAll("%ERR_DESC%", getString(R.string.error_desc))
mWebView.loadDataWithBaseURL("file:///android_asset/error.html", content, "text/html", "UTF-8", null);
As for IOUtils:
http://commons.apache.org/proper/commons-io/download_io.cgi
Instead of passing directly the video URL (following you example), i would have used tokens in the Html file. For example:
<embed src="$VIDEO_URL$" autostart="false" />
where the $VIDEO_URL$ will be the token wich will be replaced during the runtime with a real video URL.
Also, since you cannot change the contents of your asset folder during runtime you should load the html file contents into a String variable and use the replace method to replace the token with a real URL and, finally, pass that string to your webview. Something like this:
//The html variable has the html contents of the file stored in the assets folder
//and real_video_url string variable has the correct video url
html = html.replace("$VIDEO_URL$", real_video_url);
webview.loadData(html, "text/html", "utf-8");
If i would like to have something dynamic in my HTML i would have an html with dynamic parts written like this:
<B>%NAME%</B>
Then i would load my HTML:
String template = Utils.inputStreamToString(assets.open("html/template.html"));
then
Then i would replace all dynamics parts with what i want like this:
String data = template.replaceAll("%NAME%", "Alice McGee");
then i would pass it to my webView!
WebView webView = new WebView(this);
webView.loadDataWithBaseURL("file:///android_asset/html/", data, "text/html", "utf-8", null);
I managed to pass variables in a different way.
My problem was that everytime I switched to another app, when coming to the webapp, the webview kept reloading. I guess that's because of the following line in my onCreate() method: myWebView.loadUrl(url); I had the idea to pass these state variables in the url, but as you know it is not possible yet.
What I did was to save the state of some variables using onSaveInstanceState(Bundle outState) {...} and restore them with onRestoreInstanceState(Bundle savedInstanceState){...}.
In onCreate method after setting up myWebView I did the following:
myWebView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String urlString)
{
Log.i("onPageFinished", "loadVariables("+newURL+")");
if(newURL!="")
myWebView.loadUrl("javascript:loadVariables("+"\""+newURL+"\")");
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
jsInterface = new JSInterface(this,myWebView);
myWebView.addJavascriptInterface(jsInterface, "Android");
if (savedInstanceState != null)
{
// retrieve saved variables and build a new URL
newURL = "www.yoururl.com";
newURL +="?var1=" + savedInstanceState.getInt("key1");
newURL +="?var2=" + savedInstanceState.getInt("key2");
Log.i("myWebApp","NEW URL = " + newURL);
}
myWebView.loadUrl("www.yoururl.com");
So, what it happens is that first I load the page with the default URL (www.yoururl.com) and onPageFinished I call a new javascript method where I pass the variables.
In javascript loadVariables function looks like this:
function loadVariables(urlString){
// if it is not the default URL
if(urlString!="www.yoururl.com")
{
console.log("loadVariables: " + urlString);
// parse the URL using a javascript url parser (here I use purl.js)
var source = $.url(urlString).attr('source');
var query = $.url(urlString).attr('query');
console.log("URL SOURCE = "+source + " URL QUERY = "+query);
//do something with the variables
}
}
here assets means what?
String template = Utils.inputStreamToString(assets.open("html/template.html"));

Changing HTML in a WebView programmatically

I'm loading an html asset page into a WebView using
webMain.loadUrl("file:///android_asset/record.html");
which works fine, but inside the html are a number of places where I'd like to use information from the app. For instance, the HTML may contain text that reads "[Custom]". Is there a way I can replace that word with information passed from the application?
This is an old and already accepted question, however I am sure that the problem can be solved in more elegant way by using javascript.
Keep the html file in your assets folder and surround the text which you want to replace into with div elements with unique id's.
<html>
<head> ... <head>
<body>
Static text
<div id="replace1">replace me</div>
<div id="replace2">replace me too</div>
More static text ...
</body>
</html>
Now create a javascript function which will replace the innerHtml of a div with an id:
function replace(id, newContent)
{
document.getElementById(id).innerHTML = newContent;
}
This function will be best placed directly in the html file, update the <head> section to look like this:
<head>
...
<script type="text/javascript">
function replace(id, newContent)
{
document.getElementById(id).innerHTML = newContent;
}
</script>
</head>
Now we need to call the javascript function from from the WebView Android api:
WebView helpView = (WebView)findViewById(R.id.helpView);
helpView.getSettings().setJavaScriptEnabled(true);
helpView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
view.loadUrl("javascript:replace('replace1', 'new content 1')");
view.loadUrl("javascript:replace('replace2', 'new content 2')");
}
});
helpView.loadUrl("file:///android_asset/help.html");
Using this you will avoid reading potentially large data into memory and running expensive operations on it unnecessarily.
This is worked for me.
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Payment Demo</title>
</head>
<body>
<div>
<input type="text" id="uname " name="uname " value="">
<input type="text" id="pass" name="pass" value="">
</div>
</body>
</html>
This is java code.
WebView wb = (WebView) findViewById(R.id.webView1);
wb.loadUrl("file:///android_asset/web1.html");
wb.getSettings().setJavaScriptEnabled(true);
wb.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView web, String url) {
// TODO Auto-generated method stub
String uname = "email#mail.com";
String pass = "******";
web.loadUrl("javascript:(function(){document.getElementById('uname').value = '"+uname+"';})()");
web.loadUrl("javascript:(function(){document.getElementById('pass').value = '"+pass+"';})()");
}
});
Actually I do not understand why the file size of record.html will affect maintainence of the code. Read the html string (using Java reader class or what ever) from the html file in asset, use replaceAll function with Regex to replace all the [Custom] in the html file. How long the html is should not really affect how you maintain the code. It should rather be a performance problem, or the string is really really long that exceeds the java String limit.
some code I have used before :
InputStream is = getApplicationContext().getAssets().open("details/product_jsmodify.html");
Reader r = new InputStreamReader(is);
String details = Utils.readertoString(r);
details = details.replace("%product_name%",productName );
Utils is my class doing the conversion to string. I am not using Regex here as I am only replacing word for once. Then I load the string like Cata does. It is quite clean I suppose.
Yes you can do that by loading your page in a String and then load that string in your WebView.
Eg:
String summary = "<html><body>You scored <b>192</b> points.</body></html>";
webview.loadData(summary, "text/html", null);
Taken from here
This one worked for me, with the html along with the text and images.
InputStream is = getAssets().open(html_name);
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
String str = new String(buffer);
str = str.replace("InitialTextToBeReplaced", "TextAfterReplacement");
//Now instead of webview.loadURL(""), I needed to do something like -
webView.loadDataWithBaseURL("file:///android_asset/", str, "text/html", "UTF-8",null);

Jsoup select() return nothing in Android application

I'm making an Android app for my board community. The board provider gives me RSS feeds from general categories but don't generate feeds from topics. So I retreive topics URLs from these feeds and want to parse HTML with Jsoup and give it to a WebView.
It works nice except with the select() function which returns nothing.
The "HTML RETREIVED" log gives me : <html><head><title>The topic title</title></head><body></body></html>
h1 tags are in the code on test purpose : it displays well on WebView and the title of the parsed webpage too.
I also putted the log line right after the select() line. It returns nothing too.
I've tried in a pure Java project to parse with Jsoup only and it goes well.
So I assumed something's wrong with Android.
PS : Internet permission is active in the manifest.
Did I miss something ?
Here is the code :
String html;
Bundle param = this.getIntent().getExtras();
String url = param.getString("url");
try {
Document doc = Jsoup.connect(url).get();
doc.select(".topic .clear").remove();
String title = doc.title().toString();
html = doc.select(".username strong, .entry-content").toString();
html = "<html><head><title>"+title+"</title></head><body><h1>"+title+"</h1>"+html+"</body></html>";
WebView webview = new WebView(this);
getWindow().requestFeature(Window.FEATURE_PROGRESS);
setContentView(webview);
webview.getSettings().setJavaScriptEnabled(true);
final Activity activity = this;
webview.setWebChromeClient(new WebChromeClient() {
public void onProgressChanged(WebView view, int progress) {
activity.setProgress(progress * 1000);
Log.d("LOADING",""+ progress);
}
});
webview.loadData(html, "text/html", "UTF-8");
//webview.loadUrl(url);
Log.i("HTML RETREIVED", ""+html);
} catch (IOException e) {
Log.e("ERROR", "Error while generate topic");
}
Ok I've found out something interesting.
The class I wanted to select was not here because I'm getting the mobile version of the webpage. It appears Android App use a mobile user-agent, which is quite normal but not said anywhere.
Anyway I know what thinking about now.

Categories

Resources