Java and JavaScript interaction instances in Android
- 2020-06-12 10:36:09
- OfStack
Android provides a powerful WebView control for handling Web web pages, and JavaScript is a very important script in web pages. This article shows you how to implement mutual calls between Java code and Javascript code.
How to implement
Realize Java and js interaction 10 minutes convenient. The following steps are usually all that are required.
1.WebView starts JavaScript script execution
2.WebView sets up the interaction interface for JavaScript to call.
3. The client and the web side write the code to call each other.
This example code
For the sake of explanation, post the entire code
Java code
package com.example.javajsinteractiondemo;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.webkit.JavascriptInterface;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
public class MainActivity extends Activity {
private static final String LOGTAG = "MainActivity";
@SuppressLint("JavascriptInterface")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final WebView myWebView = (WebView) findViewById(R.id.myWebView);
WebSettings settings = myWebView.getSettings();
settings.setJavaScriptEnabled(true);
myWebView.addJavascriptInterface(new JsInteration(), "control");
myWebView.setWebChromeClient(new WebChromeClient() {});
myWebView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
testMethod(myWebView);
}
});
myWebView.loadUrl("file:///android_asset/js_java_interaction.html");
}
private void testMethod(WebView webView) {
String call = "javascript:sayHello()";
call = "javascript:alertMessage(\"" + "content" + "\")";
call = "javascript:toastMessage(\"" + "content" + "\")";
call = "javascript:sumToJava(1,2)";
webView.loadUrl(call);
}
public class JsInteration {
@JavascriptInterface
public void toastMessage(String message) {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
}
@JavascriptInterface
public void onSumResult(int result) {
Log.i(LOGTAG, "onSumResult result=" + result);
}
}
}
Front-end web code
<html>
<script type="text/javascript">
function sayHello() {
alert("Hello")
}
function alertMessage(message) {
alert(message)
}
function toastMessage(message) {
window.control.toastMessage(message)
}
function sumToJava(number1, number2){
window.control.onSumResult(number1 + number2)
}
</script>
Java-Javascript Interaction In Android
</html>
Invoke the sample
js call Java
The invocation format is ES44en.jsInterfaceName.methodName (parameterValues). In this case, we use control as the injection interface name.
function toastMessage(message) {
window.control.toastMessage(message)
}
function sumToJava(number1, number2){
window.control.onSumResult(number1 + number2)
}
Java call JS
The basic format for webView to call js is ES60en.loadUrl (" javascript:methodName(parameterValues) ")
Call js's argument - free - return function
String call = "javascript:sayHello()";
webView.loadUrl(call);
Call js with arguments and no return value
Note that you need to escape double quotes for strings as parameter values.
String call = "javascript:alertMessage(\"" + "content" + "\")";
webView.loadUrl(call);
Call js a function with arguments and return values
Before 4.4, Android did not provide a method to directly call the js function and get the value, so before that, the common idea is that java calls the js method, and after the execution of the js method, the java code is called again to return the value.
Java calls the js code
String call = "javascript:sumToJava(1,2)";
webView.loadUrl(call);
2. The js function handles it and returns the result by calling the java method
function sumToJava(number1, number2){
window.control.onSumResult(number1 + number2)
}
3.Java gets the return value of the js function in the callback method
@JavascriptInterface
public void onSumResult(int result) {
Log.i(LOGTAG, "onSumResult result=" + result);
}
4.4 processing
Android 4.4 is followed by evaluateJavascript. Here is a simple interaction example of an js method with a return value
function getGreetings() {
return 1;
}
java code is called with the evaluateJavascript method
private void testEvaluateJavascript(WebView webView) {
webView.evaluateJavascript("getGreetings()", new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
Log.i(LOGTAG, "onReceiveValue value=" + value);
}});
}
The output
I/MainActivity( 1432): onReceiveValue value=1
Pay attention to
1. The above qualified result return result is String, for simple types will try to convert to string return, for complex data types, it is recommended to return json as a string.
2. The evaluateJavascript method must be called on the UI thread (the main thread), so onReceiveValue also executes on the main thread.
Question answer
Alert cannot pop out
You should not have set WebChromeClient, as follows
myWebView.setWebChromeClient(new WebChromeClient() {});
Uncaught ReferenceError: functionName is not defined
The reason for the problem is that the js method is called before the page's js code is loaded. The solution is to call the js method after the page has loaded
myWebView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
// Execute what you want to call here js function
}
});
Uncaught TypeError: Object [object Object] has no method
Safety restriction problem
If only a machine older than 4.2 has a problem, then the system is in a security limit. The Android document says so
Caution: If you've set your targetSdkVersion to 17 or higher, you must add the @JavascriptInterface annotation to any method that you want available your web page code (the method must also be public). If you do not provide the annotation, then the method will not accessible by your web page when running on Android 4.2 or higher.
Chinese main idea is
Warning: If your application targets platform is 17 Or even higher, you have to add to the method that is exposed to the web page (the method must be public) @JavascriptInterface The comments. If you don't, yes 4.2 On future platforms, web pages cannot access your method.
The solution
1. Set targetSdkVersion to 17 or higher and introduce the @JavascriptInterface annotation
2. Create your own annotation interface named @JavascriptInterface and bring it in. Note that this interface should not be confused. This approach is not recommended and is probably problematic after 4.4.
Note, create @JavascriptInterface code
public @interface JavascriptInterface {
}
Code confusion problem
If it works well in the non-obturated version and the code in the obturated version runs incorrectly and says Uncaught TypeError: Object [object Object] has no method, then you are not making a obturation exception. Add code like this in the obfuscation file
-keep class com.example.javajsinteractiondemo$JsInteration {
*;
}
All WebView methods must be called on the same thread
Filtering logs have found this problem.
E/StrictMode( 1546): java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {528712d4} called on Looper (JavaBridge, tid 121) {52b6678c}, FYI main Looper is Looper (main, tid 1) {528712d4})
E/StrictMode( 1546): at android.webkit.WebView.checkThread(WebView.java:2063)
E/StrictMode( 1546): at android.webkit.WebView.loadUrl(WebView.java:794)
E/StrictMode( 1546): at com.xxx.xxxx.xxxx.xxxx.xxxxxxx$JavaScriptInterface.onCanGoBackResult(xxxx.java:96)
E/StrictMode( 1546): at com.android.org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method)
E/StrictMode( 1546): at com.android.org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:27)
E/StrictMode( 1546): at android.os.Handler.dispatchMessage(Handler.java:102)
E/StrictMode( 1546): at android.os.Looper.loop(Looper.java:136)
E/StrictMode( 1546): at android.os.HandlerThread.run(HandlerThread.java:61)
The Java callback thread after the js call is not the main thread. Such as print log can be verified
<html>
<script type="text/javascript">
function sayHello() {
alert("Hello")
}
function alertMessage(message) {
alert(message)
}
function toastMessage(message) {
window.control.toastMessage(message)
}
function sumToJava(number1, number2){
window.control.onSumResult(number1 + number2)
}
</script>
Java-Javascript Interaction In Android
</html>
8
To resolve the above exception, place the webview operation in the main thread.
<html>
<script type="text/javascript">
function sayHello() {
alert("Hello")
}
function alertMessage(message) {
alert(message)
}
function toastMessage(message) {
window.control.toastMessage(message)
}
function sumToJava(number1, number2){
window.control.onSumResult(number1 + number2)
}
</script>
Java-Javascript Interaction In Android
</html>
9