android与js交互的方式(包括三种)

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u012808234/article/details/53583927

关于android月js或者说html交互的方式,在很早的版本中是通过android端添加js支持,然后传递一个js操作本地方法的对象,然后就可以调用本地的方法。在后边的版本为了统一管理,添加了@JavascriptInterface  ,只有添加了这个标志的方法才能被js调用。

但是这样的调用方式还是存在安全的漏掉,所有后边就有了另外的俩种调用方式。

方式 一:

WebSettings webSettings = mWebView.getSettings();
		webSettings.setJavaScriptEnabled(true);
	mWebView.addJavascriptInterface(new JSObject(), "myObj");  
	添加js支持,传递调用本地方法的对象到js中。


方式二:


主要是监听shouldOverrideUrlLoading 方法,该方法是WebViewClient中实现的方法。

mWebView.setWebViewClient(new WebViewClient(){

		@Override
		public boolean shouldOverrideUrlLoading(WebView view, String url) {
				
				return super.shouldOverrideUrlLoading(view, url);
		}
	});
下边是对自己定义好的参数进行处理,因为只要点击网页中的任何按钮都会调用
shouldOverrideUrlLoading方法,所有要进行不同请求方式的不同处理。http与https让他还是默认访问本来地址,对于自己要处理的本地请求做本地处理
@Override
            public boolean shouldOverrideUrlLoading(WebView view, String url)
            {
                if (url.startsWith("http") || url.startsWith("https"))
                {
                	return super.shouldOverrideUrlLoading(view, url);
                }else{
                	Log.i("jw", "url:"+url);
    				//协议url:"js://demo?arg1=111"
    				try {
    					//只处理指定协议
    					String protocol = JSBridge.getUrlScheme(url);
    					JSBridge bridge = new JSBridge(mContext);
    					if("baidumobilegamejsload".equals(protocol)){
    						HashMap<String,String> map = JSBridge.getUrlParams(url);
    						String method = JSBridge.getUrlMethod(url);
    						JSONObject jsonObject = new JSONObject();
    						if(method.equals("downloadGame")){//下载游戏
    							String pkg = map.get(JSBridge.PACKAGER);
    							String title = map.get(JSBridge.TITLE);
    							String gameId = map.get(JSBridge.GAMEID);
    							String size = map.get(JSBridge.SIZE);
    							String download_url = map.get(JSBridge.DOWNLOADURL);
    							String icon_url = map.get(JSBridge.ICONURL);
    							String version = map.get(JSBridge.VERSION);
    							bridge.downloadGame(pkg, title, gameId, size, download_url, icon_url, version);
    						}else if(method.equals("isInstall")){//应用是否安装
    							
    							jsonObject.put(JSBridge.RESULT, bridge.isInstall(map.get(JSBridge.PACKAGER)));
    						
    						}else if(method.equals("startApp")){//打开应用
    							
    							bridge.startApp(map.get("packageName"));
    							
    						}else if(method.equals("checkStatus")){//检查应用的状态,0、未下载 ,1、已安装 。2、下载中(暂停)
    							
    							jsonObject.put(JSBridge.STATUS, bridge.getDownloadAppStatus( map.get("JSBridge.PACKAGER"), map.get(JSBridge.DOWNLOADURL)));
    						
    						}else if(method.equals("continueDownloadGame")){
    							
    							bridge.restartDownloadGame(map.get(JSBridge.DOWNLOADURL));
    						
    						}else if(method.equals("installGame")){
    							
    							bridge.installOrOpenGame(map.get(JSBridge.DOWNLOADURL));
    						}else if(method.equals("getDownloadGameProgress")){
    							int progress = bridge.getDownloadGameProgress(map.get(JSBridge.DOWNLOADURL));
    							jsonObject.put(JSBridge.PROGRESS, progress);
    						
    						}
    						mWebView.loadUrl("javascript:sys("+jsonObject.toString()+")");
    						return true;   
    					}
    				} catch (Exception e) {
    					Log.i("jw", "error:"+Log.getStackTraceString(e));
    				}
                }
            	
				return false;
            }


方式三:

方式三与方式二十分相似,是来拦截onJsAlert(js对话框),或者onJsConfirm(确认对话框)或者onJsPrompt(可编辑文本框)来进行js对于本地代码的请求。
但是要注意的是只有onJsPrompt可以传递数据到js,前边俩个只能接收js调用本地方法的请求,没有办法进行参数回传。
mWebView.setWebChromeClient(new WebChromeClient(){

			//拦截JS的alert方法
			@Override
			public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
				return super.onJsAlert(view, url, message, result);
			}

			//拦截JS的confirm方法
			@Override
			public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
				return super.onJsConfirm(view, url, message, result);
			}

			//拦截JS的prompt方法
			@Override
			public boolean onJsPrompt(WebView view, String url, String message, String defaultValue,
					JsPromptResult result) {
				Log.i("jw", "url:"+url+",message:"+message);
				//协议url:"js://demo?arg1=111"
				try {
					//只处理指定协议
					String protocol = getUrlScheme(message);
					if("js".equals(protocol)){
						HashMap<String,String> map = getUrlParams(message);
						String arg1 = map.get("arg1");//获取到指定key的参数值,调用本地方法
						String res = getPwd(arg1);
						result.confirm(res);//返回值
					}
				} catch (Exception e) {
					Log.i("jw", "error:"+Log.getStackTraceString(e));
				}
				
				return true;
			}
			
		});

这就是基本使用方式,但是要注意的是alert等框的弹出的处理,因为我们只是要交换数据,没有必要弹出对话框。
只要在拦截的方法里边return的 时候不调用相对应的super就可以拦截对话框的弹出,
直接返回true。那么就拦截了对话框的弹出,那么就可以放心的进行数据交互了。


对于为啥方式一有漏洞,可以自行百度。

展开阅读全文

没有更多推荐了,返回首页