1. 程式人生 > >android與js互動的方式(包括三種)

android與js互動的方式(包括三種)

關於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。那麼就攔截了對話方塊的彈出,那麼就可以放心的進行資料互動了。 對於為啥方式一有漏洞,可以自行百度。