通过外部链接启动 Flutter App(详细介绍及示例)

简介: 本文介绍了通过外部链接启动 Flutter App 的两种方式:`firebase_dynamic_links` 和 `app_links`。前者由 Firebase 提供,支持生成分享链接并自动处理未安装应用时的跳转(如跳转到应用商店),但已于2025年8月停止服务;后者则需开发者自行处理未安装应用时的重定向逻辑。文中详细说明了两者的配置步骤、代码实现及注意事项,推荐使用 `app_links` 进行新项目开发。

通过外部链接启动 Flutter App(firebase_dynamic_links 和 app_links)

详细介绍 通过外部链接启动flutter App 的使用及示例

在我们的APP中,经常有点击链接启动并进入APP的需求(如果未安装跳转到应用商店)。Android通过deep link或者app link(是deep link 的增强版),iOS通过 url schema,可以打开对应的app,因此我们需要对我们的app进行对应的配置。下面将会详细介绍两种方式。
推荐使用app_link

一、firebase_dynamic_links (该服务已经弃用,2025 年 8 月将关闭)

该三方服务提供了 生成分享链接、通过链接启动跳转到指定页面的方法,通知支持 未安装App的时候跳转其他的链接(例如跳转到应用商店),重定向逻辑 由 Firebase 服务自动处理,并且支持短链接。

实现步骤:

1. 安装依赖:

在 pubspec.yaml 文件中添加:

dependencies:
  flutter:
    sdk: flutter
  firebase_dynamic_links: ^6.0.5

2. 配置 Android

在 android/app/src/main/AndroidManifest.xml 文件中,添加 intent-filter 配置,以便在 Android 中处理 App Links。

<activity android:name=".MainActivity">
    <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="i89trillion.page.link"
                android:scheme="https" />
    </intent-filter>
</activity>

3. 初始化链接监听 || 生成分享链接(代码实现)

  • 先在main方法中初始化监听:(在 runApp 之前初始化)
// 初始化动态链接
await FirebaseDynamicLinkService.initDynamicLink();
  • 实现生成分享链接和监听链接的方法:
    示例如下:

import "dart:async";
import "dart:io";

import "package:easy_localization/easy_localization.dart";
import "package:firebase_dynamic_links/firebase_dynamic_links.dart";

class FirebaseDynamicLinkService {
   
  static Duration maxDuration = Duration(seconds: 5);

  static Future<void> initDynamicLink() async {
   
    // 未启动的时候监听
    final PendingDynamicLinkData? initialLink =
        await FirebaseDynamicLinks.instance.getInitialLink();
    if (initialLink != null) {
   
      final Uri deepLink = initialLink.link;
      FirebaseAnalyticsService.logEvent(
          FirebaseAnalyticsEvent.link_join_guild_finish, '0');
      _handleDeepLink(deepLink);
    }

    // 应用程序在后台启动时有效
    FirebaseDynamicLinks.instance.onLink.listen((dynamicLinkData) {
   
      final Uri deepLink = dynamicLinkData.link;
      FirebaseAnalyticsService.logEvent(
          FirebaseAnalyticsEvent.link_join_guild_finish, '1');
      _handleDeepLink(deepLink);
    }, onError: (e) {
   
      LogUtil.error(e.toString());
    });
  }

  static void _handleDeepLink(Uri deepLink) async {
   
    var isJoinGuildLink = deepLink.pathSegments.contains('joinServer');
    if (isJoinGuildLink) {
   
      String? id = deepLink.queryParameters['id'];
      if (id != null) {
   
          LogUtil.info("deepLink serverId: $id");
      }
    }
  }

  // 创建一个群邀请链接
  static Future<String> createJoinServerDynamicLink(
      bool short, int guildID) async {
   
    if (!Platform.isAndroid && !Platform.isIOS) {
   
      return "该功能只在 Android 和 iOS 上可用";
    }

    String _linkMessage;

    final DynamicLinkParameters parameters = DynamicLinkParameters(
      uriPrefix: "https://xxx.page.link",
      link: Uri.parse('https://xxx.page.link/joinServer?id=$guildID'),
      androidParameters: AndroidParameters(
        // 未安装应用程序打开的链接
        fallbackUrl: Uri.parse(
            'https://play.google.com/store/apps/details?id=xxx'),
        packageName: 'xxx',
      ),
    );

    Uri url;
    if (short) {
   
      final ShortDynamicLink shortLink = await FirebaseDynamicLinksPlatform
          .instance
          .buildShortLink(parameters);
      url = shortLink.shortUrl;
    } else {
   
      url = await FirebaseDynamicLinksPlatform.instance.buildLink(parameters);
    }
    _linkMessage = url.toString();
    return _linkMessage;
  }
}

4. 未安装时跳转

在生成链接的时候参数 fallbackUrl 为未安装App时打开的链接,firebase 服务自己做了重定向。

二、app_links

该三方库 也支持 通过链接启动App,同时解析链接参数,跳转指定页面,但是不支持App未安装的时候跳转其他链接(需要自己的服务处理重定向)
官方文档见:https://developer.android.com/studio/write/app-link-indexing?hl=zh-cn#testindent

实现步骤:

1. 安装依赖:

在 pubspec.yaml 文件中添加:

dependencies:
  flutter:
    sdk: flutter
  app_links: ^6.0.1 # 用于处理动态链接

2. 配置 Android 和 iOS 支持

在 android/app/src/main/AndroidManifest.xml 文件中,添加 intent-filter 配置,以便在 Android 中处理 App Links。

