天天看點

5分鐘搞懂Android DeepLink

最近碰到了一個新的需求,使用者在浏覽器中打開分享出去的内容,如果該使用者裝置上有我們的用戶端則打開用戶端并且定位到目前文章,如果沒有的話則進行下載下傳。調研過程中遇到了不少的坑,這裡share一下。

先看一下效果

5分鐘搞懂Android DeepLink

獻上代碼

html源碼

<!doctype html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

        <meta name="apple-mobile-web-app-capable" content="yes">
        <meta name="apple-mobile-web-app-status-bar-style" content="black"/>

        <title>this's a demo</title>
        <meta id="viewport" name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,minimal-ui">
    </head>
    <body>
        <div>
            <a id="J-call-app" href="javascript:;" class="label">立即打開&gt;&gt;</a>
            <input id="J-download-app" type="hidden" name="storeurl" value="http://m.chanyouji.cn/apk/chanyouji-2.2.0.apk">
        </div>

        <script>
            (function(){
                var ua = navigator.userAgent.toLowerCase();
                var t;
                var config = {
                    /*scheme:必須*/
                    scheme_IOS: 'will://',
                    scheme_Adr: 'will://share/testid',
                    download_url: document.getElementById('J-download-app').value,
                    timeout: 
                };
                function openclient() {
                    var startTime = Date.now();
                    var ifr = document.createElement('iframe');
                    ifr.src = ua.indexOf('os') >  ? config.scheme_IOS : config.scheme_Adr;
                    ifr.style.display = 'none';
                    document.body.appendChild(ifr);
                    var t = setTimeout(function() {
                        var endTime = Date.now();
                        if (!startTime || endTime - startTime < config.timeout + ) { 
                            window.location = config.download_url;
                        } else {

                        }
                    }, config.timeout);
                    window.onblur = function() {
                        clearTimeout(t);
                    }
                }
                window.addEventListener("DOMContentLoaded", function(){
                    document.getElementById("J-call-app").addEventListener('click',openclient,false);
                }, false);
            })()
        </script>
    </body>
</html>
           

基本思路:點選“立即打開“按鈕後如果在600毫秒後仍然沒有打開用戶端則跳到下載下傳連結;這裡大家可以任意改造,例如如果在指定時間之内沒有吊起用戶端,則打開詳情頁面等。

Android清單檔案中加入以下代碼
 <!-- 一定要在清單檔案中加入下面的intent filter !!!!!!!-->
        <activity android:name=".DeepLinkActivity">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data
                    android:host="share"
                    android:scheme="will" />
            </intent-filter>
        </activity>

**!!!!!注意:data中的host與scheme都要寫上才會生效**
           
在Activity中接受資料:
    /**
     * 從deep link中擷取資料
     */
    private void getDataFromBrowser() {
        Uri data = getIntent().getData();
        try {
            scheme = data.getScheme(); // "will"
            host = data.getHost(); // "share"
            params = data.getPathSegments();
            String testId = params.get(); // "uuid"
            tv_data.setText("Scheme: " + scheme + "\n" + "host: " + host + "\n" + "params: " + testId);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
           

好了這樣就可以實作在浏覽器中打開本地app(DeepLink)了,有的同學會問,這種方式的适配性如何?由于手頭機型有限,這裡列舉一下樓主測試過的機型與浏覽器。

5分鐘搞懂Android DeepLink

由于機型與精力所限,不能覆寫更多的機型了。請大家補充下哈。祭上官方文檔

https://developer.android.com/training/app-indexing/deep-linking.html#adding-filters

上面的文章是通過浏覽器打開用戶端

後期的文章我會詳細介紹native與h5的聯調中所踩的坑。這裡先介紹一種極其簡單的方式供大家把玩。

public class MainActivity extends AppCompatActivity {

    WebView web_main;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        web_main = (WebView) findViewById(R.id.web_main);

        web_main.loadUrl("file:///android_asset/h5.html");

        web_main.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {

                if (url.startsWith("will://")) {
                    Uri uri = Uri.parse(url);
                    Log.e("---------scheme: ", uri.getScheme() + "host: " + uri.getHost() + "Id: " + uri.getPathSegments().get());
                    Toast.makeText(MainActivity.this, "打開新的頁面", Toast.LENGTH_LONG).show();
                    return true; //傳回true,代表要攔截這個url
                }
                return super.shouldOverrideUrlLoading(view, url);
            }
        });
    }
}
           
5分鐘搞懂Android DeepLink

這樣就能實作輕量級的實作與網頁的互動了

源碼位址:https://github.com/WillSprint/DeepLink