通过 Android WebView 从 JavaScript 调用 Java 函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10389572/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Call Java function from JavaScript over Android WebView
提问by ozkolonur
I want to make a synchronous call to some Java code in my Android app.
我想对我的 Android 应用程序中的一些 Java 代码进行同步调用。
I am using this solution: https://stackoverflow.com/a/3338656
我正在使用这个解决方案:https: //stackoverflow.com/a/3338656
My Java code:
我的Java代码:
final class MyWebChromeClient extends WebChromeClient {
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
Log.d("LogTag", message);
result.confirm();
return true;
}
}
My JavaScript code:
我的 JavaScript 代码:
<html>
<script>
function java_request(){
alert('test');
}
</script>
<body>
<h2>Welcome</h2>
<div id="area"></div>
<form>
<input type="button" value="java_call" onclick="java_request()">
</form>
</body>
</html>
When I tap on the java_call
button, the button goes to the pressed state. I can see 'test'
in the console log. Everything is normal until here.
当我点击java_call
按钮时,按钮进入按下状态。我可以'test'
在控制台日志中看到。到这里一切正常。
The problem is, the button never gets back to its normal state. It stays in the pressed state. Maybe the JavaScript execution is broken or something?
问题是,按钮永远不会恢复到正常状态。它保持按下状态。也许 JavaScript 执行已损坏或什么的?
Why does the button never return to its normal state?
为什么按钮永远不会恢复到正常状态?
回答by Boris Strandjev
I don't think this is the best solution to get the javascript to execute java code. See here:
我认为这不是让 javascript 执行 java 代码的最佳解决方案。看这里:
If you want to expose native code to the HTML to be callable via javascript, do the following around your web view declaration:
如果您想将本机代码公开给 HTML 以通过 javascript 调用,请围绕您的 web 视图声明执行以下操作:
JavaScriptInterface jsInterface = new JavaScriptInterface(this);
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(jsInterface, "JSInterface");
Declare the class JavaScriptInterface
:
声明类JavaScriptInterface
:
public class JavaScriptInterface {
private Activity activity;
public JavaScriptInterface(Activity activity) {
this.activity = activity;
}
@JavascriptInterface
public void startVideo(String videoAddress){
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(videoAddress), "video/3gpp");
activity.startActivity(intent);
}
}
I am declaring a single function for playing a video, but you can do whatever you want.
我声明了一个用于播放视频的函数,但你可以做任何你想做的事情。
Finally you call this in the WebView
contents via simple javascript call:
最后,您WebView
通过简单的 javascript 调用在内容中调用它:
<video width="320" height="240" controls="controls" poster='poster.gif'
onclick="window.JSInterface.startVideo('file:///sdcard/test.3gp');" >
Your browser does not support the video tag.
</video>
The example is taken from another answer of mine, about playing videos, but should be explaining enough.
这个例子取自我的另一个关于播放视频的答案,但应该足够解释了。
EDITAs per @CedricSoubrie's comment: if the target version of the application is set to 17 or higher you need to add annotation @JavascriptInterface
above each method you want to export to the web view.
编辑根据@CedricSoubrie 的评论:如果应用程序的目标版本设置为 17 或更高版本,则需要在@JavascriptInterface
要导出到 Web 视图的每个方法上方添加注释。
回答by R. Maynard
Your function returns 'true'. That makes the 'onclick' property of your HTML code equal to true, hence the button remains 'clicked.'
您的函数返回“真”。这使得 HTML 代码的“onclick”属性等于 true,因此按钮保持“点击”状态。
回答by tyolab
The methods defined in the "YourJavaScriptInterface" class, don't forget to annotate each method that you want to expose with "@JavascriptInterface", otherwise the method won't be triggered.
“ YourJavaScriptInterface”类中定义的方法,不要忘记用“@JavascriptInterface”注释每个要公开的方法,否则不会触发该方法。
For example, the below code is from the Google Cloud Print JavaScript interface for calls from a webview page:
例如,以下代码来自 Google Cloud Print JavaScript 接口,用于从 webview 页面调用:
final class PrintDialogJavaScriptInterface {
@JavascriptInterface
public String toString() { return JS_INTERFACE; }
@JavascriptInterface
public String getType() {
return cloudPrintIntent.getType();
}
@JavascriptInterface
public String getTitle() {
return cloudPrintIntent.getExtras().getString("title");
}
@JavascriptInterface
public String getContent() {
try {
ContentResolver contentResolver = getActivity().getContentResolver();
InputStream is = contentResolver.openInputStream(cloudPrintIntent.getData());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int n = is.read(buffer);
while (n >= 0) {
baos.write(buffer, 0, n);
n = is.read(buffer);
}
is.close();
baos.flush();
return Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
@JavascriptInterface
public String getEncoding() {
return CONTENT_TRANSFER_ENCODING;
}
@JavascriptInterface
public void onPostMessage(String message) {
if (message.startsWith(CLOSE_POST_MESSAGE_NAME)) {
finish();
}
}
}