Flutter深度链接远程过程调用插件deeplink_rpc的使用

Flutter深度链接远程过程调用插件deeplink_rpc的使用

简介

deeplink_rpc 是一个基于Dart编写的通过深度链接进行远程过程调用(RPC)的库。它专门用于Flutter移动应用(iOS/Android)。

协议

深度链接编码器

深度链接消息会被附加到深度链接URI中。因此,可用的格式有一些限制。

为了使其正常工作,消息被编码为:

                     +--------------+   +------+   +--------+
method_payload :     | Json Message |-> | gzip |-> | base64 |
                     +--------------+   +------+   +--------+

Deeplink Url : `<scheme>://<host>/<method_name>/<method_payload>`

示例:

                     +--------------------------+      +----------------------------------------------------------------+
method_payload :     | { "param1" : "a_value" } |----> | "H4sIAAAAAAAAA6tWUCpILErMNVRSsFJQSowvS8wpTVVSqAUAhIgKchgAAAA=" |
                     +--------------------------+      +----------------------------------------------------------------+

Deeplink Url : `scheme://host/a_method/H4sIAAAAAAAAA6tWUCpILErMNVRSsFJQSowvS8wpTVVSqAUAhIgKchgAAAA=`

请求格式化

请求的有效载荷被封装在 <a href="https://www.jsonrpc.org/specification" rel="ugc">JSON-RPC 2.0</a> 消息中。

{
  "id": Number,                     // 唯一的客户端生成整数,用于标识请求
  "replyUrl": String,               // 发送调用结果的深度链接URL。这应该是一个由DApp处理的深度链接URL。
  "params": {
    "origin": {
      "name": String,               // 可读标识符,表示DApp
      "url": String | undefined,    // DApp的URL
      "logo": Base64 | undefined,   // DApp的Logo
    },
    "version": 2,                   // DApp API版本
    "payload": Object,              // 方法参数
  }
}

成功响应格式化

{
  "id": Number,                     // 请求标识符
  "result":  Object,                // 结果有效载荷
}

失败响应格式化

{
  "id": Number,                     // 请求标识符
  "failure": {
    "code": Number,                 // 错误代码
    "message": String | undefined,  // 错误描述
    "data": Object | undefined,     // 错误数据
  },
}

使用方法

服务器 - 监听传入的请求

/// 1. 启用您的应用程序的深度链接(https://docs.flutter.dev/development/ui/navigation/deep-linking)

/// 2. 声明深度链接-RPC接收器
/// 当接收到RPC调用 &lt;scheme&gt;://a_rpc_command/&lt;payload&gt; 时,有效载荷被解码并传输给 `handle` 方法。
final _deeplinkRpcReceiver = DeeplinkRpcRequestReceiver()
    ..registerHandler(
      DeeplinkRpcRequestHandler(
        route: const DeeplinkRpcRoute('a_rpc_command'),
        handle: (request) {
            log('Command received');
        }
      ),
    );


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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'DeeplinkRPC Demo',
      home: const SendForm(),
      onGenerateRoute: (settings) {
        /// 3. 监听传入的深度链接请求
        if (_deeplinkRpcReceiver.handleRoute(settings.name)) return;

        // ... 进行其他路由生成操作
        return null;
      },
    );
  }
}

客户端 - 发送请求并监听响应

/// 1. 启用您的应用程序的深度链接(https://docs.flutter.dev/development/ui/navigation/deep-linking)
/// 这对于接收响应是必要的。

/// 2. 声明深度链接-RPC客户端
/// 当接收到RPC调用 &lt;scheme&gt;://a_rpc_command/&lt;payload&gt; 时,有效载荷被解码并传输给 `handle` 方法。
final _deeplinkRpcClient = DeeplinkRpcClient();

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'DeeplinkRPC Demo',
      onGenerateRoute: (settings) {
        /// 3. 监听传入的深度链接请求
        if (_deeplinkRpcClient.handleRoute(settings.name)) return;

        // ... 进行其他路由生成操作
        return null;
      },
      home: Scaffold(
        floatingActionButton: FloatingActionButton(
          child: const Icon(Icons.send),
          onPressed: () async {
            final response = await _deeplinkRpcClient.send(
              timeout: const Duration(seconds: 5),
              request: DeeplinkRpcRequest(
                requestUrl: 'serverapp://server.app/request_endpoint',
                replyUrl: 'clientapp://client.app/reply_endpoint',
                params: {
                  'param1': 'value1',
                  'param2': 'value2',
                },
              ),
            );

            response.map(
              failure: (failure) {
                log(
                  'RPC request failed',
                  error: failure,
                );
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(
                      content: Text(failure.message ?? "An error occured")),
                );
              },
              success: (result) {
                log(
                  'RPC request succeed : ${json.encode(result)}',
                );
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(content: Text(json.encode(result))),
                );
              },
            );
          },
        ),
        body: const SafeArea(
          child: Padding(
            padding: EdgeInsets.all(8.0),
            child: Center(
              child: Text('Client example'),
            ),
          ),
        ),
      ),
    );
  }
}

