app中的webview通識篇(上)

前言

若是你仍是第一次與app合做開發webview的頁面,那麼對於如何調試,可能有哪些問題多是不夠了解的。本文嘗試性的根據本身的經驗給你們一個入門級別的瞭解,若是是大佬級別的,能夠繞路了。javascript

webview協議約定

爲了更好的在app中調試開發咱們的移動頁面(h5),咱們須要與app開發人員約定一些基本的原則,來保證咱們的頁面能夠很好的進行調試,包括調試工具、靈活的模擬上線時的app環境、測試交互過程當中的問題、方便自定義的修改成本身的h5地址等。前端

如下的方案僅供參考,每一條都是有實際用途的,若是公司裏的webview須要進行準確的調試和後續開發,必要性的須要考慮如下的問題。java

主題 方案 備註
統一肯定的ua標識 好比ua結尾加入【xxx】
h5公用的app頭 app端提供統一的app頭,參考支付寶以及微信的ua交互,提供顯示頁面標題,返回,關閉的簡單操做,默認頁面可滾動 以後其餘的h5默認在這個類瀏覽器外殼中,針對前端一些固定佈局的方案,須要優化完善這個外殼,前端技改時間容許的話,最好給出完整肯定的方案能夠在webview中無縫對接和展現
h5與app定製頭 針對產品以及交互特殊需求,提供的特殊頁面,好比單頁,強交互邏輯頁定製專門的頭 須要產品明確說明特殊性,不是瀏覽器的返回,好比返回須要加確認框,就須要定製
h5與app功能性交互 約定常規交互方法的格式,並給出相互通信的一些固定的可用的方法,好比獲取用戶信息,獲取app網絡狀態 這個是雙向的功能性交互,h5的一些方法也能夠設置app的狀態,頁面跳轉,數據存儲等
h5與app純交互性方法 調取相應app的加載框,加載失敗,相冊控件,掃碼控件 須要與產品,交互統一肯定是否使用app原生控件仍是h5效果。
h5與app不一樣場景的分享互通 好比:用戶在不一樣app中:app分享到h5詳情頁,h5詳情頁也能夠對應到app中打開 須要約定規則
app提供webview的外殼 能夠經過app外殼掃碼進入webview場景,模擬交互,開發階段暴露解決一些app中問題 以上的app解決方案集成在這個app外殼中

關於 app內webiew與h5通信狀況

做爲常識咱們知道,通常狀況下webview的頁面是包括兩種狀況的,一種是原本就可能限定於只有app會嵌入的h5頁面,這部分在與app進行通信的時候,咱們更多的是經過約定jsBridge的方式。一種是普通的h5頁面。ios

jsBridge說的更直白一點,就是網頁在載入時,向頁面內注入一個指定的js文件,而後頁面內就會有一個前端和app都知道的方法,經過這個方法前端能夠喚起app的交互控件,甚至是跳轉到其餘的app頁面,也能夠知道app此時的一些設備狀態、網絡狀態、用戶信息等。而app也能夠經過h5知道此時頁面的狀態,進而根據須要作能夠在必要時喚起想要的操做。git

而另外一方面,webview也可看作一個普通的瀏覽器,能夠載入任何的頁面,因此咱們非app的內嵌頁的h5也能夠在app內經過webview進行打開; 而app外的h5能夠經過app自定義的協議碼來喚起app。github

相關的通信技術點可見下面的簡陋的圖說明。web

jsBridge參考文檔

iOS與H5交互說明(ios)

iOS與H5交互,採用是JavaScriptCore方式。原理是iOS端在WebView加載完一個URL連接的時候,手動向H5頁面綁定一個JSContext對象。利用這個JSContext對象,能夠實現OC與JS間的雙向交互。注意:JSContext對象是在iOS的webViewDidFinishLoad:回調裏完成綁定的,在完成綁定前沒法使用JS與OC的任何交互。objective-c

JS調用OC接口

JS開始調用OC接口前,有幾個前提條件:

  • js的window.isReady方法已經觸發過了,JS才能調用OC提供的方法。緣由是iOS會在JSContext對象綁定成功後,纔會向js端調用isReady方法,因此js只有等isReady觸發了,才能經過JSContext調用OC方法。chrome

  • iOS在綁定JSContext對象的時候,要約定好一個字段,而後OC會將原生方法註冊到網頁window對象的這個字段上。好比window.appjson

  • js端若是要異步接收原生方法的返回結果,須要在全局做用域內定義好回調方法

JS示例代碼:

js調用OC原生方法,同步獲取用戶基本信息

// 約定好獲取用戶信息接口註冊到window的app屬性上
// getUserInfo方法是一個同步方法,能夠js端能夠直接獲取到返回值
// 返回的對象能夠是json字符串
var info = window.app.getUserInfo()
複製代碼

