From 8f1881e6d0964dff5937e4f598d3c66b9ef9fe18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hie=CC=A3=CC=82p=20Hoa=CC=80ng?= Date: Wed, 3 Jan 2024 13:44:15 +0700 Subject: [PATCH 1/8] sync call --- ios/Classes/CallKeep.h | 7 ++ ios/Classes/CallKeep.m | 164 ++++++++++++++++++---------- ios/Classes/FlutterCallkeepPlugin.m | 1 + lib/src/api.dart | 17 +++ 4 files changed, 131 insertions(+), 58 deletions(-) diff --git a/ios/Classes/CallKeep.h b/ios/Classes/CallKeep.h index 493ad183..74d5032d 100644 --- a/ios/Classes/CallKeep.h +++ b/ios/Classes/CallKeep.h @@ -16,6 +16,13 @@ @property (nonatomic, strong, nullable) CXCallController *callKeepCallController; @property (nonatomic, strong, nullable) CXProvider *callKeepProvider; @property (nonatomic, strong, nullable) FlutterMethodChannel* eventChannel; ++ (CallKeep *_Nullable)instance; +@property (nonatomic, strong, nullable) NSMutableDictionary *callMap; +@property (nonatomic, strong, nullable) NSMutableArray *callAnswered; +@property (nonatomic, strong, nullable) NSMutableArray *callEnded; + + + - (BOOL)handleMethodCall:(FlutterMethodCall* _Nonnull)call result:(FlutterResult _Nonnull )result; diff --git a/ios/Classes/CallKeep.m b/ios/Classes/CallKeep.m index 0148c54b..e371b9cd 100644 --- a/ios/Classes/CallKeep.m +++ b/ios/Classes/CallKeep.m @@ -50,12 +50,25 @@ - (instancetype)init #ifdef DEBUG NSLog(@"[CallKeep][init]"); #endif + NSLog(@"[CallKeep][init]"); if (self = [super init]) { _delayedEvents = [NSMutableArray array]; + _callMap = [[NSMutableDictionary alloc] init]; + _callAnswered = [[NSMutableArray alloc] init]; + _callEnded = [[NSMutableArray alloc] init]; } return self; } ++ (CallKeep *)instance { + static CallKeep *ins = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + ins = [[CallKeep alloc] init]; + }); + return ins; +} + + (id)allocWithZone:(NSZone *)zone { static CallKeep *sharedInstance = nil; static dispatch_once_t onceToken; @@ -142,6 +155,16 @@ - (BOOL)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { else if([@"reportUpdatedCall" isEqualToString:method]){ [self reportUpdatedCall:argsMap[@"uuid"] contactIdentifier:argsMap[@"localizedCallerName"]]; result(nil); + }else if([@"reportCallIfNeeded" isEqualToString:method]) { + NSString *uuid = [self reportCallIfNeeded:argsMap[@"callId"] serial:argsMap[@"serial"] callerName:argsMap[@"caller"] hasVideo:[argsMap[@"hasVideo"] isEqual:@(1)] withCompletionHandler:nil]; + result(uuid); + }else if ([@"checkCallAnswered" isEqualToString:method]) { + result(@([self checkCallAnswered:argsMap[@"uuid"]])); + }else if ([@"checkCallEnded" isEqualToString: method]) { + result(@([self checkCallEnded:argsMap[@"uuid"]])); + }else if ([@"cleanStringeeCall" isEqualToString:method]) { + [self cleanStringeeCall]; + result(nil); } else { return NO; @@ -179,9 +202,6 @@ + (void)initCallKitProvider { -(void)setup:(NSDictionary *)options { -#ifdef DEBUG - NSLog(@"[CallKeep][setup] options = %@", options); -#endif _version = [[[NSProcessInfo alloc] init] operatingSystemVersion]; self.callKeepCallController = [[CXCallController alloc] init]; NSDictionary *settings = [[NSMutableDictionary alloc] initWithDictionary:options]; @@ -190,12 +210,13 @@ -(void)setup:(NSDictionary *)options [[NSUserDefaults standardUserDefaults] synchronize]; [CallKeep initCallKitProvider]; - self.callKeepProvider = sharedProvider; [self.callKeepProvider setDelegate:self queue:nil]; [self voipRegistration]; + NSLog(@"[CallKeep][setup] options = %@", options); } + #pragma mark - PushKit -(void)voipRegistration @@ -203,6 +224,7 @@ -(void)voipRegistration PKPushRegistry* voipRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()]; voipRegistry.delegate = self; voipRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP]; + NSLog(@"[CallKeep][voipRegistration]"); } - (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)pushCredentials forType:(PKPushType)type { @@ -218,85 +240,109 @@ - (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPush } - (NSString *)createUUID { - CFUUIDRef uuidObject = CFUUIDCreate(kCFAllocatorDefault); - NSString *uuidStr = (NSString *)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, uuidObject)); - CFUUIDBytes bytes = CFUUIDGetUUIDBytes(uuidObject); - CFRelease(uuidObject); - return [uuidStr lowercaseString]; + return [NSUUID.UUID.UUIDString lowercaseString]; +} + +- (BOOL)checkCallAnswered:(NSString *)uuid { + return [CallKeep.instance.callAnswered containsObject:uuid]; +} + +- (BOOL)checkCallEnded:(NSString *)uuid { + return [CallKeep.instance.callEnded containsObject:uuid]; +} + +- (void)cleanStringeeCall { + _callMap = [[NSMutableDictionary alloc] init]; + _callAnswered = [[NSMutableArray alloc] init]; + _callEnded = [[NSMutableArray alloc] init]; +} + +- (NSString *)reportCallIfNeeded:(NSString *)callId serial:(NSNumber *)serial callerName: (NSString *)callerName hasVideo:(BOOL)hasVideo withCompletionHandler:(void (^)(void))completion { + // create uuid if need + + NSNumber *checkSerial; + if (serial == NULL || serial == 0) { + checkSerial = @(1); + } else { + checkSerial = serial; + } + + NSString *keyId = [[NSString alloc] initWithFormat:@"%@-%@", callId, checkSerial]; + CXCallObserver *callObs = [[CXCallObserver alloc] init]; + NSString *uuid = [CallKeep.instance.callMap objectForKey:keyId]; + if (uuid == nil) { + uuid = [self createUUID]; + [CallKeep.instance.callMap setObject:uuid forKey:keyId]; + } + + BOOL didShow = false; + for (CXCall *call in callObs.calls) { + if ([call.UUID.UUIDString.lowercaseString isEqual:uuid]) { + didShow = true; + } + } + + for (NSString *callUUID in CallKeep.instance.callEnded) { + if ([uuid isEqualToString:callUUID]) { + didShow = true; + } + } + + if (!didShow) { + [CallKeep reportNewIncomingCall:uuid + handle:@"Stringee" + handleType:@"generic" + hasVideo:hasVideo + localizedCallerName:callerName + fromPushKit:YES + payload:@{ + @"callId": callId, + @"serial": serial, + @"hasVideo": @(hasVideo), + @"caller": callerName, + @"uuid": uuid, + } + withCompletionHandler:completion]; + return uuid; + } + return uuid; } - (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type withCompletionHandler:(nonnull void (^)(void))completion { // Process the received push NSLog(@"didReceiveIncomingPushWithPayload payload = %@", payload.type); - /* payload example. - { - "uuid": "xxxxx-xxxxx-xxxxx-xxxxx", - "caller_id": "+8618612345678", - "caller_name": "hello", - "caller_id_type": "number", - "has_video": false, - } - */ NSDictionary *dic = payload.dictionaryPayload[@"data"][@"map"][@"data"][@"map"]; -// -// if (dic[@"aps"] != nil) { -// NSLog(@"Do not use the 'alert' format for push type %@.", payload.type); -// if(completion != nil) { -// completion(); -// } -// return; -// } -// -// NSString *uuid = dic[@"uuid"]; -// NSString *callerId = dic[@"caller_id"]; -// NSString *callerName = dic[@"caller_name"]; -// BOOL hasVideo = [dic[@"has_video"] boolValue]; -// NSString *callerIdType = dic[@"caller_id_type"]; -// -// -// if( uuid == nil) { -// uuid = [self createUUID]; -// } // Sua theo data của Stringee NSString *callId = dic[@"callId"] != nil ? dic[@"callId"] : @""; - int serial = dic[@"serial"] != nil ? [(NSNumber *)dic[@"serial"] intValue] : 0; + int serial = dic[@"serial"] != nil ? [(NSNumber *)dic[@"serial"] intValue] : 1; NSString *callStatus = dic[@"callStatus"] != nil ? dic[@"callStatus"] : @""; NSString *fromAlias = dic[@"from"][@"map"][@"alias"] != nil ? dic[@"from"][@"map"][@"alias"] : @""; NSString *fromNumber = dic[@"from"][@"map"][@"number"] != nil ? dic[@"from"][@"map"][@"number"] : @""; NSString *callerName = ![fromAlias isEqual:@""] ? fromAlias : (![fromNumber isEqual:@""] ? fromNumber : @"Connecting..."); - NSString *uuid = [self createUUID]; + + if (callId == nil || callId.length == 0 || ![callStatus isEqualToString:@"started"]) { + // show fake call neu cuoc goi khong den tu StringeeServer + NSString *fakeUUID = [self createUUID]; + [CallKeep reportNewIncomingCall:fakeUUID handle:@"Stringee" handleType:@"generic" hasVideo:false localizedCallerName:@"FakeCall" fromPushKit:true payload:@{} withCompletionHandler:completion]; + [CallKeep endCallWithUUID:fakeUUID reason:1]; + return; + } + + NSString *uuid = [self reportCallIfNeeded:callId serial: @(serial) callerName:callerName hasVideo: false withCompletionHandler:completion]; NSMutableDictionary *parseData = [NSMutableDictionary new]; [parseData setValue:callId forKey:@"callId"]; [parseData setValue:@(serial) forKey:@"serial"]; [parseData setValue:callStatus forKey:@"callStatus"]; - [parseData setValue:uuid forKey:@"uuid"]; - - //NSDictionary *extra = payload.dictionaryPayload[@"extra"]; - - [CallKeep reportNewIncomingCall:uuid - handle:fromNumber - handleType:@"generic" - hasVideo:false - localizedCallerName:callerName - fromPushKit:YES - payload:parseData - withCompletionHandler:completion]; + [parseData setValue: uuid forKey:@"uuid"]; // Ban them su kien khi nhan duoc push [self sendEventWithNameWrapper:CallKeepPushKitReceivedNotification body:parseData]; } -- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type { - [self pushRegistry:registry didReceiveIncomingPushWithPayload:payload forType:type withCompletionHandler:^(){ - NSLog(@"[CallKeep] received"); - }]; -} - - -(void) checkIfBusyWithResult:(FlutterResult)result { #ifdef DEBUG @@ -826,6 +872,7 @@ - (void)provider:(CXProvider *)provider performAnswerCallAction:(CXAnswerCallAct #endif [self configureAudioSession]; [self sendEventWithNameWrapper:CallKeepPerformAnswerCallAction body:@{ @"callUUID": [action.callUUID.UUIDString lowercaseString] }]; + [CallKeep.instance.callAnswered addObject:action.callUUID.UUIDString.lowercaseString]; [action fulfill]; } @@ -836,6 +883,7 @@ - (void)provider:(CXProvider *)provider performEndCallAction:(CXEndCallAction *) NSLog(@"[CallKeep][CXProviderDelegate][provider:performEndCallAction]"); #endif [self sendEventWithNameWrapper:CallKeepPerformEndCallAction body:@{ @"callUUID": [action.callUUID.UUIDString lowercaseString] }]; + [CallKeep.instance.callEnded addObject:action.callUUID.UUIDString.lowercaseString]; [action fulfill]; } diff --git a/ios/Classes/FlutterCallkeepPlugin.m b/ios/Classes/FlutterCallkeepPlugin.m index 2bd577da..a930cb9f 100644 --- a/ios/Classes/FlutterCallkeepPlugin.m +++ b/ios/Classes/FlutterCallkeepPlugin.m @@ -24,6 +24,7 @@ + (void)registerWithRegistrar:(NSObject*)registrar { viewController:viewController withTextures:[registrar textures]]; [registrar addMethodCallDelegate:_instance channel:channel]; + [CallKeep instance]; } } diff --git a/lib/src/api.dart b/lib/src/api.dart index a91d926e..080b56bd 100644 --- a/lib/src/api.dart +++ b/lib/src/api.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:ffi'; import 'dart:io'; import 'package:flutter/services.dart'; import 'package:flutter/material.dart' @@ -247,6 +248,22 @@ class FlutterCallkeep extends EventManager { await _channel.invokeMethod( 'setOnHold', {'uuid': uuid, 'hold': shouldHold}); + Future reportCallIfNeeded(String callId, int serial, + {required String caller, required bool hasVideo}) async { + return await _channel.invokeMethod('reportCallIfNeeded', { + 'callId': callId, + 'serial' : serial, + 'caller': caller, + 'hasVideo': hasVideo + }); + } + + FuturecleanStringeeCall() async => + _channel.invokeMapMethod("cleanStringeeCall", {}); + + Future checkCallAnswered(String uuid) async => await _channel.invokeMethod('checkCallAnswered', {'uuid' : uuid}); + Future checkCallEnded(String uuid) async => await _channel.invokeMethod('checkCallEnded', {'uuid' : uuid}); + Future setReachable() async { if (isIOS) { return; From 538f86e08faaa5c753da4f4bd4f174d761dc3703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hie=CC=A3=CC=82p=20Hoa=CC=80ng?= Date: Fri, 12 Jan 2024 12:12:17 +0700 Subject: [PATCH 2/8] manager call --- ios/Classes/CallKeep.h | 19 ++++++--- ios/Classes/CallKeep.m | 95 ++++++++++++++++++++++++++---------------- lib/src/api.dart | 29 +++++++++++++ 3 files changed, 102 insertions(+), 41 deletions(-) diff --git a/ios/Classes/CallKeep.h b/ios/Classes/CallKeep.h index 74d5032d..83a33fd6 100644 --- a/ios/Classes/CallKeep.h +++ b/ios/Classes/CallKeep.h @@ -12,17 +12,24 @@ #import #import +typedef NS_ENUM(NSInteger, CallState) { + CallStateNotFound = 0, + CallStateRinging = 1, + CallStateAnswered = 2, + CallStateEnded = 3 +}; + +@interface CallInfo : NSObject +@property (nonatomic, assign, nullable) NSString * uuid; +@property (nonatomic, assign, nonnull) NSNumber * callState; +@end + @interface CallKeep: NSObject @property (nonatomic, strong, nullable) CXCallController *callKeepCallController; @property (nonatomic, strong, nullable) CXProvider *callKeepProvider; @property (nonatomic, strong, nullable) FlutterMethodChannel* eventChannel; + (CallKeep *_Nullable)instance; -@property (nonatomic, strong, nullable) NSMutableDictionary *callMap; -@property (nonatomic, strong, nullable) NSMutableArray *callAnswered; -@property (nonatomic, strong, nullable) NSMutableArray *callEnded; - - - +@property (nonatomic, strong, nullable) NSMutableDictionary *callMap; - (BOOL)handleMethodCall:(FlutterMethodCall* _Nonnull)call result:(FlutterResult _Nonnull )result; diff --git a/ios/Classes/CallKeep.m b/ios/Classes/CallKeep.m index e371b9cd..239b44f1 100644 --- a/ios/Classes/CallKeep.m +++ b/ios/Classes/CallKeep.m @@ -54,8 +54,6 @@ - (instancetype)init if (self = [super init]) { _delayedEvents = [NSMutableArray array]; _callMap = [[NSMutableDictionary alloc] init]; - _callAnswered = [[NSMutableArray alloc] init]; - _callEnded = [[NSMutableArray alloc] init]; } return self; } @@ -155,14 +153,15 @@ - (BOOL)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { else if([@"reportUpdatedCall" isEqualToString:method]){ [self reportUpdatedCall:argsMap[@"uuid"] contactIdentifier:argsMap[@"localizedCallerName"]]; result(nil); - }else if([@"reportCallIfNeeded" isEqualToString:method]) { - NSString *uuid = [self reportCallIfNeeded:argsMap[@"callId"] serial:argsMap[@"serial"] callerName:argsMap[@"caller"] hasVideo:[argsMap[@"hasVideo"] isEqual:@(1)] withCompletionHandler:nil]; - result(uuid); - }else if ([@"checkCallAnswered" isEqualToString:method]) { - result(@([self checkCallAnswered:argsMap[@"uuid"]])); - }else if ([@"checkCallEnded" isEqualToString: method]) { - result(@([self checkCallEnded:argsMap[@"uuid"]])); - }else if ([@"cleanStringeeCall" isEqualToString:method]) { + } + else if([@"getCallInfo" isEqualToString:method]) { + CallInfo *callInfo = [self getCallInfo:argsMap[@"callId"] serial:argsMap[@"serial"]]; + result(@{ + @"uuid" : callInfo.uuid, + @"state": callInfo.callState + }); + } + else if ([@"cleanStringeeCall" isEqualToString:method]) { [self cleanStringeeCall]; result(nil); } @@ -243,18 +242,26 @@ - (NSString *)createUUID { return [NSUUID.UUID.UUIDString lowercaseString]; } -- (BOOL)checkCallAnswered:(NSString *)uuid { - return [CallKeep.instance.callAnswered containsObject:uuid]; -} - -- (BOOL)checkCallEnded:(NSString *)uuid { - return [CallKeep.instance.callEnded containsObject:uuid]; -} - (void)cleanStringeeCall { _callMap = [[NSMutableDictionary alloc] init]; - _callAnswered = [[NSMutableArray alloc] init]; - _callEnded = [[NSMutableArray alloc] init]; +} + +- (CallInfo *)getCallInfo:(NSString *)callId serial:(NSNumber *)serial { + NSNumber *checkSerial; + if (serial == NULL || serial == 0) { + checkSerial = @(1); + } else { + checkSerial = serial; + } + NSString *keyId = [[NSString alloc] initWithFormat:@"%@-%@", callId, checkSerial]; + CallInfo *callInfo = [CallKeep.instance.callMap objectForKey:keyId]; + if (callInfo == nil) { + callInfo = [[CallInfo alloc] init]; + callInfo.callState = @(CallStateRinging); + [CallKeep.instance.callMap setObject:callInfo forKey:keyId]; + } + return callInfo; } - (NSString *)reportCallIfNeeded:(NSString *)callId serial:(NSNumber *)serial callerName: (NSString *)callerName hasVideo:(BOOL)hasVideo withCompletionHandler:(void (^)(void))completion { @@ -269,27 +276,23 @@ - (NSString *)reportCallIfNeeded:(NSString *)callId serial:(NSNumber *)serial ca NSString *keyId = [[NSString alloc] initWithFormat:@"%@-%@", callId, checkSerial]; CXCallObserver *callObs = [[CXCallObserver alloc] init]; - NSString *uuid = [CallKeep.instance.callMap objectForKey:keyId]; - if (uuid == nil) { - uuid = [self createUUID]; - [CallKeep.instance.callMap setObject:uuid forKey:keyId]; + CallInfo *callInfo = [CallKeep.instance.callMap objectForKey:keyId]; + if (callInfo == nil) { + callInfo = [[CallInfo alloc] init]; + callInfo.callState = @(CallStateRinging); + [CallKeep.instance.callMap setObject:callInfo forKey:keyId]; } BOOL didShow = false; for (CXCall *call in callObs.calls) { - if ([call.UUID.UUIDString.lowercaseString isEqual:uuid]) { + if ([call.UUID.UUIDString.lowercaseString isEqual:callInfo.uuid]) { didShow = true; } } - for (NSString *callUUID in CallKeep.instance.callEnded) { - if ([uuid isEqualToString:callUUID]) { - didShow = true; - } - } if (!didShow) { - [CallKeep reportNewIncomingCall:uuid + [CallKeep reportNewIncomingCall:callInfo.uuid handle:@"Stringee" handleType:@"generic" hasVideo:hasVideo @@ -300,12 +303,12 @@ - (NSString *)reportCallIfNeeded:(NSString *)callId serial:(NSNumber *)serial ca @"serial": serial, @"hasVideo": @(hasVideo), @"caller": callerName, - @"uuid": uuid, + @"uuid": callInfo.uuid, } withCompletionHandler:completion]; - return uuid; + return callInfo.uuid; } - return uuid; + return callInfo.uuid; } @@ -872,7 +875,11 @@ - (void)provider:(CXProvider *)provider performAnswerCallAction:(CXAnswerCallAct #endif [self configureAudioSession]; [self sendEventWithNameWrapper:CallKeepPerformAnswerCallAction body:@{ @"callUUID": [action.callUUID.UUIDString lowercaseString] }]; - [CallKeep.instance.callAnswered addObject:action.callUUID.UUIDString.lowercaseString]; + for (CallInfo * callInfo in CallKeep.instance.callMap.allValues) { + if ([callInfo.uuid isEqualToString:action.callUUID.UUIDString.lowercaseString]) { + callInfo.callState = @(CallStateAnswered); + } + } [action fulfill]; } @@ -883,7 +890,11 @@ - (void)provider:(CXProvider *)provider performEndCallAction:(CXEndCallAction *) NSLog(@"[CallKeep][CXProviderDelegate][provider:performEndCallAction]"); #endif [self sendEventWithNameWrapper:CallKeepPerformEndCallAction body:@{ @"callUUID": [action.callUUID.UUIDString lowercaseString] }]; - [CallKeep.instance.callEnded addObject:action.callUUID.UUIDString.lowercaseString]; + for (CallInfo * callInfo in CallKeep.instance.callMap.allValues) { + if ([callInfo.uuid isEqualToString:action.callUUID.UUIDString.lowercaseString]) { + callInfo.callState = @(CallStateEnded); + } + } [action fulfill]; } @@ -947,3 +958,17 @@ - (void)provider:(CXProvider *)provider didDeactivateAudioSession:(AVAudioSessio } @end + +@implementation CallInfo + +- (instancetype)init +{ + self = [super init]; + if (self) { + _uuid = [NSUUID.UUID.UUIDString lowercaseString]; + _callState = @(CallStateNotFound); + } + return self; +} + +@end diff --git a/lib/src/api.dart b/lib/src/api.dart index 080b56bd..f9cfeffa 100644 --- a/lib/src/api.dart +++ b/lib/src/api.dart @@ -17,6 +17,18 @@ import 'package:flutter/services.dart' show MethodChannel; import 'actions.dart'; import 'event.dart'; +enum CallState { + notFound, + ringing, + answered, + ended +} + +class CallInfo { + String uuid = ""; + CallState state = CallState.notFound; +} + bool get isIOS => Platform.isIOS; bool get supportConnectionService => !isIOS && int.parse(Platform.version) >= 23; @@ -261,6 +273,23 @@ class FlutterCallkeep extends EventManager { FuturecleanStringeeCall() async => _channel.invokeMapMethod("cleanStringeeCall", {}); + Future getCallInfo(String callId, int serial) async { + var callInfo = await _channel.invokeMethod('getCallState', {'callId' : callId, 'serial' : serial}); + var status = callInfo["state"]; + CallInfo info = CallInfo(); + info.uuid = callInfo["uuid"]; + if (status == 0) { + info.state = CallState.notFound; + } else if (status == 1) { + info.state = CallState.ringing; + } else if (status == 2) { + info.state = CallState.answered; + } else { + info.state = CallState.ended; + } + return info; + } + Future checkCallAnswered(String uuid) async => await _channel.invokeMethod('checkCallAnswered', {'uuid' : uuid}); Future checkCallEnded(String uuid) async => await _channel.invokeMethod('checkCallEnded', {'uuid' : uuid}); From 113150aff8c15ea56a607e5c48c0c5503ad7e015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hie=CC=A3=CC=82p=20Hoa=CC=80ng?= Date: Fri, 12 Jan 2024 12:15:06 +0700 Subject: [PATCH 3/8] no message --- lib/src/api.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/api.dart b/lib/src/api.dart index f9cfeffa..1f332e93 100644 --- a/lib/src/api.dart +++ b/lib/src/api.dart @@ -274,7 +274,7 @@ class FlutterCallkeep extends EventManager { _channel.invokeMapMethod("cleanStringeeCall", {}); Future getCallInfo(String callId, int serial) async { - var callInfo = await _channel.invokeMethod('getCallState', {'callId' : callId, 'serial' : serial}); + var callInfo = await _channel.invokeMethod('getCallInfo', {'callId' : callId, 'serial' : serial}); var status = callInfo["state"]; CallInfo info = CallInfo(); info.uuid = callInfo["uuid"]; From 1fcf46ab20b9327c57864c586de373c97b6c4e0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hie=CC=A3=CC=82p=20Hoa=CC=80ng?= Date: Fri, 12 Jan 2024 12:18:53 +0700 Subject: [PATCH 4/8] no message --- lib/src/api.dart | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/lib/src/api.dart b/lib/src/api.dart index 1f332e93..ca846212 100644 --- a/lib/src/api.dart +++ b/lib/src/api.dart @@ -259,17 +259,7 @@ class FlutterCallkeep extends EventManager { Future setOnHold(String uuid, bool shouldHold) async => await _channel.invokeMethod( 'setOnHold', {'uuid': uuid, 'hold': shouldHold}); - - Future reportCallIfNeeded(String callId, int serial, - {required String caller, required bool hasVideo}) async { - return await _channel.invokeMethod('reportCallIfNeeded', { - 'callId': callId, - 'serial' : serial, - 'caller': caller, - 'hasVideo': hasVideo - }); - } - + FuturecleanStringeeCall() async => _channel.invokeMapMethod("cleanStringeeCall", {}); @@ -290,9 +280,6 @@ class FlutterCallkeep extends EventManager { return info; } - Future checkCallAnswered(String uuid) async => await _channel.invokeMethod('checkCallAnswered', {'uuid' : uuid}); - Future checkCallEnded(String uuid) async => await _channel.invokeMethod('checkCallEnded', {'uuid' : uuid}); - Future setReachable() async { if (isIOS) { return; From c36f93af2c6890760da135cb27c4118ab87e99d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hie=CC=A3=CC=82p=20Hoa=CC=80ng?= Date: Fri, 12 Jan 2024 12:20:42 +0700 Subject: [PATCH 5/8] no message --- lib/src/api.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/api.dart b/lib/src/api.dart index ca846212..bfd9364d 100644 --- a/lib/src/api.dart +++ b/lib/src/api.dart @@ -259,7 +259,7 @@ class FlutterCallkeep extends EventManager { Future setOnHold(String uuid, bool shouldHold) async => await _channel.invokeMethod( 'setOnHold', {'uuid': uuid, 'hold': shouldHold}); - + FuturecleanStringeeCall() async => _channel.invokeMapMethod("cleanStringeeCall", {}); From faa8e5ab545f226847f50e6f84abcaae01df065e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hie=CC=A3=CC=82p=20Hoa=CC=80ng?= Date: Fri, 12 Jan 2024 14:11:04 +0700 Subject: [PATCH 6/8] fix crash --- ios/Classes/CallKeep.h | 4 ++-- ios/Classes/CallKeep.m | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/ios/Classes/CallKeep.h b/ios/Classes/CallKeep.h index 83a33fd6..cddbfefc 100644 --- a/ios/Classes/CallKeep.h +++ b/ios/Classes/CallKeep.h @@ -20,8 +20,8 @@ typedef NS_ENUM(NSInteger, CallState) { }; @interface CallInfo : NSObject -@property (nonatomic, assign, nullable) NSString * uuid; -@property (nonatomic, assign, nonnull) NSNumber * callState; +@property (strong, nonatomic, nonnull) NSString * uuid; +@property (strong, nonatomic, nonnull) NSNumber * callState; @end @interface CallKeep: NSObject diff --git a/ios/Classes/CallKeep.m b/ios/Classes/CallKeep.m index 239b44f1..24dc1507 100644 --- a/ios/Classes/CallKeep.m +++ b/ios/Classes/CallKeep.m @@ -258,7 +258,6 @@ - (CallInfo *)getCallInfo:(NSString *)callId serial:(NSNumber *)serial { CallInfo *callInfo = [CallKeep.instance.callMap objectForKey:keyId]; if (callInfo == nil) { callInfo = [[CallInfo alloc] init]; - callInfo.callState = @(CallStateRinging); [CallKeep.instance.callMap setObject:callInfo forKey:keyId]; } return callInfo; @@ -279,7 +278,6 @@ - (NSString *)reportCallIfNeeded:(NSString *)callId serial:(NSNumber *)serial ca CallInfo *callInfo = [CallKeep.instance.callMap objectForKey:keyId]; if (callInfo == nil) { callInfo = [[CallInfo alloc] init]; - callInfo.callState = @(CallStateRinging); [CallKeep.instance.callMap setObject:callInfo forKey:keyId]; } @@ -290,8 +288,8 @@ - (NSString *)reportCallIfNeeded:(NSString *)callId serial:(NSNumber *)serial ca } } - - if (!didShow) { + if (!didShow && [callInfo.callState isEqualToNumber:@(CallStateNotFound)]) { + callInfo.callState = @(CallStateRinging); [CallKeep reportNewIncomingCall:callInfo.uuid handle:@"Stringee" handleType:@"generic" @@ -967,6 +965,7 @@ - (instancetype)init if (self) { _uuid = [NSUUID.UUID.UUIDString lowercaseString]; _callState = @(CallStateNotFound); + NSLog(@"create call info"); } return self; } From a66e274ad02f72f8a8430d7bd6842963f85d81bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hie=CC=A3=CC=82p=20Hoa=CC=80ng?= Date: Tue, 16 Jan 2024 10:28:54 +0700 Subject: [PATCH 7/8] call info manager --- ios/Classes/CallKeep.h | 3 +- ios/Classes/CallKeep.m | 49 ++++++++++++++++++----------- ios/Classes/FlutterCallkeepPlugin.m | 1 - lib/src/api.dart | 11 ++++--- 4 files changed, 39 insertions(+), 25 deletions(-) diff --git a/ios/Classes/CallKeep.h b/ios/Classes/CallKeep.h index cddbfefc..f4fe0310 100644 --- a/ios/Classes/CallKeep.h +++ b/ios/Classes/CallKeep.h @@ -13,7 +13,7 @@ #import typedef NS_ENUM(NSInteger, CallState) { - CallStateNotFound = 0, + CallStateCallOut = 0, CallStateRinging = 1, CallStateAnswered = 2, CallStateEnded = 3 @@ -28,7 +28,6 @@ typedef NS_ENUM(NSInteger, CallState) { @property (nonatomic, strong, nullable) CXCallController *callKeepCallController; @property (nonatomic, strong, nullable) CXProvider *callKeepProvider; @property (nonatomic, strong, nullable) FlutterMethodChannel* eventChannel; -+ (CallKeep *_Nullable)instance; @property (nonatomic, strong, nullable) NSMutableDictionary *callMap; - (BOOL)handleMethodCall:(FlutterMethodCall* _Nonnull)call result:(FlutterResult _Nonnull )result; diff --git a/ios/Classes/CallKeep.m b/ios/Classes/CallKeep.m index 24dc1507..68f2926f 100644 --- a/ios/Classes/CallKeep.m +++ b/ios/Classes/CallKeep.m @@ -58,14 +58,6 @@ - (instancetype)init return self; } -+ (CallKeep *)instance { - static CallKeep *ins = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - ins = [[CallKeep alloc] init]; - }); - return ins; -} + (id)allocWithZone:(NSZone *)zone { static CallKeep *sharedInstance = nil; @@ -165,6 +157,9 @@ - (BOOL)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { [self cleanStringeeCall]; result(nil); } + else if ([@"generateUUID" isEqualToString:method]) { + result([self generateUUID:argsMap[@"callId"] serial:argsMap[@"serial"]]); + } else { return NO; } @@ -247,7 +242,7 @@ - (void)cleanStringeeCall { _callMap = [[NSMutableDictionary alloc] init]; } -- (CallInfo *)getCallInfo:(NSString *)callId serial:(NSNumber *)serial { +- (NSString *)generateUUID:(NSString *)callId serial:(NSNumber *)serial { NSNumber *checkSerial; if (serial == NULL || serial == 0) { checkSerial = @(1); @@ -255,14 +250,27 @@ - (CallInfo *)getCallInfo:(NSString *)callId serial:(NSNumber *)serial { checkSerial = serial; } NSString *keyId = [[NSString alloc] initWithFormat:@"%@-%@", callId, checkSerial]; - CallInfo *callInfo = [CallKeep.instance.callMap objectForKey:keyId]; + CallInfo *callInfo = [_callMap objectForKey:keyId]; if (callInfo == nil) { callInfo = [[CallInfo alloc] init]; - [CallKeep.instance.callMap setObject:callInfo forKey:keyId]; + [_callMap setObject:callInfo forKey:keyId]; + } + return callInfo.uuid; +} + +- (CallInfo *)getCallInfo:(NSString *)callId serial:(NSNumber *)serial { + NSNumber *checkSerial; + if (serial == NULL || serial == 0) { + checkSerial = @(1); + } else { + checkSerial = serial; } + NSString *keyId = [[NSString alloc] initWithFormat:@"%@-%@", callId, checkSerial]; + CallInfo *callInfo = [_callMap objectForKey:keyId]; return callInfo; } + - (NSString *)reportCallIfNeeded:(NSString *)callId serial:(NSNumber *)serial callerName: (NSString *)callerName hasVideo:(BOOL)hasVideo withCompletionHandler:(void (^)(void))completion { // create uuid if need @@ -275,10 +283,10 @@ - (NSString *)reportCallIfNeeded:(NSString *)callId serial:(NSNumber *)serial ca NSString *keyId = [[NSString alloc] initWithFormat:@"%@-%@", callId, checkSerial]; CXCallObserver *callObs = [[CXCallObserver alloc] init]; - CallInfo *callInfo = [CallKeep.instance.callMap objectForKey:keyId]; + CallInfo *callInfo = [_callMap objectForKey:keyId]; if (callInfo == nil) { callInfo = [[CallInfo alloc] init]; - [CallKeep.instance.callMap setObject:callInfo forKey:keyId]; + [_callMap setObject:callInfo forKey:keyId]; } BOOL didShow = false; @@ -288,7 +296,7 @@ - (NSString *)reportCallIfNeeded:(NSString *)callId serial:(NSNumber *)serial ca } } - if (!didShow && [callInfo.callState isEqualToNumber:@(CallStateNotFound)]) { + if (!didShow && [callInfo.callState isEqual:nil]) { callInfo.callState = @(CallStateRinging); [CallKeep reportNewIncomingCall:callInfo.uuid handle:@"Stringee" @@ -370,6 +378,11 @@ -(void) displayIncomingCall:(NSString *)uuidString hasVideo:(BOOL)hasVideo localizedCallerName:(NSString * _Nullable)localizedCallerName { + for (CallInfo * callInfo in _callMap.allValues) { + if ([callInfo.uuid isEqualToString:uuidString]) { + callInfo.callState = @(CallStateRinging); + } + } [CallKeep reportNewIncomingCall: uuidString handle:handle handleType:handleType hasVideo:hasVideo localizedCallerName:localizedCallerName fromPushKit: NO payload:nil withCompletionHandler:nil]; } @@ -644,6 +657,7 @@ + (void)reportNewIncomingCall:(NSString *)uuidString localizedCallerName:(NSString * _Nullable)localizedCallerName fromPushKit:(BOOL)fromPushKit { + [CallKeep reportNewIncomingCall: uuidString handle:handle handleType:handleType hasVideo:hasVideo localizedCallerName:localizedCallerName fromPushKit: fromPushKit payload:nil withCompletionHandler:nil]; } @@ -873,7 +887,7 @@ - (void)provider:(CXProvider *)provider performAnswerCallAction:(CXAnswerCallAct #endif [self configureAudioSession]; [self sendEventWithNameWrapper:CallKeepPerformAnswerCallAction body:@{ @"callUUID": [action.callUUID.UUIDString lowercaseString] }]; - for (CallInfo * callInfo in CallKeep.instance.callMap.allValues) { + for (CallInfo * callInfo in _callMap.allValues) { if ([callInfo.uuid isEqualToString:action.callUUID.UUIDString.lowercaseString]) { callInfo.callState = @(CallStateAnswered); } @@ -888,7 +902,7 @@ - (void)provider:(CXProvider *)provider performEndCallAction:(CXEndCallAction *) NSLog(@"[CallKeep][CXProviderDelegate][provider:performEndCallAction]"); #endif [self sendEventWithNameWrapper:CallKeepPerformEndCallAction body:@{ @"callUUID": [action.callUUID.UUIDString lowercaseString] }]; - for (CallInfo * callInfo in CallKeep.instance.callMap.allValues) { + for (CallInfo * callInfo in _callMap.allValues) { if ([callInfo.uuid isEqualToString:action.callUUID.UUIDString.lowercaseString]) { callInfo.callState = @(CallStateEnded); } @@ -964,8 +978,7 @@ - (instancetype)init self = [super init]; if (self) { _uuid = [NSUUID.UUID.UUIDString lowercaseString]; - _callState = @(CallStateNotFound); - NSLog(@"create call info"); + _callState = nil; } return self; } diff --git a/ios/Classes/FlutterCallkeepPlugin.m b/ios/Classes/FlutterCallkeepPlugin.m index a930cb9f..2bd577da 100644 --- a/ios/Classes/FlutterCallkeepPlugin.m +++ b/ios/Classes/FlutterCallkeepPlugin.m @@ -24,7 +24,6 @@ + (void)registerWithRegistrar:(NSObject*)registrar { viewController:viewController withTextures:[registrar textures]]; [registrar addMethodCallDelegate:_instance channel:channel]; - [CallKeep instance]; } } diff --git a/lib/src/api.dart b/lib/src/api.dart index bfd9364d..4b480094 100644 --- a/lib/src/api.dart +++ b/lib/src/api.dart @@ -18,15 +18,15 @@ import 'actions.dart'; import 'event.dart'; enum CallState { - notFound, + callOut, ringing, answered, ended } class CallInfo { - String uuid = ""; - CallState state = CallState.notFound; + String? uuid = null; + CallState? state = null; } bool get isIOS => Platform.isIOS; @@ -269,7 +269,7 @@ class FlutterCallkeep extends EventManager { CallInfo info = CallInfo(); info.uuid = callInfo["uuid"]; if (status == 0) { - info.state = CallState.notFound; + info.state = CallState.callOut; } else if (status == 1) { info.state = CallState.ringing; } else if (status == 2) { @@ -279,6 +279,9 @@ class FlutterCallkeep extends EventManager { } return info; } + Future generateUUID(String callId, int serial) async { + return await _channel.invokeMethod('generateUUID', {'callId' : callId, 'serial' : serial}); + } Future setReachable() async { if (isIOS) { From 3702d5b302c67e2fa49de801bbf62bef0c93b414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hie=CC=A3=CC=82p=20Hoa=CC=80ng?= Date: Tue, 16 Jan 2024 15:43:32 +0700 Subject: [PATCH 8/8] fixbug multi CallKeep instance --- ios/Classes/CallKeep.h | 1 + ios/Classes/CallKeep.m | 75 +++++++++++++++++------------ ios/Classes/FlutterCallkeepPlugin.m | 3 +- lib/src/api.dart | 2 +- 4 files changed, 47 insertions(+), 34 deletions(-) diff --git a/ios/Classes/CallKeep.h b/ios/Classes/CallKeep.h index f4fe0310..83d5c769 100644 --- a/ios/Classes/CallKeep.h +++ b/ios/Classes/CallKeep.h @@ -29,6 +29,7 @@ typedef NS_ENUM(NSInteger, CallState) { @property (nonatomic, strong, nullable) CXProvider *callKeepProvider; @property (nonatomic, strong, nullable) FlutterMethodChannel* eventChannel; @property (nonatomic, strong, nullable) NSMutableDictionary *callMap; ++ (CallKeep *_Nullable)instance; - (BOOL)handleMethodCall:(FlutterMethodCall* _Nonnull)call result:(FlutterResult _Nonnull )result; diff --git a/ios/Classes/CallKeep.m b/ios/Classes/CallKeep.m index 68f2926f..a1f085be 100644 --- a/ios/Classes/CallKeep.m +++ b/ios/Classes/CallKeep.m @@ -54,10 +54,19 @@ - (instancetype)init if (self = [super init]) { _delayedEvents = [NSMutableArray array]; _callMap = [[NSMutableDictionary alloc] init]; + [self voipRegistration]; } return self; } ++ (CallKeep *)instance { + static CallKeep *ins = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + ins = [[CallKeep alloc] init]; + }); + return ins; +} + (id)allocWithZone:(NSZone *)zone { static CallKeep *sharedInstance = nil; @@ -148,18 +157,22 @@ - (BOOL)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { } else if([@"getCallInfo" isEqualToString:method]) { CallInfo *callInfo = [self getCallInfo:argsMap[@"callId"] serial:argsMap[@"serial"]]; - result(@{ - @"uuid" : callInfo.uuid, - @"state": callInfo.callState - }); + NSMutableDictionary *params = [[NSMutableDictionary alloc] init]; + if (callInfo.uuid) { + params[@"uuid"] = callInfo.uuid; + } + if (callInfo.callState) { + params[@"state"] = callInfo.callState; + } + result(params); + } + else if ([@"generateUUID" isEqualToString:method]) { + result([self generateUUID:argsMap[@"callId"] serial:argsMap[@"serial"]]); } else if ([@"cleanStringeeCall" isEqualToString:method]) { [self cleanStringeeCall]; result(nil); } - else if ([@"generateUUID" isEqualToString:method]) { - result([self generateUUID:argsMap[@"callId"] serial:argsMap[@"serial"]]); - } else { return NO; } @@ -188,12 +201,16 @@ - (void)sendEventWithNameWrapper:(NSString *)name body:(id)body { } + (void)initCallKitProvider { + NSLog(@"[Callkeep][initCallKitProvider]"); if (sharedProvider == nil) { NSDictionary *settings = [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"CallKeepSettings"]; - sharedProvider = [[CXProvider alloc] initWithConfiguration:[CallKeep getProviderConfiguration:settings]]; + if (settings) { + sharedProvider = [[CXProvider alloc] initWithConfiguration:[CallKeep getProviderConfiguration:settings]]; + } } } + -(void)setup:(NSDictionary *)options { _version = [[[NSProcessInfo alloc] init] operatingSystemVersion]; @@ -242,7 +259,7 @@ - (void)cleanStringeeCall { _callMap = [[NSMutableDictionary alloc] init]; } -- (NSString *)generateUUID:(NSString *)callId serial:(NSNumber *)serial { +- (CallInfo *)getCallInfo:(NSString *)callId serial:(NSNumber *)serial { NSNumber *checkSerial; if (serial == NULL || serial == 0) { checkSerial = @(1); @@ -250,15 +267,11 @@ - (NSString *)generateUUID:(NSString *)callId serial:(NSNumber *)serial { checkSerial = serial; } NSString *keyId = [[NSString alloc] initWithFormat:@"%@-%@", callId, checkSerial]; - CallInfo *callInfo = [_callMap objectForKey:keyId]; - if (callInfo == nil) { - callInfo = [[CallInfo alloc] init]; - [_callMap setObject:callInfo forKey:keyId]; - } - return callInfo.uuid; + CallInfo *callInfo = [CallKeep.instance.callMap objectForKey:keyId]; + return callInfo; } -- (CallInfo *)getCallInfo:(NSString *)callId serial:(NSNumber *)serial { +- (NSString *)generateUUID:(NSString *)callId serial:(NSNumber *)serial { NSNumber *checkSerial; if (serial == NULL || serial == 0) { checkSerial = @(1); @@ -266,11 +279,14 @@ - (CallInfo *)getCallInfo:(NSString *)callId serial:(NSNumber *)serial { checkSerial = serial; } NSString *keyId = [[NSString alloc] initWithFormat:@"%@-%@", callId, checkSerial]; - CallInfo *callInfo = [_callMap objectForKey:keyId]; - return callInfo; + CallInfo *callInfo = [CallKeep.instance.callMap objectForKey:keyId]; + if (callInfo == nil) { + callInfo = [[CallInfo alloc] init]; + [CallKeep.instance.callMap setObject:callInfo forKey:keyId]; + } + return callInfo.uuid; } - - (NSString *)reportCallIfNeeded:(NSString *)callId serial:(NSNumber *)serial callerName: (NSString *)callerName hasVideo:(BOOL)hasVideo withCompletionHandler:(void (^)(void))completion { // create uuid if need @@ -283,20 +299,23 @@ - (NSString *)reportCallIfNeeded:(NSString *)callId serial:(NSNumber *)serial ca NSString *keyId = [[NSString alloc] initWithFormat:@"%@-%@", callId, checkSerial]; CXCallObserver *callObs = [[CXCallObserver alloc] init]; - CallInfo *callInfo = [_callMap objectForKey:keyId]; + CallInfo *callInfo = [CallKeep.instance.callMap objectForKey:keyId]; + + BOOL didShow = false; if (callInfo == nil) { callInfo = [[CallInfo alloc] init]; - [_callMap setObject:callInfo forKey:keyId]; + [CallKeep.instance.callMap setObject:callInfo forKey:keyId]; + } else if (callInfo.callState) { + didShow = true; } - BOOL didShow = false; for (CXCall *call in callObs.calls) { if ([call.UUID.UUIDString.lowercaseString isEqual:callInfo.uuid]) { didShow = true; } } - if (!didShow && [callInfo.callState isEqual:nil]) { + if (!didShow) { callInfo.callState = @(CallStateRinging); [CallKeep reportNewIncomingCall:callInfo.uuid handle:@"Stringee" @@ -378,11 +397,6 @@ -(void) displayIncomingCall:(NSString *)uuidString hasVideo:(BOOL)hasVideo localizedCallerName:(NSString * _Nullable)localizedCallerName { - for (CallInfo * callInfo in _callMap.allValues) { - if ([callInfo.uuid isEqualToString:uuidString]) { - callInfo.callState = @(CallStateRinging); - } - } [CallKeep reportNewIncomingCall: uuidString handle:handle handleType:handleType hasVideo:hasVideo localizedCallerName:localizedCallerName fromPushKit: NO payload:nil withCompletionHandler:nil]; } @@ -657,7 +671,6 @@ + (void)reportNewIncomingCall:(NSString *)uuidString localizedCallerName:(NSString * _Nullable)localizedCallerName fromPushKit:(BOOL)fromPushKit { - [CallKeep reportNewIncomingCall: uuidString handle:handle handleType:handleType hasVideo:hasVideo localizedCallerName:localizedCallerName fromPushKit: fromPushKit payload:nil withCompletionHandler:nil]; } @@ -887,7 +900,7 @@ - (void)provider:(CXProvider *)provider performAnswerCallAction:(CXAnswerCallAct #endif [self configureAudioSession]; [self sendEventWithNameWrapper:CallKeepPerformAnswerCallAction body:@{ @"callUUID": [action.callUUID.UUIDString lowercaseString] }]; - for (CallInfo * callInfo in _callMap.allValues) { + for (CallInfo * callInfo in CallKeep.instance.callMap.allValues) { if ([callInfo.uuid isEqualToString:action.callUUID.UUIDString.lowercaseString]) { callInfo.callState = @(CallStateAnswered); } @@ -902,7 +915,7 @@ - (void)provider:(CXProvider *)provider performEndCallAction:(CXEndCallAction *) NSLog(@"[CallKeep][CXProviderDelegate][provider:performEndCallAction]"); #endif [self sendEventWithNameWrapper:CallKeepPerformEndCallAction body:@{ @"callUUID": [action.callUUID.UUIDString lowercaseString] }]; - for (CallInfo * callInfo in _callMap.allValues) { + for (CallInfo * callInfo in CallKeep.instance.callMap.allValues) { if ([callInfo.uuid isEqualToString:action.callUUID.UUIDString.lowercaseString]) { callInfo.callState = @(CallStateEnded); } diff --git a/ios/Classes/FlutterCallkeepPlugin.m b/ios/Classes/FlutterCallkeepPlugin.m index 2bd577da..f0f6eb30 100644 --- a/ios/Classes/FlutterCallkeepPlugin.m +++ b/ios/Classes/FlutterCallkeepPlugin.m @@ -39,6 +39,7 @@ - (instancetype)initWithChannel:(FlutterMethodChannel *)channel #endif if (self = [super init]) { _callKeep = [CallKeep allocWithZone: nil]; + [CallKeep instance]; _callKeep.eventChannel = [FlutterMethodChannel methodChannelWithName:@"FlutterCallKeep.Event" binaryMessenger:[registrar messenger]]; @@ -48,9 +49,7 @@ - (instancetype)initWithChannel:(FlutterMethodChannel *)channel - (void)dealloc { -#ifdef DEBUG NSLog(@"[FlutterCallkeepPlugin][dealloc]"); -#endif [[NSNotificationCenter defaultCenter] removeObserver:self]; _callKeep = nil; } diff --git a/lib/src/api.dart b/lib/src/api.dart index 4b480094..45efa9b2 100644 --- a/lib/src/api.dart +++ b/lib/src/api.dart @@ -274,7 +274,7 @@ class FlutterCallkeep extends EventManager { info.state = CallState.ringing; } else if (status == 2) { info.state = CallState.answered; - } else { + } else if (status == 3) { info.state = CallState.ended; } return info;