js调用Android原生:
声明@JavascriptInterface,进行对象映射
android:
myWebView = (WebView) findViewById(R.id.webview);
myWebView .getSettings().setJavaScriptEnabled(true);
myWebView .addJavascriptInterface(new JavaScriptInterface(this),"android");
public class JavaScriptInterface{
Context context;
public JavaScriptInterface(Context c){
context = c;
}
//与js交互时用到的方法
@JavascriptInterface
public void showToast(String ssss){
// todo
}
}
js:
function showText(){
android.showToast("hello world");
}
2. shouldOverrideUrlLoading
android:
class InnerWebViewClient extends WebViewClient {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
showProgress();
}
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
if (Macro.isDebug) {
handler.proceed();
} else {
super.onReceivedSslError(view, handler, error);
}
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
L.e(url);
if (!TextUtils.isEmpty(url) && url.startsWith(CallBackUrl.MOVE)) {//迁移
Uri uri = Uri.parse(url);
String token = uri.getQueryParameter("_tk");
if (TextUtils.isEmpty(token)) {
token = uri.getQueryParameter("portal_token");
}
Intent intent = new Intent();
intent.putExtra(Result.EXTRA_TOKEN, token);
setResult(RESULT_OK, intent);
finish();
return true;
}else if (!TextUtils.isEmpty(url) && url.startsWith(CallBackUrl.FORGET_PWD)){//忘记密码
Uri uri = Uri.parse(url);
String token = uri.getQueryParameter("_tk");
if (TextUtils.isEmpty(token)) {
token = uri.getQueryParameter("portal_token");
}
Intent intent = new Intent();
intent.putExtra(Result.EXTRA_TOKEN, token);
setResult(RESULT_OK, intent);
finish();
return true;
}else if (!TextUtils.isEmpty(url) && url.startsWith(CallBackUrl.PWD_SET)){//设置支密
Uri uri = Uri.parse(url);
String token = uri.getQueryParameter("_tk");
if (TextUtils.isEmpty(token)) {
token = uri.getQueryParameter("portal_token");
}
Intent intent = new Intent();
intent.putExtra(Result.EXTRA_TOKEN, token);
setResult(RESULT_OK, intent);
finish();
return true;
}
return super.shouldOverrideUrlLoading(view, url);
}
}
js:
window.location.href="http://www.baidu.com"
3.使用WebChromeClient.onConsoleMessage函数
android:
public class CustomWebChromeClient extends WebChromeClient{
@Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage){
super.onConsoleMessage(consoleMessage);
String msg = consoleMessage.message();//log内容
}
}
js:
console.log("log message that is going to native code");
4.使用WebChromeClient.onJsPrompt函数,拦截JS输入框消息
android:
public class CustomWebChromeClient extends WebChromeClient{
@Override
public boolean onJsPromt(Webview view, String url, String message,String defaultValue,JsPromptResult result){
//处理JS 的调用逻辑
result.confirm();
return true;
}
}
js:
window.prompt(message,value)
三种方法对比
调用方式
优点
缺点
使用场景
@JavascriptInterface
方便简洁
Android4.2以下存在任意代码执行漏洞
Android4.2以上相对简单互调场景
shouldOverrideUrlLoading
不存在漏洞问题
使用复杂,需要进行协议的约束;从Native层往Web层传递值比较繁琐
不需要返回值情况下的互调场景
onJsPrompt
不存在漏洞问题
使用复杂,需要进行协议的约束
能满足大多数情况下的互调场景
Android调用JS原生代码方法
1.Webview.loadUrl()
android:
//必须在新开的线程中调用,否则无法调用
mWebview.post(new Runable(){
@Override
public void run(){
mWebview.load("javascript:callJS()");
}
}
);
js:
//Android需要调用的方法
function callJS(){
alert("Android调用了JSde callJS方法");
}
2. Webview.evaluateJavascript
该方法执行不回使页面刷新,loadUrl会刷新页面
Android4.4之后才能使用
android:
mWebview.evaluateJavascript ("javascript:callJS()", new ValueCallback(){
@Override
public void onReceiveValue(String value){
//此处为js返回的结果
}
})
方法对比:
调用方式
优点
缺点
使用场景
使用loadUrl
方便简洁
效率低;获取返回值麻烦
不需要获取返回值,对性能要求较低时
使用evaluateJavascript
效率高
向下兼容性差(仅Android 4.4 以上可用)
Android 4.4以上