js調用OC原生方法,拍照上傳做業圖片,並異步獲取上傳結果

// 假設約定好做業相關的OC接口都註冊到window的homework屬性上
window.homework.uploadHomeworkPicture(questionID)

// 在全局做用域內定義好回調方法,用於接收返回值
// 原生方法會在上傳完做業圖片的時候,間接調用該回調方法
function homeworkPictureDidUploaded(questionID, picUrl) {
  	// do something...
}
複製代碼

JS裏調用通用原生接口:

/** 跳轉到課程詳情 @param productId 商品ID(string類型) */
app.gotoCourseDetail(productId);

/** 關閉當前頁面 */
app.finish();

/** 獲取用戶信息,已json字符串形式返回。主要字段以下: memberId: 用戶id token: 用戶登陸惟一標識 memberType: 用戶類型 */
app.getUserInfo();

/** toast提示 @param msg 提示語(string類型) */
app.toast(msg);

/** 顯示對話框 @param title 標題(string字符串) @param msg 消息(string字符串) @param actions 點擊事件(一個json數組字符串),每一個數組元素字段以下: title: 事件標題(string字符串,好比「取消」) callback: 事件的js回調方法(string字符串) 示例: var actions = "[{'title': '取消', 'callback': 'cancelPay'}, {'title': '肯定', 'callback': 'confirmPay'}]"; app.confirm("舒適提示", "是否支付訂單?", actions); */
app.confirm(title, msg, actions);
複製代碼

OC調用JS接口

OC在調用JS方法時的注意事項:

  • js方法應該申明到全局做用域內,不然OC獲取不到該方法

  • 若是在webViewDidFinishLoad:直接用過JSContext調用js方法,可能會出現調用無效的請求。爲了不此類問題,推薦以setTimeout方式調用js方法

示例代碼:

OC在webViewDidFinishLoad:中調用js的isReady方法

// setTimeout是JS的自帶方法
// 這裏使用setTimeout的目的是爲了將isReady方法放到js調用隊列的最後
JSValue *isReadyFunc = self.jsContext[@"isReady"];
if (isReadyFunc) {
	[self.jsContext[@"setTimeout"] callWithArguments:@[isReadyFunc, @100]];
}
複製代碼

OC在JS發起的原生方法中調用js的setUserInfo方法

// 注意,JavaScriptCore支持NSDictionary、NSArray類型做參數傳給js方法
NSDictionary *userInfo = ...;
[self.jsContext[@"setUserInfo"] callWithArguments:@[userInfo]];
複製代碼

JS提供給原生調用的通用接口定義:

/** iOS原生初始化完成後調用本方法,告訴js已經準備好了 */ 
function isReady();

/** * return boolean 類型返回值: true h5已經處理了返回,native不處理; false h5沒有處理返回,native直接返回上級原生頁面 */
function gobackIfNeeded();
複製代碼

APP喚醒

定義scheme: com.xxx.app

UserAgent

WebView的默認UserAgent爲:"xxxx XXX/1.3.0", 其中xxxx爲系統默認UserAgent。''/''後爲app版本號

內嵌H5頁面的加載(安卓)

1.原生提供一個框架頁面給H5頁面。框架只提供一個叫InnerWeb的類(這點js不須要知曉).如何須要在本地加載一個純H5的內嵌頁面,請使用IntentHelper.startWeb(Context context, String url)方法去載入一個內嵌H5頁面。具體內部只是加載這個url。以後的邏輯都交給H5處理。

Android本地經過Java調用HTML頁面中的JavaScript方法

原生調用js方法分一下兩種類型的方法:

  1. 無返回值方法
  2. 有返回值方法

調用js中無返回值方法

很簡單,咱們直接調用便可具體代碼示例以下:

/** * f1 爲js中聲明的函數 */
mWebView.loadUrl("javascript:f1()");
複製代碼

這樣就能夠調用js的方法了。

調用js中有返回值的方法

稍微複雜一點,以下:

/** * sum 爲js中定義的函數 */
mWebView.evaluateJavascript("sum(1,2)", new ValueCallback<String>() {
        @Override
        public void onReceiveValue(String value) {
            Log.e(TAG, "onReceiveValue value=" + value);
        }
    });
複製代碼

js調用Android本地Java方法

本地提供給js調用的映射對象,這須要注入,咱們同一使用一個叫app的對象。js如要調用本地方法。都以此開頭來表明咱們原生方法。

具體以下:

<script type="text/javascript">
     function s(){
     // 注意下面的‘app’
    var result = window.app.gotoLogin();
    document.getElementById("p").innerHTML = result;
    }
</script>
複製代碼

本地代碼以下:

public calss AppJavascriptInterface {

  	@JavascriptInterface
  	public void gotoLogin() {
        if (mContext.get() == null) {
            Log.w("web", "頁面已關閉");
            return;
        }
        LoginActivity.start(mContext.get());
    }
}
複製代碼

