From b6cd0d0f2b0be7d9e624d1d15c46811e9e3a1377 Mon Sep 17 00:00:00 2001 From: GYJ <1157756119@qq.com> Date: Thu, 28 Nov 2024 13:49:26 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8E=A5=E5=90=AC=E6=8C=82=E6=96=AD=E7=94=B5?= =?UTF-8?q?=E8=AF=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../czg/cashier_reserve/call/CallManager.java | 20 +++ .../cashier_reserve/channel/ChannelNames.java | 3 + .../channel/MessageChannel.java | 54 +++++++ images/call/accept.png | Bin 0 -> 6524 bytes images/call/reject.png | Bin 0 -> 4884 bytes lib/call/call_view.dart | 137 +++++++++++++++++- lib/common/channel/channel_manager.dart | 30 ++++ lib/common/channel/names.dart | 3 + lib/common/manager/event_manager.dart | 8 + lib/home/home_view_model.dart | 41 +++++- lib/home/reserve_view.dart | 8 +- lib/home/reserve_view_model.dart | 12 ++ pubspec.yaml | 2 + 13 files changed, 305 insertions(+), 13 deletions(-) create mode 100644 images/call/accept.png create mode 100644 images/call/reject.png diff --git a/android/app/src/main/java/com/czg/cashier_reserve/call/CallManager.java b/android/app/src/main/java/com/czg/cashier_reserve/call/CallManager.java index 5e46aed..8ecb104 100644 --- a/android/app/src/main/java/com/czg/cashier_reserve/call/CallManager.java +++ b/android/app/src/main/java/com/czg/cashier_reserve/call/CallManager.java @@ -17,6 +17,8 @@ import org.json.JSONObject; import java.text.SimpleDateFormat; import java.util.Date; +import cn.kaer.callmodule.ctrl.CallController; +import cn.kaer.callmodule.exceptions.CallException; import io.flutter.Log; public class CallManager { @@ -68,4 +70,22 @@ public class CallManager { broad.putExtra("callLog", callLogArray.toString()); mainActivityContext.sendBroadcast(broad); } + + public static void acceptCall() { + try { + CallController.get().answer(); + } catch (CallException e) { + e.printStackTrace(); + } + } + + public static void rejectCall() { + try { + CallController.get().term(); + } catch (CallException e) { + e.printStackTrace(); + } + } + + public static void endCall() {} } diff --git a/android/app/src/main/java/com/czg/cashier_reserve/channel/ChannelNames.java b/android/app/src/main/java/com/czg/cashier_reserve/channel/ChannelNames.java index e90f9d4..a3c6679 100644 --- a/android/app/src/main/java/com/czg/cashier_reserve/channel/ChannelNames.java +++ b/android/app/src/main/java/com/czg/cashier_reserve/channel/ChannelNames.java @@ -8,6 +8,9 @@ public class ChannelNames { public static final String CALL_LOG_CALLBACK = "callLogCallback"; public static final String CALL_STATUS_CHANGE = "callStatusChange"; + public static final String ACCEPT_CALL = "acceptCall"; + public static final String REJECT_CALL = "rejectCall"; + public static final String END_CALL = "endCall"; public static String getChannelName(String name) { return BASE_NAME + name; diff --git a/android/app/src/main/java/com/czg/cashier_reserve/channel/MessageChannel.java b/android/app/src/main/java/com/czg/cashier_reserve/channel/MessageChannel.java index 39b11f1..35403d4 100644 --- a/android/app/src/main/java/com/czg/cashier_reserve/channel/MessageChannel.java +++ b/android/app/src/main/java/com/czg/cashier_reserve/channel/MessageChannel.java @@ -8,6 +8,9 @@ import io.flutter.plugin.common.MethodChannel; public class MessageChannel { public static void addMessageChannel(BinaryMessenger messenger) { callLogChannel(messenger); + acceptCallChannel(messenger); + rejectCallChannel(messenger); + endCallChannel(messenger); } public static void callLogChannel(BinaryMessenger messenger) { @@ -26,4 +29,55 @@ public class MessageChannel { }; }); } + + public static void acceptCallChannel(BinaryMessenger messenger) { + if (messenger == null) { + return; + } + + MethodChannel methodChannel = new MethodChannel(messenger, ChannelNames.getChannelName(ChannelNames.ACCEPT_CALL)); + + methodChannel.setMethodCallHandler((call, result) -> { + System.out.println("call.method: " + call.method); + if (call.method.equals(ChannelNames.ACCEPT_CALL)) { + System.out.println("接听电话"); + result.success(null); + CallManager.acceptCall(); + } + }); + } + + public static void rejectCallChannel(BinaryMessenger messenger) { + if (messenger == null) { + return; + } + + MethodChannel methodChannel = new MethodChannel(messenger, ChannelNames.getChannelName(ChannelNames.REJECT_CALL)); + + methodChannel.setMethodCallHandler((call, result) -> { + System.out.println("call.method: " + call.method); + if (call.method.equals(ChannelNames.REJECT_CALL)) { + System.out.println("拒接电话"); + result.success(null); + CallManager.rejectCall(); + } + }); + } + + public static void endCallChannel(BinaryMessenger messenger) { + if (messenger == null) { + return; + } + + MethodChannel methodChannel = new MethodChannel(messenger, ChannelNames.getChannelName(ChannelNames.END_CALL)); + + methodChannel.setMethodCallHandler((call, result) -> { + System.out.println("call.method: " + call.method); + if (call.method.equals(ChannelNames.END_CALL)) { + System.out.println("结束通话"); + result.success(null); + CallManager.endCall(); + } + }); + } } diff --git a/images/call/accept.png b/images/call/accept.png new file mode 100644 index 0000000000000000000000000000000000000000..0723f72320b924be9dd313c662f4489c24edd8a7 GIT binary patch literal 6524 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 literal 0 HcmV?d00001 diff --git a/lib/call/call_view.dart b/lib/call/call_view.dart index abba097..4fcee6e 100644 --- a/lib/call/call_view.dart +++ b/lib/call/call_view.dart @@ -1,10 +1,14 @@ +import 'dart:async'; + import 'package:cashier_reserve/common/base/ui.dart'; import 'package:cashier_reserve/common/channel/model/call_status_change_model.dart'; +import 'package:cashier_reserve/common/manager/event_manager.dart'; class CallView extends StatefulWidget { final CallStatusChangeModel statusModel; + final Function(String action)? onAction; - const CallView({super.key, required this.statusModel}); + const CallView({super.key, required this.statusModel, this.onAction}); @override State createState() { @@ -13,6 +17,26 @@ class CallView extends StatefulWidget { } class _CallViewState extends State { + int _callDuration = 0; + Timer? _callDurationTimer; + + bool _isAccept = false; + + @override + void initState() { + super.initState(); + + EventManager.addListener(this, (event) { + _acceptCall(); + }); + } + + @override + void dispose() { + _cancelDurationTimer(); + EventManager.cancelListener(this); + super.dispose(); + } @override Widget build(BuildContext context) { @@ -27,11 +51,118 @@ class _CallViewState extends State { child: Container( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, - color: Colors.blue, - child: Container(), + color: const Color(0x55000000), + child: Center( + child: Container( + width: MediaQuery.of(context).size.width * 0.8, + height: MediaQuery.of(context).size.height * 0.8, + decoration: BoxDecoration( + color: Colors.blue.withOpacity(0.9), + borderRadius: BorderRadius.circular(10), + ), + child: _buildCallInfo(context), + ), + ), ), ), ), ); } + + String _getCallDuration() { + // 将秒数转换为时分秒 + int hour = _callDuration ~/ 3600; + int minute = _callDuration % 3600 ~/ 60; + int second = _callDuration % 60; + return "${hour.toString().padLeft(2, '0')}:${minute.toString().padLeft(2, '0')}:${second.toString().padLeft(2, '0')}"; + } + + _acceptCall() { + if (_isAccept) { + return; + } + _isAccept = true; + _startDurationTimer(); + } + + _startDurationTimer() { + _callDurationTimer = Timer.periodic(const Duration(seconds: 1), (timer) { + setState(() { + _callDuration++; + }); + }); + } + + _cancelDurationTimer() { + _callDurationTimer?.cancel(); + } + + Widget _buildCallInfo(BuildContext context) { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + _buildIncomingInfo(context), + const SizedBox(height: 70), + _buildActionBtn(context), + ], + ); + } + + Widget _buildIncomingInfo(BuildContext context) { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + "${widget.statusModel.number}", + style: const TextStyle( + fontSize: 35, color: Colors.white, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 10), + Text( + "${widget.statusModel.region}", + style: const TextStyle(fontSize: 15, color: Colors.white), + ), + const SizedBox(height: 20), + Text(_getCallDuration(), + style: const TextStyle(fontSize: 20, color: Colors.white)), + ], + ); + } + + Widget _buildActionBtn(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + InkWell( + onTap: () { + // 拒绝 + if (widget.onAction != null) { + widget.onAction!("reject"); + } + }, + child: Container( + padding: const EdgeInsets.all(10), + child: Image.asset('images/call/reject.png', width: 60, height: 60), + ), + ), + if (!_isAccept) const SizedBox(width: 80), + if (!_isAccept) InkWell( + onTap: () { + // 接听 + if (widget.onAction != null) { + widget.onAction!("accept"); + } + + _acceptCall(); + }, + child: Container( + padding: const EdgeInsets.all(10), + child: Image.asset('images/call/accept.png', width: 60, height: 60), + ), + ), + ], + ); + } } diff --git a/lib/common/channel/channel_manager.dart b/lib/common/channel/channel_manager.dart index 5e5e7f3..973da48 100644 --- a/lib/common/channel/channel_manager.dart +++ b/lib/common/channel/channel_manager.dart @@ -13,4 +13,34 @@ class ChannelManager { yjPrint('$kGetCallLog 发生异常:$e'); } } + + static Future acceptCall() async { + MethodChannel channel = MethodChannel(getChannelName(kAcceptCall)); + try { + final result = await channel.invokeMethod(kAcceptCall); + yjPrint(result); + } on PlatformException catch (e) { + yjPrint('$kAcceptCall 发生异常:$e'); + } + } + + static Future rejectCall() async { + MethodChannel channel = MethodChannel(getChannelName(kRejectCall)); + try { + final result = await channel.invokeMethod(kRejectCall); + yjPrint(result); + } on PlatformException catch (e) { + yjPrint('$kRejectCall 发生异常:$e'); + } + } + + static Future endCall() async { + MethodChannel channel = MethodChannel(getChannelName(kEndCall)); + try { + final result = await channel.invokeMethod(kEndCall); + yjPrint(result); + } on PlatformException catch (e) { + yjPrint('$kEndCall 发生异常:$e'); + } + } } \ No newline at end of file diff --git a/lib/common/channel/names.dart b/lib/common/channel/names.dart index 9e2ee7a..9947a9f 100644 --- a/lib/common/channel/names.dart +++ b/lib/common/channel/names.dart @@ -5,6 +5,9 @@ const String kGetCallLog = 'getCallLog'; const String kCallLogCallback = 'callLogCallback'; const String kCallStatusChange = 'callStatusChange'; +const String kAcceptCall = 'acceptCall'; +const String kEndCall = 'endCall'; +const String kRejectCall = 'rejectCall'; String getChannelName(name) { return kChannelBaseName + name; diff --git a/lib/common/manager/event_manager.dart b/lib/common/manager/event_manager.dart index f38ae96..cb5c019 100644 --- a/lib/common/manager/event_manager.dart +++ b/lib/common/manager/event_manager.dart @@ -55,7 +55,15 @@ class GetCallLogEvent extends MyEvent { } class CallStatusChangeEvent extends MyEvent { + /// state = IncomingNumberReceived 来电接听 + /// state = OutGoing 呼出 + /// state = End 通话结束 + /// state = Incoming 来电 CallStatusChangeModel model; CallStatusChangeEvent({required this.model}); +} + +class CallReceivedEvent extends MyEvent { + CallReceivedEvent(); } \ No newline at end of file diff --git a/lib/home/home_view_model.dart b/lib/home/home_view_model.dart index c28befa..1372e94 100644 --- a/lib/home/home_view_model.dart +++ b/lib/home/home_view_model.dart @@ -1,6 +1,7 @@ import 'package:cashier_reserve/call/call_view.dart'; import 'package:cashier_reserve/common/base/ui.dart'; import 'package:cashier_reserve/common/base/ui_model.dart'; +import 'package:cashier_reserve/common/channel/channel_manager.dart'; import 'package:cashier_reserve/common/channel/model/call_status_change_model.dart'; import 'package:cashier_reserve/common/manager/app_manager.dart'; import 'package:cashier_reserve/common/manager/event_manager.dart'; @@ -51,11 +52,27 @@ class HomeViewModel extends BaseUIModel { }); EventManager.addListener(this, (event) { - yjPrint("HomeViewModel CallStatusChangeEvent state: ${event.model.state}"); - if (event.model.state == "Incoming") { - showCallInfoView(event.model); - } else { - hideCallInfoView(); + yjPrint( + "HomeViewModel CallStatusChangeEvent state: ${event.model.state}"); + + /// state = IncomingNumberReceived 来电接听 + /// state = OutGoing 呼出 + /// state = End 通话结束 + /// state = Incoming 来电 + /// state = Idle 空闲 + + switch (event.model.state) { + case "IncomingNumberReceived": + EventManager.postEvent(CallReceivedEvent()); + break; + case "OutGoing": + break; + case "Incoming": + showCallInfoView(event.model); + break; + default: + hideCallInfoView(); + break; } }); } @@ -85,7 +102,19 @@ class HomeViewModel extends BaseUIModel { if (isShowCallView) { return; } - YJPush.presentWidget(context!, CallView(statusModel: model)); + YJPush.presentWidget( + context!, + CallView( + statusModel: model, + onAction: (action) { + yjPrint("call view action: $action"); + if (action == "accept") { + ChannelManager.acceptCall(); + } else { + ChannelManager.rejectCall(); + hideCallInfoView(); + } + })); isShowCallView = true; } diff --git a/lib/home/reserve_view.dart b/lib/home/reserve_view.dart index 62511df..32278c7 100644 --- a/lib/home/reserve_view.dart +++ b/lib/home/reserve_view.dart @@ -78,7 +78,9 @@ class ReserveView extends BaseUI with TickerProviderStateMixin { width: 15, ), InkWell( - onTap: () { }, + onTap: () { + provider.testCallIncoming(); + }, child: SizedBox( width: 40, height: 40, @@ -95,9 +97,7 @@ class ReserveView extends BaseUI with TickerProviderStateMixin { width: 5, ), InkWell( - onTap: () { - provider.loadTableAreaList(); - }, + onTap: () { }, child: SizedBox( width: 40, height: 40, diff --git a/lib/home/reserve_view_model.dart b/lib/home/reserve_view_model.dart index 013821d..7a20a9a 100644 --- a/lib/home/reserve_view_model.dart +++ b/lib/home/reserve_view_model.dart @@ -1,6 +1,7 @@ import 'package:cashier_reserve/common/base/ui_model.dart'; import 'package:cashier_reserve/common/channel/model/call_log_model.dart'; import 'package:cashier_reserve/common/channel/channel_manager.dart'; +import 'package:cashier_reserve/common/channel/model/call_status_change_model.dart'; import 'package:cashier_reserve/common/manager/app_manager.dart'; import 'package:cashier_reserve/common/manager/event_manager.dart'; import 'package:cashier_reserve/common/print/print.dart'; @@ -138,6 +139,17 @@ class ReserveViewModel extends BaseUIModel { loadReserveSms(); } + void testCallIncoming() { + CallStatusChangeModel model = CallStatusChangeModel( + state: "Incoming", + number: "123456789", + name: "测试", + region: "陕西省 西安市", + ); + + EventManager.postEvent(CallStatusChangeEvent(model: model)); + } + void loadCallLog() { ChannelManager.getCallLog("getCallLog"); } diff --git a/pubspec.yaml b/pubspec.yaml index 8aa50d6..3c9fe0a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -84,6 +84,8 @@ flutter: - images/reserve/ + - images/call/ + # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/to/resolution-aware-images