手機瀏覽器開啟APP ,或者導向App Store or Google Play下載

若使用者有安裝APP,則自動啟用,若無安裝,則導向下載頁面。

在 iOS 之前,如果要從各種瀏覽器啟動APP,都必須透過 URI Scheme

在 iOS9 之後的版本,只要你的應用程式支援 Universal Links(通用連結),就可以直接透過HTTP來啟動APP (在此不討論Universal Links)

下表格分別比較幾種瀏覽器啟動APP的方式:

Universal Link Android App Link URI Scheme Chrome Intent
系統版本 >= iOS 9 >= Android 6 Chrome1 < 25, iOS Chrome1 >= 25
未安裝APP 開啟 Web 開啟 Web 錯誤警示 開啟 Web
能否不發生跳轉 不能 不能
前往下載地址 不能
iFrame觸發 不能 不能 Chrome1 <= 18, iOS < 9 不能
連結組成 正常的 URL 正常的 URL 自定義 URL 格式 自定義 intent URL

(來源: http://harttle.land)

url scheme

scheme 是 Web 端和App約定好的一個URL協議,也可夾帶參數、路徑…。

手機如果安裝APP,理論上都能透過 url scheme 的方式來開啟APP

myappname://

可以根據需求來添加參數,在APP接收參數再進行對應的處理

以 Twitter APP Scheme為例:

twitter://user?id=12345
twitter://timeline
twitter://mentions
twitter://messages
twitter://list?screen_name=lorenb&slug=abcd
twitter://post?message=hello%20world
twitter://search?query=%23hashtag

[有安裝APP的情況]

直接透過Http來動

透過這樣的方式就能直接開啟 twitter app

window.location="twitter://post?message=hello%20world";

備註: 直接透過 scheme 方式,在 iOS9.0以上的版本,若未安裝APP,則會多跳出一個無效頁面 若有APP,則也會多一個確認視窗 若想強化這些體驗,可考慮研究 Universal Links 解決方式。

沒有安裝APP的情況

“若有安裝APP,當APP開啟時,Web頁面會暫時掛著”

我們可以透過這樣的方式來判斷是否有安裝APP,若無安裝APP則導向下載

var beforeTime = Date.now();//(1) 先取得目前時間

window.location="Scheme連結";//(2) 開啟APP scheme,若scheme 有被開啟,網頁會暫時被掛著

setTimeout(function () {
	var afterTime = Date.now();//(3) 此時間會直到APP返回時才會取得 (如果沒有安裝APP,理論上,很快就會取得這個時間)
	if(beforeTime - afterTime < 時間參數){
    	window.location = "App Store or Google Play 下载页面";//(4) 研判沒有安裝APP,引導到下載頁
	}
}, 延遲時間);

啟動APP 實作,依照不同系統來設計啟動APP方式

開啟APP的方式在 Android, iOS, WindowsPhone 都不同

  function AndroidOpenApp(){
    var before = new Date().valueOf();
    setTimeout(function(){
      var after = new Date().valueOf();
      if(after - before > 200){ return; }
      window.location = ('https://play.google.com/store/apps/details?id=com.twitter.android');
    },50);  
    window.location = ("twitter://post?message=hello%20world%23thisisyourhashtag.");
  }
  
  function iOSOpenApp(){
    var before = new Date().valueOf();
    setTimeout(function () {
      var after = new Date().valueOf();
      if(after - before > 2000){ return; }
      window.location = ('https://itunes.apple.com/tw/app/twitter/id333903271?mt=8');
    }, 1000);
    window.location = ('twitter://post?message=hello%20world');
    // window.location = 'googletranslate://';
  }

Chrome Intent

Chrome for Android 25 之後的環境,就能透過 Chrome Intent 來啟動APP

Chrome Intent 基本格式如下:

   HOST/URI-path // Optional host 
   <URL>#Intent; 
      package=[string]; 
      action=[string]; 
      category=[string]; 
      component=[string]; 
      scheme=[string]; 
      S.browser_fallback_url=要返回的路徑;

例如,啟動掃描QR Code APP的 Intent

window.location = ("intent://scan/#Intent;scheme=zxing;package=com.google.zxing.client.android;end");

另外再舉例,開啟 twitter APP的 Intent範例

  AndroidChromeOpenApp(){
    window.location = ("intent:twitter#Intent;scheme=twitter://post?message=hello%20world;package=com.twitter.android;end");
  }

Iframe 方式,在現行版本測試會有問題

透過 iframe 拋出 scheme 連結的方式,來啟動 App

在過去,透過建立一個iframe 生成器的方式

能在背景拋出 scheme 連結,啟動APP

但是這種方式,目前實測都會發生 scheme 無法偵測到 onload 事件的問題

由於使用 scheme 無法偵測到 onload 事件,因此在啟動APP之後,仍會繼續前往 Store

(src若改成一般網址,onload就會被偵測到)

不確定在不同裝置是否會正常運作,因此有興趣的朋友也可以參考,測試看看:

  crateIframe = (function(){
      let iframe;
      return function(obj){
          var timer  = setTimeout(function(){
            window.location=obj.store_url;
          },1000);
          
          if(iframe){
            iframe.onload = function(){
              clearTimeout(timer);
            }
            iframe.src=obj.url;
          }else{
            iframe = document.createElement('iframe');
            iframe.style.display = 'none';
            iframe.onload = function(){
              clearTimeout(timer);
            }
            iframe.src=obj.url;
            document.body.appendChild(iframe);
          }
      }
  }
  )();
  
  function IframeOpenApp(){
      crateIframe({
        url:"twitter://post?message=hello%20world",
        store_url:"https://play.google.com/store/apps/details?id=com.twitter.android"
      });
  }