一、Android调用JS

方式1: WebView#loadUrl(String url)

//javascript.html                    WebView                        This is HTML!    //MainActivitymCalljsBtn.setOnClickListener(new View.OnClickListener() {    @Override    public void onClick(View v) {        String msg = "来自Android";        mWebview.loadUrl("javascript:androidCallJS('" + msg + "')");    }});//MainActivitymWebview.setWebChromeClient(new WebChromeClient(){    //若返回true,则WebView不处理JavaScript的警告事件,由自己编写的程序处理JavaScript的警告事件    //若返回false,则WebView处理JavaScript的警告事件    @Override    public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {        AlertDialog.Builder buidler = new AlertDialog.Builder(MainActivity.this);        buidler.setTitle("JS alert 回调");        buidler.setMessage(message);        buidler.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {            @Override            public void onClick(DialogInterface dialog, int which) {                result.confirm();            }        });        buidler.setCancelable(false);        buidler.create().show();        return true;    }});

方式2: WebView#evaluateJavascript(String script, ValueCallback resultCallback)

//javascript.html                    WebView                        This is HTML!    //MainActivitymCalljsBtn.setOnClickListener(new View.OnClickListener() {    @Override    public void onClick(View v) {        String msg = "来自Android";        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {            mWebview.evaluateJavascript("javascript:androidCallJS('" + msg + "')", new ValueCallback() {                @Override                public void onReceiveValue(String value) {                    Log.d(TAG, "zwm, onReceiveValue: " + value);                }            });        }    }});

方式对比

控件 -- WebView -- Android与JS交互_第1张图片 方式对比

使用建议

两种方式混合使用,Android 4.4以下使用方式1,Android 4.4以上方式2。

