I have a WebView which in the click of an Android button loads some JavaScript into the WebView.
My question is how would I go about passing an Android variable to the JavaScript when it's loaded.
My Current code to load the JavaScript into the WebView
private OnClickListener OnClick_grabit = new OnClickListener() {
public void onClick(View v) {
webView.loadUrl("javascript: function loadScript(scriptURL) {
var scriptElem = document.createElement('SCRIPT');
scriptElem.setAttribute('language', 'JavaScript');
scriptElem.setAttribute('src', scriptURL);
document.body.appendChild(scriptElem);
} loadScript('http://www.pathtojavascript/javascript.js');");
}
};
SO I need to pass something to the JavaScript initialize() from Android.
Java Class:
public class JavaScriptInterface {
Context mContext;
JavaScriptInterface(Context c) {
mContext = c;
}
#JavascriptInterface
public String getFromAndroid() {
return "This is from android.";
}
}
Webview code :
WebView webView = (WebView) findViewById(R.id.webview);
webView.setWebChromeClient(new WebChromeClient() {});
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setDomStorageEnabled(true);
webView.addJavascriptInterface(new JavaScriptInterface(this), "Android");
Html and javascript:
<input type="button" value="Get from android" onClick="getFromAndroid()" />
<script type="text/javascript">
var myVar = null;
function getFromAndroid() {
myVar = Android.getFromAndroid();
alert(myVar);
}
</script>
First of all you need to load the script only once (your onClick is loading it every time), then call loadUrl("javascript:initialize(" + myNumber + ");")
The correct syntax that worked for me is
StringBuilder buf=new StringBuilder("javascript:testFunction('"+bar+"','"+foo+"')");
Log.d(TAG, "returned string:"+buf.toString());
mWebView.loadUrl(buf.toString());
You need to loadUrl in your webView, I got something like this in my previous app:
webView.loadUrl("javascript:wrapJS.functionName("+value+","+value+")"+);
Add the JitPack repository to your build file
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
Add this to app gradle file:
dependencies {
compile 'com.github.wendux:WebViewJavascriptBridge:master-SNAPSHOT'
}
prepare your java script like this:
<!doctype html>
<html><head>
</head><body>
<p>Mehdico</p>
<script>
function setupWebViewJavascriptBridge(callback) {
var bridge=window.WebViewJavascriptBridge||window.WKWebViewJavascriptBridge
if (bridge) { return callback(bridge); }
var callbacks=window.WVJBCallbacks||window.WKWVJBCallbacks
if (callbacks) { return callbacks.push(callback); }
window.WVJBCallbacks=window.WKWVJBCallbacks = [callback];
if(window.WKWebViewJavascriptBridge){
window.webkit.messageHandlers.iOS_Native_InjectJavascript.postMessage(null)
}else{
var WVJBIframe = document.createElement('iframe');
WVJBIframe.style.display = 'none';
WVJBIframe.src = 'https://__bridge_loaded__';
document.documentElement.appendChild(WVJBIframe);
setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
}
}
setupWebViewJavascriptBridge(function(bridge) {
bridge.callHandler('sendToJava', { success:'true' }, function(response) {
})
})
</script>
</body></html>
if you want more handlers just duplicate this lines and change [jsToJava] and data part (success:true)
bridge.callHandler('sendToJava', { success:'true' }, function(response) {
})
in your xml:
<wendu.webviewjavascriptbridge.WVJBWebView
android:id="#+id/webView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
and java:
webView = findViewById(R.id.webView);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webView.setWebViewClient(new AppWebViewClients((ProgressBar) findViewById(R.id.progressBar)));
if (Build.VERSION.SDK_INT >= 21) { // for fix invalid https certification
webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}
webView.registerHandler("sendToJava", new WVJBWebView.WVJBHandler() {
#Override
public void handler(Object data, WVJBWebView.WVJBResponseCallback callback) {
Toast.makeText(ActivityPaymentStepBank.this, data.toString(), LENGTH_SHORT).show();
Log.d("wvjsblog", data.toString());
callback.onResult(data);
}
});
webView.loadUrl("URL OF YOUR HTML FILE");
Related
I have a strange problem; JSBridge doesn't work after the page loads but it does when the button is clicked.
Test site:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body bgcolor="#A0BEC4">
<input type="button" value="PLAY" onclick="play()"><br><br>
<script>
window.onload = function() { //does not work
stb.play("hello3");
}
function play() { // work
stb.play("hello2");
}
window.addEventListener('load', (event) => {
stb.play("hello4"); //does not work
});
stb.play("hello"); //does not work
function checkJSBridge(){ // !!! WORK !!!
if (typeof (stb.play) === "function") {
stb.play("WORK");
clearTimeout(bridge_timer);
}
}
let bridge_timer = setTimeout(checkJSBridge, 1000);
</script>
</body>
</html>
My code (JavaFX 18.0.1 and JDK 18.0.1.1):
private WebEngine webEngine = webView.getEngine();
private Worker<?> engineWorker = webEngine.getLoadWorker();
private JSBridge bridge = new JSBridge();
#Override
public final void start(Stage stage) throws Exception {
engineWorker.stateProperty().addListener(new ChangeListener<Worker.State>() {
#Override
public void changed(ObservableValue ov, Worker.State oldState, Worker.State newState) {
if (newState == State.SUCCEEDED) {
JSObject jsobj = (JSObject) webEngine.executeScript("window");
jsobj.setMember("stb", bridge);
}
}
});
}
I am using a WebView to display a web-page on an android application. https://developer.android.com/guide/webapps/webview.html
After clicking a button from the HTML, I can successfully get to the Android class WebAppInterface (From the example) and display a "Toast" alert, but trying to callback to the a javacsript function defined in my web-page is not working.
This is the code of the web-page: (Android.html)
<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" />
<script type="text/javascript">
function showAndroidToast(toast) {
if (typeof Android != 'undefined')
Android.showToast(toast);
}
function ChangeColor()
{
document.body.style.background = 'pink';
}
</script>
This is the code of the MainActivity of the Android app. It loads the url and displays it.
public class MainActivity extends AppCompatActivity {
WebView m_Webview;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
m_Webview = (WebView) findViewById(R.id.webview);
WebSettings webSettings = m_Webview.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
m_Webview.setWebViewClient(new WebViewClient());
m_Webview.loadUrl("android.html");
WebView webView = (WebView) findViewById(R.id.webview);
webView.addJavascriptInterface(new WebAppInterface(this,webView), "Android");
}
}
This is the WebAppInterface on the Android app:
public class WebAppInterface {
Context mContext;
WebView mView;
/** Instantiate the interface and set the context */
WebAppInterface(Context c,WebView w) {
mContext = c;
mView = w;
}
/** Show a toast from the web page */
#JavascriptInterface
public void showToast(String toast) {
Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
mView.loadUrl("javascript:ChangeColor()");
}
}
The JavaScript function ChangeColor is not getting called after the toast is getting displayed.
For more reference see: https://stackoverflow.com/a/14145116/7751339
Thanks!
The solution was to use the "post" function like this:
public void showToast(String toast) {
Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
// WebView Web = new WebView(mContext);
// mView.getSettings().setUserAgentString("Android WebView");
mView.post(new Runnable() {
public void run() {
mView.loadUrl("javascript:ChangeColor()");
}
});
}
Also on KitKat and forward you need to use evaluateJavascript:
mView.evaluateJavascript("ChangeColor();",null);
I'm making an Android app to my book I have an html page I want to add a button on it which is linked to this Java code
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// listeners of our two buttons
View.OnClickListener handler = new View.OnClickListener() {
public void onClick(View v) {
switch (v.getId()) {
case R.id.buttonShareTextUrl:
shareTextUrl();
break;
}
}
};
// our buttons
findViewById(R.id.buttonShareTextUrl).setOnClickListener(handler);
}
// Method to share either text or URL.
private void shareTextUrl() {
Intent share = new Intent(android.content.Intent.ACTION_SEND);
share.setType("text/plain");
share.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
// Add data to the intent, the receiving app will decide
// what to do with it.
share.putExtra(Intent.EXTRA_SUBJECT, "book");
share.putExtra(Intent.EXTRA_TEXT, "https://play.google.com/store/apps/details?id=com.sohaibm.assrar_bac");
startActivity(Intent.createChooser(share, "share with"));
}
}
so I want you to give me an HTML code of the page that contains the button linked to this activity and thank you so much
If you use WebView to show book content you can use WebViewClient:
WebViewClient mWebClient = new WebViewClient(){
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(url.startsWith("handle:")){
// do something
return true;
}
else{
view.loadUrl(url);
}
return true;
}
};
mWebView.setWebViewClient(mWebClient);
And your link should be:
Link text
Try like this:
Html Page:
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css" href="style.css" />
<script type="text/javascript">
function moveToScreenTwo() {
Android.moveToNextScreen();
}
</script>
</head>
<body>
<div>
<input type="button" value="Locate" onClick="moveToScreenTwo()" />
</div>
</body>
</html>
FirstACtivity.java:
import android.webkit.JavascriptInterface;
webView = (WebView) findViewById(R.id.load_url);
webView.getSettings().setJavaScriptEnabled(true);
if (new File(url).exists()) {
webView.loadUrl(FILENAME_PREFIX + url);
Log.d("fileurl", "" + FILENAME_PREFIX + url);
webView.addJavascriptInterface(new WebAppInterface(this), "Android");
}
//Class to be injected in Web page
public class WebAppInterface {
Context mContext;
/**
* Instantiate the interface and set the context
*/
WebAppInterface(Context c) {
mContext = c;
}
#JavascriptInterface
public void moveToNextScreen() {
Intent i = new Intent(FirstActivity.this,SecondActivity.class);
startActivity(i);
}
}
For more Reference: Check this tutorial.
I have tried everything and still doesn't work, please help:
I setup my WebView here:
public class MainActivity extends ActionBarActivity {
private WebView mWebView;
private MyWebViewClient mWebViewClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
mWebViewClient = new MyWebViewClient(context);
mWebView = (WebView) findViewById(R.id.activity_main_webview);
mWebView.addJavascriptInterface(mWebViewClient, "Android");
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setAllowFileAccessFromFileURLs(true);
webSettings.setAllowUniversalAccessFromFileURLs(true);
webSettings.setDomStorageEnabled(true);
mWebView.setWebViewClient(mWebViewClient);
mWebView.loadUrl("file:///android_asset/index.html");
}
}
This is where I call my function from JS:
<script>
$("#logInButton").click(function(){
if(isAndroid){
Android.onJavaLogIn();
}
return false;
});
</script>
<input type="button" value="Log In" id="logInButton" />
Here is how I handle it:
public class MyWebViewClient extends android.webkit.WebViewClient {
private MainActivity context;
public MyWebViewClient(MainActivity context) {
this.context = context;
}
#JavascriptInterface
public void onJavaLogIn(){
context.onMainLogIn();
}
}
public class MainActivity extends ActionBarActivity {
public void onMainLogIn(){
mWebView.loadUrl("javascript:onJSLogIn();");
}
}
This is the JS function it's suppose to call:
<script>
function onJSLogIn(){
$("#logInButton").hide();
$("#logOutButton").show();
}
</script>
The entire chain seem to be correct, and I verify via debug that onMainLogIn() in MainActivity does get called, but the JS function onJSLogIn() never get called, why?
It turn out WebView only work on the main UI thread. So I had to warp the call function like this:
public void onMainLogIn(){
this.runOnUiThread(new Runnable() {
#Override
public void run() {
mWebView.loadUrl("javascript:onJSLogIn();");
}
});
}
Yes, here everything looks fine. Since we can't debug it, we can only suggest few things. 1. First write one alert in onJSLogIn JS method to make sure function not getting called.Because logInButton, logOutButton dom elements might not have loaded. 2. Connect your webview to remote debug and check for errors using chrome ADB tool.
I used webView to show javaScript,one image was included in the javaScrip,but the webView not run the image on the contrary appear a "?"image. Idonot why?
my code:
demo.html
<html>
<script language="javascript">
/* This function is invoked by the activity */
function wave() {
document.getElementById("droid").src="android_waving.png";
alert("2");
}
</script>
<body>
<!-- Calls into the javascript interface for the activity -->
<a onClick="window.demo.clickOnAndroid()"><div style="width:80px;
margin:0px auto;
padding:10px;
text-align:center;
border:2px solid #202020;" >
<img id="droid" src="android_normal.png"/><br>
Click me!
</div></a>
</body>
</html>
public class webJsDemo extends Activity {
/** Called when the activity is first created. */
private WebView mWebView;
private Handler mHandler = new Handler();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mWebView = (WebView) findViewById(R.id.wv1);
WebSettings webSettings = mWebView.getSettings();
webSettings.setSavePassword(false);
webSettings.setSaveFormData(false);
webSettings.setJavaScriptEnabled(true);
webSettings.setSupportZoom(false);
mWebView.setWebChromeClient(new MyWebChromeClient());
mWebView.addJavascriptInterface(new DemoJavaScriptInterface(), "demo");
mWebView.loadUrl("file:///android_asset/demo.html");
}
final class DemoJavaScriptInterface {
DemoJavaScriptInterface() {
}
/**
* This is not called on the UI thread. Post a runnable to invoke
* loadUrl on the UI thread.
*/
public void clickOnAndroid() {
mHandler.post(new Runnable() {
public void run() {
mWebView.loadUrl("javascript:wave()");
}
});
}
}
/**
* Provides a hook for calling "alert" from javascript. Useful for
* debugging your javascript.
*/
final class MyWebChromeClient extends WebChromeClient {
#Override
public boolean onJsAlert(WebView view, String url, String message,
JsResult result) {
// TODO Auto-generated method stub
Log.d("aa", message);
Log.d("url", url);
Log.d("result", ""+result);
result.confirm();
return super.onJsAlert(view, url, message, result);
}
}
}
i put android_normal.png and android_waving.png in the assets and drawable folder
the result
Did you try putting your image in the same location your html file is?