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

news2025/1/19 9:45:08

通过外部链接启动 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中的<intent-filter…>的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上面重定向跳转.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2278870.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

nss刷题3

[SWPUCTF 2022 新生赛]webdog1__start level1&#xff1a; 打开环境后什么也&#xff0c;没有&#xff0c;查看源码&#xff0c;看到第一关是MD5值&#xff0c;要get传参web&#xff0c;然后web的值的MD5和它原来值相等&#xff0c;0e开头的字符在php中都是0&#xff0c;传入…

深入了解计算机网络中的路由协议与性能优化

在计算机网络中&#xff0c;路由协议是决定数据如何从源节点到达目标节点的关键组成部分。不同的路由协议各有特点&#xff0c;如何根据实际需求选择合适的协议&#xff0c;并对网络性能进行优化&#xff0c;是每个网络管理员需要面临的重要课题。 本篇文章将深入探讨计算机网…

通过视觉语言模型蒸馏进行 3D 形状零件分割

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01;对应英文要求比较高&#xff0c;特此说明&#xff01; Abstract This paper proposes a cross-modal distillation framework, PartDistill, which transfers 2D knowledge from vision-language models …

Apple Vision Pro 距离视网膜显示还有多远

本文介绍了视网膜屏幕的概念和人眼视敏度极限,以及头戴显示设备在视场角和角分辨率之间的权衡设计。文章还提到了苹果公司的新产品Apple Vision Pro的设计规范和视觉效果。 Retina display 是苹果公司针对其高分辨率屏幕技术的一种营销术语。这个术语最早由乔布斯在 2010 年 6…

微服务学习-快速搭建

1. 速通版 1.1. git clone 拉取项目代码&#xff0c;导入 idea 中 git clone icoolkj-microservices-code: 致力于搭建微服务架构平台 1.2. git checkout v1.0.1版本 链接地址&#xff1a;icoolkj-microservices-code 标签 - Gitee.com 2. 项目服务结构 3. 实现重点步骤 …

美最高法维持TikTok禁令,不卖就禁或有转机,TikTok直播专线助力企业在挑战中前行

一、TikTok 面临的危机与转机 最近&#xff0c;TikTok 在美国的命运可谓是波谲云诡。当地时间 1 月 17 日&#xff0c;美国联邦最高法院裁定 TikTok “不卖就禁” 的法律不违宪&#xff0c;这就意味着该法案将于 1 月 19 日生效 &#xff0c;TikTok 似乎已被逼至悬崖边缘。然而…

编写Wireshark的Lua脚本详解及示例解析

编写Wireshark的Lua脚本详解及示例解析 编写Wireshark Lua脚本的基本步骤SMGP.lua脚本解析脚本解析要点总结Wireshark是一个强大的网络协议分析工具,支持通过Lua脚本扩展其功能,以解析自定义或复杂的协议。下面将详细介绍如何编写Wireshark的Lua脚本,并通过解析一个具体的SM…

【20】Word:小许-质量管理-论文❗

目录 题目​ NO1.2.3.4.5 NO6.7 NO8 NO9 NO10.11 题目 NO1.2.3.4.5 另存为“Word.docx”文件在考生文件夹下&#xff0c;F12Fn是另存为的作用布局→页面设置对话框→纸张&#xff1a;大小A4→页边距&#xff1a;上下左右不连续ctrl选择除表格外的所有内容→开始→字体对…

【软件开发过程管理规范】需求管理,需求分析,设计开发管理,测试管理(Word)

一、需求管理规程 1 简介 2 过程总体描述 2.1 过程概述 2.2 过程流程图 3 过程元素描述 3.1 准备阶段 3.2 需求调研 3.3 需求分析 软件开发人员及用户往往容易忽略信息沟通&#xff0c;这导致软件开发出来后不能很好地满足用户的需要&#xff0c;从而造成返工。而返工不仅在技术…

RabbitMQ-消息可靠性以及延迟消息

目录 消息丢失 一、发送者的可靠性 1.1 生产者重试机制 1.2 生产者确认机制 1.3 实现生产者确认 &#xff08;1&#xff09;开启生产者确认 &#xff08;2&#xff09;定义ReturnCallback &#xff08;3&#xff09;定义ConfirmCallback 二、MQ的持久化 2.1 数据持久…

