今天就跟大家聊聊有關(guān)android怎么與HTML混合開發(fā),可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
為武進(jìn)等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計制作服務(wù),及武進(jìn)網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務(wù)為網(wǎng)站制作、成都網(wǎng)站設(shè)計、武進(jìn)網(wǎng)站設(shè)計,以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會得到認(rèn)可,從而選擇與我們長期合作。這樣,我們也可以走得更遠(yuǎn)!
1、關(guān)于HTML5種cookie
網(wǎng)頁中可能會用到 用戶信息等很多參數(shù),可以提前把這些信息放到cookie中,可以采用以下方法:
public static void addCookies(Context context, WebView webView, String url) { String url=“https://www.xxxx.com/xx/xx/” String protocol = ""; String authority = ""; try { URL urlObj = new URL(url); protocol = urlObj.getProtocol(); authority = urlObj.getAuthority(); } catch (Exception e) { e.printStackTrace(); } String ua = webView.getSettings().getUserAgentString(); webView.getSettings().setUserAgentString(Constant.PROJECT_NAME + "/" + ParamHandler.getVersion(context) + "(" + ua + "; HFWSH)"); if (!TextUtils.isEmpty(url) && !TextUtils.isEmpty(protocol) && !TextUtils.isEmpty(authority)) { if (protocol.equals("https") && authority.indexOf("liepin.com") > -1) { CookieSyncManager.createInstance(context); CookieManager cookieManager = CookieManager.getInstance(); cookieManager.setAcceptCookie(true); try { List<String> data = getCookiesString(); if (!ListUtils.isEmpty(data)) { for (String value : data) { cookieManager.setCookie(url, value); } } cookieManager.setCookie(url, "client_id=" + Constant.CLIENT_ID + ";path=/;domain=.XXXX.com"); cookieManager.setCookie(url, "appVersion=" + Constant .VERSION + ";path=/;domain=.XXXX.com"); CookieSyncManager.getInstance().sync(); } catch (Exception e) { LogUtils.e("Exception:" + e.getMessage()); } } } }
public List<String> getCookiesString() { ArrayList data = new ArrayList(); this.clearExpired(); Collection values = this.mCookies.values(); Iterator var3 = values.iterator(); while(var3.hasNext()) { SwiftCookie c = (SwiftCookie)var3.next(); data.add(c.toCookieString()); } return data; }
在 mWebView.loadUrl(Url)之前添加cookie,網(wǎng)頁就可以通過cookie取到相應(yīng)的參數(shù)值了。
2、關(guān)于js的安全問題
js在4.2以前有漏洞
通過JavaScript,可以訪問當(dāng)前設(shè)備的SD卡上面的任何東西,甚至是聯(lián)系人信息,短信等。好,我們一起來看看是怎么出現(xiàn)這樣的錯誤的。
1,WebView添加了JavaScript對象,并且當(dāng)前應(yīng)用具有讀寫SDCard的權(quán)限,也就是:android.permission.WRITE_EXTERNAL_STORAGE
2,JS中可以遍歷window對象,找到存在“getClass”方法的對象的對象,然后再通過反射的機(jī)制,得到Runtime對象,然后調(diào)用靜態(tài)方法來執(zhí)行一些命令,比如訪問文件的命令.
3,再從執(zhí)行命令后返回的輸入流中得到字符串,就可以得到文件名的信息了。然后想干什么就干什么,好危險。核心JS代碼如下:
function execute(cmdArgs) { for (var obj in window) { if ("getClass" in window[obj]) { alert(obj); return window[obj].getClass().forName("java.lang.Runtime") .getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs); } } }
解決方案:
1,Android 4.2以上的系統(tǒng)
在Android 4.2以上的,google作了修正,通過在Java的遠(yuǎn)程方法上面聲明一個@JavascriptInterface,如下面代碼:
class JsObject { @JavascriptInterface public String toString() { return "injectedObject"; } } webView.addJavascriptInterface(new JsObject(), "injectedObject"); webView.loadData("", "text/html", null); webView.loadUrl("javascript:alert(injectedObject.toString())");
2,Android 4.2以下的系統(tǒng)
這個問題比較難解決,但也不是不能解決。
首先,我們肯定不能再調(diào)用addJavascriptInterface方法了。關(guān)于這個問題,最核心的就是要知道JS事件這一個動作,JS與Java進(jìn)行交互我們知道,有以下幾種,比prompt, alert等,
這樣的動作都會對應(yīng)到WebChromeClient類中相應(yīng)的方法,對于prompt,它對應(yīng)的方法是onJsPrompt方法,這個方法的聲明如下:
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result)
通過這個方法,JS能把信息(文本)傳遞到Java,而Java也能把信息(文本)傳遞到JS中,通知這個思路我們能不能找到解決方案呢?
經(jīng)過一番嘗試與分析,找到一種比較可行的方案,請看下面幾個小點(diǎn):
【1】讓JS調(diào)用一個Javascript方法,這個方法中是調(diào)用prompt方法,通過prompt把JS中的信息傳遞過來,這些信息應(yīng)該是我們組合成的一段有意義的文本,可能包含:特定標(biāo)識,方法名稱,參數(shù)等。
在onJsPrompt方法中,我們?nèi)ソ馕鰝鬟f過來的文本,得到方法名,參數(shù)等,再通過反射機(jī)制,調(diào)用指定的方法,從而調(diào)用到Java對象的方法。
【2】關(guān)于返回值,可以通過prompt返回回去,這樣就可以把Java中方法的處理結(jié)果返回到Js中。
【3】我們需要動態(tài)生成一段聲明Javascript方法的JS腳本,通過loadUrl來加載它,從而注冊到html頁面中,具體的代碼如下:
javascript:(function JsAddJavascriptInterface_(){ if (typeof(window.jsInterface)!='undefined') { console.log('window.jsInterface_js_interface_name is exist!!');} else { window.jsInterface = { onButtonClick:function(arg0) { return prompt('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onButtonClick',args:[arg0]})); }, onImageClick:function(arg0,arg1,arg2) { prompt('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onImageClick',args:[arg0,arg1,arg2]})); }, }; } } )()
說明:
1,上面代碼中的jsInterface就是要注冊的對象名,它注冊了兩個方法,onButtonClick(arg0)和onImageClick(arg0, arg1, arg2),如果有返回值,就添加上return。
2,prompt中是我們約定的字符串,它包含特定的標(biāo)識符MyApp:,后面包含了一串JSON字符串,它包含了方法名,參數(shù),對象名等。
3,當(dāng)JS調(diào)用onButtonClick或onImageClick時,就會回調(diào)到Java層中的onJsPrompt方法,我們再解析出方法名,參數(shù),對象名,再反射調(diào)用方法。
4,window.jsInterface這表示在window上聲明了一個Js對象,聲明方法的形式是:方法名:function(參數(shù)1,參數(shù)2)
3、在html5中進(jìn)行java和js的交互
1)、方法一:
mWebView.getSettings().setJavaScriptEnabled(true); mWebView.addJavascriptInterface(this, "xxx");
然后在當(dāng)前類中實(shí)現(xiàn)以下方法:
@JavascriptInterface public void callbackFromH5(final String j) { //TODO }
callbackFromH5的名字必須和網(wǎng)頁中的js方法名一樣
Java調(diào)用js方法:
mWebView.loadUrl(String.format("javascript:java2js(0)"));//這里是java端調(diào)用webview的JS
js方法名需要和網(wǎng)頁端一直
2)方法二:
jsbridge方法(https://github.com/lzyzsd/JsBridge)
Android JsBridge 就是用來在 Android app的原生 java 代碼與 javascript 代碼中架設(shè)通信(調(diào)用)橋梁的輔助工具
1 將jsBridge.jar引入到我們的工程
Android Studio:
repositories { // ... maven { url "https://jitpack.io" } } dependencies { compile 'com.github.lzyzsd:jsbridge:1.0.4' }
2、布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <!-- button 演示Java調(diào)用web --> <Button android:id="@+id/button" android:layout_width="match_parent" android:text="@string/button_name" android:layout_height="dp" /> <!-- webview 演示web調(diào)用Java --> <com.github.lzyzsd.jsbridge.BridgeWebView android:id="@+id/webView" android:layout_width="match_parent" android:layout_height="match_parent" > </com.github.lzyzsd.jsbridge.BridgeWebView> </LinearLayout>
3、java代碼
//加載服務(wù)器網(wǎng)頁 webView.loadUrl("https://www.baidu.com"); //必須和js同名函數(shù)。 webView.registerHandler("submitFromWeb", new BridgeHandler() { @Override public void handler(String data, CallBackFunction function) { String str ="html返回給java的數(shù)據(jù):" + data; makeText(MainActivity.this, str, LENGTH_SHORT).show(); Log.i(TAG, "handler = submitFromWeb, data from web = " + data); function.onCallBack( str + ",Java經(jīng)過處理后:"+ str.substring(,)); } }); //模擬用戶獲取本地位置 User user = new User(); Location location = new Location(); location.address = "xxx"; user.location = location; user.name = "Bruce"; webView.callHandler("functionInJs", new Gson().toJson(user), new CallBackFunction() { @Override public void onCallBack(String data) { makeText(MainActivity.this, "網(wǎng)頁在獲取你的信息", LENGTH_SHORT).show(); } }); webView.send("hello");
webView.callHandler("functionInJs", "data from Java", new CallBackFunction() { @Override public void onCallBack(String data) { // TODO Auto-generated method stub Log.i(TAG, "reponse data from js " + data); } });
js調(diào)用
var str1 = document.getElementById("text1").value; var str2 = document.getElementById("text2").value; //調(diào)用本地java方法 window.WebViewJavascriptBridge.callHandler( 'submitFromWeb' , {'param': str} , function(responseData) { document.getElementById("show").innerHTML = "send get responseData from java, data = " + responseData } ); //注冊事件監(jiān)聽 document.addEventListener( 'WebViewJavascriptBridgeReady' , function() { callback(WebViewJavascriptBridge) }, false ); //注冊回調(diào)函數(shù),第一次連接時調(diào)用 初始化函數(shù) connectWebViewJavascriptBridge(function(bridge) { bridge.init(function(message, responseCallback) { console.log('JS got a message', message); var data = { 'Javascript Responds': 'Wee!' }; console.log('JS responding with', data); responseCallback(data); }); bridge.registerHandler("functionInJs", function(data, responseCallback) { document.getElementById("show").innerHTML = ("data from Java: = " + data); var responseData = "Javascript Says Right back aka!"; responseCallback(responseData); }); })
4、關(guān)于webView的優(yōu)化
1、設(shè)置WebView 緩存模式
private void initWebView() { mWebView.getSettings().setJavaScriptEnabled(true); mWebView.getSettings().setRenderPriority(RenderPriority.HIGH); mWebView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT); //設(shè)置 緩存模式 // 開啟 DOM storage API 功能 mWebView.getSettings().setDomStorageEnabled(true); //開啟 database storage API 功能 mWebView.getSettings().setDatabaseEnabled(true); String cacheDirPath = getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME; // String cacheDirPath = getCacheDir().getAbsolutePath()+Constant.APP_DB_DIRNAME; Log.i(TAG, "cacheDirPath="+cacheDirPath); //設(shè)置數(shù)據(jù)庫緩存路徑 mWebView.getSettings().setDatabasePath(cacheDirPath); //設(shè)置 Application Caches 緩存目錄 mWebView.getSettings().setAppCachePath(cacheDirPath); //開啟 Application Caches 功能 mWebView.getSettings().setAppCacheEnabled(true);
2、清除緩存
/** * 清除WebView緩存 */ public void clearWebViewCache(){ //清理Webview緩存數(shù)據(jù)庫 try { deleteDatabase("webview.db"); deleteDatabase("webviewCache.db"); } catch (Exception e) { e.printStackTrace(); } //WebView 緩存文件 File appCacheDir = new File(getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME); Log.e(TAG, "appCacheDir path="+appCacheDir.getAbsolutePath()); File webviewCacheDir = new File(getCacheDir().getAbsolutePath()+"/webviewCache"); Log.e(TAG, "webviewCacheDir path="+webviewCacheDir.getAbsolutePath()); //刪除webview 緩存目錄 if(webviewCacheDir.exists()){ deleteFile(webviewCacheDir); } //刪除webview 緩存 緩存目錄 if(appCacheDir.exists()){ deleteFile(appCacheDir); } }
3、在使用WebView加載網(wǎng)頁的時候,有一些固定的資源文件如js/css/圖片等資源會比較大,如果直接從網(wǎng)絡(luò)加載會導(dǎo)致頁面加載的比較慢,而且會消耗比較多的流量。所以這些文件應(yīng)該放在assets里面同app打包。
解決這個問題用到API 11(HONEYCOMB)提供的shouldInterceptRequest(WebView view, String url) 函數(shù)來加載本地資源。
API 21又將這個方法棄用了,是重載一個新的shouldInterceptRequest,需要的參數(shù)中將url替換成了成了request。
比如有一個圖片xxxxx.png,這個圖片已經(jīng)放在了assets中,現(xiàn)在加載了一個外部html,就需要直接把a(bǔ)ssets里面的圖片拿出來加載而不需要重新從網(wǎng)絡(luò)獲取。當(dāng)然可以在html里面將圖片鏈接換成file:///android_asset/xxxxx.png,
但是這樣這個html就不能在Android ,ios,WAP中公用了。
webView.setWebViewClient(new WebViewClient() { @Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) { WebResourceResponse response = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){ response = super.shouldInterceptRequest(view,url); if (url.contains("xxxxx.png")){ try { response = new WebResourceResponse("image/png","UTF-8",getAssets().open("xxxxx.png")); } catch (IOException e) { e.printStackTrace(); } } } // return super.shouldInterceptRequest(view, url); return response; } @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { WebResourceResponse response = null; response = super.shouldInterceptRequest(view, request); if (url.contains("xxxxx.png")){ try { response = new WebResourceResponse("image/png","UTF-",getAssets().open("xxxxx.png")); } catch (IOException e) { e.printStackTrace(); } } return response; } }
看完上述內(nèi)容,你們對android怎么與HTML混合開發(fā)有進(jìn)一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。
網(wǎng)頁題目:android怎么與HTML混合開發(fā)
當(dāng)前地址:http://aaarwkj.com/article12/pcdodc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站維護(hù)、網(wǎng)站排名、用戶體驗(yàn)、響應(yīng)式網(wǎng)站、面包屑導(dǎo)航、網(wǎng)站策劃
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)