I am developing and anroid apps that will show the coundown of a event.For that I used html,css,and java script,it works fine in normal html.But when I put it in android studio,it shows the html page with WebView but it doesn't add the css ad javascript with it .I put java script and css in the same directory.Here is the code
<html>
<head>
<link type="text/css" rel="stylesheet" href="flipclock.css" />
</head>
<body>
<div class="clock-builder-output"></div>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script type="text/javascript" src="flipclock.js"></script>
<style text="text/css">body .flip-clock-wrapper ul li a div div.inn, body .flip-clock-small-wrapper ul li a div div.inn { color: #CCCCCC; background-color: #333333; } body .flip-clock-dot, body .flip-clock-small-wrapper .flip-clock-dot { background: #323434; } body .flip-clock-wrapper .flip-clock-meridium a, body .flip-clock-small-wrapper .flip-clock-meridium a { color: #323434; }</style>
<script type="text/javascript">
$(function(){
FlipClock.Lang.Custom = { days:'Days', hours:'Hours', minutes:'Minutes', seconds:'Seconds' };
var opts = {
clockFace: 'HourCounter',
countdown: true,
language: 'Custom'
};
var countdown = 1495943700 - ((new Date().getTime())/1000); // from: 05/28/2017 09:55 am +0600
countdown = Math.max(1, countdown);
$('.clock-builder-output').FlipClock(countdown, opts);
});
</script>
</body>
</html>
Here is the WebView
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String url = "file:///android_asset/www/index.html";
WebView view = (WebView)this.findViewById(R.id.webView);
view.getSettings().setJavaScriptEnabled(true);
view.loadUrl(url);
view.setWebViewClient(new MyBrowser());
}
private class MyBrowser extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading (WebView view,String url){
view.loadUrl(url);
return true;
}
}
}
You must have two folders in which your "index" is located. What could happen is that the external is stepping on the internal so you should put the references of javascript and css in the internal. If this does not work try putting the references on the outside.
Greetings.
To load external css and javascript files, you need to use a similar url construction as you did when you loaded in the html url into the webview. So for example, you used:
String url = "file:///android_asset/www/index.html";
as the URL for the file. To load the javascript, assuming it's in the same /asset/www/ directory, you'd say in the HTML:
<script type="text/javascript" src="file:///android_asset/www/flipclock.js"/>
A stylesheet file would be loaded as:
<link rel="stylesheet" type="text/css" href="file:///android_asset/www/myCss.css"/>
As an aside, to run injected javascript on-the-fly on pre-KIT-KAT, use:
webView.loadUrl("javascript:(function(){####JSGOESHERE####})();");
and post-KIT-KAT use:
webView.evaluateJavascript("####JSGOESHERE####", null);
Related
I've read many posts but I can't get my Android app call a Javascript function. This is what I have
public class BorrameActivity extends AppCompatActivity {
private static BorrameActivity.MyJavaScriptInterface myJavaScriptInterface;
private static WebView webView;
public class MyJavaScriptInterface {
Context mContext;
MyJavaScriptInterface(Context c) {
mContext = c;
}
#android.webkit.JavascriptInterface
public void doEchoTest(String echo){
Log.e("printer", echo);
Toast toast = Toast.makeText(mContext, echo, Toast.LENGTH_SHORT);
toast.show();
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_borrame);
myJavaScriptInterface = new BorrameActivity.MyJavaScriptInterface(this);
webView = (WebView) findViewById(R.id.mybrowserAuthorise);
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(myJavaScriptInterface, "JSInterface");
webView.loadUrl("file:///android_asset/loginProtocol.html");
//webView.loadUrl("javascript:JSInterface.doEchoTest('test')"); // THIS WORKS!!
webView.loadUrl("javascript:testEcho()"); // THIS DOES NOT WORK
}
}
This works when I execute
webView.loadUrl("javascript:JSInterface.doEchoTest('test')");
But it doesn't work when the Javascript function is in loginProtocol.html:
webView.loadUrl("javascript:testEcho()");
Where
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width; user-scalable=0;" />
<title></title>
</head>
<body style="visibility:visible">
<!-- Used for debugging -->
<h1>HELLO</h1>
<script>
function testEcho(){
JSInterface.doEchoTest('This does not get printed in Android Log');
}
</script>
</body>
</html>
and
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.sedicii.app.sedicii.BorrameActivity">
<WebView
android:id="#+id/mybrowserAuthorise"
android:layout_width="353dp"
android:layout_height="442dp"/>
</LinearLayout>
The WebView seems to be loading correctly (I can see the HELLO from loginProtocol.html on the Android screen).
What am I missing?
SOLUTION
I have to wait until the HTML page is loaded. Thanks #KosWarm
webView.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
webView.loadUrl("javascript:testEcho()");
}
});
I think you just need to give parameter to your loadUrl method:
webView.loadUrl("javascript:testEcho('Hello World!')");
and your javascript function must look like:
function testEcho(testHello){
window.JSInterface.doEchoTest(testHello);
}
You execute the method loadUrl twice
At the second execution, the first page is closed, so its script can not be executed
The following page code works
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width; user-scalable=0;" />
<title></title>
</head>
<body style="visibility:visible">
<!-- Used for debugging -->
<h1>HELLO</h1>
<script>
function testEcho(){
JSInterface.doEchoTest('This does not get printed in Android Log');
}
testEcho() //added this line
</script>
</body>
</html>
Update
from this place Calling Javascript method from within webview in Android
rewrite Activity onCrete method as
myJavaScriptInterface = new MyJavaScriptInterface(this);
webView = (WebView) findViewById(R.id.mybrowserAuthorise);
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(myJavaScriptInterface, "JSInterface");
webView.loadUrl("file:///android_asset/loginProtocol.html");
webView.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
webView.loadUrl("javascript:testEcho()");
}
});
I am able to get HTML source code using following code. but when I am trying with https://marriott.medallia.com/sso/marriott/homepage.do?v=bnAaQvo3*lVHsqtnwluPh_CMCsIHyFkti&alreftoken=6d0d31c7eb7583b964d0ecb89b55e12b
The page URL is getting changed dynamically and on next generated page when I see source view I only get the following code in the HTML body:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>IdP Selection</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="style.min.css">
</head>
<body>
<div id="app-container" class="app-container"></div>
<script>
AppContext = {
idps: '[{"entityId":"MI-PROD-SAML2-IDP-MEDALLIA","name":"Marriott International (any associate w/ EID)"},{"entityId":"https://identity.starwoodhotels.com","name":"Starwood Hotels"}]'
};
</script>
<script src="main.min.js"></script>
</body>
</html>
when I inspect on generated radio button I am able to get HTML element in browser developer elements tab.
My C# code is as follows:
public Form1()
{
InitializeComponent();
this.webBrowser1.ObjectForScripting = new MyScript();
}
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
webBrowser1.Navigate("javascript: window.external.CallServerSideCode();");
}
[ComVisible(true)]
public class MyScript
{
public void CallServerSideCode()
{
var doc = ((Form1)Application.OpenForms[0]).webBrowser1.Document;
var renderedHtml = doc.GetElementsByTagName("HTML")[0].OuterHtml;
var marelement = doc.GetElementById("MI-PROD-SAML2-IDP-MEDALLIA");
HtmlElementCollection eCollections = doc.GetElementsByTagName("HTML");
string strDoc = eCollections[0].OuterHtml;
}
}
I think It's because of ajax! After ajax previous handler of element is not updates and you should attach handler on OnPropertyChanged event:
var element = webBrowser.Document.GetElementsByTagName("HTML")[0];
element != null ? element.AttachEventHandler("onpropertychange", handler) : return;
private string renderedHtml;
private void handler(Object sender, EventArgs e)
{
var element = webBrowser.Document.GetElementsByTagName("HTML")[0];
if (element != null)
renderedHtml = element.OuterHtml;
}
So the page is rendered by ReactJS so you are going to have a bad time getting this to work. The best thing I can think of is creating a something that 'waits' for the element to be created in the WebBrowserControl....
!(function() {
function check(){
if(!document.getElementById("MI-PROD-SAML2-IDP-MEDALLIA")) {
setTimeout(check, 100);
} else {
window.external.CallServerSideCode();
}
}
check();
}());
Which can then be minified to something you can use...
webBrowser1.Navigate(#"javascript:!(function(){function c(){if(!document.getElementById('MI-PROD-SAML2-IDP-MEDALLIA')){setTimeout(c, 100);}else{window.external.CallServerSideCode();}}c();}());");
I'm utilizing a System.Windows.Forms.WebBrowser (used in a separate .dll file) from my WPF application in order to print some HTML content in the background.
My problem is that the HTML elemnts are not being affected by the javascript in the page.
I know that there are no errors in the page because that if I copy its content after the DocumentCompleted event and paste it into a plain HTML file the script works.
My HTML template:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<script>
function loaded() {
document.getElementById("content").innerHTML = "after javascript";
}
</script>
</head>
<body onload="loaded()">
<h1 id="content">before javascript</h1> <!--<= This value does not change-->
</body>
</html>
I use this HTML as follows:
private void PrintTest()
{
string curDir = Directory.GetCurrentDirectory();
string fullPath = Path.Combine(curDir, "PrintDocs\\HTMLPage1.html");
string html = File.ReadAllText(fullPath);
HtmlPrint.Print(html);
}
public static class HtmlPrint
{
public static void Print(string html, string documentTitle = "")
{
var wb = new System.Windows.Forms.WebBrowser { DocumentText = html };
wb.DocumentCompleted += wb_DocumentCompleted;
}
private static void wb_DocumentCompleted(object sender, System.Windows.Forms.WebBrowserDocumentCompletedEventArgs e)
{
var wb = ((System.Windows.Forms.WebBrowser)sender);
wb.Print();
wb.Dispose();
}
}
What am I missing here?
You forgot the Braces in onload:
<body onload="loaded()">
As mentioned in my comments you can call the InvokeScript() method from your C# code and pass in your js function name as which should do the trick.
wb.Document.InvokeScript("loaded");
I think you have to change onload="loaded" to onload="loaded()"
I want to dynamically load and interact with SVG image into Android WebView using javascript and HTML5. The below is the html source code
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="obj_idset.js"></script>
<script type="text/javascript" src="global.js"></script>
<script type="text/javascript" src="map_zoom_pan_effects.js"></script>
<script type="text/javascript" src="client-menu_position.js"></script>
<script type="text/javascript" src="client-menu_routing.js"></script>
<script type="text/javascript" src="obj_positionpoint.js"></script>
<script type="text/javascript" src="obj_borderline.js"></script>
<script type="text/javascript" src="obj_borderpoint.js"></script>
<script type="text/javascript" src="obj_edge.js"></script>
<script type="text/javascript" src="obj_polygon.js"></script>
<script type="text/javascript" src="obj_stepmarker.js"></script>
<script type="text/javascript" src="obj_vertex.js"></script>
<script type="text/javascript" src="obj_category.js"></script>
<script type="text/javascript" src="obj_gpsmarker.js"></script>
<script type="text/javascript" src="menu_import.js"></script>
<script type="text/javascript" src="routing.js"></script>
<script type="text/javascript" src="affiliation_match.js"></script>
<script type="text/javascript" src="android.js"></script>
<script type="text/javascript" src="interface.js"></script>
<script type="text/javascript" src="demowalk.js"></script>
<script type="text/javascript" src="convertCoordinates.js"></script>
<script>
$("embed").ready(function() {
// Replaces onload () for initialization may take place only after the DOM has been built completely.
console.log('version 24');
//G.loadMaps(false);
G.init();
G.loadMaps(0);
console.log("???");
});
</script>
</head>
<body>
<div id="location"></div>
<!-- Inside this div the map will be rendered -->
<div id="map_container"></div>
<!-- <div id="page-wrapper">
<h1>Text File Reader</h1>
<div>
Select a text file:
<input type="file" id="fileInput">
</div>
<pre id="fileDisplayArea"><pre>
</div>
-->
<div id="mainmenu">
<p>Set the position</p>
<!-- <button onclick="menu('top');">top</button> -->
<button onclick="Interface.position_setSVG (125,125,0);">Set postion</button>
</div>
</body>
</html>
As above html script, the html web page includes a render SVG map which is dynamically load into element and a "Set position" button as below in desktop Chrome.
Now I want to display the same in Android WebView (all java script files and svg files are placed in Android assests folder). The below is Android code in main Fragment
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
private SvgWebView mWebView;
private Button positionBtn;
private Button destinationBtn;
private Button routingBtn;
private Button clearBtn;
public PlaceholderFragment() {
}
#Override
#SuppressLint({ "JavascriptInterface", "SetJavaScriptEnabled" })
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
mWebView = new SvgWebView((WebView) rootView.findViewById(R.id.webView1));
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setBuiltInZoomControls(false);
mWebView.getSettings().setUseWideViewPort(true);
mWebView.getSettings().setSupportZoom(true);
mWebView.getWebView().setInitialScale(0);
mWebView.getWebView().setWebChromeClient(new WebChromeClient());
// http://stackoverflow.com/questions/2378800/clicking-urls-opens-default-browser
mWebView.getWebView().setWebViewClient(new WebViewClient(){
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
CustomJavaScriptHandler js = new CustomJavaScriptHandler(getActivity());
mWebView.getWebView().addJavascriptInterface(js, "svgapp");
js.addInstructor(new CustomJavaScriptHandler.JSInstructor() {
#Override
public void jsinstruct(String s) {
String parts[] = s.split(":");
if (parts[0].equals("position")) {
//nodeSelected(Integer.valueOf(parts[1]));
}
}
});
CopyFilesAsyncTask copyTask = new CopyFilesAsyncTask();
copyTask.execute();
positionBtn = (Button) rootView.findViewById(R.id.positionBtn);
positionBtn.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
mWebView.svgPositionBySvg(100.0, 200.0, 0);
}
});
destinationBtn = (Button) rootView.findViewById(R.id.destinationBtn);
routingBtn = (Button) rootView.findViewById(R.id.routingBtn);
clearBtn = (Button) rootView.findViewById(R.id.clearBtn);
return rootView;
}
/* the function is called after copying files from assest folder to external device */
public void copyFinished() {
try {
Toast.makeText(getActivity(), "Copy done", Toast.LENGTH_LONG).show();
String htmlPath = Utils.getSdDir(Utils.SVG_MAP_DATA_EXT_FOLDER).toURI().toURL().toString() + File.separator + Utils.ANDROID_HTML;
// load the android.html
mWebView.loadUrl(htmlPath);
} catch (MalformedURLException e) {
Log.e(TAG, "Error ", e);
}
}
class CopyFilesAsyncTask extends AsyncTask<Void, Void, Void> {
public CopyFilesAsyncTask() {
}
#Override
protected Void doInBackground(Void... arg0) {
AssetManager assetManager = getActivity().getAssets();
copyAssestsToExtDir(assetManager, Utils.SVG_MAP_DATA_ASSEST_FOLDER);
return null;
}
#Override
protected void onPostExecute(Void arg0) {
copyFinished();
}
}
/* copy files in assest to external dir when the application start */
private void copyAssestsToExtDir(AssetManager assetManager, String subfolder) {
String[] files = null;
try {
files = assetManager.list(subfolder);
} catch (IOException e) {
Log.e(TAG, "Failed to get asset file list.", e);
}
for(String filename : files) {
Log.i(TAG, "File: " + filename);
// this is file, hence copy
InputStream instr = null;
OutputStream outstr = null;
try {
instr = assetManager.open(subfolder + File.separator + filename);
File out_dir = Utils.getSdDir(Utils.SVG_MAP_DATA_EXT_FOLDER);
File outFile = new File(out_dir, filename);
outstr = new FileOutputStream(outFile);
byte[] buffer = new byte[1024];
int read;
while ((read = instr.read(buffer)) != -1) {
outstr.write(buffer, 0, read);
}
outstr.flush();
instr.close();
outstr.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
The thing is that when running in Android, the WebView does not load svg image into its element. It calls default Android Web Browser to display the svg image as below pictures
As above pictures, the WebView only display the "Set postion" button, it call Android web Browser to display SVG. Hence, I could not interact with loaded SVG because SVG does not include any javascript itself (javascript files are embeded into html file not svg).
Am I missing something? Could anyone give me the solution to solve this problem?
The problem is Android 4.4 KitKat.
If the above application run on 4.2 or below, it works well. But if running in 4.4, Android will call Android browser to display the embed svg image.
Due to some security feature, KitKat does not allow to load file stored in internal device. You must place the file on a external server.
I have the following script that I need to show in a browser. I tried loading
with WebView loadData and loadDataWithBaseURL but with no success (empty view).
I probably miss something with the MIME, Encoding, etc.
<head>
<meta name='viewport' content='width=device-width'/>
<script type='text/javascript' src='http://www.googletagservices.com/tag/js/gpt_mobile.js'></script>
<script type='text/javascript'>eval(window.location.search.substring(1));googletag.cmd.push(function(){googletag.defineSlot('/7047/AppCamoli_Iphone_Transition_Splash',[320,480],'div-gpt-ad-2935936626049-0').addService(googletag.pubads());googletag.enableServices();});</script>
</head>
<body style="margin:0; padding: 0;">
<div id='div-gpt-ad-2935936626049-0'>
<script type='text/javascript'>
document.getElementById('div-gpt-ad-2935936626049-0').id='div-gpt-ad-2935936626049-0';googletag.cmd.push(function(){googletag.display('div-gpt-ad-2935936626049-0')});
</script>
</div>
</body>
The code I have is followed:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.web);
try {
webView = (WebView) findViewById(R.id.webView1);
webView.getSettings().setJavaScriptEnabled(true);
Intent i = getIntent();
boolean typeURL = i.getBooleanExtra("urlType", true);
String url = i.getStringExtra("url");
if (typeURL)
webView.loadUrl(url);
else {
//String html = "<html><body>You scored <b>hello world</b> points.</body></html>";
String html = "<html><head><meta name='viewport' content='width=device-width'/><script type='text/javascript' src='http://www.googletagservices.com/tag/js/gpt_mobile.js'></script><script type='text/javascript'>eval(window.location.search.substring(1));googletag.cmd.push(function(){googletag.defineSlot('/7047/AppCamoli_Iphone_Transition_Splash',[320,480],'div-gpt-ad-2935936626049-0').addService(googletag.pubads());googletag.enableServices();});</script></head><body style='margin:0; padding: 0;'><div id='div-gpt-ad-2935936626049-0'><script type='text/javascript'>document.getElementById('div-gpt-ad-2935936626049-0').id='div-gpt-ad-2935936626049-0';googletag.cmd.push(function(){googletag.display('div-gpt-ad-2935936626049-0')});</script></div></body></html>";
//webView.loadDataWithBaseURL(null, html, "text/javascript", "UTF-8", null);
webView.loadData(html, "text/javascript", "UTF-8");
}
} catch (Exception e) {
Log.e("webView","failed to load URL");
e.printStackTrace();
}
}
This results in an empty webView.
Thanks,
Simon
Did you try modifying the WebSettings and enabling JavaScript?
webview.getSettings().setJavaScriptEnabled(true);
I have the answer at THIS link.
"You missed the part in the tutorial where he adds
webView.setWebChromeClient(new WebChromeClient());
right after adding
webView.getSettings().setJavaScriptEnabled(true);"