移動瀏覽器H5頁面經過scheme打開本地應用

在移動端瀏覽器H5頁面中,點擊按鈕打開本地應用主要經過 scheme 協議。本文主要介紹如何在瀏覽器H5頁面中經過 scheme 協議打開本地應用。javascript

scheme協議定義

scheme 是一種頁面之間跳轉的協議,不只能夠用於app之間進行跳轉,還能夠用於 H5 頁面跳轉到app頁面。html

不管Android仍是IOS,均可以經過在H5頁面中打開 scheme 協議的地址,從而打開本地app。java

scheme 協議定義和 http 協議相似,都是標準的 URI 結構。android

[scheme:][//host:port][path][?query][#fragment]
  • scheme : 協議名稱 - 必須
  • host : 協議地址 - 必須
  • port : 協議的端口,能夠不填
  • path : 協議路徑,可用 / 鏈接多個
  • query : 攜帶的參數可用 & 鏈接多個
  • fragment : 錨點

下面看一個例子:web

wexin://tencent.com:8080/dl/news/open?data=902323&params=test
  • weixin : 協議名稱
  • tencent.com : 域名
  • 8080 : 端口
  • /dl/news/open : 頁面的路徑
  • data, params : 傳遞的參數

URI中的參數若是包含特殊字符,須要預先進行url編碼,不然的話URI可能不能打開。數組

在 Android 中聲明實現 scheme

要使得在瀏覽器或者別的應用中經過打開 scheme 協議來喚起應用,須要對該應用進行相關的配置。瀏覽器

首先須要在Android工程的 Manifest文件,給想要接收跳轉的Activity添加 intent-filter 節點的配置攔截器規則微信

<activity
    <!--定義響應該scheme協議的 activity 的名稱 -->
    android:name=".DeepLinkActivity"
    <!--須要添加下面的intent-filter配置-->
    <intent-filter>
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <!--scheme 容許在瀏覽器中打開-->
        <category android:name="android.intent.category.BROWSABLE"/>
        <!--scheme 相關信息配置-->
        <data android:scheme="uuopen"
              android:host="uusama.com"/>
    </intent-filter>
</activity>

上面的 data 節點中能夠包含下面的信息來對相應的scheme進行過濾,通常須要配置 scheme 和 host。app

<data 
    android:scheme=""
    android:host=""
    android:port=""
    android:path=""
    android:mimeType=""
    android:pathPattern=""
    android:pathPrefix=""
    android:ssp=""
    android:sspPattern=""
    android:sspPrefix=""/>

而後在相應的 activity 能夠獲取 uri 中參數。ide

public class DeepLinkActivity extends AppCompatActivity {
    private static final String TAG = "DeepLinkActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent = getIntent();
        Log.e(TAG, "scheme:"  + intent.getScheme());
        Uri uri = intent.getData();
        Log.e(TAG, "scheme: " + uri.getScheme()); // 獲取 scheme 名稱
        Log.e(TAG, "host: " + uri.getHost());     // 獲取 scheme 的host
        Log.e(TAG, "path: " + uri.getPath());     // 獲取 scheme 的路徑
        Log.e(TAG, "queryString: "+  uri.getQuery()); // 獲取 scheme 的參數,?後面的部分
        Log.e(TAG, "queryParameter: " + uri.getQueryParameter("param")); // 獲取 scheme 中的 param 參數
    }
}

