I searched, but I didn't find an answer. I'm developing an Android app based on webview, using HTML5 and JavaScript. Can I call an Android method, like makeToast()
from JavaScript?
Asked
Active
Viewed 5.2k times
43

bodruk
- 3,242
- 8
- 34
- 52
-
1Check this answer http://stackoverflow.com/questions/10472839/using-javascript-in-android-webview – Marco Acierno Apr 06 '14 at 14:10
5 Answers
89
You can do this by adding a JavaScript Interface to your WebView and exposing specific methods to the JavaScript code running in your web view. In other words, you'll need to wrap the calls to Android's Toast class in a method you create in your activity/fragment.
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView android:id="@+id/web_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</RelativeLayout>
MainActivity.java
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView webView = (WebView)findViewById(R.id.web_view);
webView.loadUrl("file:///android_asset/web.html");
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new WebViewJavaScriptInterface(this), "app");
}
/*
* JavaScript Interface. Web code can access methods in here
* (as long as they have the @JavascriptInterface annotation)
*/
public class WebViewJavaScriptInterface{
private Context context;
/*
* Need a reference to the context in order to sent a post message
*/
public WebViewJavaScriptInterface(Context context){
this.context = context;
}
/*
* This method can be called from Android. @JavascriptInterface
* required after SDK version 17.
*/
@JavascriptInterface
public void makeToast(String message, boolean lengthLong){
Toast.makeText(context, message, (lengthLong ? Toast.LENGTH_LONG : Toast.LENGTH_SHORT)).show();
}
}
}
assets/web.html
<!DOCTYPE html>
<html>
<head>
<title>JavaScript View</title>
<script type="text/javascript">
function showToast(){
var message = document.getElementById("message").value;
var lengthLong = document.getElementById("length").checked;
/*
Call the 'makeToast' method in the Java code.
'app' is specified in MainActivity.java when
adding the JavaScript interface.
*/
app.makeToast(message, lengthLong);
return false;
}
/*
Call the 'showToast' method when the form gets
submitted (by pressing button or return key on keyboard).
*/
window.onload = function(){
var form = document.getElementById("form");
form.onsubmit = showToast;
}
</script>
</head>
<body>
<form id="form">
Message: <input id="message" name="message" type="text"/><br />
Long: <input id="length" name="length" type="checkbox" /><br />
<input type="submit" value="Make Toast" />
</form>
</body>
</html>

Ian
- 7,480
- 2
- 47
- 51
-
@Ian, this looks like exactly what I am looking for but I'm getting an error when I call the method from within my JavaScript as folows: `(function(event){appInterface.reloadSite();return false;})`. This is called with `onClick="appInterface.reloadSite();return false;"` on an HTML IMG element, and my JavaScript interface is created with `mWebView.addJavascriptInterface(new WebViewJavaScriptInterface(this), "appInterface");` Unfortunately the error in Chrome's debug inspector console is not very helpful. – Fat Monk Jan 22 '16 at 21:52
-
Sorry, I'm not sure. Perhaps the Java code is missing the @JavascriptInterface annotation?? – Ian Jan 22 '16 at 22:15
-
I've got two methods that I want to call from the JavaScript onClick events and both have @JavascriptInterace right before the definition within the WebViewJavaScriptInterface class. Is there anything special needed in how the methods are called from JavaScript (via callbacks or something) or can I just call directly via the onClick event as I described? – Fat Monk Jan 23 '16 at 11:14
-
No, you don't need any special callbacks. I think it might be easier if you start off with the example in my answer and then change it to match what you need. – Ian Jan 23 '16 at 13:03
-
1I found my problem... The methods that I was calling did things that need to be run in the UI Thread. It seems that anything run via the JavaScript interface will run in its own thread, so you need to use `RunOnUiThread()` - as described in http://stackoverflow.com/questions/5161951/android-only-the-original-thread-that-created-a-view-hierarchy-can-touch-its-vi - to do anything that affects the view etc. – Fat Monk Jan 28 '16 at 10:47
-
-
-
Very nicely explained. I have kept this html template to test future such changes. Very good answer. – Sameer Shelar Feb 07 '22 at 08:14
1
Just because it is more convenient (layout):
<?xml version="1.0" encoding="utf-8"?>
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/webView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />

Andrei Anhurets
- 143
- 1
- 13
-
-
1I say that it makes no sense to insert WebView in RelativeLayout if WebView stretched on the screen. WebView logical to use as the root element. – Andrei Anhurets Aug 05 '15 at 09:31
0
After creating your Main Activity code you need to create your Javascript code and call WebviewInterface from that, Let's see the example:
public class MainActivity extends AppCompatActivity {
String TAG = "MainActivity";
Context context;
WebView mWebView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = this;
mWebView = (WebView) findViewById(R.id.webview);
initWebView();
String ENROLLMENT_URL = "file:///android_asset/about_page.html";
mWebView.loadUrl(ENROLLMENT_URL);
}
@SuppressLint({ "SetJavaScriptEnabled" })
private void initWebView() {
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebChromeClient(new WebChromeClient());
mWebView.addJavascriptInterface(new WebviewInterface(), "Interface");
}
public class WebviewInterface {
@JavascriptInterface
public void javaMehod(String val) {
Log.i(TAG, val);
Toast.makeText(context, val, Toast.LENGTH_SHORT).show();
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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.legendblogs.android.MainActivity">
<WebView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/webview"/>
</RelativeLayout>

Amit Pandey
- 1
- 2
0
In Kotlin You can try below code:
In Youre acitivity/fragment that have wevbview add this code:
binding.webViewTest.loadUrl("youreUrl")
binding.webViewTest.settings.javaScriptEnabled = true
binding.webViewTest.addJavascriptInterface(
WebViewJavaScriptInterface(this), "testApp")
and add this class:
class WebViewJavaScriptInterface(context: Context) {
private val context: Context
/*
* This method can be called from Android. @JavascriptInterface
* required after SDK version 17.
*/
@JavascriptInterface
fun makeToast(message: String?) {
Toast.makeText(
context,
message,
Toast.LENGTH_SHORT
).show()
}
init {
this.context = context
}
}
and add this code in your web page:
function showToast(){
/*
Call the 'makeToast' method in the Kotlin code.
'appTest' is specified in MainActivity/Fragment when
adding the JavaScript interface.
*/
testApp.makeToast("Hello Kotlin :)");
return false;
}

Seyed Masood Khademi
- 163
- 1
- 9