diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift
index b4ad5b3..5b1bfee 100644
--- a/ios/Runner/AppDelegate.swift
+++ b/ios/Runner/AppDelegate.swift
@@ -1,11 +1,13 @@
import UIKit
+import PushKit
import Flutter
import Firebase
+import flutter_callkit_incoming
import flutter_local_notifications
-
+// PKPushRegistryDelegate
@UIApplicationMain
-@objc class AppDelegate: FlutterAppDelegate {
+@objc class AppDelegate: FlutterAppDelegate, PKPushRegistryDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
@@ -18,6 +20,51 @@ import flutter_local_notifications
UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate
}
GeneratedPluginRegistrant.register(with: self)
- return super.application(application, didFinishLaunchingWithOptions: launchOptions)
- }
+
+ //Setup VOIP
+ let mainQueue = DispatchQueue.main
+ let voipRegistry: PKPushRegistry = PKPushRegistry(queue: mainQueue)
+ voipRegistry.delegate = self
+ voipRegistry.desiredPushTypes = [PKPushType.voIP]
+
+ return super.application(application, didFinishLaunchingWithOptions: launchOptions)
+ }
+
+ // Handle updated push credentials
+ func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, for type: PKPushType) {
+ print(credentials.token)
+ let deviceToken = credentials.token.map { String(format: "%02x", $0) }.joined()
+ print(deviceToken)
+ print("deviceToken From Swift")
+ //Save deviceToken to your server
+ SwiftFlutterCallkitIncomingPlugin.sharedInstance?.setDevicePushTokenVoIP(deviceToken)
+ }
+
+ func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) {
+ print("didInvalidatePushTokenFor")
+ SwiftFlutterCallkitIncomingPlugin.sharedInstance?.setDevicePushTokenVoIP("")
+ }
+
+ // Handle incoming pushes
+ func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
+ print("didReceiveIncomingPushWith")
+ guard type == .voIP else { return }
+ print(payload.dictionaryPayload)
+// let id = payload.dictionaryPayload["id"] as? String ?? ""
+// let nameCaller = payload.dictionaryPayload["nameCaller"] as? String ?? ""
+// let handle = payload.dictionaryPayload["handle"] as? String ?? ""
+ let isVideo = payload.dictionaryPayload["isVideo"] as? Bool ?? false
+//
+//
+ let data = flutter_callkit_incoming.Data(id: "1", nameCaller: "Mohemm", handle: "handle", type: isVideo ? 1 : 0)
+// //set more data
+// data.extra = ["user": "abc@123", "platform": "ios"]
+// //data.iconName = ...
+// //data.....
+// data.appName = "Mohemm"
+// data.iconName = "Mohemm"
+ SwiftFlutterCallkitIncomingPlugin.sharedInstance?.showCallkitIncoming(data, fromPushKit: true)
+ }
+
+
}
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index a62656f..50ff832 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -94,5 +94,7 @@
TAG
+ UIApplicationSupportsIndirectInputEvents
+
diff --git a/lib/classes/notifications.dart b/lib/classes/notifications.dart
index 30d90f5..db59171 100644
--- a/lib/classes/notifications.dart
+++ b/lib/classes/notifications.dart
@@ -5,7 +5,6 @@ import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
-// import 'package:huawei_hmsavailability/huawei_hmsavailability.dart';
import 'package:huawei_push/huawei_push.dart' as huawei_push;
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
diff --git a/lib/classes/voip_chat_call.dart b/lib/classes/voip_chat_call.dart
index 5454eff..89468cb 100644
--- a/lib/classes/voip_chat_call.dart
+++ b/lib/classes/voip_chat_call.dart
@@ -23,8 +23,8 @@ class ChatVoipCall {
factory ChatVoipCall() => _instance;
- late ChatProviderModel chatProvider;
- late ChatCallProvider callProvider;
+ late ChatProviderModel prov;
+ late ChatCallProvider cProv;
dynamic inCallData;
Future showCallkitIncoming({required String uuid, RemoteMessage? data, bool isOnline = false, CallDataModel? incomingCallData}) async {
@@ -46,6 +46,7 @@ class ChatVoipCall {
await initProviders();
SingleUserChatModel callerData = SingleUserChatModel.fromJson(jsonDecode(data!.data["user_chat_history_response"]));
ALM.Response autoLoginData = ALM.Response.fromJson(jsonDecode(data.data["user_token_response"]));
+ data!.data["callType"] == "video" ? cProv.isVideoCall = true : cProv.isVideoCall = false;
CallKitParams params = CallKitParams(
id: uuid,
nameCaller: callerData.targetUserName,
@@ -108,8 +109,8 @@ class ChatVoipCall {
}
Future initProviders() async {
- callProvider = Provider.of(AppRoutes.navigatorKey.currentContext!, listen: false);
- chatProvider = Provider.of(AppRoutes.navigatorKey.currentContext!, listen: false);
+ cProv = Provider.of(AppRoutes.navigatorKey.currentContext!, listen: false);
+ prov = Provider.of(AppRoutes.navigatorKey.currentContext!, listen: false);
}
void connection({required data}) async {
@@ -119,10 +120,10 @@ class ChatVoipCall {
response: Response.fromJson(callData[0]["loginDetails"]),
errorResponses: null,
);
- callProvider.startIncomingCallViaKit(inCallData: inCallData);
+ cProv.startIncomingCallViaKit(inCallData: data);
try {
- await chatProvider.buildHubConnection(context: AppRoutes.navigatorKey.currentContext!, ccProvider: callProvider).whenComplete(() {
- callProvider.init();
+ await prov.buildHubConnection(context: AppRoutes.navigatorKey.currentContext!, ccProvider: cProv).whenComplete(() {
+ cProv.init();
});
} catch (e) {
logger.w(e);
@@ -143,13 +144,13 @@ class ChatVoipCall {
break;
case Event.ACTION_CALL_ACCEPT:
Navigator.pushNamedAndRemoveUntil(AppRoutes.navigatorKey.currentContext!, AppRoutes.chatStartCall, (_) => false);
- // Navigator.pushNamed(AppRoutes.navigatorKey.currentContext!, AppRoutes.chatStartCall);
+ // Navigator.pushNamed(AppRoutes.navigatorKey.currentContext!, AppRoutes.chatStartCall);
break;
case Event.ACTION_CALL_DECLINE:
- callProvider.isIncomingCall = true;
+ cProv.isIncomingCall = true;
Utils.saveStringFromPrefs("isIncomingCall", "false");
Utils.saveStringFromPrefs("inComingCallData", "null");
- callProvider.endCall();
+ cProv.endCall();
break;
case Event.ACTION_CALL_ENDED:
Utils.saveStringFromPrefs("isIncomingCall", "false");
diff --git a/lib/provider/chat_call_provider.dart b/lib/provider/chat_call_provider.dart
index 89a23fb..decbdd0 100644
--- a/lib/provider/chat_call_provider.dart
+++ b/lib/provider/chat_call_provider.dart
@@ -15,6 +15,7 @@ import 'package:mohem_flutter_app/models/chat/webrtc_payloads.dart';
import 'package:mohem_flutter_app/provider/chat_provider_model.dart';
import 'package:mohem_flutter_app/ui/chat/call/start_call_screen.dart';
import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart';
+import 'package:signalr_netcore/hub_connection.dart';
import 'package:uuid/uuid.dart';
class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin {
@@ -136,9 +137,13 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin {
Future endCall() async {
if (isIncomingCall) {
- await invoke(invokeMethod: "UpdateUserStatusAsync", currentUserID: AppState().chatDetails!.response!.id!, targetUserID: incomingCallData.targetUserId!, userStatus: 1);
- await invoke(invokeMethod: "HangUpAsync", currentUserID: AppState().chatDetails!.response!.id!, targetUserID: incomingCallData.targetUserId!, userStatus: 1);
- _pc.dispose();
+ if (chatHubConnection.state == HubConnectionState.Connected) {
+ await invoke(invokeMethod: "UpdateUserStatusAsync", currentUserID: AppState().chatDetails!.response!.id!, targetUserID: incomingCallData.targetUserId!, userStatus: 1);
+ await invoke(invokeMethod: "HangUpAsync", currentUserID: AppState().chatDetails!.response!.id!, targetUserID: incomingCallData.targetUserId!, userStatus: 1);
+ }
+ if (_pc.connectionState == RTCPeerConnectionState.RTCPeerConnectionStateConnected) {
+ _pc.dispose();
+ }
isCallStarted = false;
isVideoCall = false;
isCamOff = false;
@@ -149,9 +154,13 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin {
isIncomingCall = false;
return true;
} else {
- await invoke(invokeMethod: "UpdateUserStatusAsync", currentUserID: outGoingCallData.callerId!, targetUserID: outGoingCallData.receiverId!, userStatus: 1);
- await invoke(invokeMethod: "HangUpAsync", currentUserID: outGoingCallData.callerId!, targetUserID: outGoingCallData.receiverId!, userStatus: 1);
- _pc.dispose();
+ if (chatHubConnection.state == HubConnectionState.Connected) {
+ await invoke(invokeMethod: "UpdateUserStatusAsync", currentUserID: outGoingCallData.callerId!, targetUserID: outGoingCallData.receiverId!, userStatus: 1);
+ await invoke(invokeMethod: "HangUpAsync", currentUserID: outGoingCallData.callerId!, targetUserID: outGoingCallData.receiverId!, userStatus: 1);
+ }
+ if (_pc.connectionState == RTCPeerConnectionState.RTCPeerConnectionStateConnected) {
+ _pc.dispose();
+ }
isCallStarted = false;
isVideoCall = false;
isCamOff = false;
@@ -421,16 +430,35 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin {
logger.i("rtc ice gathering state: " + state.name);
};
pc!.onIceConnectionState = (RTCIceConnectionState state) {
- // invoke(
- // invokeMethod: "InvokeMobile",
- // currentUserID: AppState().getchatUserDetails!.response!.id!,
- // targetUserID: incomingCallData.targetUserId!,
- // debugData: {"location": "onIceConnection", "parms": state.name});
+ if (RTCIceConnectionState.RTCIceConnectionStateFailed == state ||
+ RTCIceConnectionState.RTCIceConnectionStateDisconnected == state ||
+ RTCIceConnectionState.RTCIceConnectionStateClosed == state) {
+ logger.i("Ice Connection State:" + state.name);
+ endCall();
+ }
};
- pc!.onRenegotiationNeeded = () {};
+ pc!.onRenegotiationNeeded = _onRenegotiate;
return pc;
}
+ void _onRenegotiate() async {
+ try {
+ print('onRenegotiationNeeded start');
+ // makingOffer = true;
+ await _pc.setLocalDescription(await _pc.createOffer(videoConstraints));
+ print('onRenegotiationNeeded state after setLocalDescription: ' + _pc.signalingState.toString());
+ // send offer via callManager
+ var localDesc = await _pc.getLocalDescription();
+ // callManager.sendCallMessage(MsgType.rtc_offer, RtcOfferAnswer(localDesc.sdp, localDesc.type));
+ print('onRenegotiationNeeded; offer sent');
+ } catch (e) {
+ print("onRenegotiationNeeded error: " + e.toString());
+ } finally {
+ // makingOffer = false;
+ print('onRenegotiationNeeded done');
+ }
+ }
+
void playRingtone() async {
player.stop();
await player.setVolume(1.0);
diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart
index c536376..4e44ea9 100644
--- a/lib/provider/chat_provider_model.dart
+++ b/lib/provider/chat_provider_model.dart
@@ -457,7 +457,6 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
}
if (isChatScreenActive && data.first.currentUserId == receiverID) {
int index = userChatHistory.indexWhere((SingleUserChatModel element) => element.userChatHistoryId == 0);
- logger.d(index);
userChatHistory[index] = data.first;
}
diff --git a/pubspec.yaml b/pubspec.yaml
index adcab03..5782482 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -119,7 +119,7 @@ dependencies:
dependency_overrides:
- firebase_core_platform_interface: 4.5.1
+ #firebase_core_platform_interface: 4.5.3
dev_dependencies: