接听挂断电话
This commit is contained in:
parent
1da1683adc
commit
b6cd0d0f2b
|
|
@ -17,6 +17,8 @@ import org.json.JSONObject;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import cn.kaer.callmodule.ctrl.CallController;
|
||||||
|
import cn.kaer.callmodule.exceptions.CallException;
|
||||||
import io.flutter.Log;
|
import io.flutter.Log;
|
||||||
|
|
||||||
public class CallManager {
|
public class CallManager {
|
||||||
|
|
@ -68,4 +70,22 @@ public class CallManager {
|
||||||
broad.putExtra("callLog", callLogArray.toString());
|
broad.putExtra("callLog", callLogArray.toString());
|
||||||
mainActivityContext.sendBroadcast(broad);
|
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_LOG_CALLBACK = "callLogCallback";
|
||||||
|
|
||||||
public static final String CALL_STATUS_CHANGE = "callStatusChange";
|
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) {
|
public static String getChannelName(String name) {
|
||||||
return BASE_NAME + name;
|
return BASE_NAME + name;
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,9 @@ import io.flutter.plugin.common.MethodChannel;
|
||||||
public class MessageChannel {
|
public class MessageChannel {
|
||||||
public static void addMessageChannel(BinaryMessenger messenger) {
|
public static void addMessageChannel(BinaryMessenger messenger) {
|
||||||
callLogChannel(messenger);
|
callLogChannel(messenger);
|
||||||
|
acceptCallChannel(messenger);
|
||||||
|
rejectCallChannel(messenger);
|
||||||
|
endCallChannel(messenger);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void callLogChannel(BinaryMessenger 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/base/ui.dart';
|
||||||
import 'package:cashier_reserve/common/channel/model/call_status_change_model.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 {
|
class CallView extends StatefulWidget {
|
||||||
final CallStatusChangeModel statusModel;
|
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
|
@override
|
||||||
State<StatefulWidget> createState() {
|
State<StatefulWidget> createState() {
|
||||||
|
|
@ -13,6 +17,26 @@ class CallView extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CallViewState extends State<CallView> {
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
@ -27,11 +51,118 @@ class _CallViewState extends State<CallView> {
|
||||||
child: Container(
|
child: Container(
|
||||||
width: MediaQuery.of(context).size.width,
|
width: MediaQuery.of(context).size.width,
|
||||||
height: MediaQuery.of(context).size.height,
|
height: MediaQuery.of(context).size.height,
|
||||||
color: Colors.blue,
|
color: const Color(0x55000000),
|
||||||
child: Container(),
|
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');
|
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 kCallLogCallback = 'callLogCallback';
|
||||||
|
|
||||||
const String kCallStatusChange = 'callStatusChange';
|
const String kCallStatusChange = 'callStatusChange';
|
||||||
|
const String kAcceptCall = 'acceptCall';
|
||||||
|
const String kEndCall = 'endCall';
|
||||||
|
const String kRejectCall = 'rejectCall';
|
||||||
|
|
||||||
String getChannelName(name) {
|
String getChannelName(name) {
|
||||||
return kChannelBaseName + name;
|
return kChannelBaseName + name;
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,15 @@ class GetCallLogEvent extends MyEvent {
|
||||||
}
|
}
|
||||||
|
|
||||||
class CallStatusChangeEvent extends MyEvent {
|
class CallStatusChangeEvent extends MyEvent {
|
||||||
|
/// state = IncomingNumberReceived 来电接听
|
||||||
|
/// state = OutGoing 呼出
|
||||||
|
/// state = End 通话结束
|
||||||
|
/// state = Incoming 来电
|
||||||
CallStatusChangeModel model;
|
CallStatusChangeModel model;
|
||||||
|
|
||||||
CallStatusChangeEvent({required this.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/call/call_view.dart';
|
||||||
import 'package:cashier_reserve/common/base/ui.dart';
|
import 'package:cashier_reserve/common/base/ui.dart';
|
||||||
import 'package:cashier_reserve/common/base/ui_model.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/channel/model/call_status_change_model.dart';
|
||||||
import 'package:cashier_reserve/common/manager/app_manager.dart';
|
import 'package:cashier_reserve/common/manager/app_manager.dart';
|
||||||
import 'package:cashier_reserve/common/manager/event_manager.dart';
|
import 'package:cashier_reserve/common/manager/event_manager.dart';
|
||||||
|
|
@ -51,11 +52,27 @@ class HomeViewModel extends BaseUIModel {
|
||||||
});
|
});
|
||||||
|
|
||||||
EventManager.addListener<CallStatusChangeEvent>(this, (event) {
|
EventManager.addListener<CallStatusChangeEvent>(this, (event) {
|
||||||
yjPrint("HomeViewModel CallStatusChangeEvent state: ${event.model.state}");
|
yjPrint(
|
||||||
if (event.model.state == "Incoming") {
|
"HomeViewModel CallStatusChangeEvent state: ${event.model.state}");
|
||||||
showCallInfoView(event.model);
|
|
||||||
} else {
|
/// state = IncomingNumberReceived 来电接听
|
||||||
hideCallInfoView();
|
/// 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) {
|
if (isShowCallView) {
|
||||||
return;
|
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;
|
isShowCallView = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,9 @@ class ReserveView extends BaseUI with TickerProviderStateMixin {
|
||||||
width: 15,
|
width: 15,
|
||||||
),
|
),
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () { },
|
onTap: () {
|
||||||
|
provider.testCallIncoming();
|
||||||
|
},
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: 40,
|
width: 40,
|
||||||
height: 40,
|
height: 40,
|
||||||
|
|
@ -95,9 +97,7 @@ class ReserveView extends BaseUI with TickerProviderStateMixin {
|
||||||
width: 5,
|
width: 5,
|
||||||
),
|
),
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () {
|
onTap: () { },
|
||||||
provider.loadTableAreaList();
|
|
||||||
},
|
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: 40,
|
width: 40,
|
||||||
height: 40,
|
height: 40,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:cashier_reserve/common/base/ui_model.dart';
|
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/model/call_log_model.dart';
|
||||||
import 'package:cashier_reserve/common/channel/channel_manager.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/app_manager.dart';
|
||||||
import 'package:cashier_reserve/common/manager/event_manager.dart';
|
import 'package:cashier_reserve/common/manager/event_manager.dart';
|
||||||
import 'package:cashier_reserve/common/print/print.dart';
|
import 'package:cashier_reserve/common/print/print.dart';
|
||||||
|
|
@ -138,6 +139,17 @@ class ReserveViewModel extends BaseUIModel {
|
||||||
loadReserveSms();
|
loadReserveSms();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void testCallIncoming() {
|
||||||
|
CallStatusChangeModel model = CallStatusChangeModel(
|
||||||
|
state: "Incoming",
|
||||||
|
number: "123456789",
|
||||||
|
name: "测试",
|
||||||
|
region: "陕西省 西安市",
|
||||||
|
);
|
||||||
|
|
||||||
|
EventManager.postEvent(CallStatusChangeEvent(model: model));
|
||||||
|
}
|
||||||
|
|
||||||
void loadCallLog() {
|
void loadCallLog() {
|
||||||
ChannelManager.getCallLog("getCallLog");
|
ChannelManager.getCallLog("getCallLog");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,8 @@ flutter:
|
||||||
|
|
||||||
- images/reserve/
|
- images/reserve/
|
||||||
|
|
||||||
|
- images/call/
|
||||||
|
|
||||||
# An image asset can refer to one or more resolution-specific "variants", see
|
# An image asset can refer to one or more resolution-specific "variants", see
|
||||||
# https://flutter.dev/to/resolution-aware-images
|
# https://flutter.dev/to/resolution-aware-images
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue