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

1 回复

更多关于Flutter网络发送插件sendingnetwork_dart_sdk的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


sendingnetwork_dart_sdk 是一个用于在 Flutter 应用中发送网络请求的 Dart SDK。虽然它不是 Flutter 官方推荐的网络请求插件(官方推荐的是 httpdio),但它可能是一个特定场景下使用的 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');
}
回到顶部