iOS中使用schema協議調用APP和使用iframe開啟APP的例子

來源:互聯網
上載者:User

標籤:

在iOS中,需要調起一個app可以使用schema協議,這是iOS原生支援的,並且因為iOS系統中都不能使用自己的瀏覽器核心,所以所有的瀏覽器都支援,這跟android生態不一樣,android是可以自己搞核心的,但是iOS不行。

在iOS中提供了兩種在瀏覽器中開啟APP的方法:Smart App Banner和schema協議。

Smart App Banner

即通過一個meta 標籤,在標籤上帶上app的資訊,和開啟後的行為,例如:app-id之類的,代碼形如:

<meta name="apple-itunes-app" content="app-id=myAppStoreID, affiliate-data=myAffiliateData, app-argument=myURL">

具體可以看下開發文檔:https://developer.apple.com/library/ios/documentation/AppleApplications/Reference/SafariWebContent/PromotingAppswithAppBanners/PromotingAppswithAppBanners.html
今天Smart APP Banner不是我們的主角,我們說的是schema

使用schema URL來開啟iOS APP

schema類似自訂url協議,我們可以通過自訂的協議來開啟自己的應用,形如:

myapplink://# 例如 facebook的fb://# itunes的itms-apps://# 還有簡訊也是類似的sms://

如果要開啟一個app,最簡單的方式是通過一個連結,如我們在html中這樣寫:

<a href="myapplink://">開啟我的app</a>

當使用者點選連結的時候就可以開啟對應的app。

綁定click事件

但是實際中我們更多的情況是綁定事件,比如做個彈層啥的,不能一味的用a標籤啊,所以可以通過兩種方式來解決:location.href和iframe。

iframe的方式是開發中常用的,但是他也有一些問題:

1.我們沒很好的方式來判斷是否開啟了app
2.會引起history變化
3.因為引起history變化,所以一些webview會有問題,比如:我查查,開啟一個頁面,如果有iframe,選擇在safari中開啟,實際開啟的是iframe的頁面
4.如果頁面暴漏給了android系統,那麼也會出現頁面打不開,之類的問題
5.如果沒有app,調起不成功,ios的safari會自己彈出一個對話方塊:打不開網址之類的提示

所以現在的問題是:如何知道iframe已經開啟了某個app,即解決iframe開啟app回調。

使用iframe在iOS系統中開啟app

聰明的你可能想到了,iframe的onload事件啊,可是遺憾的說,無效!所以我們找到了定時器(setTimeout),通過一個定時器,如果在一段時間內(比如500ms),當點擊了按鈕(記錄time1),頁面沒有切走(調起app之後,頁面進程會被中斷),進程中斷,那麼計時器也會中斷,這時候應該不會觸發timer,如果調起失敗,那麼timer會就觸發,我們判斷下在一定時間內如果頁面沒有被切走,就認為調起失敗。

另外通過timer觸發時候的timer2,做差,判斷是否太離譜了(切走了之後的時間應該比timer實際定時的500ms要長):

function openIos(url, callback) {    if (!url) {        return;    }    var node = document.createElement(‘iframe‘);    node.style.display = ‘none‘;    var body = document.body;    var timer;    var clear = function(evt, isTimeout) {       (typeof callback===‘function‘) &&  callback(isTimeout);        if (!node) {            return;        }        node.onload = null;        body.removeChild(node);        node = null;       };    var hide = function(e){        clearTimeout(timer);        clear(e, false);    };    node.onload = clear;    node.src = url;    body.appendChild(node);    var now = +new Date();    //如果事件失敗,則1秒設定為空白    timer = setTimeout(function(){        var newTime = +new Date();          if(now-newTime>600){            //因為切走了,在切回來需要消耗時間            //所以timer即使執行了,但是兩者的時間差應該跟500ms有較大的出入            //但是實際並不是這樣的!            clear(null, false);          }else{            clear(null, true);          }    }, 500);}

看上去方法很靠譜,但是現實總是那麼的殘酷!

不同的瀏覽器app(包括webview),都有自己在背景常駐時間,即:假如一個瀏覽器他在被切走之後,後台常駐10s,那麼我們設定定時器5s到期就是徒勞的,而且5s的定時器,使用者要空等5s!互動也不讓你這樣幹啊!

最後我們想到了pageshow和pagehide事件,即如果瀏覽器被切走到了要開啟的app,應該會觸發瀏覽器的pagehide事件,而從app重新返回到瀏覽器,就會觸發pageshow方法。

但是經過代碼測試發現,在uc、chrome中,不會觸發pagehide和pageshow的方法,而在safari中可以的。

結論:

1.使用iframe調用schema URL
2.使用定時器判斷在一段時間內是否調起成功
3.使用pageshow和pagehide來輔助定時器做更詳細的判斷
4.定時器中如果有alert可能不會被彈出,這一點很吃驚!後面的dom竟然5.執行了,但是alert沒彈出,可能跟alert的實現有關係吧
6.在實驗中我使用了兩個定時器,是因為切回瀏覽器之後,有時候timeout觸發要在pagehide和pageshow之前
7.計算timer實際執行時間差,也是不靠譜的

最後附上研究的代碼,算是比較靠譜的方法了,雖然還是有一定的失敗(第三方瀏覽器pagehide和pageshow不觸發):

 <button id="btn">點我點我啊!alert,不會彈出</button>  <button id="btn2">點我點我啊!alert2,雖然有alert和info,info執行,但是alert不彈出</button>  <button id="btninfo">點我點我啊!info可以</button>    $(function(){    var $info = $(‘#info‘);    function info(msg){    var p = $(‘ ‘+msg+‘ ‘);    $info.append(p);  }    $(‘#btn‘).on(‘click‘, function(){    openIos(‘baiduboxapp://‘, function(t){      if(t){        alert(‘timeout or no baidu APP‘);      }else{        alert(‘invoke success‘);      }    });  });  $(‘#btn2‘).on(‘click‘, function(){    openIos(‘baiduboxapp://‘, function(t){      if(t){        info(‘timeout or no baidu APP2‘);        alert(‘timeout or no baidu APP2‘);      }else{        info(‘invoke success2‘);        alert(‘invoke success2‘);      }    });  });  $(‘#btninfo‘).on(‘click‘, function(){    openIos(‘baiduboxapp://‘, function(t){      if(t){        info(‘timeout or no baidu APP‘);      }else{        info(‘invoke success‘);      }    });  });  });  function openIos(url, callback) {    if (!url) {        return;    }    var node = document.createElement(‘iframe‘);    node.style.display = ‘none‘;    var body = document.body;    var timer;    var clear = function(evt, isTimeout) {       (typeof callback===‘function‘) &&  callback(isTimeout);        window.removeEventListener(‘pagehide‘, hide, true);        window.removeEventListener(‘pageshow‘, hide, true);        if (!node) {            return;        }          node.onload = null;        body.removeChild(node);        node = null;      };    var hide = function(e){        clearTimeout(timer);        clear(e, false);    };    window.addEventListener(‘pagehide‘, hide, true);    window.addEventListener(‘pageshow‘, hide, true);    node.onload = clear;    node.src = url;    body.appendChild(node);    var now = +new Date();    //如果事件失敗,則1秒設定為空白    timer = setTimeout(function(){        timer = setTimeout(function(){          var newTime = +new Date();          if(now-newTime>1300){            clear(null, false);          }else{            clear(null, true);          }          }, 1200);    }, 60);}


iOS中使用schema協議調用APP和使用iframe開啟APP的例子

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.