I am working with JitsiMeet iOS (Create Jitsi Meet Framework for native iOS application and integrate in Xcode Project) for video call implementation in an application. For background mode calling I am trying to achieve a skype like interface. Where user receives an audio call can start talking right away by accepting that call. Hence when I receive PKPushNotification, I trigger this code to initiate calling screen:
[JMCallKitProxy reportNewIncomingCallWithUUID:activeCallUUID_ handle:message.messageText displayName:message.senderName hasVideo:false completion:^(NSError * _Nullable error) {
if (error != nil) NSLog(#"%s error = %#", __PRETTY_FUNCTION__, error.localizedDescription);
}];
This works fine and call get triggered as native call. Then I have implemented then I have implemented JMCallKitListener and inside performAnswerCallWithUUID I tried to initialize my JitsiViewController to joint the call group.
But problem is when application is in background these listeners doesn't trigger. Although they work fine when app is active.
Related
I started messing around with the Watch OS framework today and wanted to throw together a quick app, but have come to a couple questions.
I made an iOS app that just shows the current battery % as well as the state of the battery. I then wanted to show that over on the watch.
The only time the watch app will update is when I totally close the iOS app, then open it, while the watch app is active. How do I allow my watch app to be updated if I open it after the iOS app has been opened?
This kind of goes with number 2. But how do I allow the watch app to fetch info from the iOS app, after it has been in the background? As an example, lets say the iOS app has been in the background and I wanted to fetch the battery % without opening the iOS app to the foreground.
Some side notes on how I set this up -
Within the iOS app, in the viewDidLoad method, I start my session.
if ([WCSession isSupported]) {
wcSession = [WCSession defaultSession];
wcSession.delegate = self;
[wcSession activateSession];
}
Then call my method to update the actual battery % and state. Within that method, I have this which sends the info over to the watch:
NSDictionary *message = #{
#"message" : [NSString stringWithFormat:#"%#", [numberFormatter stringFromNumber:levelObj]],
#"message_2" : [NSString stringWithFormat:#"%ld",(long)[UIDevice currentDevice].batteryState],
};
[wcSession sendMessage:message replyHandler:nil errorHandler:^(NSError * _Nonnull error) {
NSLog(#"%#", error.localizedDescription);
}];
I also call this same method in the viewDidAppear, so I don't have to relaunch the app completely, to allow refreshing of the watch counterpart.
On the watch side I have the viewWillActivate method with the same activation as the iOS side as well as the method to handle what the watch app receives from the iOS side. But it will only update when I restart the iOS app fully.
- (void)session:(WCSession *)session didReceiveMessage:(NSDictionary<NSString *,id> *)message {
NSLog(#"Message recieved!");
[_batteryLevelLabelW setText:message[#"message"]];
}
Also in there is the code to handle the battery state message, which is a bit long.
I hope I gave a good amount of information to help.
According to documentation:
Use the sendMessage(_:replyHandler:errorHandler:) or
sendMessageData(_:replyHandler:errorHandler:) method to
transfer data to a reachable counterpart. These methods are intended
for immediate communication between your iOS app and WatchKit
extension. The isReachable property must currently be true for these
methods to succeed.
If watchapp is not foreground, message will not be delivered since isReachable is false.
Method you should use is updateApplicationContext(_:) - it will wait till watch app will be opened at foreground and only then will be delivered.
I'm planning to create an iOS VoIP app(not made any iOS app before). I was reading about Callkit in IOS by which one can make his app receive phone call through iPhone native call screen.
I read Callkit api here where it is mentioned that one can know if a call is answered.
Going through this tutorial and here is the code which detects the call is answered:
-(void)reportIncomingCallWithHandle:(NSString *)handle
success:(void (^)())success
failure:(void (^)(NSError * error))failure {
CXCallUpdate *update = [self newCallUpdateWithHandle:handle];
self.callId = [NSUUID UUID];
[self.provider reportNewIncomingCallWithUUID:self.callId update:update completion:^(NSError * _Nullable error) {
if (error) {
if (failure) failure(error);
} else {
if (success) {
success();
}
}
}];
}
See the success block. So is there is a way to open my app when this success block executed? Or can I override default buttons on caller screen to open my app?
I know there is no way to open an app on receiving any kind of notification, or event trigger. So thought may be there is some way if I can do the same using Callkit
I Googled everything but found no clue regarding my above queries. Please help me if it is possible or not.
I encountered the same issue. The behavior varies depending on if the device is locked or not.
Locked: System calling screen appears. You can run the app in the background including view transitions. However, the user will only see the system calling screen although your app is kind of presented underneath the view. As the device is locked, deep links does not work as well.
Unlocked: Calling screen is the same but once the user answers the call, the app will be presented.
As you may know, we can change the icon of the button on the calling screen which opens the app, and that's the best we can do as of now.
You can not open your own VoIP app or custom UI of your App from CallKit. Use can use it in a way as Whatsapp does.
Means you can awake your app from background without using local notification. And OS will show the default incoming screen. You need not to handle anything during call. CallKit is specially made for enhancing VoIP apps by receiving calls in background, by making outgoing calls, by managing Call directory and blocking of users.
I currently have an ionic app, which uses the following plugin: https://github.com/jeduan/cordova-plugin-facebook4 so that users can login to my app using the Facebook SDK, and so that I can track certain custom events, using the logEvent method.
Since it is an ionic app, I have a iOS and an Android build of the app. The custom events are working as expected on the Android platform. The strange thing is that in iOS, when an event is fired, I can clearly see the success event handler being called, indicating success, however, going to the Facebook analytics, I can clearly see that no custom event data is being saved. It tracks the usual app opens etc, it's just that custom events don't seem to be getting recorded for iOS.
Just to be clear any of this logging happens after the user has already logged in, I have heard it only works for iOS if you are authenticated with FB first.
So I have a generic function first:
$scope.fbLogEvent = function(eventName, params, valueToSum) {
if (valueToSum == null) {
valueToSum = 1;
}
if (!ionic.Platform.is('browser')) {
return facebookConnectPlugin.logEvent(eventName, params, valueToSum, function(success) {
return console.info('FB', eventName, 'event has been logged');
}, function(error) {
return console.error(error);
});
}
};
I then call the following function to do the actual tracking
$scope.fbLogEvent('item-requested', { item: $scope.item });
It works perfectly on Android
When I add an item on iOS (using Safari developer logging on the app running on my phone), I can see that the success function is called, because it logs the following message: FB item-requested event has been logged.
I have tested this with the latest version of the plugin (just to be sure), but that did not seem to make a difference.
UPDATE 3/3/2017 - for what it's worth, it does seem to pickup these events if they predefined events, as opposed to custom events.
I am using iOS 6 Game Center API for turn based games.
When the device is disconnected from internet
In the completion handler of the method
[currentMatch endTurnWithNextParticipant:nextParticipant matchData:data completionHandler:^(NSError *error) {
if (error) {
NSLog(#"%#", error);
} else {
//save the new state of the game
}
I get an error. But then, game center standard UI that displays matches list, says "Their turn". when connected again it changes to "Your turn".
The code from famous tutorial at http://www.raywenderlich.com/5509/beginning-turn-based-gaming-with-ios-5-part-2 has the same exact problem.
How I should handle this problem?
If you are using iOS 6 Game Center API then you will have to use
-endTurnWithNextParticipants:turnTimeout:matchData:completionHandler:
because...
–endTurnWithNextParticipant:matchData:completionHandler: Deprecated in iOS 6.0
http://developer.apple.com/library/ios/#documentation/GameKit/Reference/GKTurnBasedMatch_Ref/Reference/Reference.html
The thing is, that when you use GC methods that change status of the match (matchData and synchronization info in this case), data is uploaded to the GC server so that other player(s) get the update. If you're disconnected and ignore the error, your local GKTurnBasedMatch and its matchData change, as well as your synchronization info (which is used to determine if it is your turn to act among other things).
However, since you are diconnected, only your local instance of GCTurnBasedMatch is updated (you get error so that you app is aware of that). When you're reconnected, your app authenticates the user and updates match state (if you're following the tutorial code). Updating match data reverts the sync data (so it's still your turn).
At this point, you should either submit the turn again (provided that you cached gameData that was passed to GC while you were disconnected) and/or call updateMatchData so that your local GKTurnBasedMatch and its matchData get in sync with what's on the server. You should also re-layout your game board with previous turn's data if you didn't re-submit turn after reconnection.
The following code is called once upon applicationDidFinishLaunching:; however, it runs each time my app re-enters the foreground again.
[localPlayer authenticateWithCompletionHandler:^(NSError *error) {
if (localPlayer.isAuthenticated)
{
// Some implementation
}
}];
This makes sense, according to the Game Kit Programming Guide:
... it also retains your completion handler for later use. Each time your application is moved from the background to the foreground, Game Kit automatically authenticates the local player again on your behalf and calls your completion handler to provide updated information about the state of the authenticated player.
Is there any way to delay this authentication until Game Center is actually needed? The reason I ask is that I would like to avoid showing the "Welcome back, userX!" banner each and every time the app is brought to the foreground.
No, you can't, at least not with public APIs.