自学内容网 自学内容网

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

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


原文地址:https://blog.csdn.net/qq_47831505/article/details/145149736

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!