產品協議

協議的主要以原生提供給H5的爲主, 下面是我詳細羅列的:

/** * 跳轉登陸 */
@JavascriptInterface
public void gotoLogin();
/** * 跳轉課程詳情 */
@JavascriptInterface
public void gotoCourseDetail();
/** * 關閉當前頁面 */
@JavascriptInterface
public void finish();
/** * 關閉當前頁面獲取當前用戶信息,若是爲空,說明用戶未登陸 * * 目前有以下信息(以json格式返回給H5): * memberId: 用戶id * token: 用戶登陸惟一標識 * memberType: 用戶類型 */
@JavascriptInterface
public String getUserInfo();

/** * 返回 * * 目前有以下信息(以json格式返回給H5): * memberId: 用戶id * token: 用戶登陸惟一標識 * memberType: 用戶類型 */
public void back();

/** * */
public void toast(String msg);

public void confirm(String title, String msg, String positiveFunctionName, String negativeFunctionName);
複製代碼
/** * return boolean 類型返回值: true h5已經處理了返回,native不處理; false h5沒有處理返回,native返回上一個非H5頁面 */
function gobackIfNeeded(); 複製代碼

app的喚醒方式方案:

1.定義scheme: com.xxx.app

2.另外具體頁面的打開待定

約定ua: "xxxx XXX/1.3.0", 其中xxxx爲系統默認ua。iOS與Android不同。"/"後爲app版本號

h5喚起app

h5喚起app已經變成了目前不可或缺的功能之一,做爲前端技術棧的必備技術棧之一,咱們須要知道如何在非app環境內喚起app,以及正確識別是系統中是否安裝了app.

系統相關

應用名稱 URL Scheme
短信 sms://
app store itms-apps://
電話 tel://
無線局域網 App-Prefs:root=WIFI
藍牙 App-Prefs:root=Bluetooth
蜂窩移動網絡 App-Prefs:root=MOBILE_DATA_SETTINGS_ID
我的熱點 App-Prefs:root=INTERNET_TETHERING
運營商 App-Prefs:root=Carrier
通知 App-Prefs:root=NOTIFICATIONS_ID
通用 App-Prefs:root=General
通用-關於本機 App-Prefs:root=General&path=About
通用-鍵盤 App-Prefs:root=General&path=Keyboard
通用-輔助功能 App-Prefs:root=General&path=ACCESSIBILITY
通用-語言與地區 App-Prefs:root=General&path=INTERNATIONAL
通用-還原 App-Prefs:root=Reset
牆紙 App-Prefs:root=Wallpaper
Siri App-Prefs:root=SIRI
隱私 App-Prefs:root=Privacy
Safari App-Prefs:root=SAFARI
音樂 App-Prefs:root=MUSIC
音樂-均衡器 App-Prefs:root=MUSIC&path=com.apple.Music:EQ
照片與相機 App-Prefs:root=Photos
FaceTime App-Prefs:root=FACETIME

應用

應用名稱 URL Scheme
微博 weibo://
QQ mqq://
QQ羣組 mqqapi://card/show_pslcard?src_type=internal&version=1&card_type=group&uin={QQ羣號}
QQ聯繫人 mqqapi://card/show_pslcard?src_type=internal&version=1&uin={QQ號碼}
支付寶 alipay://
微信 weixin://
微信 wechat://
微信-掃一掃 weixin://dl/scan
微信-反饋 weixin://dl/feedback
微信-朋友圈 weixin://dl/moments
微信-設置 weixin://dl/settings
微信-消息通知設置 weixin://dl/notifications
微信-聊天設置 weixin://dl/chat
微信-通用設置 weixin://dl/general
微信-公衆號 weixin://dl/officialaccounts
微信-遊戲 weixin://dl/games
微信-幫助 weixin://dl/help
微信-我的信息 weixin://dl/profile
微信-功能插件 weixin://dl/features
蝦米音樂 xiami://
chrome googlechrome://
微博國際版 weibointernational://
摩拜單車 mobike://
ofo ofoapp://
有道雲筆記 youdaonote://
印象筆記 evernote://
今日頭條 snssdk141://
網易新聞 newsapp://
網易雲音樂 orpheuswidget://
QQ音樂 qqmusic://
QQ音樂最近播放 qqmusic://today?mid=31&k1=2&k4=0
美團外賣 meituanwaimai://
美團 imeituan://
Gmail googlegmail://
網易郵箱 neteasemail://
QQ郵箱 qqmail://
騰訊視頻 tenvideo://
愛奇藝 iqiyi://
12306 cn.12306://
有道詞典 yddict://
釘釘 dingtalk://

參考文章

相關文章
相關標籤/搜索