diff --git a/images/call_me_icon.jpg b/images/call_me_icon.jpg new file mode 100644 index 00000000..ebc66b3e Binary files /dev/null and b/images/call_me_icon.jpg differ diff --git a/lib/main.dart b/lib/main.dart index 496b2b69..6ef88135 100755 --- a/lib/main.dart +++ b/lib/main.dart @@ -18,6 +18,7 @@ import 'package:star_lock/talk/starChart/status/appLifecycle_observer.dart'; import 'package:star_lock/tools/bugly/bugly_tool.dart'; import 'package:star_lock/tools/device_info_service.dart'; import 'package:star_lock/tools/platform_info_services.dart'; +import 'package:star_lock/tools/push/notification_service.dart'; import 'package:star_lock/tools/push/xs_jPhush.dart'; import 'package:star_lock/tools/storage.dart'; import 'package:star_lock/translations/trans_lib.dart'; @@ -36,7 +37,7 @@ FutureOr main() async { AppLifecycleObserver appLifecycleObserver = AppLifecycleObserver(); WidgetsBinding.instance.addObserver(appLifecycleObserver); - await ApmHelper.instance.initApp(); + // await ApmHelper.instance.initApp(); await _setCommonServices(); // 设置国际化信息 @@ -54,6 +55,8 @@ FutureOr main() async { } }); + NotificationService().init(); // 初始化通知服务 + //ToDo: 增加对讲调试、正式可删除 runApp(MultiProvider(providers: [ ChangeNotifierProvider(create: (_) => DebugInfoModel()), diff --git a/lib/talk/starChart/handle/impl/udp_talk_request_handler.dart b/lib/talk/starChart/handle/impl/udp_talk_request_handler.dart index 45fc0c63..9fb5ce97 100644 --- a/lib/talk/starChart/handle/impl/udp_talk_request_handler.dart +++ b/lib/talk/starChart/handle/impl/udp_talk_request_handler.dart @@ -14,6 +14,7 @@ import 'package:star_lock/talk/starChart/proto/gateway_reset.pb.dart'; import 'package:star_lock/talk/starChart/proto/generic.pb.dart'; import 'package:star_lock/talk/starChart/proto/talk_expect.pb.dart'; import 'package:star_lock/talk/starChart/proto/talk_request.pb.dart'; +import 'package:star_lock/tools/push/xs_jPhush.dart'; import 'package:star_lock/tools/storage.dart'; class UdpTalkRequestHandler extends ScpMessageBaseHandle @@ -78,6 +79,24 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle // 收到来电请求时进行本地通知 Future _showTalkRequestNotification( {required String talkObjectName}) async { + final Map message = { + 'platform': 'all', + 'audience': 'all', + 'notification': >{ + 'android': { + 'title': '呼叫提醒'.tr, + 'alert': '${'收到来自'.tr}($talkObjectName)${'锁的呼叫'.tr}。', + 'extras': { + 'image_url': + 'https://image.baidu.com/search/detail?ct=503316480&z=0&ipn=d&word=视频通话图标&step_word=&hs=0&pn=18&spn=0&di=7456461798821068801&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&istype=0&ie=utf-8&oe=utf-8&in=&cl=2&lm=-1&st=undefined&cs=3670633426%2C2210940696&os=2119936476%2C3383901310&simid=3670633426%2C2210940696&adpicid=0&lpn=0&ln=1216&fr=&fmq=1738909566404_R&fm=&ic=undefined&s=undefined&hd=undefined&latest=undefined©right=undefined&se=&sme=&tab=0&width=undefined&height=undefined&face=undefined&ist=&jit=&cg=&bdtype=0&oriquery=&objurl=https%3A%2F%2Ftenfei03.cfp.cn%2Fcreative%2Fvcg%2Fnowarter800%2Fnew%2FVCG211249198901.jpg&fromurl=ippr_z2C%24qAzdH3FAzdH3Fooo_z%26e3Bev2_z%26e3Bv54AzdH3Fv6jwptejAzdH3F8dnla9lla0&gsm=1e&rpstart=0&rpnum=0&islist=&querylist=&nojc=undefined&dyTabStr=MCwxMiwzLDEsMiwxMyw3LDYsNSw5&lid=9610633549467928081' + } + } + } + }; + + XSJPushProvider().showCustomNotification(message); + + /* const AndroidNotificationDetails androidPlatformChannelSpecifics = AndroidNotificationDetails('1', 'flutter_channel', importance: Importance.max, @@ -94,6 +113,7 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle await flutterLocalNotificationsPlugin.show(0, '呼叫提醒'.tr, '${'收到来自'.tr}($talkObjectName)${'锁的呼叫'.tr}。', platformChannelSpecifics, payload: 'item x'); + */ } @override diff --git a/lib/tools/push/notification_service.dart b/lib/tools/push/notification_service.dart new file mode 100644 index 00000000..596f6735 --- /dev/null +++ b/lib/tools/push/notification_service.dart @@ -0,0 +1,107 @@ +import 'dart:convert'; +import 'dart:typed_data'; +import 'package:flutter/services.dart' show rootBundle; + +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:http/http.dart' as http; + +class NotificationService { + factory NotificationService() { + return _instance; + } + NotificationService._internal(); + static final NotificationService _instance = NotificationService._internal(); + + final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); + + void init() { + const AndroidInitializationSettings initializationSettingsAndroid = + AndroidInitializationSettings('@mipmap/ic_launcher'); + + const InitializationSettings initializationSettings = + InitializationSettings(android: initializationSettingsAndroid); + + _flutterLocalNotificationsPlugin.initialize(initializationSettings); + } + + /// **📌 方法1:显示普通文本通知** + Future showTextNotification(String title, String body) async { + const AndroidNotificationDetails androidPlatformChannelSpecifics = + AndroidNotificationDetails( + '1', + 'flutter_channel', + importance: Importance.max, + priority: Priority.high, + ); + + const NotificationDetails platformChannelSpecifics = + NotificationDetails(android: androidPlatformChannelSpecifics); + + await _flutterLocalNotificationsPlugin.show( + 0, + title, + body, + platformChannelSpecifics, + ); + } + + /// **📌 方法2:显示带图片的推送通知** + Future showImageNotification( + String title, String body, String imageUrl) async { + // //读取网络下载图片 + // final ByteArrayAndroidBitmap? bigPicture = await _downloadImage(imageUrl); + // 读取本地图片 + final ByteData imageData = await rootBundle.load('images/call_me_icon.jpg'); + final Uint8List imageBytes = imageData.buffer.asUint8List(); + final ByteArrayAndroidBitmap bigPicture = + ByteArrayAndroidBitmap(imageBytes); + + if (bigPicture == null) { + showTextNotification(title, body); + return; + } + + final BigPictureStyleInformation bigPictureStyleInformation = + BigPictureStyleInformation( + bigPicture, + contentTitle: title, + summaryText: body, + ); + + final AndroidNotificationDetails androidPlatformChannelSpecifics = + AndroidNotificationDetails( + '1', + 'flutter_channel', + importance: Importance.max, + priority: Priority.high, + styleInformation: bigPictureStyleInformation, + sound: const RawResourceAndroidNotificationSound( + 'assets/ring1.mp3'), // 自定义铃声 + ); + + final NotificationDetails platformChannelSpecifics = + NotificationDetails(android: androidPlatformChannelSpecifics); + + await _flutterLocalNotificationsPlugin.show( + 0, + title, + body, + platformChannelSpecifics, + ); + } + + /// **📌 辅助方法:下载网络图片** + Future _downloadImage(String url) async { + try { + final http.Response response = await http.get(Uri.parse(url)); + if (response.statusCode == 200) { + return ByteArrayAndroidBitmap.fromBase64String( + base64Encode(response.bodyBytes)); + } + } catch (e) { + print('❌ 图片下载失败: $e'); + } + return null; + } +} diff --git a/lib/tools/push/xs_jPhush.dart b/lib/tools/push/xs_jPhush.dart index 1d1847f2..254773bb 100755 --- a/lib/tools/push/xs_jPhush.dart +++ b/lib/tools/push/xs_jPhush.dart @@ -8,12 +8,14 @@ import 'package:star_lock/mine/minePersonInfo/minePersonInfoEditAccount/minePers import 'package:star_lock/network/api_repository.dart'; import 'package:star_lock/tools/baseGetXController.dart'; import 'package:star_lock/tools/push/message_management.dart'; +import 'package:star_lock/tools/push/notification_service.dart'; import 'package:star_lock/tools/storage.dart'; import '../../app_settings/app_settings.dart'; class XSJPushProvider { final JPush jpush = JPush(); + final NotificationService _notificationService = NotificationService(); // appKey: 251fc8074820d122b6de58d2--鑫泓佳AppKey // appKey: 7ff37d174c1a568a89e98dad--sky @@ -45,6 +47,8 @@ class XSJPushProvider { jpush.addEventHandler( onReceiveNotification: (Map message) async { AppLog.log('onReceiveNotification: $message'); + // 这里可以用 flutter_local_notifications 自定义通知样式 + showCustomNotification(message); }, onOpenNotification: (Map message) async { AppLog.log('onOpenNotification: $message'); @@ -72,6 +76,16 @@ class XSJPushProvider { ); } + Future showCustomNotification(Map message) async { + final String title = message['notification']['android']['title'] ?? '默认标题'; + final String content = + message['notification']['android']['alert'] ?? '默认内容'; + final String imageUrl = message['notification']['android']['extras'] + ?['image_url']; // 从 extras 获取图片 + + NotificationService().showImageNotification(title, content, imageUrl); + } + Future pushBindDeviceID(String deviceID, int deviceType) async { try { final MineUnbindPhoneOrEmailEntity entity =