Flutter插件xmtp的介绍与使用_xmtp提供了用于 Flutter 应用的 XMTP 消息 API 客户端的 Dart 实现

Flutter插件xmtp的介绍与使用

xmtp-flutter 提供了用于 Flutter 应用的 XMTP 消息 API 客户端的 Dart 实现。

使用 xmtp-flutter 可以构建通过区块链账户发送消息的应用程序,包括直接消息(DMs)、通知、公告等。

要了解最新的 SDK 发展情况,请查看此仓库中的 问题标签页

要了解更多关于 XMTP 和常见问题的答案,请参阅 XMTP 文档

Flutter插件xmtp快速入门应用

使用 XMTP Flutter 快速入门应用 作为工具开始构建 XMTP 应用。这个基础的消息应用有一个有意不带偏见的用户界面,以帮助你更容易地进行构建。

参考文档

查看参考

访问 Dart 客户端 SDK 参考文档

安装

flutter pub add xmtp

要查看更多选项,请查看 已验证的 XMTP Dart 包

使用概述

XMTP 消息 API 围绕一个允许检索和发送消息给其他 XMTP 网络参与者的消息 API 客户端(client)展开。客户端必须在启动时连接到钱包应用程序。如果这是客户端第一次创建,客户端将生成一个密钥包,该密钥包用于加密和认证消息。该密钥包以加密形式持久化在网络中,并使用账户签名。密钥包的公有部分也会定期在网络上宣传,以便各方建立共享加密密钥。所有这些都透明地发生,无需任何额外代码。

import 'package:xmtp/xmtp.dart' as xmtp;
import 'package:web3dart/credentials.dart';
import 'dart:math';

var wallet = EthPrivateKey.createRandom(Random.secure());
var api = xmtp.Api.create();
var client = await xmtp.Client.createFromWallet(api, wallet);

使用本地存储

重要

如果你正在构建生产级应用,确保使用包含 XMTP SDK 支持的本地缓存架构。

要了解更多,请参阅 使用本地缓存

创建客户端

客户端有两个构造函数:createFromWalletcreateFromKeys

当用户第一次在一个新设备上使用时,他们应该调用 createFromWallet。这会提示他们签署一条消息以执行以下操作之一:

  • 如果他们是新手,则创建一个新的身份。
  • 如果他们之前使用过 XMTP,则启用他们的现有身份。

当这成功时,它会用一组可以安全存储在设备上的 keys 配置客户端。

var api = xmtp.Api.create();
var client = await Client.createFromWallet(api, wallet);
await mySecureStorage.save(client.keys.writeToBuffer());

当用户第二次启动应用时,他们应该使用从上次会话中存储的 keys 调用 createFromKeys

var stored = await mySecureStorage.load();
var keys = xmtp.PrivateKeyBundle.fromBuffer(stored);
var api = xmtp.Api.create();
var client = await Client.createFromKeys(api, keys);

配置客户端

当你调用 Api.create() 时,你可以配置客户端环境。

默认情况下,它将连接到一个 local 的 XMTP 网络。有关连接到环境的重要细节,请参阅 XMTP 生产和开发网络环境

列出现有的对话

你可以列出现有的对话并发送消息。

var conversations = await client.listConversations();
for (var convo in conversations) {
  debugPrint('Saying GM to ${convo.peer}');
  await client.sendMessage(convo, 'gm');
}

这些对话包括用户的所有对话,无论哪个应用创建了对话。这种功能提供了可互操作收件箱的概念,使用户能够在任何使用 XMTP 构建的应用中访问其所有对话。

监听新的对话

你还可以实时监听新对话的启动。这将允许应用显示来自新联系人的传入消息。

var listening = client.streamConversations().listen((convo) {
  debugPrint('Got a new conversation with ${convo.peer}');
});
// 当你想停止监听:
await listening.cancel();

开始新的对话

你可以使用 XMTP 网络上的任何以太坊地址创建新的对话。

var convo = await client.newConversation("0x...");

发送消息

为了能够发送消息,接收者必须至少创建一次客户端并因此在网络上发布其密钥包。

消息使用账户地址进行寻址。

消息内容可以是纯文本字符串。或者你可以配置自定义内容类型。有关不同类型的详细信息,请参阅 处理不同类型的内容

var convo = await client.newConversation("0x...");
await client.sendMessage(convo, 'gm');

列出对话中的消息

你可以获取对话中的完整消息历史记录。

// 只显示过去24小时内的消息。
var messages = await alice.listMessages(convo,
    start: DateTime.now().subtract(const Duration(hours: 24)));

分页列出对话中的消息

可能需要分页检索和处理对话中的消息。你可以通过指定 limitend 来实现这一点,这将返回在指定时间之前发送的消息数量。

var messages = await alice.listMessages(convo, limit: 10);
var nextPage = await alice.listMessages(
    convo, limit: 10, end: messages.last.sentAt);

监听对话中的新消息

你可以通过调用 client.streamMessages(convo) 来监听对话中的任何新消息(传入或传出)。

