Flutter for OpenHarmony

一、插件介绍

test_uni_links是一个专为OpenHarmony优化的Flutter深度链接(Deep Link)测试工具,用于在Flutter应用中实现和测试Universal Links功能。该工具允许应用通过自定义URI Scheme接收来自外部的链接请求,并根据链接参数执行相应操作。
在这里插入图片描述

主要功能特点:

  • 支持OpenHarmony API 9+平台
  • 实现自定义URI Scheme注册与处理
  • 支持应用启动时的初始链接获取
  • 提供实时链接监听功能
  • 支持链接参数解析与页面跳转逻辑
  • 适配鸿蒙系统的原生能力调用

二、环境准备

系统要求:

  • OpenHarmony API 9+
  • Flutter SDK 3.0+
  • DevEco Studio 3.0+

三、插件使用

3.1 依赖引入

由于该三方库为自定义修改版本,需要以git形式引入。在项目的pubspec.yaml文件中添加以下配置:

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.2
  x_uni_links:
    git:
      url: "https://atomgit.com/flutter/plugins"
      path: "packages/x_uni_links/x_uni_links"

然后执行flutter pub get命令获取依赖。

3.2 URI Scheme配置

在OpenHarmony项目中,需要在module.json5文件中注册自定义URI Scheme。配置示例如下:

{
  "module": {
    "abilities": [
      {
        "name": "EntryAbility",
        "exported": true,
        "skills": [
          {
            "entities": [
              "entity.system.home",
              "entity.system.browsable"
            ],
            "actions": [
              "action.system.home",
              "ohos.want.action.viewData"
            ],
            "uris": [
              {
                "scheme": "links",
                "host": "com.example.test",
                "path": "localpath"
              }
            ]
          }
        ]
      }
    ]
  }
}

3.3 API调用示例

3.3.1 初始化链接监听

在Flutter应用的入口页面中初始化链接监听:

import 'package:flutter/material.dart';
import 'package:x_uni_links/scheme_util.dart';
import 'package:x_uni_links/x_uni_links.dart';

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  final String title;

  
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool isInitedXLinks = false;

  
  void initState() {
    super.initState();
  }

  _initXLinks() async {
    // 获取应用启动时的初始链接
    getInitialLink().then((initialLink) {
      print('XlinksDebug initialLink:$initialLink');
      CustomSchemeUtil.recordNextPage(initialLink);
    });

    // 监听实时链接变化
    linkStream.listen((link) {
      print('XlinksDebug linkStream:$link');
      CustomSchemeUtil.recordNextPage(link);
    });

    setState(() {
      isInitedXLinks = true;
    });
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              isInitedXLinks ? "XLinks is initialized" : "XLinks hasn't been initialized yet",
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _initXLinks,
        tooltip: 'initXLinks',
        child: const Icon(Icons.add),
      ),
    );
  }
}
3.3.2 链接参数解析

使用CustomSchemeUtil工具类解析链接参数:

import 'package:x_uni_links/scheme_util.dart';

// 解析链接获取页面参数
String? nextPage = CustomSchemeUtil.getNextPage('links://com.example.test/localpath?name=detail');
print('解析到的页面参数: $nextPage'); // 输出: detail

// 记录需要跳转的页面
CustomSchemeUtil.recordNextPage('links://com.example.test/localpath?name=home');

// 检查并执行页面跳转
CustomSchemeUtil.checkGoSchemeNextPage();
3.3.3 完整的链接处理流程
import 'package:flutter/material.dart';
import 'package:x_uni_links/scheme_util.dart';
import 'package:x_uni_links/x_uni_links.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'test_uni_links Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const LinkHandlerPage(),
    );
  }
}

class LinkHandlerPage extends StatefulWidget {
  const LinkHandlerPage({super.key});

  
  State<LinkHandlerPage> createState() => _LinkHandlerPageState();
}