其中的 intent 實例有下面的方法能夠獲取相應的 scheme 信息:

  • getScheme() :獲取Uri中的scheme名稱:[scheme:]
  • getSchemeSpecificPart() :獲取Uri中的scheme-specific-part:部分:[//host:port][path]
  • getFragment() :獲取Uri中的Fragment部分:[#fragment]
  • getAuthority() :獲取Uri中Authority部分:[//host:port]
  • getPath() :獲取Uri中path部分:[path]
  • getQuery() :獲取Uri中的query部分:[?query]
  • getHost() :獲取Authority中的Host字符串
  • getPost() :獲取Authority中的Port字符串
  • List< String> getPathSegments() :依次提取出Path的各個部分的字符串,以字符串數組的形式輸出
  • getQueryParameter(String key) :獲取query部分中 key 對應的參數值

在瀏覽器中打開 scheme

在瀏覽器中打開 scheme 就像打開一個不一樣的http地址同樣。能夠在一個 a 標籤中打開。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Scheme</title>
</head>
<body>
<a href="wexin://" id="open">打開應用</a>
</body>
</html>

點擊上面的H5頁面中的連接將會嘗試喚醒微信,在一些瀏覽器中,可能會彈出一個提示框,詢問用戶是否容許打開應用。

若是打開的 scheme 在本地沒有對應的 app,則點擊鏈接不會反應。

固然還可使用 JavaScript 代碼打開,只須要添加相應的事件觸發和處理便可。

在JavaScript代碼中打開鏈接有如下幾種方式:

  • 新建一個隱藏的 iframe ,地址指向須要打開的url
  • 使用 window.location 或者 window.location.href 刷新當前頁面
  • 新建一個隱藏的 a 標籤,地址指向打開的url,並觸發打開連接事件
  • 動態建立一個script腳本,在這個腳本中新建一個a標籤並打開
// 打開url的方式
var urlOpen = {
    'iframe' : function(url) {
        var iframe = document.createElement('iframe');
        iframe.style.display = 'none';
        iframe.src = url;
        document.body.appendChild(iframe);
    },
    'location' : function(url) {
        window.location = url;
    },
    'href' : function(url) {
        var a = document.createElement('a');
        a.style.display = 'none';
        a.href = url;
        document.body.appendChild(a);
        a.click();
    },
    'script' : function(url) {
        var script = document.createElement('script');
        script.setAttribute('type', 'test/javascript');
        script.innerHTML = '(function(){' +
            'var a = document.createElement("a");' +
            'a.style.display = "none";' +
            'a.href = "' + url.replace(/"/g, '\\"') + '";' +
            'document.body.appendChild(a);' +
            'a.click();' +
            '})()';
        document.body.appendChild(script);
    },
    'open' : function(url) {
        window.open(url);
    }
};

瀏覽器判斷是否安裝應用

不少時候用戶在瀏覽器中打開 scheme 連接的時候,用戶不必定安裝了應用,這個時候打開會失效,咱們但願打開這個動做應該下載應用。這個時候須要判斷用戶是否安裝應用。

其實判斷用戶是否安裝某個應用的方法,就是直接打開這個應用的 scheme,查看是否打開成功。可是這就是問題之所在。

咱們沒法在瀏覽器中準確地知道打開 scheme 是否成功,瀏覽器或者系統沒有給我麼這樣的回調。咱們只能用迂迴的方法去判斷。

好比在JavaScript中判斷頁面是否進入後臺來判斷打開成功。有下面這些事件和屬性能夠利用:

  • pagehide : 頁面隱藏時觸發
  • visibilitychange : 頁面隱藏沒有在當前顯示時觸發(切換tab也會觸發該事件)
  • document.hidden : 當頁面隱藏時,該值爲true,顯示時爲false

上面這些事件或者屬性並非全部瀏覽器都支持。下面是一個給出爲 id 爲 open 的按鈕添加打開scheme或者下載事件的例子。

var downloader, 
    scheme = 'weixin://',  // 須要打開的 scheme 地址
    download='index';  // 若是打開scheme失效的app下載地址

// 給 id 爲 open 的按鈕添加點擊事件處理函數
document.getElementById('open').onclick = function () {
        window.location.href = scheme;  // 嘗試打開 scheme 

        // 設置3秒的定時下載任務,3秒以後下載app
        downloader = setTimeout(function(){
            window.location.href = download;
        }, 3000);
    };

    document.addEventListener('visibilitychange webkitvisibilitychange', function () {
        // 若是頁面隱藏,推測打開scheme成功,清除下載任務
        if (document.hidden || document.webkitHidden) {
            clearTimeout(downloader);
        }
    });
    window.addEventListener('pagehide', function() {
        clearTimeout(downloader);
    });
}

對於經過判斷打開 scheme 的耗時來確實是否打開應用的作法是很容易失效的,由於沒法判斷打開成功之後,頁面的JS是否還在執行,並且打開應用的耗時也是不可控的。

總之,沒有完美的解決方案在H5頁面中判斷本地是否安裝了某個應用,不過使用監聽當前頁面是否隱藏的方法可以很大程度的做爲判斷依據。

也有的應用無論用戶是否安裝應用,用戶點擊連接的時候,同時打開 scheme 和拉起下載頁面,這種方式犧牲了很大的用戶體驗。

侷限性

這種經過 scheme 打開本地應用的方式並非全部瀏覽器都支持,尤爲是在微信瀏覽器中是不支持使用 scheme 打開應用的,除非微信官方添加了白名單。QQ瀏覽器中卻是支持。

並且一些瀏覽器會詢問用戶是否打開,而另一些則直接打開應用。

通常的作法是,判斷當前瀏覽器是否爲微信,若是是微信的話,則彈出一個遮罩層,提示用戶使用其餘瀏覽器打開。

還有就是在微信瀏覽器中使用應用寶的微下載,將當前頁面重定向到應用寶的下載頁面,不過這種方式的轉化率很低。

有一個好消息是,在IOS9.0以上的系統中,可使用 universal links 打開本地應用,不過Android不支持。

另一個備選方案是,在微信瀏覽器中,使用iframe的方式打開一個包體地址(.apk結尾的url)進行下載時,會拉起一個選擇框,讓你選擇打開的應用。不過這種方式對於某些域名無效,對於一些特殊的下載文件無效,如不能下載.rar的文件。並且對於已經安裝了應用的用戶來講,用戶體驗也很差。

使用這種技術的同時,考慮到其不肯定性,應該作好備選方案。充分考慮到該頁面的用戶羣體是否主要爲新用戶,以及訪問的瀏覽器分佈,從而制定相應的對用戶來講比較友好的引導和備選方案。

原文出處:http://uusama.com/493.html

相關文章
相關標籤/搜索