通用連結(Universal Links)實踐筆記

躍然發表於2017-03-03

一、實現大致思路

前提條件:
1. 支援https的伺服器
我使用的是阿里雲伺服器,ssl證照使用的是pianyissl.com的測試證照,可以免費使用三個月。配好證照,使用tomcat、nginx部署環境。
2. 伺服器繫結域名
3. 在伺服器根目錄上傳apple-app-site-association檔案
效果需要滿足訪問https:domain.com/apple-app-site-association 能夠下載或者開啟json內容

二、開發中我的問題

  1. 微信中點選開啟App網頁按鈕,想一個連結同時相容iOS 9以上及以下。iOS9以上,點選連結直接進入app指定頁面,iOS9以下進入應用寶下載頁面。開發中遇到問題,微信網頁內使用js沒有找到判斷手機是否安裝了app,導致在未安裝app時候點選連結進入404頁面,展示很不好。開始嘗試將404頁面重定向到應用寶下載app頁面,這樣又出現app安裝時點選開啟按鈕無法啟動app。後來想了一個方法,終於解決了問題。
    a. 初始通用連結這樣寫:
    https://joeychang.me/s?name=test&url=http://baidu.com&type=2
    這樣可以實現通用連結,但是在iOS9以下及未安裝app情況下,連結無效。
    b. 後改成這樣https://joeychang.me/s.html?name=test&url=http://baidu.com&type=2
    https://joeychang.me/s.html檔案執行js重定向,使用者點選這個頁面,跳轉到應用寶下載頁。這樣可以相容iOS9以下及未安裝app情況。
    c. 再後來,為了和安卓統一,引數格式定為
    http://blog.joeychang.me/index.html?params={“type”:”3”,”url”:”http://baidu.com“,”name”:”test”}
    進入index.html這個頁面,js方法抓取到params,點選頁面內開啟按鈕,將引數傳遞給app,從未進入特定頁面。
    d. 為了處理特殊符號,將params={“type”:”3”,”url”:”http://baidu.com“,”name”:”test”}進行[urlEncode](http://tool.chinaz.com/tools/urlencode.aspx
    )之後再拼接到http://blog.joeychang.me/index.html?之後,生成長連結,再[短連結處理](http://dwz.wailian.work/
    )生成短連結。短連結即可分享。

  2. 從iOS 9.2開始,在相同的domain內Universal Links是不work的,必須要跨域才生效,我們實測值需要跨子域名即可,比如 m.domain.com 跳轉 o.domain.com 是可以觸發跳轉App。

    這個又踩到坑了,在這裡費了好長時間,最後還是和同事商討才找到的答案。
    apple-app-site-association檔案,s.html放在joeychang.me伺服器根目錄,是為同一個域名內,而開啟app.html為微信內喚醒app過渡網頁,這個放在blog.joeychang.me域名下,才成功跳轉。開始同樣放在joeychang.me域名下,怎麼也啟動不了,險些要放棄開發,後來換了下域名,問題解決。坑死人。

