Deeplink RPC
一个用 Dart 编写的通过 deeplink 进行 RPC 通信的库。该库专为 Flutter 移动应用程序(iOS / Android)设计。
协议
Deeplink 编解码器
Deeplink 消息会被附加到 deeplink 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=`
请求格式
请求的 payload 被封装在一个 **JSON-RPC 2.0** 消息中。
{
"id": Number, // An unique client-generated integer identifying the request
"replyUrl": String, // Deeplink URL to which send the invokation result. This should be a Deeplink URL handled by the DApp.
"params": {
"origin": {
"name": String, // Human readable identifier of the DApp
"url": String | undefined, // URL of the DApp
"logo": Base64 | undefined, // Logo of the DApp
},
"version": 2, // Version of the DApp API
"payload": Object, // Method parameters
}
}
成功响应格式
{
"id": Number, // The request identifier
"result": Object, // Result payload
}
失败响应格式
{
"id": Number, // The request identifier
"failure": {
"code": Number, // Error code
"message": String | undefined, // Error description
"data": Object | undefined, // Error data
},
}
用法
服务器 – 监听传入请求
/// 1. Enable deeplinking for your application (https://docs.flutterdart.cn/development/ui/navigation/deep-linking)
/// 2. Declare the deeplink-rpc receiver
/// When a RPC call <scheme>://a_rpc_command/<payload> is received, the payload is decoded
/// and transmitted to the `handle` method.
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
Widget build(BuildContext context) {
return MaterialApp(
title: 'DeeplinkRPC Demo',
home: const SendForm(),
onGenerateRoute: (settings) {
if (_deeplinkRpcReceiver.canHandle(settings.name)) {
_deeplinkRpcReceiver.handle(settings.name);
return null;
}
return null;
},
);
}
}
客户端 – 发送请求并监听响应
/// 1. Enable deeplinking for your application (https://docs.flutterdart.cn/development/ui/navigation/deep-linking)
/// It is necessary to receive responses.
/// 2. Declare the deeplink-rpc client
/// When a RPC call <scheme>://a_rpc_command/<payload> is received, the payload is decoded
/// and transmitted to the `handle` method.
final _deeplinkRpcClient = DeeplinkRpcClient();
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
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) {
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'),
),
),
),
),
);
}
}