了解 .mgJSON 文件

.mgJSON &#xff08;Motion Graphics JSON&#xff09;是一个基于标准 JSON 格式的文件扩展名&#xff0c;专门用于存储和交换与动态图形、动画和多媒体应用相关的数据。该格式支持静态和动态数据流&#xff0c;能够精确描述动画、物体变换、图形效果等。 .mgJSON 文件通过层级…

小白爬虫——selenium入门超详细教程

目录 一、selenium简介 二、环境安装 2.1、安装Selenium 2.2、浏览器驱动安装 三、基本操作 3.1、对页面进行操作 3.1.1、初始化webdriver 3.1.2、打开网页 3.1.3、页面操作 3.1.4、页面数据提取 3.1.5、关闭页面 ?3.1.6、综合小案例 3.2、对页面元素进行操作 3…

pycharm+pyside6+desinger实现查询汉字笔顺GIF动图

一、引言 这学期儿子语文期末考试有一道这样的题目&#xff1a; 这道题答案是B&#xff0c;儿子做错了选了C。我告诉他“车字旁”和“车”的笔顺是不一样的&#xff0c;因为二者有一个笔画是不一样的&#xff0c;“车字旁”下边那笔是“提”&#xff0c;而“车”字是“横”&am…

快手极速版如何查找ip归属地?怎么关掉

在数字化时代&#xff0c;个人隐私的保护成为了广大用户关注的焦点。快手极速版作为一款备受欢迎的短视频应用&#xff0c;其IP归属地的显示与关闭功能自然也成了用户热议的话题。本文将详细介绍如何在快手极速版中查找IP归属地以及如何关闭IP属地显示&#xff0c;帮助用户更好…

C++ 模拟真人鼠标轨迹算法 - 防止游戏检测

一.简介 鼠标轨迹算法是一种模拟人类鼠标操作的程序&#xff0c;它能够模拟出自然而真实的鼠标移动路径。 鼠标轨迹算法的底层实现采用C/C语言&#xff0c;原因在于C/C提供了高性能的执行能力和直接访问操作系统底层资源的能力。 鼠标轨迹算法具有以下优势&#xff1a; 模拟…

Go语言strings包与字符串操作:从基础到高级的全面解析

Go语言strings包与字符串操作:从基础到高级的全面解析 引言 Go语言以其简洁、高效和强大的标准库而闻名,其中strings包是处理字符串操作的核心工具。本文将深入探讨Go语言中strings包的功能及其在实际开发中的应用,帮助开发者更好地理解和使用这一工具。 1. strings包概述…

基于YOLOv4与Tkinter的口罩识别系统

往期精彩 基于YOLOv11的番茄成熟度实时检测系统设计与实现 用YOLOv11检测美国手语&#xff1a;挥动手腕的科技魔法 基于YOLOv11模型PyQt的实时鸡行为检测系统研究 OpenCV与YOLO在人脸识别中的应用研究(论文源码) 计算机视觉&#xff1a;农作物病虫害检测系统&#xff1a;基于Y…

电力场景红外测温图像绝缘套管分割数据集labelme格式2436张1类别

数据集格式&#xff1a;labelme格式(不包含mask文件&#xff0c;仅仅包含jpg图片和对应的json文件) 图片数量(jpg文件个数)&#xff1a;2436 标注数量(json文件个数)&#xff1a;2436 标注类别数&#xff1a;1 标注类别名称:["arrester"] 每个类别标注的框数&am…

AI编程工具使用技巧——通义灵码

活动介绍通义灵码1. 理解通义灵码的基本概念示例代码生成 2. 使用明确的描述示例代码生成 3. 巧妙使用注释示例代码生成 4. 注意迭代与反馈原始代码反馈后生成优化代码 5. 结合生成的代码进行调试示例测试代码 其他功能定期优化生成的代码合作与分享结合其他工具 总结 活动介绍…

电梯系统的UML文档05

Dispatcher 不控制实际的电梯组件&#xff0c;但它在软件系统中是重要的。每一个电梯有一个ispatcher&#xff0c;主要功能是计算电梯的移动方向、移动目的地以及保持门的打开时间。它和系统中除灯控制器以外的几乎所有控制对象交互。 安全装置也是一个环境对象&#xff0c;它…