From d7d90f620eb3b396a76ee56a111f532e58e3ce7b Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Mon, 12 Jun 2023 15:16:28 +0300 Subject: [PATCH] VoIP udpates --- ios/Runner/AppDelegate.swift | 68 ++++++++++++------------ ios/Runner/Info.plist | 8 +++ lib/classes/notifications.dart | 1 + lib/provider/chat_call_provider.dart | 2 +- lib/ui/login/login_screen.dart | 78 +++++++++++++++++++++++++--- pubspec.yaml | 3 ++ 6 files changed, 118 insertions(+), 42 deletions(-) diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index 96c55d9..fab432d 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -7,7 +7,7 @@ import flutter_local_notifications // PKPushRegistryDelegate @UIApplicationMain -@objc class AppDelegate: FlutterAppDelegate, PKPushRegistryDelegate { +@objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? @@ -16,49 +16,49 @@ import flutter_local_notifications FlutterLocalNotificationsPlugin.setPluginRegistrantCallback { (registry) in GeneratedPluginRegistrant.register(with: registry) } - if #available(iOS 10.0, *) { - UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate - } +// if #available(iOS 10.0, *) { +// UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate +// } GeneratedPluginRegistrant.register(with: self) //Setup VOIP - let mainQueue = DispatchQueue.main - let voipRegistry: PKPushRegistry = PKPushRegistry(queue: mainQueue) - voipRegistry.delegate = self - voipRegistry.desiredPushTypes = [PKPushType.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() - //Save deviceToken to your server - SwiftFlutterCallkitIncomingPlugin.sharedInstance?.setDevicePushTokenVoIP(deviceToken) - } +// func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, for type: PKPushType) { +// print(credentials.token) +// let deviceToken = credentials.token.map { String(format: "%02x", $0) }.joined() +// //Save deviceToken to your server +// SwiftFlutterCallkitIncomingPlugin.sharedInstance?.setDevicePushTokenVoIP(deviceToken) +// } - func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) { - print("didInvalidatePushTokenFor") - SwiftFlutterCallkitIncomingPlugin.sharedInstance?.setDevicePushTokenVoIP("") - } +// 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) -// data.extra = ["user": "abc@123", "platform": "ios"] -// data.iconName = "Mohemm" - SwiftFlutterCallkitIncomingPlugin.sharedInstance?.showCallkitIncoming(data, fromPushKit: true) - } +// // 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) +//// data.extra = ["user": "abc@123", "platform": "ios"] +//// data.iconName = "Mohemm" +// SwiftFlutterCallkitIncomingPlugin.sharedInstance?.showCallkitIncoming(data, fromPushKit: true) +// } } diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index df3e12c..447afb8 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -95,5 +95,13 @@ TAG + FIVKIconName + AppIcon-VoIPKit + FIVKLocalizedName + VoIP-Kit + FIVKSupportVideo + + FIVKSkipRecallScreen + diff --git a/lib/classes/notifications.dart b/lib/classes/notifications.dart index 8036a72..9de4e91 100644 --- a/lib/classes/notifications.dart +++ b/lib/classes/notifications.dart @@ -123,6 +123,7 @@ class AppNotifications { Utils.saveStringFromPrefs("isAppOpendByChat", "true"); Utils.saveStringFromPrefs("notificationData", message.data["user_chat_history_response"].toString()); } else if (message.data.isNotEmpty && message.data["messageType"] == 'call') { + logger.d(message.toMap().toString()); ChatVoipCall().showCallkitIncoming(uuid: const Uuid().v4(), data: message); } } diff --git a/lib/provider/chat_call_provider.dart b/lib/provider/chat_call_provider.dart index 9bdf0f9..c1e44f7 100644 --- a/lib/provider/chat_call_provider.dart +++ b/lib/provider/chat_call_provider.dart @@ -1,5 +1,6 @@ import 'dart:convert'; import 'dart:io'; + import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_callkit_incoming/flutter_callkit_incoming.dart'; @@ -163,7 +164,6 @@ class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin { providerContext, MaterialPageRoute( builder: (BuildContext context) => StartCallPage(), - allowSnapshotting: false, )).then((value) { Navigator.of(providerContext).pop(); }); diff --git a/lib/ui/login/login_screen.dart b/lib/ui/login/login_screen.dart index fd53752..bbfc60d 100644 --- a/lib/ui/login/login_screen.dart +++ b/lib/ui/login/login_screen.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:convert'; import 'dart:io'; @@ -11,6 +12,8 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_callkit_incoming/entities/call_event.dart'; import 'package:flutter_callkit_incoming/flutter_callkit_incoming.dart'; +import 'package:flutter_ios_voip_kit/call_state_type.dart'; +import 'package:flutter_ios_voip_kit/flutter_ios_voip_kit.dart'; // import 'package:huawei_hmsavailability/huawei_hmsavailability.dart'; import 'package:mohem_flutter_app/api/login_api_client.dart'; @@ -25,8 +28,6 @@ import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; 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/incoming_call_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'; @@ -48,7 +49,7 @@ class LoginScreen extends StatefulWidget { } } -class _LoginScreenState extends State { +class _LoginScreenState extends State with WidgetsBindingObserver { TextEditingController username = TextEditingController(); TextEditingController password = TextEditingController(); @@ -69,6 +70,9 @@ class _LoginScreenState extends State { // late HmsApiAvailability hmsApiAvailability; + final voIPKit = FlutterIOSVoIPKit.instance; + late Timer timeOutTimer; + @override void initState() { super.initState(); @@ -78,6 +82,67 @@ class _LoginScreenState extends State { // checkDeviceSafety(); // } callListeners(); + WidgetsBinding.instance.addObserver(this); + setupVoIPCallBacks(); + } + + void _timeOut({ + int seconds = 15, + }) async { + timeOutTimer = Timer(Duration(seconds: seconds), () async { + print('🎈 example: timeOut'); + var incomingCallerName = await voIPKit.getIncomingCallerName(); + voIPKit.unansweredIncomingCall( + skipLocalNotification: false, + missedCallTitle: '📞 Missed call', + missedCallBody: 'There was a call from $incomingCallerName', + ); + }); + } + + void setupVoIPCallBacks() { + if (Platform.isIOS) { + voIPKit.getVoIPToken().then((value) { + print('🎈 example: getVoIPToken: $value'); + }); + + voIPKit.onDidUpdatePushToken = (String token) { + print('🎈 example: onDidUpdatePushToken: $token'); + }; + } + + voIPKit.onDidReceiveIncomingPush = ( + Map payload, + ) async { + print('🎈 example: onDidReceiveIncomingPush $payload'); + _timeOut(); + }; + + voIPKit.onDidRejectIncomingCall = ( + String uuid, + String callerId, + ) async { + try { + var logText = "did reject call $callerId"; + } catch (err) {} + }; + + voIPKit.onDidAcceptIncomingCall = ( + String uuid, + String callerId, + ) async { + var callerID = "did accept call $callerId"; + + debugPrint(callerID); + + await voIPKit.acceptIncomingCall(callerState: CallStateType.calling); + await voIPKit.callConnected(); + Future.delayed(const Duration(milliseconds: 2500), () { + voIPKit.endCall().then((value) async {}); + }); + + timeOutTimer.cancel(); + }; } // void checkDeviceSafety() async { @@ -119,7 +184,7 @@ class _LoginScreenState extends State { case Event.ACTION_CALL_ENDED: Utils.saveStringFromPrefs("isIncomingCall", "false"); Utils.saveStringFromPrefs("inComingCallData", "null"); - FlutterCallkitIncoming.endAllCalls(); + FlutterCallkitIncoming.endAllCalls(); break; case Event.ACTION_CALL_TIMEOUT: Utils.saveStringFromPrefs("isIncomingCall", "false"); @@ -137,17 +202,16 @@ class _LoginScreenState extends State { if (calls.isNotEmpty) { Utils.hideLoading(context); var pageRoute = MaterialPageRoute(builder: (context) => StartCallPage()); - Navigator.push(context, pageRoute).whenComplete((){ + Navigator.push(context, pageRoute).whenComplete(() { checkFirebaseToken(); }); - }else{ + } else { FlutterCallkitIncoming.endAllCalls(); Utils.showToast("Something wen't wrong"); } } } - @override void dispose() { super.dispose(); diff --git a/pubspec.yaml b/pubspec.yaml index b50b4c6..d685ecb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -119,6 +119,9 @@ dependencies: store_checker: ^1.1.0 google_api_availability: ^3.0.1 + flutter_ios_voip_kit: ^0.1.0 + file: ^6.1.4 + dependency_overrides: firebase_core_platform_interface: 4.5.1