示例代码

以下是完整的示例代码,展示了如何使用 deeplink_rpc 插件。

/// SPDX-License-Identifier: AGPL-3.0-or-later
import 'dart:convert';

import 'package:deeplink_rpc/deeplink_rpc.dart';
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';

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

final _deeplinkRpcClient = DeeplinkRpcClient();

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

  final _messengerKey = GlobalKey<ScaffoldMessengerState>();
  final _logger = Logger('Example app');

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      scaffoldMessengerKey: _messengerKey,
      title: 'DeeplinkRPC Demo',
      onGenerateRoute: (settings) {
        if (_deeplinkRpcClient.handleRoute(settings.name)) return;
        return null;
      },
      home: Scaffold(
        floatingActionButton: FloatingActionButton(
          child: const Icon(Icons.send),
          onPressed: () async {
            final response = await _deeplinkRpcClient.send(
              timeout: const Duration(seconds: 5),
              request: DeeplinkRpcRequest(
                requestUrl: 'serverapp://server.app/request_endpoint',
                replyUrl: 'clientapp://client.app/reply_endpoint',
                params: {
                  'param1': 'value1',
                  'param2': 'value2',
                },
              ),
            );

            response.map(
              failure: (failure) {
                _logger.severe(
                  'RPC request failed',
                  failure,
                );
                _messengerKey.currentState?.showSnackBar(
                  SnackBar(
                    content: Text(failure.message ?? 'An error occured'),
                  ),
                );
              },
              success: (result) {
                _logger.info(
                  'RPC request succeed : ${json.encode(result)}',
                );
                _messengerKey.currentState?.showSnackBar(
                  SnackBar(content: Text(json.encode(result))),
                );
              },
            );
          },
        ),
        body: const SafeArea(
          child: Padding(
            padding: EdgeInsets.all(8),
            child: Center(
              child: Text('Client example'),
            ),
          ),
        ),
      ),
    );
  }
}

更多关于Flutter深度链接远程过程调用插件deeplink_rpc的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter深度链接远程过程调用插件deeplink_rpc的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中集成和使用deeplink_rpc插件的示例代码。这个插件允许你通过深度链接(Deep Linking)进行远程过程调用(RPC)。

1. 添加依赖

首先,你需要在pubspec.yaml文件中添加deeplink_rpc插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  deeplink_rpc: ^latest_version  # 替换为最新版本号

2. 导入插件

在你的Flutter项目中,导入deeplink_rpc插件:

import 'package:deeplink_rpc/deeplink_rpc.dart';

3. 配置AndroidManifest.xml

为了在Android上支持深度链接,你需要在AndroidManifest.xml文件中添加相应的配置。例如:

<activity
    android:name=".MainActivity"
    android:launchMode="singleTop"
    android:theme="@style/LaunchTheme"
    android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
    android:hardwareAccelerated="true"
    android:windowSoftInputMode="adjustResize">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    <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:scheme="http" android:host="yourapp.com" android:pathPrefix="/rpc" />
    </intent-filter>
</activity>

4. 初始化插件并处理深度链接

在你的Flutter应用的入口文件(通常是main.dart)中,初始化deeplink_rpc插件并处理深度链接:

import 'package:flutter/material.dart';
import 'package:deeplink_rpc/deeplink_rpc.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Deep Link RPC Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
      onGenerateRoute: (RouteSettings settings) {
        if (settings.name == '/rpc') {
          // 处理深度链接RPC调用
          final uri = Uri.parse(settings.arguments as String);
          handleRpcCall(uri);
          return MaterialPageRoute(builder: (_) => MyHomePage()); // 返回主页面或合适的页面
        }
        return null; // 返回null表示未处理该路由
      },
    );
  }

  void handleRpcCall(Uri uri) {
    // 解析URI并处理RPC调用
    final rpcMethod = uri.queryParameters['method'] ?? '';
    final rpcParams = uri.queryParameters['params'] ?? '';

    print('RPC Method: $rpcMethod');
    print('RPC Params: $rpcParams');

    // 在这里实现RPC方法调用逻辑
    // 例如,根据rpcMethod的值调用不同的函数,并传递rpcParams作为参数
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Deep Link RPC Demo'),
      ),
      body: Center(
        child: Text('Open a deep link with RPC parameters to see them handled here.'),
      ),
    );
  }
}

5. 测试深度链接

为了测试深度链接,你可以使用设备的浏览器或其他应用打开一个链接,例如:

http://yourapp.com/rpc?method=testMethod&params=testParams

如果配置正确,handleRpcCall方法应该会被调用,并打印出RPC MethodRPC Params

注意事项

  • 确保你已经在Android和iOS平台上正确配置了深度链接支持。
  • 对于iOS,你需要在Info.plist文件中添加相应的配置来支持URL Scheme。
  • 在实际项目中,你可能需要更复杂的URI解析和RPC方法处理逻辑。

这个示例代码展示了如何在Flutter项目中集成deeplink_rpc插件,并通过深度链接处理RPC调用。希望这对你有所帮助!

回到顶部