Ios Voip Kit Changes

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

@ -203,5 +203,11 @@ class AppState {
_iosVoipPlayerID = 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 { Future<void> voipDeclineCall(IosCallPayload? _iosCallPayload ) async {
try { try {
ALM.UserAutoLoginModel model = await ChatApiClient().getUserCallToken(userid: _iosCallPayload!.callData!.split("-").first); ALM.UserAutoLoginModel model = await ChatApiClient().getUserCallToken(userid: _iosCallPayload!.incomingCallReciverId.toString());
dynamic Res = await ChatApiClient().callDecline(cUserID: int.parse(_iosCallPayload!.incomingCallerId!), tUserID: int.parse(_iosCallPayload!.callData!.split("-").first), targetUsertoken: model.response!.token!); dynamic Res = await ChatApiClient().callDecline(cUserID: int.parse(_iosCallPayload!.incomingCallerId!), tUserID: int.parse(_iosCallPayload!.incomingCallReciverId.toString()), targetUsertoken: model.response!.token!);
} catch (err) { } catch (err) {
print(err); print(err);
} }

@ -48,7 +48,7 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin {
late BuildContext providerContext; late BuildContext providerContext;
List<MediaDeviceInfo> devices = []; List<MediaDeviceInfo> devices = [];
var _videoDeviceId ; var _videoDeviceId;
void initCallListeners({required BuildContext context}) { void initCallListeners({required BuildContext context}) {
providerContext = context; providerContext = context;
@ -64,29 +64,6 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin {
// chatHubConnection.on("OnIncomingCallAsync", OnIncomingCallAsync); // 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 // Audio Constraints
Map<String, Object> audioConstraints = { Map<String, Object> audioConstraints = {
"sampleRate": 8000, "sampleRate": 8000,
@ -112,6 +89,12 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin {
await initStreams(); await initStreams();
await startCall(callType: isVideoCall ? "Video" : "Audio", context: context); await startCall(callType: isVideoCall ? "Video" : "Audio", context: context);
_pc = await creatOfferWithCon(); _pc = await creatOfferWithCon();
connectOutgoing();
notifyListeners();
}
void connectOutgoing() {
isOutGoingCall = true;
notifyListeners(); notifyListeners();
} }
@ -589,13 +572,68 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin {
///////////////// Incoming Call /////////////////////////////// ///////////////// Incoming Call ///////////////////////////////
Future<void> initStreams() async { Future<void> initStreams() async {
devices = await navigator.mediaDevices.enumerateDevices(); List<MediaDeviceInfo> devices = await navigator.mediaDevices.enumerateDevices();
localVideoRenderer = RTCVideoRenderer(); localVideoRenderer = RTCVideoRenderer();
remoteRenderer = RTCVideoRenderer(); remoteRenderer = RTCVideoRenderer();
await localVideoRenderer!.initialize(); 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; localVideoRenderer!.srcObject = _localStream;
await remoteRenderer!.initialize(); await remoteRenderer!.initialize();
notifyListeners(); notifyListeners();

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

@ -25,16 +25,18 @@ class OutGoingCall extends StatefulWidget {
class _OutGoingCallState extends State<OutGoingCall> { class _OutGoingCallState extends State<OutGoingCall> {
late ChatCallProvider callProvider; late ChatCallProvider callProvider;
late ChatProviderModel chatProvider; late ChatProviderModel chatProvider;
bool loader = true;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
} }
void init() { Future<void> init() async {
widget.isVideoCall ? callProvider.isVideoCall = true : callProvider.isVideoCall = false; widget.isVideoCall ? callProvider.isVideoCall = true : callProvider.isVideoCall = false;
callProvider.isOutGoingCall = true; 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 @override
@ -52,7 +54,11 @@ class _OutGoingCallState extends State<OutGoingCall> {
if (chatcp.isCallEnded) { if (chatcp.isCallEnded) {
Navigator.pop(context); Navigator.pop(context);
} }
return Stack( return loader
? const Center(
child: CircularProgressIndicator(),
)
: Stack(
alignment: FractionalOffset.center, alignment: FractionalOffset.center,
children: <Widget>[ children: <Widget>[
if (chatcp.isVideoCall) if (chatcp.isVideoCall)

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

Loading…
Cancel
Save