Flutter网络发送插件sendingnetwork_dart_sdk的使用
Flutter网络发送插件sendingnetwork_dart_sdk的使用
1) 导入SDK
import 'package:sendingnetwork_dart_sdk/sdn.dart';
2) 创建客户端并填写服务器域名
final client = Client('SDN Example Chat', databaseBuilder: (_) async {
final dir = await getApplicationSupportDirectory();
final db = HiveCollectionsDatabase('sdn_example_chat', dir.path);
await db.open();
return db;
});
client.sdnnode = Uri.parse('https://XXX.network'); // 填写你的节点域名
2. 接口
请参阅我们的GitBook以获取详细的API文档:
以下是一个完整的示例Demo:
import 'dart:convert';
import 'dart:math';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get_state_manager/get_state_manager.dart';
import 'package:sendingnetwork_dart_sdk/sdn.dart';
import 'package:provider/provider.dart';
import 'package:fluttertoast/fluttertoast.dart';
import "package:web3dart/web3dart.dart";
import 'package:web3dart/crypto.dart';
import 'package:intl/intl.dart';
import 'package:eth_sig_util/eth_sig_util.dart';
import 'package:path_provider/path_provider.dart';
String privKey = ""; // 私钥
String addressHexAll = "";
String homeUrl = "https://portal0101.sending.network"; // 节点域名
// https://portal0101.sending.network
// 只用于演示,应该使用自己的开发签名URL
String developSignUrl = "https://rewards.sending.network/_api/appservice/sign";
late Room currentRoom;
void main() async {
WidgetsFlutterBinding.ensureInitialized();
final client = Client('SDN Example Chat', databaseBuilder: (_) async {
final dir = await getApplicationSupportDirectory();
final db = HiveCollectionsDatabase('sdn_example_chat', dir.path);
await db.open();
return db;
});
client.sdnnode = Uri.parse(homeUrl);
await client.init();
runApp(SDNExampleChat(client: client));
}
class SDNExampleChat extends StatelessWidget {
final Client client;
const SDNExampleChat({required this.client, Key? key}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'SDN Example Chat',
builder: (context, child) => Provider<Client>(
create: (context) => client,
child: child,
),
home: client.isLogged() ? const RoomListPage() : const LoginPage(),
);
}
}
class LoginPage extends StatefulWidget {
const LoginPage({Key? key}) : super(key: key);
[@override](/user/override)
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
bool _loading = false;
void createAddress() {
Random rng = Random.secure();
print("rng value: $rng"); //BigInt.from(12345678);
getDIDList(addressHexAll);
}
Uint8List bigIntToUint8List(BigInt value) {
List<int> byteList = [];
while (value > BigInt.zero) {
byteList.add(value.toUnsigned(8).toInt());
value >>= 8;
}
byteList = byteList.reversed.toList();
return Uint8List.fromList(byteList);
}
void getDIDList(String address) async {
print('getDIDList address => $address');
setState(() {
_loading = true;
});
final client = Provider.of<Client>(context, listen: false);
SDNDIDListResponse response = await client.getDIDList(address: address);
print("getDIDList response.did= ${response.data}");
if (response.data.isNotEmpty) {
showToast("getDIDListresult:did=:${response.data[0]}");
}
postPreLoginDID(response, address);
setState(() {
_loading = false;
});
}
void postPreLoginDID(SDNDIDListResponse response1, String address) async {
setState(() {
_loading = true;
});
final client = Provider.of<Client>(context, listen: false);
SDNLoginResponse response;
if (response1.data.isNotEmpty) {
response = await client.postPreLoginDID(did: response1.data[0]);
} else {
response = await client.postPreLoginDID(address: address);
}
print("postPreLoginDID response.did= ${response.did}");
print("postPreLoginDID response.message= ${response.message}");
print("postPreLoginDID response.updated= ${response.updated}");
print("postPreLoginDID random_server= ${response.random_server}");
showToast("postPreLoginDIDresultdid=:${response.did}");
appServiceSign(response);
setState(() {
_loading = false;
});
}
Future<void> appServiceSign(SDNLoginResponse responsesdn) async {
setState(() {
_loading = true;
});
final client = Provider.of<Client>(context, listen: false);
ApperviceSignResponse response = await client.appServiceSign(
message: responsesdn.message, address: developSignUrl);
print('appServiceSign message => ${response.signature}');
postLoginDId(responsesdn, response);
setState(() {
_loading = false;
});
}
void postLoginDId(SDNLoginResponse responsesdn, ApperviceSignResponse meessageSign) async {
setState(() {
_loading = true;
});
final client = Provider.of<Client>(context, listen: false);
try {
print("Message responsesdn.message : ${responsesdn.message}");
String str = responsesdn.message; ////responsesdn.message;
String signMessage = EthSigUtil.signPersonalMessage(
privateKey: privKey, message: convertStringToUint8List(str));
print("Message Hash signMessage (Uint8List): $signMessage");
Map<String, dynamic> jsonData = {
"did": responsesdn.did,
"address": addressHexAll,
"token": signMessage,
"message": str,
"app_token": meessageSign.signature
};
print("jsonString $jsonData");
var response = await client.postLoginDId(
type: "m.login.did.identity",
updated: responsesdn.updated,
identifier: jsonData,
random_server: responsesdn.random_server,
);
print("postLoginDId response.access_token= ${response.access_token}");
print("postLoginDId response.device_id= ${response.device_id}");
print("postLoginDIdresponse.user_id= ${response.user_id}");
showToast(
"postLoginDIdresult:did=:${response.user_id} ${response.error} ${response.errorcode} ");
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (_) => const RoomListPage()),
(route) => false,
);
} catch (e) {
print('Exception caught: $e');
showToast('Exception caught: $e');
}
setState(() {
_loading = false;
});
}
Uint8List encode(String s) {
var encodedString = utf8.encode(s);
var encodedLength = encodedString.length;
var data = ByteData(encodedLength + 4);
data.setUint32(0, encodedLength, Endian.big);
var bytes = data.buffer.asUint8List();
bytes.setRange(4, encodedLength + 4, encodedString);
return bytes;
}
Uint8List convertStringToUint8List(String str) {
final List<int> codeUnits = utf8.encode(str);
final Uint8List unit8List = Uint8List.fromList(codeUnits);
return unit8List;
}
void showToast(String text) {
Fluttertoast.showToast(
msg: text,
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.BOTTOM,
backgroundColor: Colors.grey,
textColor: Colors.white,
fontSize: 13.0,
);
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Demo网络测试')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: _loading ? null : createAddress,
child: _loading
? const LinearProgressIndicator()
: const Text('登录'),
),
),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: null,
child: _loading
? const LinearProgressIndicator()
: const Text('登录需要钱包地址和私钥'),
),
)
],
),
),
);
}
}
class RoomListPage extends StatefulWidget {
const RoomListPage({Key? key}) : super(key: key);
[@override](/user/override)
_RoomListPageState createState() => _RoomListPageState();
}
class _RoomListPageState extends State<RoomListPage> {
void _logout() async {
final client = Provider.of<Client>(context, listen: false);
await client.logout();
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (_) => const LoginPage()),
(route) => false,
);
}
void _join(Room room) async {
if (room.membership != Membership.join) {
print("roomid=${room.id}");
currentRoom = room;
await room.join();
print("joined roomid=${room.id}");
}
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => RoomPage(room: room),
),
);
}
[@override](/user/override)
Widget build(BuildContext context) {
final client = Provider.of<Client>(context, listen: false);
return Scaffold(
appBar: AppBar(
title: const Text('聊天列表'),
actions: [
IconButton(
icon: const Icon(Icons.logout),
onPressed: _logout,
),
],
),
body: StreamBuilder(
stream: client.onSync.stream,
builder: (context, _) => ListView.builder(
itemCount: client.rooms.length,
itemBuilder: (context, i) => ListTile(
leading: CircleAvatar(
foregroundImage: client.rooms[i].avatar == null
? null
: NetworkImage(
client.rooms[i].avatar!
.getThumbnail(
client,
width: 56,
height: 56,
)
.toString(),
),
),
title: Row(
children: [
Expanded(child: Text(client.rooms[i].displayname)),
if (client.rooms[i].notificationCount > 0)
Material(
borderRadius: BorderRadius.circular(99),
color: Colors.red,
child: Padding(
padding: const EdgeInsets.all(2.0),
child:
Text(client.rooms[i].notificationCount.toString()),
))
],
),
subtitle: Text(
client.rooms[i].lastEvent?.body ?? '无消息',
maxLines: 1,
),
onTap: () => _join(client.rooms[i]),
),
),
),
);
}
}
void _invite(Room room) async {
print("roomid=${room.id}");
currentRoom = room;
await room.invite("XXX");
print("invite userid=${room.id}");
}
void _setRoomRules(BuildContext context, Room room) async {
String jsonString = '''
{
"join_rule":"token.access",
"join_params":{
"logic":"ANY",
"requirements":[
{
"requiredToken":{
"name":"USD Coin",
"symbol":"USDC",
"logo":"https://static.alchemyapi.io/images/assets/3408.png",
"address":"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
},
"requiredAmount":10
},
{
"requiredToken":{
"name":"0N1 Force",
"symbol":"0N1",
"logo":"https://lh3.googleusercontent.com/7gOej3SUvqALR-qkqL_ApAt97SpUKQOZQe88p8jPjeiDDcqITesbAdsLcWlsIg8oh7SRrTpUPfPlm12lb4xDahgP2h32pQQYCsuOM_s=s120",
"address":"0x3bf2922f4520a8ba0c2efc3d2a1539678dad5e9d",
"type":"ERC721"
},
"requiredAmount":1
}
]
},
"join_advance":{
"rule_name":"",
"rule_interface":""
}
}
''';
Map<String, dynamic> jsonData = jsonDecode(jsonString);
final client = Provider.of<Client>(context, listen: false);
print("id=${room.id}");
print("jsonString=${jsonString}");
print("setRoomStateWithKeyjsonData=${jsonData}");
print("setRoomStateWithKeyjclient=${client}");
var response = await client.setRoomStateWithKey(
room.id,
"m.room.join_rules",
'',
jsonData,
);
print("setRoomStateWithKeyresponse=$response");
}
void _permissionCheck(BuildContext context, Room room) async {
final client = Provider.of<Client>(context, listen: false);
print("id=${room.id}");
// print("setRoomStateWithKeyjsonData=${jsonData}");
// print("setRoomStateWithKeyjclient=${client}");
SDNRoomPermissionCheckResponse response = await client.permissionCheck(
room_id: room.id,
access_token: client.accessToken!,
permission_id: "room.manage_message");
print("permissionCheck=${response.result}");
print("permissionCheck=${response.message}");
}
void _showAlertDialog(BuildContext context, Room room) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('更多测试'),
content: const Text('点击按钮进行更多测试'),
actions: [
TextButton(
onPressed: () {
_invite(room);
Navigator.of(context).pop();
},
child: const Text('邀请'),
),
TextButton(
onPressed: () {
_setRoomRules(context, room);
Navigator.of(context).pop();
},
child: const Text('设置房间规则'),
),
TextButton(
onPressed: () {
_permissionCheck(context, room);
Navigator.of(context).pop();
},
child: const Text('权限检查'),
),
],
);
},
);
}
class RoomPage extends StatefulWidget {
final Room room;
const RoomPage({required this.room, Key? key}) : super(key: key);
[@override](/user/override)
_RoomPageState createState() => _RoomPageState();
}
class _RoomPageState extends State<RoomPage> {
late final Future<Timeline> _timelineFuture;
final GlobalKey<AnimatedListState> _listKey = GlobalKey<AnimatedListState>();
[@override](/user/override)
void initState() {
_timelineFuture = widget.room.getTimeline(onChange: (i) {
print('on change! $i');
_listKey.currentState?.setState(() {});
}, onInsert: (i) {
print('on insert! $i');
_listKey.currentState?.insertItem(i);
}, onRemove: (i) {
print('On remove $i');
_listKey.currentState?.removeItem(i, (_, __) => const ListTile());
}, onUpdate: () {
print('On update');
});
super.initState();
}
final TextEditingController _sendController = TextEditingController();
void _send() {
widget.room.sendTextEvent(_sendController.text.trim());
_sendController.clear();
}
void _leave(Room room) async {
await widget.room.leave();
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.room.displayname),
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
Navigator.of(context).pop();
},
),
actions: [
ElevatedButton(
onPressed: () {
_showAlertDialog(context, widget.room);
},
child: const Text('更多测试'),
),
ElevatedButton(
onPressed: () {
_leave(widget.room);
print("返回");
Navigator.of(context).pop();
},
child: const Text('离开'),
)
],
),
body: SafeArea(
child: Column(
children: [
Expanded(
child: FutureBuilder<Timeline>(
future: _timelineFuture,
builder: (context, snapshot) {
final timeline = snapshot.data;
if (timeline == null) {
return const Center(
child: CircularProgressIndicator.adaptive(),
);
}
return Column(
children: [
Center(
child: TextButton(
onPressed: timeline.requestHistory,
child: const Text('加载更多...')),
),
const Divider(height: 1),
Expanded(
child: AnimatedList(
key: _listKey,
reverse: true,
initialItemCount: timeline.events.length,
itemBuilder: (context, i, animation) =>
timeline.events[i].relationshipEventId != null
? Container()
: ScaleTransition(
scale: animation,
child: Opacity(
opacity: timeline.events[i].status.isSent
? 1
: 0.5,
child: ListTile(
leading: CircleAvatar(
foregroundImage: timeline.events[i]
.sender.avatarUrl ==
null
? null
: NetworkImage(timeline
.events[i].sender.avatarUrl!
.getThumbnail(
widget.room.client,
width: 56,
height: 56,
)
.toString()),
),
title: Row(
children: [
Expanded(
child: Text(timeline
.events[i].sender
.calcDisplayname()),
),
Text(
timeline.events[i].originServerTs
.toIso8601String(),
style:
const TextStyle(fontSize: 10),
),
],
),
subtitle: Text(timeline.events[i]
.getDisplayEvent(timeline)
.body),
),
),
),
),
),
],
);
},
),
),
const Divider(height: 1),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Row(
children: [
Expanded(
child: TextField(
controller: _sendController,
decoration: const InputDecoration(
hintText: '发送消息',
),
)),
IconButton(
icon: const Icon(Icons.send_outlined),
onPressed: _send,
),
],
),
),
],
),
),
);
}
}
更多关于Flutter网络发送插件sendingnetwork_dart_sdk的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter网络发送插件sendingnetwork_dart_sdk的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
sendingnetwork_dart_sdk
是一个用于在 Flutter 应用中发送网络请求的 Dart SDK。虽然它不是 Flutter 官方推荐的网络请求插件(官方推荐的是 http
或 dio
),但它可能是一个特定场景下使用的 SDK。以下是一个基本的使用指南,假设你已经将 sendingnetwork_dart_sdk
添加到你的 pubspec.yaml
文件中。
1. 添加依赖
首先,确保你已经在 pubspec.yaml
文件中添加了 sendingnetwork_dart_sdk
依赖:
dependencies:
sendingnetwork_dart_sdk: ^1.0.0 # 使用最新版本
然后运行 flutter pub get
来获取依赖。
2. 初始化 SDK
在你的 Flutter 应用中初始化 sendingnetwork_dart_sdk
。通常,你需要在应用的 main
函数或某个初始化函数中进行初始化。
import 'package:sendingnetwork_dart_sdk/sendingnetwork_dart_sdk.dart';
void main() {
// 初始化 SDK
SendingNetworkSDK.initialize(
baseUrl: 'https://api.example.com', // 你的 API 基础 URL
apiKey: 'your_api_key', // 你的 API 密钥(如果需要)
);
runApp(MyApp());
}
3. 发送网络请求
使用 SendingNetworkSDK
发送网络请求。以下是一个简单的 GET 请求示例:
import 'package:flutter/material.dart';
import 'package:sendingnetwork_dart_sdk/sendingnetwork_dart_sdk.dart';
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('SendingNetwork SDK Example'),
),
body: Center(
child: ElevatedButton(
onPressed: () async {
try {
// 发送 GET 请求
var response = await SendingNetworkSDK.instance.get('/endpoint');
print('Response: ${response.body}');
} catch (e) {
print('Error: $e');
}
},
child: Text('Send Request'),
),
),
),
);
}
}
4. 处理响应
在上面的示例中,response
对象包含了服务器返回的数据。你可以根据需要进行处理。
var response = await SendingNetworkSDK.instance.get('/endpoint');
if (response.statusCode == 200) {
// 请求成功
print('Response: ${response.body}');
} else {
// 请求失败
print('Error: ${response.statusCode}');
}
5. 发送 POST 请求
发送 POST 请求的示例如下:
var response = await SendingNetworkSDK.instance.post(
'/endpoint',
body: {
'key1': 'value1',
'key2': 'value2',
},
);
6. 处理错误
在实际应用中,网络请求可能会失败。你可以使用 try-catch
来捕获和处理错误。
try {
var response = await SendingNetworkSDK.instance.get('/endpoint');
print('Response: ${response.body}');
} catch (e) {
print('Error: $e');
}