react-native-callkeep
react-native-callkeep copied to clipboard
Cannot signal callkit call rejection when app receives call while in background (IOS)
I have a voip video calling app.
I am using Callkeep exclusively for IOS, to access IOS callkit.
I have a component that listens to both onRNCallKeepPerformAnswerCallAction and onRNCallKeepPerformEndCallAction. In both cases it will send a message back to the server to update the database about the status of the call - answered or rejected, respectively.
With app in foreground there is no problem, everything works fine.
When the app is in kill state or background, however, and a call comes in, it rings using the callkit ui, as expected.
When I answer, everything works fine.
But when I reject the call the 'onRNCallKeepPerformEndCallAction' listener in react native is not triggered. Instead the app is killed. Therefore, my function signaling to the server that the receiver has rejected the call never goes out.
Only after I manually restart the app, or bring it to the foreground, do I see the api call conveying the message. This is too late. It needs to happen immediately so that the caller knows the call has been rejected.
How can I communicate between callkit UI and react-native for rejected calls when the app is in the background?
Versions
- Callkeep: 3.0.10
- React Native: 0.61.5
- iOS: 12.4.5
- Phone model: IPhone6
Hi @Praxey do you have more iOS logs for this issue ? Maybe the app is killed because you didn't report the call earlier.
I'm having the same issue. The 'endCall' action works if the app is in foreground, but is not being called in JS if the app is killed/in background (the call is being reported in AppDelegate.m, the listeners are binded in index.js).
On Android, I am getting the same issue. Start call work perfect but end call not working then app was killed
I'm having the same issue. Platform iOS, in event 'endCall', I call API to reject the call, but it does not work when app in background/ kill app .
Hi, it happens because framework fulfills native CXActions in the moment when event is sent to JS. Instead CXActions should be fulfilled when action is actually handled. System thought that you have handled action and app is ready to be killed. So it is killed before your JS code is executed.
Hi @Vespen, do you have any idea to fix this? How to queue the event to send when a listener is added for it?
@tuanbm did you happen to find a solution here?
Same issue:
1.) "Person 1" initiates the call 2.) "Person 2" declines the call 3.) I'm using apollographql to communicate with the server. I'm trying to send the "endCall" signal to the server after "Person 2" declines the call, but it's not working.
same here
+1
You have time between CallKit end call button touch and end call action's full fill.
RNCallKeep.addEventListener('endCall', ({ callUUID }) => // <== Start from here
// Do your clean up job in this event. ex: End SIP or WebRCT connection..
RNCallKeep.endAllCalls(); // <== And call this. or just endCall. This makes end call transaction and full fill.
Does anybody figured out how to handle this? @Praxey
Check out Romick2005's two answers: https://github.com/react-native-webrtc/react-native-callkeep/issues/330#issuecomment-799525290 https://github.com/react-native-webrtc/react-native-callkeep/issues/418#issuecomment-892952509
Works flawlessly for me.
Simply use his fork instead of this repo.
You can load it in package.json like this:
"react-native-callkeep": "git+https://github.com/Romick2005/react-native-callkeep.git"
@ankitbishtapollo @johnjoshuadablo @CaptainJeff @linus-komnick
Found a solution that doesn't require to use any fork of react-native-callkeep
The solution is to use on iOS CallKit to listen to the call events, when the end call event is dispatched then you can do whatever you want, in my case I send an HTTP request to my server to tell the caller that the called refused the call.
In AppDelegate.m
#import <CallKit/CXCallObserver.h>
#import <CallKit/CXCall.h>
// ...
// before @implementation AppDelegate
@interface AppDelegate ()<CXCallObserverDelegate>
@property (strong, nonatomic) CXCallObserver *callObserver;
@end
// ...
// in - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
CXCallObserver *callObserver = [[CXCallObserver alloc] init];
[callObserver setDelegate:self queue:nil];
self.callObserver = callObserver;
// ...
// before @end
- (void)callObserver:(CXCallObserver *)callObserver callChanged:(CXCall *)call{
NSLog (@"[CallObserver] event from call with UUID: %@", call.UUID);
if (call.hasEnded) {
NSLog (@"[CallObserver] call %@ ended", call.UUID);
// here do whatever you like to inform the caller that the called refused the call
}
}
Hope it helps