通过 Android WebView 从 JavaScript 调用 Java 函数

我想在我的 Android 应用程序中同步调用一些 Java 代码。

I am using this solution: https://stackoverflow.com/a/3338656

我的 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;
}
}

我的 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.

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?

为什么按钮永远不会恢复到正常状态?

72378 次浏览

我不认为这是让 javascript 执行 java 代码的最佳解决方案:

如果你想把原生代码暴露给 HTML,让它可以通过 javascript 调用,那么在你的 web 视图声明中执行以下操作:

JavaScriptInterface jsInterface = new JavaScriptInterface(this);
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(jsInterface, "JSInterface");

声明类 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.

最后,通过简单的 javascript 调用在 WebView内容中调用:

<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>

这个例子是从我的另一个答案,关于播放视频,但应该足够解释。

EDIT 正如@CedricSoubrie 的评论: 如果应用程序的目标版本设置为17或更高,你需要在每个想要导出到 web 视图的方法上面添加注释 @JavascriptInterface

函数返回“ true”。这使得 HTML 代码的“ onclick”属性等于 true,因此按钮保持为“ click”

在“ YourJavaScriptInterface”类中定义的方法,不要忘记对要用“@JavascriptInterface”公开的每个方法进行注释,否则将不会触发该方法。

例如,下面的代码来自 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();
}
}
}