String msg = "来自Android";if(Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {    mWebview.loadUrl("javascript:androidCallJS('" + msg + "')");} else {    mWebview.evaluateJavascript("javascript:androidCallJS('" + msg + "')", new ValueCallback() {        @Override        public void onReceiveValue(String value) {            Log.d(TAG, "zwm, onReceiveValue: " + value);        }    });}

二、JS调用Android

方式1: 通过WebView#addJavascriptInterface(Object object, String name)进行对象映射

//JSCallAndroidObjectpublic class JSCallAndroidObject {    private static String TAG = JSCallAndroidObject.class.getSimpleName();    @JavascriptInterface    public String jsCallAndroid(String msg) {        Log.d(TAG, "zwm, jsCallAndroid msg: " + msg);        return "来自Android";    }}//MainActivitymWebSettings.setJavaScriptEnabled(true);mWebview.addJavascriptInterface(new JSCallAndroidObject(), "jsCallAndroidObject");mWebview.loadUrl("file:///android_asset/javascript.html");//MainActivitymWebview.setWebChromeClient(new WebChromeClient(){    //若返回true,则WebView不处理JavaScript的警告事件,由自己编写的程序处理JavaScript的警告事件    //若返回false,则WebView处理JavaScript的警告事件    @Override    public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {        AlertDialog.Builder buidler = new AlertDialog.Builder(MainActivity.this);        buidler.setTitle("JS alert 回调");        buidler.setMessage(message);        buidler.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {            @Override            public void onClick(DialogInterface dialog, int which) {                result.confirm();            }        });        buidler.setCancelable(false);        buidler.create().show();        return true;    }});//javascript.html                    WebView                        This is HTML!        

安全漏洞:
在Android 4.2以前(不包含Android 4.2,API 17),使用WebView#addJavascriptInterface方法会引起远程代码执行漏洞。
1.产生原因
当JS拿到Android映射对象后,就可以调用这个对象的所有方法,还可以获取系统类对象(java.lang.Runtime),从而进行任意代码执行。

获取系统类对象过程如下:(结合Java反射机制)
(1)Android中的对象有一个公共的方法:getClass;
(2)该方法可以获取当前类的类型:Class;
(3)该类型有一个关键方法:Class.forName;
(4)该方法可以加载一个类对象:java.lang.Runtime;
(5)该类对象可以执行本地命令。

获取系统类对象代码如下:

//分析://1.execute方法:遍历所有window对象,找到包含getClass方法的对象,利用这个对象,找到java.lang.Runtime类,//然后调用getRuntime静态方法得到Runtime的实例,再调用exec方法来执行某段命令。//2.getContents方法:从流中读取内容。//3.执行结果:列出SDCard中的文件。

2.解决方案
对于Android 4.2以前(不包含Android 4.2,API 17),需要采用拦截JS prompt的方式进行漏洞修复。
对于Android 4.2以后,只需要对被调用的函数以@JavascriptInterface进行注解。

方式2: 通过WebViewClient#shouldOverrideUrlLoading回调拦截url

shouldOverrideUrlLoading(WebView view, String url) //在API 24以后过时
shouldOverrideUrlLoading(WebView view, WebResourceRequest request) //在API 24以后新加的

//javascript.html                    WebView                        This is HTML!        
//MainActivitymWebSettings.setJavaScriptEnabled(true);mWebview.loadUrl("file:///android_asset/javascript.html");//MainActivitymWebview.setWebViewClient(new WebViewClient(){ @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { Log.d(TAG, "zwm, shouldOverrideUrlLoading, url: " + url); //约定的url协议为:js://webview?arg1=111&arg2=222 Uri uri = Uri.parse(url); if (uri.getScheme().equals("js")) { if (uri.getAuthority().equals("webview")) { String arg1 = uri.getQueryParameter("arg1"); String arg2 = uri.getQueryParameter("arg2"); Log.d(TAG, "zwm, JS调用Android, 来自JS, arg1: " + arg1 + ", arg2: " + arg2); } return true; } return super.shouldOverrideUrlLoading(view, url); }});

如果JS想要得到Android方法的返回值,只能通过WebView#loadUrl方法去执行JS方法,把返回值传递回去,代码如下:

//javascript.htmlfunction returnResult(result){    alert("result: " + result);}//MainActivitymWebView.loadUrl("javascript:returnResult('" + result + "')");

方式3: 通过WebChromeClient的onJsAlert方法、onJsConfirm方法、onJsPrompt方法回调拦截JS的alert警告事件、confirm确认事件、prompt输入事件

常用的拦截是:拦截JS的prompt输入事件。因为只有prompt输入框可以返回任意类型的值,而alert警告框没有返回值,confirm确认框只能返回两种状态值。

//javascript.html                    WebView                        This is HTML!        
//MainActivitymWebSettings.setJavaScriptEnabled(true);mWebview.loadUrl("file:///android_asset/javascript.html");//MainActivitymWebview.setWebChromeClient(new WebChromeClient(){ //若返回true,则WebView不处理JavaScript的警告事件,由自己编写的程序处理JavaScript的警告事件 //若返回false,则WebView处理JavaScript的警告事件 @Override public boolean onJsAlert(WebView view, String url, String message, final JsResult result) { AlertDialog.Builder buidler = new AlertDialog.Builder(MainActivity.this); buidler.setTitle("JS alert 回调"); buidler.setMessage(message); buidler.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { result.confirm(); } }); buidler.setCancelable(false); buidler.create().show(); return true; } //若返回true,则WebView不处理JavaScript的输入事件,由自己编写的程序处理JavaScript的输入事件 //若返回false,则WebView处理JavaScript的输入事件 @Override public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) { Log.d(TAG, "zwm, onJsPrompt, url: " + url); //约定的message协议为:js://webview?arg1=111&arg2=222 Uri uri = Uri.parse(message); if (uri.getScheme().equals("js")) { if (uri.getAuthority().equals("webview")) { String arg1 = uri.getQueryParameter("arg1"); String arg2 = uri.getQueryParameter("arg2"); Log.d(TAG, "zwm, JS调用Android, 来自JS, arg1: " + arg1 + ", arg2: " + arg2); } result.confirm("来自Android"); return true; } return super.onJsPrompt(view, url, message, defaultValue, result); }});

方式对比

控件 -- WebView -- Android与JS交互_第2张图片 方式对比

更多相关文章

  1. 删除android ScrollView边界阴影方法
  2. Android显示网络图片相关实现方法浅谈
  3. android 中Drawable跟Bitmap转换及常用于图片相关操作方法 - And
  4. Android屏幕自适应的四种方法
  5. Android中隐藏ActionBar的方法
  6. 在线升级android studio的方法
  7. Android View类属性及方法
  8. android事件分发机制总结
  9. Android ListView getView()方法重复调用导致position错位

随机推荐

  1. UDP广播遇到的坑
  2. Android使用WindowManager构造悬浮view
  3. java.lang.UnsatisfiedLinkError: dlopen
  4. Android(安卓)检测软键盘的弹起与隐藏
  5. 【转】Android中保存Activity的状态
  6. android源码中makefile文件中各参数说明
  7. Android中的Service组件详解
  8. Android(安卓)Studio 新建页面和跳转
  9. Android的menu(菜单)按钮的使用(by星空武
  10. 2012传智播客黑马程序员内部视频