5 分钟搞懂 Android DeepLink

5,989 阅读3分钟
原文链接: blog.csdn.net

最近碰到了一个新的需求,用户在浏览器中打开分享出去的内容,如果该用户设备上有我们的客户端则打开客户端并且定位到当前文章,如果没有的话则进行下载。调研过程中遇到了不少的坑,这里share一下。

先看一下效果
效果图

献上代码

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: 600
                };
                function openclient() {
                    var startTime = Date.now();
                    var ifr = document.createElement('iframe');
                    ifr.src = ua.indexOf('os') > 0 ? 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 + 200) { 
                            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(0); // "uuid"
            tv_data.setText("Scheme: " + scheme + "\n" + "host: " + host + "\n" + "params: " + testId);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

好了这样就可以实现在浏览器中打开本地app(DeepLink)了,有的同学会问,这种方式的适配性如何?由于手头机型有限,这里列举一下楼主测试过的机型与浏览器。
所测机型
由于机型与精力所限,不能覆盖更多的机型了。请大家补充下哈。祭上官方文档
developer.android.com/training/ap…


上面的文章是通过浏览器打开客户端
后期的文章我会详细介绍native与h5的联调中所踩的坑。这里先介绍一种极其简单的方式供大家把玩。

html中加入一个超链接    <a id="J-call-app" href="will://share/testId" class="label">立即打开&gt;&gt;</a>
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(0));
                    Toast.makeText(MainActivity.this, "打开新的页面", Toast.LENGTH_LONG).show();
                    return true; //返回true,代表要拦截这个url
                }
                return super.shouldOverrideUrlLoading(view, url);
            }
        });
    }
}

效果图
这样就能实现轻量级的实现与网页的交互了
源码地址:github.com/WillSprint/…