记录一次Android Deeplink跳转失败问题修复

叁叁肆2018-11-20 15:24

此文已由作者申国骏授权网易云社区发布。

欢迎访问网易云社区,了解更多网易技术产品运营经验。


Android Deeplink实现

在Android中,Deeplnk通过声明Activity的intent-filter来实现对自定义url访问事件的捕捉。在有道背单词的项目中,我们需要通过前端分享词单的方式,将词单分享给别人,并通过点击前端页面收藏按钮,实现调起客户端收藏词单的功能。
从前端通过自定义url的方式调起客户端这个功能原来一直都没有什么问题,直到最近有部分用户反馈在某些浏览器下无法调起。下面我们来看一下分析查找问题的方法以及如何解决。

检查客户端deeplink配置

在AndroidManifest.xml文件中,对路由Activity配置如下:

<activity
            android:name=".deeplink.RouterActivity"
            android:configChanges="keyboardHidden|orientation|screenSize"
            android:launchMode="singleTask"
            android:theme="@style/Theme.Translucent">
            <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="youdao.com"
                    android:scheme="recite"
                    android:pathPattern=".*"/>
            </intent-filter>

            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value=".home.ui.MainActivity" />
        </activity>

里面比较重要的部分是intent-filter中的data配置,检查后发现配置正常,可以正常拦截到 recite://youdao.com/.*的所有请求。
转到RouterActivity通过断点调试,发现并没有到达。从而可以确认是浏览器调起的时候发生了异常。

tips: adb 命令同样可以启动deeplink进行测试

分析浏览器对deeplink处理

通过用户反馈,主要集中是在UC和华为自带的浏览器点击前端页面的【收藏词单】无法调起有道背单词
同时我们在chrome上面发现通过deeplink只有第一次会跳转到应用,往后几次都是没有任何相应,确实有点百思不得其解。
经过查找资料,发现了chrome的一个对Android Intent处理的介绍
Android Intents with Chrome
里面提到

One scenario is launching an app when the user lands on a page, which you can achieve by embedding an iframe in the page with a custom URI-scheme set as the src, as follows: <iframe src="paulsawesomeapp://page1> . This works in the Chrome for Android browser, version 18 and earlier. It also works in the Android browser, of course.


The functionality has changed slightly in Chrome for Android, versions 25 and later. It is no longer possible to launch an Android app by setting an iframe's src attribute. For example, navigating an iframe to a URI with a custom scheme such as paulsawesomeapp:// will not work even if the user has the appropriate app installed. Instead, you should implement a user gesture to launch the app via a custom scheme, or use the “intent:” syntax described in this article.

翻译一下,大概的意思就是之前通过iframe标签没有用户主动操作就打开app的行为在chrome25版本及之后会被禁止。开发者必须通过用户操作来触发跳转应用的行为。目前chrome的版本都已经68了,证明这个规则已经由来已久。抱着试试看的姿态,开始查找是否是前端的代码有问题。
通过chrome inspect,捕捉到前端代码果然有一处疑似iframe的使用


随后经过对前端代码debug,果然有走了这段逻辑

证据确凿,可以找前端大神反馈了。经过了解,确实是之前有改动过这部分的代码,使用了iframe来处理deeplink的打开。处理的办法也相对简单,将iframe换成href来做跳转处理就可以了。


测试


最后我们对国内的浏览器试了一下deeplink是否生效


UC浏览器


会弹出一个应用打开提醒,如果用户本次没有【允许】操作,则浏览器下次会拦截打开应用行为,没有任何提醒,不知道这是一个bug还是故意为之。点击【允许】后可以跳转应用

QQ浏览器


同样会弹出应用打开题型,如果用户本次没有【打开】,下次用户操作还是会继续提醒。点击【打开】后可以跳转应用

360浏览器


行为与QQ浏览器类似,每次都会提醒

猎豹浏览器


行为与QQ浏览器类似,每次都会提醒

一加系统默认浏览器


行为与QQ浏览器类似,每次都会提醒

搜狗浏览器

没有提醒,直接跳转到app


chrome

行为与搜狗浏览器类似,没有提醒,直接跳转app 

测试结果除了UC浏览器第一次不点击跳转之后会跳转不了之外, 其他浏览器跳转app问题得到解决。


结语

通过这次查deeplink跳转的问题,收获了两点知识。 

  • 一个是前端使用iframe来处理deeplink跳转会有问题
  • 二个是除了采用
    "scheme://host/path"
    
    这种deeplink方式之外,还可以采用
    "intent://about/#Intent;action=[string];scheme=[string];package=[string];S.browser_fallback_url=[encoded_full_url];end"
    
    的方式来触发应用intent的请求访问。

免费体验云安全(易盾)内容安全、验证码等服务

更多网易技术、产品、运营经验分享请点击