成功接收到的消息(通过解码和解密)可以信任为真实消息。这意味着消息是由 message.sender 账户的拥有者发送的,并且在传输过程中未被修改。message.sentAt 时间可以信任为由发送者设置的时间。

var listening = client.streamMessages(convo).listen((message) {
  debugPrint('${message.sender}> ${message.content}');
});
// 当你想停止监听:
await listening.cancel();

注意

此包目前不包括 XMTP 客户端 SDK for JavaScript (xmtp-js) 中的 streamAllMessages() 功能。

处理不同类型的内容

在发送消息时,你可以指定内容类型。这允许你指定不同于默认值(简单字符串,ContentTypeText)的不同类型的内容。

要了解有关内容类型的更多信息,请参阅 XMTP 的内容类型

在客户端构建期间注册附加的 Codec 可以添加对其他类型内容的支持,包括 customCodecs 参数。每个编解码器声明一个特定的内容类型标识符,ContentTypeId,用于向客户端指示应使用哪个编解码器来处理正在发送或接收的内容。有关编解码器和内容类型的更多详细信息,请参阅 XIP-5

编解码器和内容类型可以通过 XRCs 作为互操作标准提出。

/// 示例 [Codec] 用于发送 [int] 值。
final contentTypeInteger = xmtp.ContentTypeId(
  authorityId: "com.example",
  typeId: "integer",
  versionMajor: 0,
  versionMinor: 1,
);
class IntegerCodec extends Codec<int> {
  [@override](/user/override)
  xmtp.ContentTypeId get contentType => contentTypeInteger;

  [@override](/user/override)
  Future<int> decode(xmtp.EncodedContent encoded) async =>
      Uint8List.fromList(encoded.content).buffer.asByteData().getInt64(0);

  [@override](/user/override)
  Future<xmtp.EncodedContent> encode(int decoded) async => xmtp.EncodedContent(
    type: contentType,
    content: Uint8List(8)..buffer.asByteData().setInt64(0, decoded),
    fallback: decoded.toString(),
  );
}

// 使用自定义编解码器发送整数。
var client = await Client.createFromWallet(api, wallet, customCodecs:[IntegerCodec()]);
var convo = await client.newConversation("0x...");
await client.sendMessage(convo, "Hey here comes my favorite number:");
await client.sendMessage(convo, 42, contentType: contentTypeInteger);

如上所示,你必须提供内容回退值。使用它来提供原始内容的类似 alt 文本的描述。提供内容回退值使得不支持内容类型的客户端仍能显示有意义的内容。

警告

如果不提供内容回退值,不支持内容类型的客户端将显示空消息。这会导致糟糕的用户体验并破坏互操作性。

压缩

此包目前不支持消息内容压缩。

破坏性修订

由于 xmtp-flutter 正处于活跃开发阶段,你可能会遇到一些需要你采用最新 SDK 版本才能继续工作的破坏性修订。

XMTP 在 XMTP Discord 社区 中讨论破坏性修订,尽可能提前通知。此外,xmtp-flutter 版本中的破坏性修订将在 发布页面 中描述。

废弃

旧版本的 SDK 最终会被废弃,这意味着:

  1. 网络不会支持并且最终会主动拒绝使用过期版本客户端的连接。
  2. 过期版本中不会修复错误。

下表提供了废弃计划。

公告 有效日期 最低版本 理由
目前没有为 xmtp-flutter 安排废弃计划。

欢迎根据这些 贡献指南 提交 bug 报告、功能请求和 PR。

XMTP 生产和开发网络环境

XMTP 提供了生产和开发网络环境以支持项目的开发阶段。

生产和开发网络是完全独立且不可互换的。例如,对于给定的区块链账户,其在开发网络上的 XMTP 身份与其在生产网络上的身份完全不同,与其相关的消息也是如此。此外,在开发网络上创建的 XMTP 身份和消息不能从开发网络访问或转移到生产网络,反之亦然。

注意

当你 创建客户端 时,它默认连接到一个 XMTP local 环境。当你创建用于客户端的 Api 时,它必须有一个有效的网络 host

以下是何时使用每个环境的一些最佳实践:

  • dev (host: "dev.xmtp.network"): 用于让客户端与开发网络通信。作为一种最佳实践,开发和测试你的应用时使用 dev。遵循这一最佳实践以隔离测试消息到开发收件箱。
  • production (host: "production.xmtp.network"): 用于让客户端与生产网络通信。作为一种最佳实践,当你的应用服务于真实用户时使用 production。遵循这一最佳实践以隔离真实用户之间的消息到生产收件箱。
  • local (host: "127.0.0.1",默认): 用于让客户端与本地运行的 XMTP 节点通信。例如,XMTP 节点开发者可以使用 local 生成客户端流量以测试本地运行的节点。

生产网络配置为永久存储消息。XMTP 有时会从开发网络删除消息和密钥,并会在 XMTP Discord 社区 中提供提前通知。