三、幾點注意:

  1. apple-app-site-association檔案不能帶字尾,務必把”.json”的字尾去掉!有些人的電腦是隱藏檔案字尾的,這要格外注意;

  2. apple-app-site-association要傳到域名根目錄或者/apple-app-site-association目錄下;

  3. 如果想測試這個功能,可以讓後臺搭一個測試伺服器,並繫結域名,然後iOS這邊通過host訪問域名就可以了。注意”applink:”後面寫的一定是域名,不能是IP;

  4. 抓包的結果顯示,網路順暢的情況下,應用會在在剛安裝(不是開啟)的時候會去applink中的地址下載apple-app-site-association檔案,所以如果需要測試,請保證網路通暢;

  5. 當所有都準備好,需要測試該功能的時候,只需要在記事本或簡訊中輸入App能識別的連結(例如:https://www.joeychang.me/s/oaze4qfl97hksef/IMG_0019%20%281%29.png?dl=0 ),然後直接點選或是長按就可以了,直接點的效果是跳轉到你的App,然後右上角是“去網頁”的箭頭,長按的效果是彈出的選單中第二項是“在’XXX’中開啟”,這也代表著成功。直接在Safari中輸入連結是無效的,必須從一處跳入才可以(比如上一級網頁)。

  6. 蘋果有個網址(這裡)可以檢測你的apple-app-site-association是否是有效的,準備好了可以測試一下。

  7. 測試的時候,建議使用dev證照打包,之後安裝到手機上測試功能。未安裝應用的情況下直接在手機上跑好像也是可以的,因為抓到過請求。

四、使用apple 的測試介面測試出現的問題:

蘋果測試網站

校驗時出現問題 Applinks validator “domain missing from entitlement”,查了下資料,有這樣說的:

This is the “App Search API Validation Tool”, not the “Universal Links Validation Tool” (which doesn’t exist from Apple). The results from this tool have no connection to whether Universal Links work or not.

This tool causes a lot of confusion, because domains that definitely work with Universal Links (https://google.com, https://jet.com, for example) still throw errors. Officially, it is comparing your website’s apple-app-site-association file to your app’s listing on the App Store, so if the version of your app that is publicly available does not yet have Universal Links entitlements, that will cause these errors. However, Universal Links will still work fine with local builds.

If your links are correctly opening your app, there is probably no need to worry.

我的實踐是,即使校驗不通過,只有配置檔案json格式正確,上傳目錄正確,就可以開啟應用。我出現的問題,apple-app-site-association內容,bundle Id中的teamId寫錯了,導致很長時間沒有找到出錯原因。後來對比了下蘋果開發者中心才發現問題所在。白白浪費了很多時間。

五、參考連結:

  1. Universal Links官方文件
  2. Universal Links – Make the Connection
  3. iOS Universal Links(通用連結) (很不錯的教程)
  4. 突破微信跳轉限制-Universal-Links那些坑
  5. 好文:iOS 9學習系列:打通 iOS 9 的通用連結(Universal Links)

六、附開啟app過渡頁.html示例原始碼

<!DOCTYPE html">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width,minimum-scale=1.0">

    <body bgcolor = "#FFEEDD">
    <input type="text" id="acti">
        <p>下載頁面<a href="javascript:;" onclick="open_iOS_App()">ios 點選連結</a></p>

    </body>

 <a href="" id="aaa"></a>

 <script type="text/javascript">

        var timeout;
        function open_iOS_App() {
            if (isWeiXin()) {
                open_App();
            }else{
                open_App();
                timeout = setTimeout('open_itunes()', 3000);
            };
        }

        function open_Android_App() {
            if (isWeiXin()) {
                open_android_weixin();
            }else{
                open_App_Android();
            };
        }

        function open_android_weixin() {
           var acti = document.getElementById("acti").value;
           var linkUrl = "xxxxxxxxxxxxx://utils?action=sendIntent¶ms=" + acti;
           var yingyongbaoUrl = "http://a.app.qq.com/o/simple?pkgname=com.xxxx.xxxxx&android_schema=" 
            + encodeURI(linkUrl);
           window.location = yingyongbaoUrl; 
        }

        function open_App() {

                     var ver = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/);  
                     ver = parseInt(ver[1], 10);  
                     if(ver<9)  
                     {  
                             if (isWeiXin()) {
                                open_weixin_App();
                             }else{
                                open_itunes();
                              }
                      } else{
                               var activity = document.getElementById("acti").value;  

                               document.getElementById("aaa").href = "https://joeychang.me/s.html?params="+ encodeURI(activity);

                               //  alert(document.getElementById("aaa").href);
                               // alert(activity);
                               document.getElementById("aaa").click();
                      } 
        }

        function open_App_Android() {
            var acti = document.getElementById("acti").value;
            window.location = "intent://xxxxxxxxx?params="+ acti +"#Intent;package=com.xxxx.xxxxx;scheme=xxxxxxx;launchFlags=268435456;end;";    
        }
        function open_itunes() {/* 開啟app store */
            window.location="http://itunes.apple.com/cn/app/idxxxxxxxx"; 
        }
                function open_weixin_App() {/* 開啟騰訊應用寶 間接跳轉 */
                var acti = document.getElementById("acti").value;
            window.location="http://a.app.qq.com/o/simple.jsp?pkgname=com.xxxx.xxxxx&activity=" + acti; 
        }

        /*
            判斷是否是微信瀏覽器
        */
        function isWeiXin(){
            var ua = window.navigator.userAgent.toLowerCase();
            if(ua.match(/MicroMessenger/i) == 'micromessenger'){
                return true;
            }else{
                return false;
            }
        }
        function linktoApp() {
                        var queryStr = decodeURI(window.location.search.substr(1));
                        var ua = navigator.userAgent.toLowerCase(); 
                        if (queryStr.indexOf("}") >= 0 && queryStr.indexOf("{") >= 0) {
                              var activity = queryStr.substring(queryStr.indexOf("{"), queryStr.lastIndexOf("}") + 1);
                              document.getElementById("acti").value = activity; 
                             if (/iphone|ipad|ipod/.test(ua)) {
                         // IOS
                         } else if (/android/.test(ua)) {
                        // Android
                                open_Android_App();
                         } else {
                                // 其他瀏覽器
                                window.location="http://a.app.qq.com/o/simple.jsp?pkgname=com.xxxxxxx.xxxxxxxx";
                             }
                         } else {
                              document.getElementById("acti").value = "引數格式錯誤"; 
                         }        
        }

        // 用js實現在載入完成一個頁面後自動執行一個方法
        /*用window.onload呼叫myfun()*/
        window.onload=linktoApp;//不要括號
    </script>
</head>
<body>
</body>
</html>

相關文章