Ios Voip Kit Changes

development_aamir
Aamir Muhammad 2 years ago
parent 9f33b2e0e7
commit 3ec44940df

@ -202,6 +202,12 @@ class AppState {
set setiosVoipPlayerID(String value) {
_iosVoipPlayerID = value;
}
bool _isUserOnline = false;
bool get getisUserOnline => _isUserOnline;
set setisUserOnline(bool value) {
_isUserOnline = value;
}
}

@ -156,8 +156,8 @@ class ChatVoipCall {
Future<void> voipDeclineCall(IosCallPayload? _iosCallPayload ) async {
try {
ALM.UserAutoLoginModel model = await ChatApiClient().getUserCallToken(userid: _iosCallPayload!.callData!.split("-").first);
dynamic Res = await ChatApiClient().callDecline(cUserID: int.parse(_iosCallPayload!.incomingCallerId!), tUserID: int.parse(_iosCallPayload!.callData!.split("-").first), targetUsertoken: model.response!.token!);
ALM.UserAutoLoginModel model = await ChatApiClient().getUserCallToken(userid: _iosCallPayload!.incomingCallReciverId.toString());
dynamic Res = await ChatApiClient().callDecline(cUserID: int.parse(_iosCallPayload!.incomingCallerId!), tUserID: int.parse(_iosCallPayload!.incomingCallReciverId.toString()), targetUsertoken: model.response!.token!);
} catch (err) {
print(err);
}

@ -48,7 +48,7 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin {
late BuildContext providerContext;
List<MediaDeviceInfo> devices = [];
var _videoDeviceId ;
var _videoDeviceId;
void initCallListeners({required BuildContext context}) {
providerContext = context;
@ -64,29 +64,6 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin {
// chatHubConnection.on("OnIncomingCallAsync", OnIncomingCallAsync);
}
//Video Constraints
Map<String, Object> videoConstraints = {
"video": {
"mandatory": {
"width": {"min": 1280},
"height": {"min": 720}
},
"optional": [
// {'sourceId': _videoDeviceId},
{
"width": {"max": 1280}
},
{"frameRate": 60},
{"facingMode": "user"}
]
},
"frameRate": 60,
"width": 1280, //420,//640,//1280,
"height": 720, //240//480//720
"audio": true,
};
// Audio Constraints
Map<String, Object> audioConstraints = {
"sampleRate": 8000,
@ -112,6 +89,12 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin {
await initStreams();
await startCall(callType: isVideoCall ? "Video" : "Audio", context: context);
_pc = await creatOfferWithCon();
connectOutgoing();
notifyListeners();
}
void connectOutgoing() {
isOutGoingCall = true;
notifyListeners();
}
@ -589,13 +572,68 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin {
///////////////// Incoming Call ///////////////////////////////
Future<void> initStreams() async {
devices = await navigator.mediaDevices.enumerateDevices();
List<MediaDeviceInfo> devices = await navigator.mediaDevices.enumerateDevices();
localVideoRenderer = RTCVideoRenderer();
remoteRenderer = RTCVideoRenderer();
await localVideoRenderer!.initialize();
_localStream ??= await navigator.mediaDevices.getUserMedia(isVideoCall ? videoConstraints : audioConstraints);
_localStream ??= await navigator.mediaDevices.getUserMedia(isVideoCall
// ? Platform.isIOS
// ? // iOS media constraints for maximum quality camera
// {
// 'audio': true,
// 'video': {
// 'facingMode': 'user', // Use 'user' for front camera, 'environment' for back camera
// 'width': {
// 'ideal': 1080, // Set the ideal width (maximum quality)
// },
// 'height': {
// 'ideal': 1920, // Set the ideal height (maximum quality)
// },
// 'frameRate': {
// 'ideal': 30, // Set the ideal frame rate (adjust as needed)
// },
// },
// }
// : // Android media constraints for maximum quality camera
// {
// 'audio': true,
// 'video': {
// 'facingMode': 'user', // Use 'user' for front camera, 'environment' for back camera
// 'width': {
// 'ideal': 1920, // Set the ideal width (maximum quality)
// },
// 'height': {
// 'ideal': 1080, // Set the ideal height (maximum quality)
// },
// 'frameRate': {
// 'ideal': 30, // Set the ideal frame rate (adjust as needed)
// },
// },
// }
? {
"video": {
"mandatory": {
"width": {"min": 1080},
"height": {"min": 1920}
},
"optional": [
{'sourceId': devices[1].deviceId},
{
"width": {"max": 1080}
},
{"frameRate": 30},
{"facingMode": "user"}
]
},
"frameRate": 30,
"width": 1080, //420,//640,//1280,
"height": 1920, //240//480//720
"audio": true,
}
: audioConstraints);
localVideoRenderer!.srcObject = _localStream;
await remoteRenderer!.initialize();
notifyListeners();

@ -81,14 +81,15 @@ class _StartCallPageState extends State<StartCallPage> {
}
void startIosCall() async {
print(await Utils.getStringFromPrefs("iosCallPayload"));
IosCallPayload _iosCallPayload = IosCallPayload.fromRawJson(await Utils.getStringFromPrefs("iosCallPayload"));
var userID = _iosCallPayload!.callData!.split("-").first;
var callType = _iosCallPayload!.callData!.split("-").last;
var userID = _iosCallPayload!.incomingCallReciverId;
var callType = _iosCallPayload!.incomingCallType;
SingleUserChatModel inCallData = SingleUserChatModel(
targetUserName: _iosCallPayload.incomingCallerName,
chatEventId: 3,
targetUserId: int.parse(_iosCallPayload.incomingCallerId!),
currentUserId: int.parse(userID),
currentUserId: int.parse(userID.toString()),
);
if (provider.isUserOnline) {
cProv.isUserOnline = provider.isUserOnline;
@ -103,7 +104,7 @@ class _StartCallPageState extends State<StartCallPage> {
print("====== Processing Incoming Call =========");
}
cProv.isUserOnline = provider.isUserOnline;
UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserCallToken(userid: userID);
UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserCallToken(userid: userID.toString());
if (userLoginResponse.response != null) {
AppState().setchatUserDetails = userLoginResponse;
Utils.saveStringFromPrefs("userLoginChatDetails", jsonEncode(userLoginResponse.response));
@ -142,19 +143,20 @@ class _StartCallPageState extends State<StartCallPage> {
child: Center(child: CircularProgressIndicator()),
)
: provider.isIncomingCall
? SizedBox(
? Container(
width: double.infinity,
height: double.infinity,
color: Colors.black,
child: Stack(
alignment: FractionalOffset.center,
children: <Widget>[
if (!provider.isAudioCall && provider.isVideoCall)
Positioned.fill(
child: RTCVideoView(
provider.remoteRenderer!,
objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover,
key: const Key('remote'),
),
RTCVideoView(
provider.remoteRenderer!,
objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitContain,
filterQuality: FilterQuality.high
,
key: const Key('remote'),
),
if (provider.isVideoCall)
DraggableWidget(
@ -173,6 +175,7 @@ class _StartCallPageState extends State<StartCallPage> {
child: RTCVideoView(
provider.localVideoRenderer!,
mirror: true,
filterQuality: FilterQuality.high,
objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover,
),
),
@ -374,12 +377,10 @@ class _StartCallPageState extends State<StartCallPage> {
alignment: FractionalOffset.center,
children: <Widget>[
if (!provider.isAudioCall && provider.isVideoCall)
Positioned.fill(
child: RTCVideoView(
provider.remoteRenderer!,
objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover,
key: const Key('remote'),
),
RTCVideoView(
provider.remoteRenderer!,
objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitContain,
key: const Key('remote'),
),
if (provider.isVideoCall)
DraggableWidget(

@ -25,16 +25,18 @@ class OutGoingCall extends StatefulWidget {
class _OutGoingCallState extends State<OutGoingCall> {
late ChatCallProvider callProvider;
late ChatProviderModel chatProvider;
bool loader = true;
@override
void initState() {
super.initState();
}
void init() {
Future<void> init() async {
widget.isVideoCall ? callProvider.isVideoCall = true : callProvider.isVideoCall = false;
callProvider.isOutGoingCall = true;
callProvider.initLocalCamera(chatProvmodel: chatProvider, callData: widget.outGoingCallData, context: context);
await callProvider.initLocalCamera(chatProvmodel: chatProvider, callData: widget.outGoingCallData, context: context);
loader = false;
}
@override
@ -52,129 +54,133 @@ class _OutGoingCallState extends State<OutGoingCall> {
if (chatcp.isCallEnded) {
Navigator.pop(context);
}
return Stack(
alignment: FractionalOffset.center,
children: <Widget>[
if (chatcp.isVideoCall)
Positioned.fill(
child: RTCVideoView(
chatcp.localVideoRenderer!,
objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover,
),
),
Positioned.fill(
child: ClipRect(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 5.0, sigmaY: 5.0),
child: Container(
decoration: BoxDecoration(
color: MyColors.grey57Color.withOpacity(
0.3,
return loader
? const Center(
child: CircularProgressIndicator(),
)
: Stack(
alignment: FractionalOffset.center,
children: <Widget>[
if (chatcp.isVideoCall)
Positioned.fill(
child: RTCVideoView(
chatcp.localVideoRenderer!,
objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
40.height,
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
margin: const EdgeInsets.all(21.0),
child: Container(
Positioned.fill(
child: ClipRect(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 5.0, sigmaY: 5.0),
child: Container(
decoration: BoxDecoration(
color: MyColors.grey57Color.withOpacity(
0.3,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
40.height,
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
margin: const EdgeInsets.all(21.0),
child: Container(
margin: const EdgeInsets.only(
left: 10.0,
right: 10.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
SvgPicture.asset(
"assets/images/user.svg",
height: 70,
width: 70,
fit: BoxFit.cover,
),
10.height,
Text(
widget.outGoingCallData.receiverName.toString().replaceAll(".", " "),
style: const TextStyle(
fontSize: 21,
fontWeight: FontWeight.bold,
color: MyColors.white,
letterSpacing: -1.26,
height: 23 / 12,
),
),
const Text(
"Ringing...",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Color(
0xffC6C6C6,
),
letterSpacing: -0.48,
height: 23 / 24,
),
),
const SizedBox(
height: 2,
),
],
),
),
),
],
),
const Spacer(),
Container(
margin: const EdgeInsets.only(
left: 10.0,
right: 10.0,
bottom: 70.0,
left: 49,
right: 49,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceAround,
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SvgPicture.asset(
"assets/images/user.svg",
height: 70,
width: 70,
fit: BoxFit.cover,
),
10.height,
Text(
widget.outGoingCallData.receiverName.toString().replaceAll(".", " "),
style: const TextStyle(
fontSize: 21,
fontWeight: FontWeight.bold,
color: MyColors.white,
letterSpacing: -1.26,
height: 23 / 12,
RawMaterialButton(
onPressed: () {
chatcp.endCall(isUserOnline: chatProvider.isUserOnline).then((bool value) {
if (value) {
Navigator.of(context).pop();
// print("Reintiiiiiiitttzzzz");
// chatcp.initStreams();
}
});
},
elevation: 2.0,
fillColor: MyColors.redA3Color,
padding: const EdgeInsets.all(
15.0,
),
),
const Text(
"Ringing...",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Color(
0xffC6C6C6,
),
letterSpacing: -0.48,
height: 23 / 24,
shape: const CircleBorder(),
child: const Icon(
Icons.call_end,
color: MyColors.white,
size: 35.0,
),
),
const SizedBox(
height: 2,
),
],
),
),
),
],
),
const Spacer(),
Container(
margin: const EdgeInsets.only(
bottom: 70.0,
left: 49,
right: 49,
),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RawMaterialButton(
onPressed: () {
chatcp.endCall(isUserOnline: chatProvider.isUserOnline).then((bool value) {
if (value) {
Navigator.of(context).pop();
// print("Reintiiiiiiitttzzzz");
// chatcp.initStreams();
}
});
},
elevation: 2.0,
fillColor: MyColors.redA3Color,
padding: const EdgeInsets.all(
15.0,
),
shape: const CircleBorder(),
child: const Icon(
Icons.call_end,
color: MyColors.white,
size: 35.0,
),
),
],
),
),
],
),
),
),
),
),
),
],
);
],
);
}),
);
}

@ -32,7 +32,6 @@ import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/main.dart';
import 'package:mohem_flutter_app/models/chat/call.dart';
import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart';
import 'package:mohem_flutter_app/models/check_mobile_app_version_model.dart';
import 'package:mohem_flutter_app/models/get_mobile_login_info_list_model.dart';
import 'package:mohem_flutter_app/models/member_information_list_model.dart';
@ -40,10 +39,7 @@ import 'package:mohem_flutter_app/models/member_login_list_model.dart';
import 'package:mohem_flutter_app/models/privilege_list_model.dart';
import 'package:mohem_flutter_app/ui/chat/call/chat_incoming_call_screen.dart';
import 'package:mohem_flutter_app/widgets/button/default_button.dart';
import 'package:mohem_flutter_app/widgets/button/hmg_connectivity_button.dart';
import 'package:mohem_flutter_app/widgets/input_widget.dart';
// import 'package:safe_device/safe_device.dart';
import 'package:wifi_iot/wifi_iot.dart';
class LoginScreen extends StatefulWidget {
@ -77,7 +73,7 @@ class _LoginScreenState extends State<LoginScreen> with WidgetsBindingObserver {
// late HmsApiAvailability hmsApiAvailability;
final voIPKit = FlutterIOSVoIPKit.instance;
final FlutterIOSVoIPKit voIPKit = FlutterIOSVoIPKit.instance;
late Timer timeOutTimer;
@override
@ -93,13 +89,15 @@ class _LoginScreenState extends State<LoginScreen> with WidgetsBindingObserver {
callListeners();
checkAndNavigationCallingPage();
}
setupVoIPCallBacks();
if (Platform.isIOS) {
setupVoIPCallBacks();
}
}
// IOS Voip Call
void setupVoIPCallBacks() {
if (Platform.isIOS) {
voIPKit.getVoIPToken().then((value) async {
voIPKit.getVoIPToken().then((String? value) async {
if (value != null) {
AppState().setiosVoipPlayerID = await ChatApiClient().oneSignalVoip(value!);
}
@ -114,8 +112,7 @@ class _LoginScreenState extends State<LoginScreen> with WidgetsBindingObserver {
Map<String, dynamic> payload,
) async {
_iosCallPayload = IosCallPayload.fromJson(payload);
isIncomingCall = true;
_timeOut();
// _timeOut();
};
voIPKit.onDidRejectIncomingCall = (
@ -130,17 +127,15 @@ class _LoginScreenState extends State<LoginScreen> with WidgetsBindingObserver {
String uuid,
String callerId,
) async {
var callerID = "did accept call $callerId";
timeOutTimer.cancel();
await connectCall();
await voIPKit.acceptIncomingCall(callerState: CallStateType.calling);
await voIPKit.callConnected();
await connectCall(uuid: uuid, callDetails: callerId);
voIPKit.acceptIncomingCall(callerState: CallStateType.calling);
voIPKit.callConnected();
};
}
void _timeOut() async {
timeOutTimer = Timer(const Duration(seconds: 25), () async {
var incomingCallerName = await voIPKit.getIncomingCallerName();
String? incomingCallerName = await voIPKit.getIncomingCallerName();
voIPKit.unansweredIncomingCall(
skipLocalNotification: false,
missedCallTitle: '📞 Missed call',
@ -151,17 +146,31 @@ class _LoginScreenState extends State<LoginScreen> with WidgetsBindingObserver {
});
}
Future<void> connectCall() async {
try {
Future<void> connectCall({required String uuid, required String callDetails}) async {
isIncomingCall = true;
if (AppState().getisUserOnline) {
_iosCallPayload = IosCallPayload(
uuid: uuid, incomingCallerId: callDetails.split("-")[0], incomingCallReciverId: callDetails.split("-")[1], incomingCallerName: _iosCallPayload!.incomingCallerName, incomingCallType: callDetails.split("-").last);
} else {
_iosCallPayload = IosCallPayload(
uuid: uuid, incomingCallerId: callDetails.split("-")[0], incomingCallReciverId: callDetails.split("-")[1], incomingCallerName: null, incomingCallType: callDetails.split("-").last);
}
if (_iosCallPayload!.incomingCallerName == null) {
if (Platform.isIOS) {
Utils.hideLoading(context);
}
await Utils.saveStringFromPrefs("iosCallPayload", jsonEncode(_iosCallPayload));
MaterialPageRoute pageRoute = await MaterialPageRoute(builder: (BuildContext context) => StartCallPage());
Navigator.push(context, pageRoute);
} else if (AppState().getisUserOnline) {
await Utils.saveStringFromPrefs("iosCallPayload", jsonEncode(_iosCallPayload));
BuildContext context = AppRoutes.navigatorKey.currentContext!;
Utils.hideLoading(context);
Utils.saveStringFromPrefs("iosCallPayload", jsonEncode(_iosCallPayload));
var pageRoute = MaterialPageRoute(builder: (context) => StartCallPage());
Navigator.push(context, pageRoute).whenComplete(() {
checkFirebaseToken();
});
} catch (e) {
logger.d(e);
MaterialPageRoute pageRoute = await MaterialPageRoute(builder: (BuildContext context) => StartCallPage());
Navigator.push(context, pageRoute);
} else {
FlutterCallkitIncoming.endAllCalls();
Utils.showToast("Something wen't wrong");
}
}
@ -180,21 +189,9 @@ class _LoginScreenState extends State<LoginScreen> with WidgetsBindingObserver {
// print(error);
// }
// }
// Future<void> connectCall() async {
// try {
// UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserCallToken(userid: _iosCallPayload!.incomingCallerId!.split("-").last);
// if (userLoginResponse.response != null) {
// AppState().setchatUserDetails = userLoginResponse;
// Utils.saveStringFromPrefs("userLoginChatDetails", jsonEncode(userLoginResponse.response));
// }
// } catch (e) {
// logger.d(e);
// }
// }
Future<void> callListeners() async {
try {
print("Call Listeners Init");
FlutterCallkitIncoming.onEvent.listen((CallEvent? event) async {
switch (event!.event) {
case Event.actionCallIncoming:
@ -238,7 +235,7 @@ class _LoginScreenState extends State<LoginScreen> with WidgetsBindingObserver {
if (Platform.isAndroid) {
Utils.hideLoading(context);
}
var pageRoute = MaterialPageRoute(builder: (context) => StartCallPage());
MaterialPageRoute pageRoute = MaterialPageRoute(builder: (BuildContext context) => StartCallPage());
Navigator.push(context, pageRoute).whenComplete(() {
checkFirebaseToken();
});
@ -254,7 +251,6 @@ class _LoginScreenState extends State<LoginScreen> with WidgetsBindingObserver {
var calls = await FlutterCallkitIncoming.activeCalls();
if (calls is List) {
if (calls.isNotEmpty) {
print('DATA: $calls');
return calls[0];
} else {
return null;
@ -267,7 +263,7 @@ class _LoginScreenState extends State<LoginScreen> with WidgetsBindingObserver {
if (currentCall != null && Platform.isAndroid) {
isIncomingCall = true;
Utils.hideLoading(context);
Navigator.push(context, MaterialPageRoute(builder: (context) => StartCallPage()));
Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => StartCallPage()));
}
}
@ -390,7 +386,7 @@ class _LoginScreenState extends State<LoginScreen> with WidgetsBindingObserver {
// if (isAppOpenBySystem!) checkFirebaseToken();
Utils.showLoading(context);
Future.delayed(const Duration(seconds: 2)).whenComplete(() {
Future.delayed(Duration(seconds: Platform.isIOS ? 3 : 2)).whenComplete(() {
if (!isIncomingCall) {
if (isAppOpenBySystem!) checkFirebaseToken();
}

Loading…
Cancel
Save