发布新版本到 pub.dev

  1. 根据 当前发布的版本 确定下一个版本号。
  2. 更新 common/api.dart 中的 sdkVersion 以使用新版本。
  3. 更新 CHANGELOG.md 以包括新版本号的发布说明。
  4. 通过拉取请求将步骤 2 和 3 中的更新合并到 main 分支。
  5. 检出 main 分支,拉取最新更改并运行以下命令,将 {VERSION_NUMBER} 替换为新版本。
    git tag -a v{VERSION_NUMBER} -m "xmtp release v{VERSION_NUMBER}"
    git push origin v{VERSION_NUMBER}
    
  6. 观察 GitHub Actions 并确保 Release 操作成功,确认包已发布。
  7. 确保新版本在 https://pub.dev/packages/xmtp 上是最新的。

示例代码

以下是 xmtp-flutter 的示例代码,位于 example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter_app_badger/flutter_app_badger.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

import 'router.dart';
import 'session/foreground_session.dart';

void main() async {
  /// 如果他们保存了凭证,初始化会话。
  /// 如果不是,他们将被重定向到登录页面。
  await session.loadSaved();
  _monitorTotalUnreadBadge();
  runApp(const XmtpApp());
}

class XmtpApp extends HookWidget {
  const XmtpApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp.router(
      title: 'XMTP',
      theme: ThemeData(primarySwatch: Colors.deepPurple),
      routerConfig: createRouter(),
    );
  }
}

/// 更新应用徽章,当未读消息数量变化时。
void _monitorTotalUnreadBadge() {
  if (!session.initialized) {
    return;
  }
  session.watchTotalNewMessageCount().listen((count) {
    if (count > 0) {
      FlutterAppBadger.updateBadgeCount(count);
    } else {
      FlutterAppBadger.removeBadge();
    }
  });
}

更多关于Flutter插件xmtp的介绍与使用_xmtp提供了用于 Flutter 应用的 XMTP 消息 API 客户端的 Dart 实现的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter插件xmtp的介绍与使用_xmtp提供了用于 Flutter 应用的 XMTP 消息 API 客户端的 Dart 实现的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


Flutter 未知功能插件 xmtp 的介绍与使用

介绍

xmtp 是一个相对不太为人知的 Flutter 插件,尽管其具体功能和用途在官方文档或常见资源中可能缺乏详尽的描述,但我们可以假设它提供了某种特定的数据传输或通信功能,基于其名称可能暗示的“扩展消息传输协议”(仅为假设,实际功能可能不同)。

由于 xmtp 并非 Flutter 社区广泛使用的标准插件,以下内容将基于一般 Flutter 插件的使用方法和假设的功能进行介绍。请注意,具体实现细节和 API 调用可能需要根据实际插件文档进行调整。

使用步骤

  1. 添加依赖

    首先,在 pubspec.yaml 文件中添加 xmtp 插件的依赖。由于 xmtp 并非一个真实存在的示例插件,这里我们使用一个假设的依赖项名称和版本号:

    dependencies:
      flutter:
        sdk: flutter
      xmtp: ^0.0.1  # 假设的版本号,实际使用时需替换为真实版本号
    

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

  2. 导入插件

    在你的 Dart 文件中导入 xmtp 插件:

    import 'package:xmtp/xmtp.dart';
    
  3. 初始化插件

    根据插件的具体要求,可能需要进行初始化。以下是一个假设的初始化过程:

    void main() {
      WidgetsFlutterBinding.ensureInitialized();
      // 假设 xmtp 插件有一个初始化方法
      Xmtp.instance.initialize().then((_) {
        runApp(MyApp());
      }).catchError((error) {
        print('Failed to initialize xmtp: $error');
      });
    }
    
  4. 使用插件功能

    假设 xmtp 插件提供了一个发送和接收消息的方法,以下是如何使用这些功能的示例代码:

    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: Text('XMTP Demo'),
            ),
            body: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  ElevatedButton(
                    onPressed: () {
                      // 发送消息示例
                      Xmtp.instance.sendMessage('Hello, XMTP!')
                        .then((response) {
                          print('Message sent successfully: $response');
                        })
                        .catchError((error) {
                          print('Failed to send message: $error');
                        });
                    },
                    child: Text('Send Message'),
                  ),
                  ElevatedButton(
                    onPressed: () {
                      // 接收消息示例(假设需要注册一个监听器)
                      Xmtp.instance.addMessageListener((message) {
                        print('Received message: $message');
                      });
                      // 注意:这里的监听器注册可能是一个持续运行的过程,不需要在按钮点击事件中完成
                    },
                    child: Text('Start Listening for Messages'),
                  ),
                ],
              ),
            ),
          ),
        );
      }
    }
    

注意事项

  • 由于 xmtp 是一个假设的插件名称,上述代码和步骤均基于假设的功能和 API。实际使用时,请参考插件的官方文档。
  • 插件的初始化和功能调用可能涉及异步操作,因此需要使用 async/await.then() 方法处理异步结果。
  • 确保在 AndroidManifest.xmlInfo.plist 文件中配置必要的权限和设置,如果插件需要与设备硬件或系统服务交互。

由于 xmtp 插件的具体细节未知,以上内容仅供参考。在实际项目中,请务必查阅插件的官方文档和示例代码以获取准确的使用指南。

回到顶部