前端學習筆記:通過H5頁面呼叫不同客戶端的原生頁面

王先生2019加油發表於2019-04-02

前言

昨天遇到一個非常有趣的需求場景,背景如下:我們是一家電商平臺,經常會做一些商品的促銷專題活動。昨天我司產品經理找到我和APP的開發工程師,希望我們解決一個問題:在APP端點選專題活動中的商品,開啟的頁面是H5頁面,而不是客戶端的原生頁面。產品經理希望開啟原生頁面,以讓使用者獲得更好的體驗。見下圖,左圖是在APP中打H5頁面,右圖是在APP中開啟APP原生頁面。

前端學習筆記:通過H5頁面呼叫不同客戶端的原生頁面

原因

發現了問題以後,我初步瞭解了導致這個問題的原因。原來,APP端展示的專題活動頁面和小程式一樣,採用的是webview的解決方案,即APP指定一個物件(我覺得是路徑,不過據我司APP開發工程師介紹,APP中只有物件的說法,沒有路徑的說法),接收H5頁面的連結,並將連結中的HTML鋪到APP的物件(路徑)中。使用者點選專題中的商品連結也是同樣的方式,因此最後展示出來的商品詳情頁就是H5頁面,而不是客戶端的原生頁面。

小程式、安卓、蘋果各不相同

小程式的處理邏輯

我目前在公司主要是負責小程式端的。在此之前,我接觸過小程式類似的業務場景。在小程式中如果想要實現類似的邏輯,需要在H5頁面的頭部引入一段JS程式碼。這段JS程式碼的主要作用,是在window物件中加入一個新的名為wx的屬性。這個屬性是一個物件,有自己的屬性和方法。通過呼叫wx.miniProgram.getEnv()方法,並傳入一個回撥函式,即

wx.miniProgram.getEnv(res => {
    if(res.miniProgram) {
        //小程式環境
        let url;
        wx.miniProgram.navigateTo({url: url});
    } else {
        //微信中開啟內建瀏覽器
    }
})
複製程式碼

以上判斷完成之後,就完成了在小程式端跳轉到原生頁面的邏輯。

安卓客戶端的處理邏輯

因為有這個基礎,我下意識認為APP端如果想要實現類似的邏輯,也需要先引入一段類似的JS程式碼。但和APP工程師溝通後發現,客戶端的API已經支援了這段JS程式碼需要實現的功能。我司APP工程師還給我展示了一段之前使用的程式碼:

if(window.android) { //判斷android物件是否存在
   window.android.navigateTo(url); //呼叫android分享
} else {
   //呼叫ios支付方法!
   window.webkit.messageHandlers.navigateTo.postMessage(url);
}
複製程式碼

我的猜想是這樣的:客戶端(Android、iOS)中APP工程師通過API提供的方法,給JS的執行環境window增加了對應的屬性:Android客戶端增加的屬性是android,iOS客戶端增加的屬性是webkit。這兩個屬性都是物件,在給這兩個屬性增加對應的方法以後,就可以直接在JS程式碼中引用了。為了證明我的猜想,我特意百度了一下“通過js呼叫android原生方法”,發現了以下這段程式碼。

//設定webview
myWebView = (WebView) findViewById(R.id.myWebView);
myWebView.getSettings().setJavaScriptEnabled(true);
myWebView.addJavascriptInterface(new JavaScriptinterface(this),"android");
myWebView.setWebViewClient(new myWebViewClient());

//建立JavaScriptinterface類
public class JavaScriptinterface {
    Context context;
    public JavaScriptinterface(Context c) {
        context= c;
    }

    /**
     * 與js互動時用到的方法,在js裡直接呼叫的
     */
    @JavascriptInterface
    public void showToast(String ssss) {

        Toast.makeText(mContext, ssss, Toast.LENGTH_LONG).show();
    }
}

//在JS中呼叫android原生方法
<script type="text/javascript">   
function showToast() {       
    android.showToast("哈哈啊哈 ");
     }
</script>

</head>
<body>
<input type="button" value="呼叫"
     onClick="showToast()"/>
</body>
複製程式碼

雖然沒有學過客戶端的相關知識,但這個邏輯還是一目瞭然的。從這段程式碼也可以看出,安卓客戶端除了可以指定方法的名稱外,還可以指定設定在window物件下的屬性的名稱,也就是上一行程式碼中的window.android。你可以改成window.Android、window.app,由app工程師指定。

確認該屬性的名稱後,再為這個屬性新增方法,這個方法由H5頁面的前端工程師和app開發工程師約定名字。app開發工程師實現邏輯跳轉,前端工程師直接引用,即可實現跳轉到app的原生頁面。

蘋果客戶端的解決邏輯

與安卓客戶端的實現邏輯一樣,蘋果客戶端也是在window物件下新增指定的屬性,在該屬性下面新增方法,即可跳轉到指定的app原生頁面。不過需要注意的是,由於客戶端API版本的不同,可能引用的方式也不同。目前我已經接觸到了以下兩個引用方式:

//第一種引用方式
window.webkit.messageHandlers.shareLink.postMessage(shareData);
//第二種引用方式
window.RequiredSkill.shareLink(shareData)
複製程式碼

總結

由於之前主要工作在小程式端,所以初次接觸該問題時,習慣性的用了小程式的處理思路。也是第一次接觸到和客戶端的JS互動方式,感覺比較有意思,所以記錄下來。

另外一個收穫是,以前一直以為window物件就是指瀏覽器中的window;但通過解決這個問題發現,小程式、APP端也有相應的window物件,而且小程式和APP端的window物件還有獨有的屬性。想想確實是這個道理,不同的瀏覽器window物件的屬性都不同,更何況不同的客戶端?

相關文章