android與js互動的方式(包括三種)
阿新 • • 發佈:2019-02-19
關於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。那麼就攔截了對話方塊的彈出,那麼就可以放心的進行資料互動了。 對於為啥方式一有漏洞,可以自行百度。