Flutter -- 开发之Deep Link

1,529 阅读6分钟

想象一个场景,你点击了某个链接之后,APP可以跳转到某个特定的页面。省去你搜索,或者一步一步点击的时间。这就是Deep link要干的事情。你对deep link也有一个直观的了解。

Deep Link的组成

其实deep link就是一个url,由如下几个部分组成。

  • Schema:一般它是用来指定特定资源的类型和协议的,比如https。在Flutter app中就是用来指定要打开的是哪个app了。
  • Host:在schema之后,一般是用来指定域或者是网络地址。在Flutter app里资源放在哪里的。
  • 路径(Path):这就是用来指出具体在App的哪个位置了。

以上几部分组成的字符串最后可以唯一的确定是你的app,最好还能确定是app的哪一个页面。这样的功能呢也就是deep link有用的地方。

有的时候还会用到这些部分:

  • Query Parameter:查询参数,一般出现在?号之后,可以在查询或者排序的时候用到。
  • Port:端口,一般用在访问后端的时候,没有指定的话HTTP和HTTPS对应的是80和443.
  • Fragment:片段,有时也叫做锚点。在#后面,用来直接跳转到网页的某个部分。

在解释deep link的时候不免说到了http、https开头组成的url,deep link是他们的一个超集,看起来可以是这样的:

yourSchema://your-domain.com?queryStrings

自定义模式(Custom Schema)

自定义模式,这个就非常好用了。这个模式你可以随意定义,只要在app里配置上了就可以用。

当然,在开发的过程中出现某个在开发的页面访问流程过长的时候也可以用deep link带上参数直接访问这个页面查看显示的结果。

好处我们一早就提到过帮助用户直接跳转到某个页面。坏处也多少有一些,开发者们在开发中需要注意。比如别有用心的人可以用你的自定义模式把你的可以访问的页面挨个都访问一次。App容易被看光光。

另外,也可能出现一个正常用户在访问的时候跳转到了一个不存在的路径上。这时候抛出异常提示还好,如果app直接崩溃了就不好了。

HTTP/HTTPS 模式

每天都会遇到这样的模式:

https://your-demain.com

这个是给移动app添加deep link的一个相对安全的方式。

这些要求你拥有一个域名,在app端配置好并且在后端验证app。

这样的deep link,你的app认识,后端也会验证等于是双保险了。

配置Deep Link

配置Deep Link需要在Android和iOS上分别配置。

在Android上配置

温馨提示,这个配置能用Android Studio的话还是用AS的好。VS Code不够智能。

配置Android的Deep Link需要修改AndroidManifest.xml文件。

  • 打开android/app/src/main/AndroidManifest.xml文件
  • activity下增加一个intent-filter
  • 指定schema和host这些
  • [可选]定义支持的路径

以下是intent filter看起来的样子:

<intent-filter android:label="@string/filter_view_http_port_autoiit_custom">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data
        android:scheme="autoiit"
        android:host="maddog"
        />
</intent-filter>

如果你想使用一个HTTP/HTTPS的模式比如http://yourDomain.com/yourPath,可以这样:

<intent-filter android:label="@string/filter_view_http_port_autoiit">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data
        android:scheme="http"
        android:host="localhost"
        android:port="5051"/>
</intent-filter>

说了半天还没加上路径呢。没有路径,那么app不管遇到什么样的deep link,只要是你的域名都会打开。如果需要更多的控制这就需要Path上场了。通常用到的有pathpathPatternpathPrefix。举个例子:

<!-- 精确匹配,必须是 "/login/" -->
<data android:path="/login/" />  

<!-- 路径的开头必须是 "/product/" 后面可以跟任意的字符,比如productID -->
<data android:pathPattern="/product/.*" />

<!-- 路径开头必须是 /account/, 可以是 /account/confirm, 或者 /account/verify等等 -->
<data android:pathPrefix="/account/" />

更多关于Android添加Deep link的内容可以在官网找到。

验证Android的Deeplink

这里假设你已经把adb这个工具配置好了。

首先打开Android模拟器,然后在终端(Terminal)里输入如下的命令:

如果是HTTP、HTTPS的话:

