貨拉拉Android H5離線方案
Android Hybrid 方案之 離線文件加載
可調式協(xié)議頁面chrome://inspect/#devices
圖片引自
更新及相關配置加載
上傳時將文件MD5值記錄,后通過接口以json方式下達,用以給客戶端校驗
菜單點擊后 ? 離線包版本,本地是否有 ? 無則當場加載 ? 有則離線加載
//離線包check請求后臺返參
{
"bisName":"enteprise-1.0.3", //業(yè)務線名-版本名(對應包名)
"updateFlag":0,//-1降一級-2降低兩級0沒有更新1更新
"downloadUrl":"",//下載包的地址
"effectMode":0,//0冷啟動生效 1:立即生效
"versionCode":12,//版本code碼
"versionName":"1.0.3",//版本codeName碼
"desc":"版本描述",
"md5":"ads123dsafgl1243kmk",
"whiteDomain":["http://www.baidu/com",""]//白色域名名單,只有這些才會被正確訪問,其它的譬如小視頻網(wǎng)站就會被攔截
}
//離線包check請求參數(shù)
{
"bisName":"業(yè)務線",//租戶號
"os":"android",//android、ios、pc、other
"versionCode":12
}
加載首頁規(guī)律
首頁地址:
host + 包文件名 + path + ...
示例:https://www.baidu.com/?offweb=act3-2108-turntable
需要包名是因為需要校驗解壓包中的index.html,以此判定是否有離線包
原生導航欄動態(tài)設置
H5頁面?zhèn)鬟f給原生數(shù)據(jù)標題欄根據(jù)如下數(shù)據(jù)配置進行動態(tài)更改,標題欄Topic不可隱藏,沒有時傳""
,isShowTitleBar用來動態(tài)控制標題欄是否隱藏true:展示 false:隱藏,默認不配制為顯示狀態(tài)
teaBarLeftBtn1 | teaBarTopic | teaBarRightBtn2 | teaBarRightBtn1 |
---|---|---|---|
左1按鈕 | 主標題 | 右二按鈕 | 右一按鈕 |
{
"isShowTitleBar":true,
"teaBarTopic": "主標題",
"teaBarLeftBtn1": {
"iconUrl": "",
"show": true
},
"teaBarRightBtn2": {
"iconUrl": "",
"show": true
},
"teaBarRightBtn1": {
"iconUrl": "",
"show": true
}
}
標題欄按鈕點擊調用js方法,js方法根據(jù)業(yè)務調用本地native方法或者自有邏輯,js方法分別為
teaBarLeftBtn1Tap(jsonParams);
teaBarRightBtn2Tap(jsonParams);
teaBarRightBtn1Tap(jsonParams);
過程:原生點擊 ? 原生調用JS的固定方法teaBarLeftBtn1Tap(jsonParams)
? JS進行點擊邏輯處理,其可以是JS自己的邏輯也可以調用native方法。
回調交互
- JS給原生傳入大量參數(shù)時使用prompt(),由原生攔截彈窗獲取prompt本來要彈框的內容
- JS定義名為
methodsCall(callCode,exeStatus,result)
的方法給原生調用。
說明:JS封裝回調統(tǒng)一方法methodsCall(callCode,exeStatus,result)
,exeStatus
目前只有success
,failure
,cancel
,此方法由Android調用JS統(tǒng)一處理回調code的方法,js自己封裝一份調用的類來統(tǒng)一管理原生調用與回調處理,JS需自己封裝超時處理,原生交互與后臺請求邏輯相似,交互習慣模仿微信小程序,cancell
時并不是調用錯誤,而是這個操作被原生取消,那么js從funMap中主動將本次緩存的調用方法移除即可。
示例:
//js封裝類中定義一個全局變量funcMap方法
const funcMap = new Map();
//js封裝類中定義一個方法名為`methodsCall`
function methodsCall(callCode,exeStatus,result){
console.log("回調callCode", "$callCode;$exeStatus;result");
const func = funcMap.get(callCode)
if(func){
func(exeStatus,result);
} else {
console.error(`No function registered for code: ${code}`);
}
funcMap.delete(callCode);
}
//js封裝類中定義一個方法用于被具體業(yè)務調用
selectFile(func){
const callCode = {即時生成callCode}
window.TeaJSBridge.selectFile(callCode);
funcMap.set(callCode,func);
}
//方法中設置超時從map中取消,且方法取消
//業(yè)務調用
selectFile(function(status,result){
//todo 具體業(yè)務邏輯
})
//Android端調用數(shù)據(jù)示例:js接收3個參數(shù),第三個不同方法數(shù)據(jù)也會不同
javascript:methodsCall('1001','success','{"size":56952,"kbsize":55.6171875,"fileExt":"jpg","path":"%2Fstorage%2Femulated%2F0%2FAndroid%2Fdata%2Fcom.xyzl.android.mpass%2Fcache%2F1739504957884%2F2038.jpg"}')
前端打包
- 靜態(tài)資源打離線包使用相對路徑
缺失:真實前端打包、前端真實網(wǎng)絡調用
JS可調用的原生方法。
帶 * 號的是Android與ios都有該方法,不帶 * 號的暫時只有Android擁有該方法
示例:
window.TeaJSBridge.selectFile("10003");
說明:window對象掛載的對象名稱為:TeaJSBridge
;JS需要拿回調結果的話第一個參數(shù)傳入callCode;在Android中若原生方法的入?yún)ocallCode則可以直接返回String不走回調
- initTitlebar(String params)
每個頁面都必須調用的方法,傳入的字符串為固定格式,具體見標題原生導航欄動態(tài)設置
下 json字符串 - *selectFile(String callCode) 選擇文件(DucumentFile方式選擇)
//方法返回數(shù)據(jù)
Android:
{"size":1812186,"kbsize":1769.712890625,"fileExt":"mp4","path":"%2Fstorage%2Femulated%2F0%2FAndroid%2Fdata%2Fcom.xyzl.android.mpass%2Fcache%2F1740562622403%2Fstart-55b51670.mp4"}
把返回值傳給uploadFile即可完成上傳(json與地址字符串都支持)
- *uploadFile(String callCode,String path) 上傳文件
返回給js調用端的數(shù)據(jù)由服務端透傳 - *takePhoto(String callCode) 拍照
//返回結果為URLEncoder之后的路徑;ios暫時沒有使用URLEncoder進行編碼
%2Fstorage%2Femulated%2F0%2FAndroid%2Fdata%2Fcom.xyzl.android.mpass%2Ffiles%2FPictures%2Fimage_2828668122646479783.png
- *openAlbum(String callCode,int openType) 打開相冊 openType=0:單選,openType>0多選,ios暫不支持多選,但是ios支持相冊選擇視頻
//相冊的結果:
同上 selectFile(String callCode) 返回值
* encrypt(String callCode,String content)無需回調直接返回加密字符串(僅Android可用)
* decrypt(String content)解密字符串,種子在原生端定義不可傳入(僅Android可用)
- setStorage(String fileName, String key, String value) 本地存儲
- getStorage(String fileName, String key) 獲取本地存儲
- *closeH5() H5主動關閉自己
- *prePage() 前一頁,若不可退則結束當前WebView
- *goPage(String routeUrl, boolean singleWebView) 前往路由所在頁,singleWebView為true時在原實例上跳轉路由,singleWebView為false時新開一個原生Activity
- *goBackOrForward(int step) 前進或后退步數(shù)頁,step為正負整數(shù),若不可退則結束當前WebView
- *downloadBySysBrowser(String url) 傳入一個下載鏈接調用系統(tǒng)瀏覽器進行下載,WebView本身只有下載觸發(fā)接口不具備下載功能
- *poiSearch(String callCode, String keyword, String city, double lat, double lng, int radius, int pageNum, int pageSize)此方法為定位點附近的興趣點搜索,搜索結果會返回一個地址列表,入?yún)?code>radius為半徑,
keyword
為興趣點搜索關鍵字,只需要獲取附近地址列表時建議為空,其將搜索默認數(shù)據(jù)
[{"name":"北京建工","address":"江蘇省南京市雨花臺區(qū)雨花南路與雨花大道交叉口東80米","latitude":31.99254,"longitude":118.782037},{"name":"中興通訊南京雨花一期研發(fā)中心東區(qū)","address":"江蘇省南京市雨花臺區(qū)紫荊花路68號","latitude":31.989445,"longitude":118.776352},{"name":"南京閱城農(nóng)貿(mào)市場管理有限公司","address":"江蘇省南京市雨花臺區(qū)紫荊花路與花神大道交叉口東220米","latitude":31.988048,"longitude":118.77701},{"name":"長發(fā).諸公營銷中心","address":"江蘇省南京市雨花臺區(qū)雨花南路5號","latitude":31.993232,"longitude":118.778289},{"name":"中興","address":"江蘇省南京市雨花臺區(qū)紫荊花路68號","latitude":31.989945,"longitude":118.77488}]
- *geocodeSearch(String callCode, double latitude, double longitude, float radius) 逆地理編碼,將坐標轉為話文字地理信息,附帶默認的poi列表信息,
radius
為檢索半徑
{"address":"江蘇省南京市雨花臺區(qū)雨花街道雨花臺中學(紫荊花路校區(qū))","poiList":[{"name":"雨花臺中學(紫荊花路校區(qū))","address":"江蘇省南京市雨花臺區(qū)紫荊花路","latitude":31.988721,"longitude":118.779096}]}
- *getLocation(String callCode) 獲取定位信息
{
"title": "潤和創(chuàng)智中心",
"address": "江蘇省南京市雨花臺區(qū)才智路18號B棟潤和創(chuàng)智中心",
"latitude": 31.97288,
"longitude": 118.757841,
"city": "南京市"
}
Android端返回的多余字段可以輔助調試查看
showLoading(String txtContent,boolean cancellable) 展示一個加載框,可添加提示語、可控制是否點擊可退出,txtContent為空時提示語不展示hideLoading() 隱藏加載框relogin(boolean cover) 重新登錄,cover = true:用于當前頁面沒登錄不能查看時展示登錄頁面,此時登錄頁面覆蓋在當前頁面,登錄完成后當前頁面會刷新,cover = false:用于結束掉所有頁面全新重登錄- *scanQr(String callCode) 掃描二維碼,返回二維碼信息字符串
- checkNfcStatus()檢測NFC狀態(tài),返回值有 1:有NFC并且已經(jīng)打開、-1:NFC尚未打開、0:沒有NFC。
- 接收NFC結果;NFC需要前端自己根據(jù)之前的JS SDK進行function注冊,原生只對NFC的觸發(fā)結果負責,當觸發(fā)后我們針對固定CallCode進行調用,原生端callcode = 20008;觸發(fā)后返回給js通用接收方法的結果格式為
{
"content": "",//NFC掃碼結果
"cardId": ""http://NFC卡片id
}
-
showDateTimePicker(String formatMode,String callCode)調用一個原生時間選擇彈框
image.png
formatMode的值如下:
public static final String FORMAT_MODE_1 = "YYYY-MM-DD HH:MM:SS";
public static final String FORMAT_MODE_2 = "YYYY-MM-DD";
public static final String FORMAT_MODE_3 = "YYYY-MM-DD HH:MM";
暫未實現(xiàn)方法:
recordVoice
openSignBoard
playMedia