<activity android:name=".MainActivity">
    <!-- Add the intent-filter for handling app links -->
    <intent-filter android:autoVerify="true">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="https" android:host="yourapp.page.link" android:pathPrefix="/joinServer"/>
    </intent-filter>
</activity>

注意: 这里注意下,开启autoVerify的activity中的\的action必须为android.intent.action.VIEW,category必须包含android.intent.category.BROWSABLE,data的scheme必须包含http/https,否则不生效,而且AppLinks必须在Android 6.0 以上的手机才可生效。
android\:host 为域名,android\:pathPrefix为地址前缀,根据实际需求配置

2. 初始化链接监听 || 生成分享链接(代码实现)

  • 先在main方法中初始化监听:(在 runApp 之前初始化)
// 初始化动态链接
    await AppLinkService.initializeDynamicLinks();
  • 实现生成分享链接和监听链接的方法:
    示例如下:
import 'package:app_links/app_links.dart';
import "package:beehive/utils/logger.dart";
import "dart:async";

class AppLinkService {
   
  static final AppLinks appLinks = AppLinks();

  // 初始化动态链接
  static Future<void> initializeDynamicLinks() async {
   
    print('Initializing dynamic links...');
    // 监听动态链接流
    appLinks.uriLinkStream.listen((Uri? uri) {
   
      print("appLink listen: $uri");
      if (uri != null) {
   
        _handleDeepLink(uri);
      }
    });
  }

  // 处理动态链接,跳转到相应页面
  static void _handleDeepLink(Uri deepLink) async {
   
    var isJoinGuildLink = deepLink.pathSegments.contains('joinServer');
    if (!isJoinGuildLink){
   
      return;
    }
    String? id = deepLink.queryParameters['id'];
    LogUtil.info("appLink serverId: $id");
  }

  // 生成分享链接
  static Future<String> generateShareLink(int serverId) async {
   
    final String deepLinkUrl = 'https://yourapp.page.link/joinServer?id=$serverId';

    final Uri dynamicLink = Uri.parse(deepLinkUrl);
    return dynamicLink.toString(); // 返回生成的动态链接
  }
}

3. 链接识别启动进App

需要在域名<https://yourapp.page.link> 根目录下面 放一个JSON文件:.well-known/assetlinks.json 。该JSON文件就是用于识别进入App的,如果是谷歌商店的App,可以直接在管理中心生成,如果是测试,就自己生成。
内容格式如下:
[
  {
   
    "relation": ["delegate_permission/common.handle_all_urls"],
    "target": {
   
      "namespace": "android_app",
      "package_name": "xxxx",
      "sha256_cert_fingerprints":
      ["7F:48:F9:..."]
    }
  }
]

4. 未安装时跳转逻辑

app link没有实现未安装跳转其他URL,需要自己在自己的服务域名下面进行重定向处理。(例如重定向到应用商店)
快速的方法:将 一个重定向的HTML也放到域名根目录下面。客户端 识别链接就是这个html,可以在链接中加参数。分享链接就是:https://yourapp.page.link/applink.html
例如:applink.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <title>App Link</title>
</head>
<script>
    window.onload = function() {
    
        if (/(android)/i.test(navigator.userAgent)) {
    
            // 用户使用的是 Android 设备
            window.location.href = "https://play.google.com/store/apps/details?id=xxx";
        } else if (/(iphone|ipad|ipod|ios)/i.test(navigator.userAgent)) {
    
            // 用户使用的是 iOS 设备
            window.location.href = "https://itunes.apple.com/app/idxxx";
        } else {
    
            // 用户使用的是其他设备
            console.log("This device is not supported.");
        }
    };
</script>
<body>

</body>
</html>

也可以在该域名对应的服务中对某个接口实现重定向逻辑:
例如:(go语言 gframe框架为例)

func (ctrl *linkCtrl) LinkRedirect(r *ghttp.Request) {
   
    userAgent := r.Header.Get("User-Agent")
    log.LogRuntime(log.LEVEL_INFO, "[LinkRedirect] userAgent:", userAgent)
    if strings.Contains(strings.ToLower(userAgent), "android") {
   
        // 用户使用的是 Android 设备
        r.Response.RedirectTo(define.GooglePlayAdd)
    } else {
   
        // 用户使用的是其他设备
        r.Response.Write("This device is not supported.")
    }
}

或者也可以直接在NGINX上面重定向跳转.

目录
相关文章
|
1月前
|
前端开发 安全 开发工具
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
180 90
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
2月前
|
Dart 前端开发
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
132 75
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
1月前
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
182 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
2月前
|
Dart 前端开发 容器
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
102 18
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
1月前
|
Dart 前端开发 Android开发
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
58 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
24天前
|
缓存
flutter3-wetrip跨平台自研仿携程app预约酒店系统模板
基于最新跨平台框架flutter3.x+dart3+getx+flutter_datepicker纯手写实战的一款仿去哪儿/携程旅游酒店预约客房app系统。
35 4
|
2月前
|
前端开发 Java 开发工具
【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
183 18
【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
|
2月前
|
缓存 前端开发 Android开发
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
117 12
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
|
2月前
|
Dart 前端开发 架构师
【01】vs-code如何配置flutter环境-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈-供大大的学习提升
【01】vs-code如何配置flutter环境-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈-供大大的学习提升
232 26
|
1月前
|
缓存 视频直播
flutter3-dart3-dymall原创仿抖音(直播+短视频+聊天)商城app系统模板
基于最新版flutter3.27+dart3.x+Getx+mediaKit原创实战研发抖音app带货商城项目。集成了直播+短视频+聊天三大功能模块。实现了类似抖音app首页全屏沉浸式联动左右滑动页面模块、上下滑动短视频。
70 1

热门文章

最新文章