adb shell am start -a android.intent.action.VIEW \
    -c android.intent.category.BROWSABLE \
    -d https://yourDomain.com \
    <package name>

如果是自定义的模式:

adb shell am start -a android.intent.action.VIEW \
     -c android.intent.category.BROWSABLE \
     -d yourSchema://yourDomain \
     <package name>

首先,这个<package name>在哪里找呢。这时你的App已经在模拟器里跑起来了,然后打开Android Studio的logcat,在这里显示的信息包含你的package name。

也可以在android/app/build.gradle里找到:

android {
    namespace = "com.example.autoiit_app"  // **这里就是你的package name
    compileSdk = flutter.compileSdkVersion
    ndkVersion = flutter.ndkVersion

    // 略...
    
}

注意:如果是Windows系统的话,命令行缓缓归用^换行。或者这个命令直接写成一行。

另外一种测试deep link的方法是把这个deep link的发送给你自己,比如微信、邮件、短信之类的。然后点开这个链接。

现在还只是打开了app,之后会详细介绍如何导航到正确的页面。

在iOS上配置

在iOS上配置deep link和android上差别有点大。

要配置iOS的deep link有如下步骤:

  • 首先在Xcode打开这个文件:ios/Runner.xcworkspace
  • 打开:Runner > Signing & Capabilities > + Capability > Associated Domains

image.png

image.png

  • applinks开始添加一个域

image.png

如果要添加自定义的模式,那就需要在Xcode里额外配置:

  • 打开Info.plist文件
  • 点在Information Property List边上的+号按钮,添加URL Types
  • URL Types下面,添加URL Schemmes。在这个下面添加一个scheme:yourScheme。在本例中就是autoiit
  • 然后再添加URL Identitier。添加一个你的scheme。

加完之后看起来就是这样的:

image.png

另外也可以在VS Code里的ios/Runner/Info.list路径下直接修改这个文件。效果是这样的:

    <key>CFBundleURLTypes</key>
    <array>
        <dict>
            <key>CFBundleURLName</key>
            <string>maddog</string>
            <key>CFBundleURLSchemes</key>
            <array>
                <string>autoiit</string>
            </array>
        </dict>
    </array>

测试iOS的Deep Link

要测试iOS的deep link只需要点一下deep link链接。或者开用下面的命令测试:

HTTP/HTTPS:

xcrun simctl openurl booted https://yourDomain.com/path

或者是自定义模式:

xcrun simctrl openurl booted yourScheme://yourDomain/path

使用GoRouter处理Deep Link

GoRouter是Flutter app常用的一个款导航工具。它使用类似URL一样的配置来实现不同屏幕的导航。这和deep link非常契合。

下面就来看看如何用GoRouter来处理deep link,直接调转到想要的页面。

现在有一个配置好的GoRouter,是这样的:

    GoRoute(
      path: '/detail/:id',
      builder: (context, state) =>
        DetailScreen(id: state.pathParameters['id']!)),

Detail路由接受一个参数id,在Detail页面显示这个id下的具体信息。

导航到Deep Link指定页面

导航已经配置好了,在Web上已经可以用了。在App上还要具体处理。

在Android上,给AndroidManifest.xml文件的activity标签下添加如下的内容:

<meta-data android:name="flutter_deeplinking_enabled" android:value="true" />

在iOS,给Info.plist文件添加:

<key>FlutterDeepLinkingEnabled</key>
<true/>

上面的配置就可以让你的app处理deep link了,不管是这个app跑起来还是没跑起来。

现在可以测试一下了。老规矩,Android用ddb,iOS用xcrun

Android:

adb shell am start -a android.intent.action.VIEW \
    -c android.intent.category.BROWSABLE \
    -d yourSchema://yourDemain/detail/10
    <package name>

iOS:

xcrun simctl openurl booted yourSchema://yourDomain/detail/100

这两个命令跑一下就可以看到app会跳转到detail页面,然后里面会显示那个id的值,如:

最后

现在开发app基本上都有deep link。让用户从推广直接进入到服务用户的页面,让用户少去了很多点击的步骤更容易满足用户需求。

而且在开发的时候可以使用deep link直接跳转到开发中的页面,这样也省去了很多点击的步骤让开发更轻松一些。