class _LinkHandlerPageState extends State<LinkHandlerPage> {
  String _latestLink = 'No link received yet';
  String _parsedPage = 'No page parsed yet';

  
  void initState() {
    super.initState();
    _initLinkHandling();
  }

  Future<void> _initLinkHandling() async {
    // 获取初始链接
    String? initialLink = await getInitialLink();
    if (initialLink != null) {
      _handleLink(initialLink);
    }

    // 监听新链接
    linkStream.listen((link) {
      if (link != null) {
        _handleLink(link);
      }
    });
  }

  void _handleLink(String link) {
    setState(() {
      _latestLink = link;

      // 解析链接参数
      String? page = CustomSchemeUtil.getNextPage(link);
      _parsedPage = page ?? 'Invalid link format';

      // 记录需要跳转的页面
      CustomSchemeUtil.recordNextPage(link);
    });

    // 执行页面跳转逻辑
    _navigateToPage(_parsedPage);
  }

  void _navigateToPage(String page) {
    // 根据解析到的页面参数执行相应的跳转逻辑
    switch (page) {
      case 'home':
        print('Navigate to home page');
        // Navigator.push(context, MaterialPageRoute(builder: (context) => const HomePage()));
        break;
      case 'detail':
        print('Navigate to detail page');
        // Navigator.push(context, MaterialPageRoute(builder: (context) => const DetailPage()));
        break;
      case 'profile':
        print('Navigate to profile page');
        // Navigator.push(context, MaterialPageRoute(builder: (context) => const ProfilePage()));
        break;
      default:
        print('Unknown page: $page');
    }
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Link Handler')),
      body: Center(
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Text('Latest Received Link:', style: TextStyle(fontWeight: FontWeight.bold)),
              const SizedBox(height: 8),
              Text(_latestLink, textAlign: TextAlign.center),
              const SizedBox(height: 20),
              const Text('Parsed Page Parameter:', style: TextStyle(fontWeight: FontWeight.bold)),
              const SizedBox(height: 8),
              Text(_parsedPage, textAlign: TextAlign.center),
            ],
          ),
        ),
      ),
    );
  }
}

四、测试方法

4.1 命令行测试

使用DevEco Studio的命令行工具模拟发送链接请求:

hdc shell aa start -a ohos.want.action.viewData -b com.example.test_uni_links -u links://com.example.test/localpath?name=detail

4.2 浏览器测试

在OpenHarmony设备的浏览器中输入以下URL:

links://com.example.test/localpath?name=home

4.3 应用内测试

在另一个应用中使用Intent发送链接请求:

Want want = new Want();
want.setUri(Uri.parse("links://com.example.test/localpath?name=profile"));
want.setAction("ohos.want.action.viewData");
startAbility(want);

五、常见问题与解决方案

5.1 链接无法被应用接收

可能原因

  • URI Scheme配置错误
  • 应用未在后台运行
  • 链接格式不符合配置要求

解决方案

  • 检查module.json5中的URI Scheme配置是否正确
  • 确保应用已启动并在后台运行
  • 验证链接格式是否与配置的scheme、host、path一致

5.2 初始链接获取失败

可能原因

  • 应用已启动后才调用getInitialLink()
  • 启动时未携带链接参数

解决方案

  • 在应用启动时立即调用getInitialLink()
  • 确保使用正确的命令行参数启动应用

六、总结

test_uni_links是一个功能强大的Flutter深度链接测试工具,专为OpenHarmony平台优化。通过本指南,你可以了解如何:

  1. 以git形式引入自定义修改的x_uni_links依赖
  2. 在OpenHarmony项目中配置URI Scheme
  3. 使用API获取初始链接和监听实时链接
  4. 解析链接参数并执行页面跳转逻辑
  5. 测试深度链接功能

该工具为Flutter应用在OpenHarmony平台上实现深度链接功能提供了完整的解决方案,帮助开发者实现应用间的无缝跳转和数据传递。

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