import 'dart:async'; import 'dart:isolate'; import 'dart:math'; import 'dart:ui'; import 'package:fast_gbk/fast_gbk.dart'; import 'package:flutter/material.dart'; import 'package:mqtt_client/mqtt_client.dart'; import 'package:mqtt_client/mqtt_server_client.dart'; import 'package:flutter_notification_listener/flutter_notification_listener.dart'; import 'package:uuid/uuid.dart'; Future main() async { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'MokiBox', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(title: 'Moki收款宝'), ); } } class Listener { Mqtt mqtt = Mqtt(); Listener() { initPlatformState(); } @pragma('vm:entry-point') static void _callback(NotificationEvent evt) { final SendPort? send = IsolateNameServer.lookupPortByName("notifications_send_port"); if (send == null) print("can't find the sender"); send?.send(evt); } void testSendMsg() { String msg = "{\"type\":\"tts_dynamic\",\"msgid\":\"${Random().nextInt(999999)}\",\"txt\":\"设备已连接!\"}"; mqtt.sendMsg(msg); } void onData(NotificationEvent event) { String? msg; if (event.packageName == 'com.eg.android.AlipayGphone' && event.title == '店员通') { msg = event.text; if (msg == null) return; final number = RegExp(r'\d+\.\d+').firstMatch(msg); final orderId = Random().nextInt(999999); if (number != null) { final regAmount = double.parse(number.group(0)!); String amount = regAmount.toStringAsFixed(2); if (amount.endsWith('.00')) { amount = amount.replaceAll('.00', ''); } String msgPush = '866374061547503|1007-2|$orderId|2001|$amount|7571'; mqtt.sendMsg(msgPush); } } if (event.packageName == 'com.tencent.mm' && event.title == '微信收款助手') { msg = event.text; if (msg == null) return; final number = RegExp(r'\d+\.\d+').firstMatch(msg); final orderId = Random().nextInt(999999); if (number != null) { final regAmount = double.parse(number.group(0)!); String amount = regAmount.toStringAsFixed(2); if (amount.endsWith('.00')) { amount = amount.replaceAll('.00', ''); } String msgPush = '866374061547503|1007-2|$orderId|2003|$amount|7571'; mqtt.sendMsg(msgPush); } } } // 监听到消息后转到处理函数 Future initPlatformState() async { NotificationsListener.initialize(callbackHandle: _callback); // register you event handler in the ui logic. NotificationsListener.receivePort?.listen((evt) => onData(evt)); } void startListening() async { print("start listening"); var isR = await NotificationsListener.isRunning; if (!isR!) { await NotificationsListener.startService(); } } Future checkPermission() async { var hasPermission = await NotificationsListener.hasPermission; if (!hasPermission!) { print("no permission, so open settings"); NotificationsListener.openPermissionSettings(); return; } } } class Mqtt { late MqttServerClient client; Mqtt() { connect(); } Future connect() async { var uuid = const Uuid(); client = MqttServerClient.withPort('47.92.50.210', uuid.v4(), 9883); client.logging(on: true); String willMsg = "{\"type\":\"tts_dynamic\",\"msgid\":\"${Random().nextInt(999999)}\",\"txt\":\"lost connect!\"}"; final connMessage = MqttConnectMessage() .authenticateAs('moki', 'Moki@886.') .withWillTopic('866374061547503') .withWillMessage(willMsg) .startClean() // 清理会话 .withWillQos(MqttQos.atLeastOnce); client.connectionMessage = connMessage; client.autoReconnect = true; client.keepAlivePeriod = 120; try { await client.connect(); } catch (e) { print('Exception: $e'); client.disconnect(); } return client; } Future sendMsg(String msg) async { // 发布消息 final builder = MqttClientPayloadBuilder(); // builder.addString(msg); final bytes = gbk.encode(msg); for (var element in bytes) { builder.addByte(element); } // MqttServerClient client = await connect(); client.publishMessage( '866374061547503', MqttQos.atLeastOnce, builder.payload!); return 'success'; } // // 断开连接 // await // // client.disconnect(); } class MyHomePage extends StatefulWidget { const MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @override State createState() => _MyHomePageState(); } class _MyHomePageState extends State { late Listener listener = Listener(); // 弹框信息 void _showDialog(BuildContext context, String msg, bool tag) { String title = tag ? '成功!' : '失败'; showDialog( context: context, builder: (BuildContext context) { return Theme( data: Theme.of(context).copyWith( dialogTheme: DialogTheme( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(5.0)))), child: AlertDialog( title: Text(title), content: Text(msg), actions: [ TextButton( child: const Center(child: Text('确定')), onPressed: () { Navigator.of(context).pop(); }, ), ], )); }, ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), backgroundColor: Colors.cyan, ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text( '欢迎使用魔基盒收款宝', style: TextStyle( fontSize: 22, // 设置字体大小为20 ), textAlign: TextAlign.center, ), const Text( '请依次点击如下按钮!', style: TextStyle( fontSize: 16, // 设置字体大小为20 ), textAlign: TextAlign.center, ), ElevatedButton.icon( icon: const Icon(Icons.ad_units_outlined), label: const Text("申请权限"), style: ElevatedButton.styleFrom( foregroundColor: Colors.white, backgroundColor: Colors.cyan, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(5), // 设置按钮的圆角半径为10 ), ), onPressed: () async { listener.checkPermission(); }, ), ElevatedButton.icon( icon: const Icon(Icons.add_chart_rounded), onPressed: () async { listener.startListening(); _showDialog(context, '服务已成功启动!', true); }, label: const Text('开启监听'), style: ElevatedButton.styleFrom( foregroundColor: Colors.white, backgroundColor: Colors.greenAccent, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(5), // 设置按钮的圆角半径为10 ), ), ), ElevatedButton.icon( icon: const Icon(Icons.add_alert_outlined), onPressed: () async { listener.testSendMsg(); }, label: const Text('检测设备'), style: ElevatedButton.styleFrom( foregroundColor: Colors.white, backgroundColor: Colors.grey, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(5), // 设置按钮的圆角半径为10 ), ), ) ], ), ), ); } }