接听挂断电话
This commit is contained in:
parent
1da1683adc
commit
b6cd0d0f2b
|
|
@ -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() {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 6.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.8 KiB |
|
|
@ -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<StatefulWidget> createState() {
|
||||
|
|
@ -13,6 +17,26 @@ class CallView extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _CallViewState extends State<CallView> {
|
||||
int _callDuration = 0;
|
||||
Timer? _callDurationTimer;
|
||||
|
||||
bool _isAccept = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
EventManager.addListener<CallReceivedEvent>(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<CallView> {
|
|||
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),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,4 +13,34 @@ class ChannelManager {
|
|||
yjPrint('$kGetCallLog 发生异常:$e');
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> 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<void> 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<void> endCall() async {
|
||||
MethodChannel channel = MethodChannel(getChannelName(kEndCall));
|
||||
try {
|
||||
final result = await channel.invokeMethod(kEndCall);
|
||||
yjPrint(result);
|
||||
} on PlatformException catch (e) {
|
||||
yjPrint('$kEndCall 发生异常:$e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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<CallStatusChangeEvent>(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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue