CallDirectory Extension beginRequestWithExtensionContext not called - ios

I'm trying to add the CallDirectory extension to enable the call identification based on the contacts available in my app.
I have enabled the permissions under Call settings.
But beginRequestWithExtensionContext is not called even when the device receives the call.
beginRequestWithExtensionContext is in the subclass of CXCallDirectoryProvider which conforms to CXCallDirectoryExtensionContextDelegate
The documentation says:
You set up both identification and blocking of incoming calls in the
implementation of the beginRequest(with:) method of the
CXCallDirectoryProvider subclass of your Call Directory extension.
This method is called when the system launches the app extension.
When does the system launches the app extension ?
I setup it as following in my delegate:
[[CXCallDirectoryManager sharedInstance] getEnabledStatusForExtensionWithIdentifier:#"com.x.CallerID" completionHandler:^(CXCallDirectoryEnabledStatus enabledStatus, NSError * _Nullable error) {
if (enabledStatus == 0) {
// NSLog(#"Code 0 tells you that there's an error. Common is that the identifierString is wrong.");
} else if (enabledStatus == 1) {
DDLogDebug(#"%#",#"CallerID - Code 1 is deactivated extension");
[self enableCallerIdAlert];
} else if (enabledStatus == 2) {
DDLogDebug(#"%#",#"CallerID - Code 2 is an activated extension");
}
}];
[[CXCallDirectoryManager sharedInstance] reloadExtensionWithIdentifier:#"com.x.CallerID" completionHandler:^(NSError *error){
if(error) {
NSLog(#"CallerID - refresh failed. error is %#",[error description]);
}
//your completetion
}];
CallDirectoryHAndler.m:
- (void)beginRequestWithExtensionContext:(CXCallDirectoryExtensionContext *)context
{
[super beginRequestWithExtensionContext:context];
context.delegate = self;
//phoneNumber , label are dummy
[context addIdentificationEntryWithNextSequentialPhoneNumber:phoneNumber label:label];
[context completeRequestWithCompletionHandler:nil];
}
Could someone please point out What I'm missing here?

Related

webview stays open after successful facebook log in with azure sdk

I'm utilizing the facebook log in from Azure SDK, I'm utilizing the following code in a button:
-(void)fblogin
{
[_azureService.client loginWithProvider:#"facebook" urlScheme:#"dribel" controller:self animated:YES completion:^(MSUser * _Nullable user, NSError * _Nullable error)
{
if (error)
{
NSLog(#"Login failed with error: %#, %#", error, [error userInfo]);
}
else
{
_azureService.client.currentUser = user;
NSLog(#"User logged in: %#", user.userId);
[self fblogin];
}
}];
}
A webview like this, opens and does all the facebook log in process...
And when it ends, it calls the following method in the app delegate and since it's true, it resumes the log in flow...
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
if ([[url.scheme lowercaseString] isEqualToString:#"dribel"])
{
// Resume login flow
return [self.azureService.client resumeWithURL:url];
}
else {
return NO;
}
}
but the webview is supposed to be dismissed and after being dismissed the code is supposed to land on the else statement of the first piece of code, but it's not doing anything. I have to press done and lands on the if true statement and it says I canceled it. Does anyone has an idea of what could be wrong?
We have set up the external url in the azure portal to redirect to the correct appname:// so that's why it we get true in the app delegate. But what else is missing?

GKMatchmaker findMatchForRequest invite never received

I'm trying to invite nearby players to a match, but the invite is either never sent or never received.
GKMatchMaker startBrowsingForNearbyPlayersWithHandler works and returns nearby players that are on same wifi, but then I use findMatchForRequest and it returns a match without any players, and the players I try to invite never receive an invite notification. Here is my code.
I start by authenticating the local player:
GKLocalPlayer.localPlayer.authenticateHandler= ^(UIViewController *controller, NSError *error)
{
if (error)
{
NSLog(#"%s:: Error authenticating: %#", __PRETTY_FUNCTION__, error.localizedDescription);
return;
}
if(controller)
{
// User has not yet authenticated
[pViewController presentViewController:controller animated:YES completion:^(void)
{
[self lookForNearbyPlayers];
}];
return;
}
[self lookForNearbyPlayers];
};
-(void)lookForNearbyPlayers
{
if(!GKLocalPlayer.localPlayer.authenticated)
{
NSLog(#"%s:: User not authenticated", __PRETTY_FUNCTION__);
return;
}
I register my view controller as a delegate of GKLocalPlayerListener:
[GKLocalPlayer.localPlayer registerListener:self]; // self is a view controller.
// This works. My test local player which is a second device and appleID I setup shows up when this handler is called.
[GKMatchmaker.sharedMatchmaker startBrowsingForNearbyPlayersWithHandler:^(GKPlayer *player, BOOL reachable)
{
NSArray * paPlayers= [NSArray arrayWithObject:player];
_pMatchRequest= [[GKMatchRequest alloc] init];
_pMatchRequest.minPlayers= 2;
_pMatchRequest.maxPlayers= 4;
_pMatchRequest.recipients = paPlayers;
_pMatchRequest.inviteMessage = #"Join our match!";
_pMatchRequest.recipientResponseHandler = ^(GKPlayer *player, GKInviteeResponse response)
{
// This is never called.
NSLog((response == GKInviteeResponseAccepted) ? #"Player %# Accepted" : #"Player %# Declined", player.alias);
};
// This returns with a match without any players.
[GKMatchmaker.sharedMatchmaker findMatchForRequest:_pMatchRequest withCompletionHandler:^(GKMatch *match, NSError *error)
{
if(error)
{
NSLog(#"%s:: %#", __PRETTY_FUNCTION__, error.localizedDescription);
return;
}
else if(match != nil)
{
_pMatch= match;
match.delegate = self;
NSLog(#"players count= %lu", (unsigned long)_pMatch.players.count); // Always returns 0
}
}];
}
}
I have delegate methods for GKLocalPlayerListener setup, but they are never called:
- (void)player:(GKPlayer *)player didRequestMatchWithRecipients:(NSArray<GKPlayer *> *)recipientPlayers
{
NSLog(#"%s", __PRETTY_FUNCTION__);
}
- (void)player:(GKPlayer *)player didAcceptInvite:(GKInvite *)invite
{
NSLog(#"%s", __PRETTY_FUNCTION__);
}
Does anyone know how to get this to work without GKMatchmakerViewController and for iOS9? The only examples I can find have the deprecated -inviteHandler method.
This code is working in Swift if you know how you can convert it to Objective-C and to try it.
GKMatchmaker.sharedMatchmaker().findMatchForRequest(
request,
withCompletionHandler: {(match : GKMatch!, error: NSError!) -> Void in
NSLog("This works")
})
Based on multiple questions here on SO, Game Center seems to be getting stuck from time to time. In the best case, it returns "Game not recognized" errors. In the worst case, it just cheerfully returns nil to GC calls. Sometimes it resumes working on it's own, sometimes it doesn't. But it seems you can kickstart it again by logging into iTunesConnect and do any of the following:
Add a leaderboard
Change the default leaderboard
Add an achievement
I've added this to my debugging routine. If some aspect of GC stops working, or returns nil, I try making one of the above changes in iTunesConnect before proceeding. In my case, I get the "game not recognized" several times per week, but several others have noted the "nil return values."
I know this an older post, but I ran across it when trying to establish a connection between several app instances over the internet. I believe the part you're missing is that after registering for the listener, you need to receive the connected status with
- (void)match:(GKMatch *)match
player:(GKPlayer *)player
didChangeConnectionState:(GKPlayerConnectionState)state
{
NSLog(#">>> did change state");
if (state == GKPlayerStateConnected)
{
NSLog(#">>>> match:%# did change to Connected for player %# ",match, player.displayName);
}
else if (state == GKPlayerStateDisconnected)
{
NSLog(#">>>> match:%# disconnected for player %# ",match, player.displayName);
}
I find the match has 0 players when the completionHandler is called from findMatchForRequest:, but that I can successfully use the GKMatch and GKPlayer as returned in didChangeConnectionState:
Hope that helps someone who reads this long after the OP.

openParentApplication:reply: error with asynchronous network call in containing app

I'm getting stuck with an error when using my Watchkit Application. When I launch it, I ask the containing iOS app to get some data from network. The problem is that I get an error saying the containing app never calls 'reply()' :o But looking at my code, it should call it.
I tried to debug every step from openParentApplication to the 'reply()' call, and it seems to work well =X
Here is my code in the Watchkit extension
- (void)initDiaporamasWithSuccess:(void (^)())success andFailure:(void (^)(NSError*))failure {
NSLog(#"Ask to load diapos");
__weak typeof(self) weakSelf = self;
[WKInterfaceController openParentApplication:#{#"watchKit": #"watchKit.initDiapos"} reply:^(NSDictionary *replyInfo, NSError *error) {
if (error) {
NSLog(#"%#", error);
if (failure) {
failure(error);
}
return;
}
NSLog(#"got items : %#", replyInfo[#"diapos"]);
weakSelf.diaporamas = replyInfo[#"diapos"];
[weakSelf setDiaporama:replyInfo[#"firstDiapo"] AtIndex:0];
if (success) {
success();
}
}];
}
The result should be an NSDictionary containing an NSArray with some diaporamas basic informations, and an object (Diapo) containing the full informations of the first diaporama (e.g. self.diaporamas[0])
And here is the code in the containing app's AppDelegate :
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply {
// Maybe we could handle multiple watchKit extension calls that way ?
// Something like a key-value 'protocol' to run the right block of code
NSString *watchKitCall = userInfo[#"watchKit"];
NSLog(#"watchKit handled");
if ([watchKitCall isEqualToString:#"watchKit.initDiapos"]) {
[AppDelegate watchInitialObjects:^(NSDictionary *info) {
NSLog(#"Managed to get initial infos");
reply(info);
} failure:^(NSError *error) {
NSLog(#"Fail : %#", error);
reply(#{#"error": error});
}];
}
}
+ (void) watchInitialObjects:(void (^)(NSDictionary *info))success failure:(void (^)(NSError *error))failure {
NSDictionary *parameters = #{#"site" : #(14), #"limit" : #(10)};
[AppDelegate requestDiapoListWithParams:parameters success:^(NSArray *items) {
if ([items count] == 0)
{
NSError *error = [NSError errorWithDomain:#"com.domain.app" code:404 userInfo:nil];
failure(error);
return;
}
Diapo *firstDiapo = [items firstObject];
[AppDelegate requestDiapoDetailWithDiapo:firstDiapo success:^(Diapo *diapo) {
if (!diapo)
{
NSError *error = [NSError errorWithDomain:#"com.domain.app" code:404 userInfo:nil];
failure(error);
return;
}
NSDictionary *result = #{
#"firstDiapo" : diapo,
#"diapos" : items
};
success(result);
} failure:^(NSError *error) {
failure(error);
}];
} failure:^(NSError *error) {
failure(error);
}];
}
In the watchKitHandler, I call watchInitialObjects to get the diaporamas array and the first diaporama's informations.
In the watchInitialObjects, I make a first network call to get the array, and on success, I make an other network call to get the firs diaporama informations.
To make the calls and map the JSON into objects, I use RESTKit
I really don't get what could be the error =x
UPDATE
I forgot to write the error I get, here it is :
Error Domain=com.apple.watchkit.errors Code=2 "The UIApplicationDelegate in the iPhone App never called reply() in -[UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:]" UserInfo=0x7fcb53e12830 {NSLocalizedDescription=The UIApplicationDelegate in the iPhone App never called reply() in -[UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:]}
And I kept trying to know why I get this error, and I think I found it:
It seems that there is a (very little) timeout to do the work in the containing app. But I mapped the JSON data I received directly in the containing app and then, send those custom objects in the reply(). But when I removed the mapping part, it worked well !
So...that's why I think that was the problem =X
Does anybody could approve my thoughts or corrects me ?
After hours of searching and testing different codes, I finally found my problem...and it's obvious when we read the Apple documentation about 'application:handleWatchKitExtensionRequest:reply:' seriously...
here is the answer : (it's in the documentation)
The contents of the dictionary must be serializable to a property list file.
Which means that objects can ONLY be dictionaries, arrays, strings, numbers (integer and float), dates, binary data, or Boolean values
...I feel dumb ><

HMAccessoryDelegate Method not called

I want to get value of updatable characteristics for particular accessory.
So I am using func accessory(accessory: HMAccessory!, service: HMService!, didUpdateValueForCharacteristic characteristic: HMCharacteristic!) method.
But this method is not called. Another method from same delegate is being called. What should be the problem?
Enabled notification for the characteristic in viewWillAppear.
for (HMCharacteristic *thisCharacteristic in characteristicsArray) {
if ([thisCharacteristic.properties containsObject:HMCharacteristicPropertySupportsEventNotification]) {
[thisCharacteristic enableNotification:TRUE completionHandler:^(NSError *error) {
if (error) {
NSLog(#"Error while enabling notification");
}
else {
NSLog(#"Notification enabled");
}
}];
}
Also Disable the notification in viewWillDisappear

SoundCloud API Login

I'm having trouble with the authentication part of the SoundCloud API. I am following the tutorial located here: http://developer.soundcloud.com/docs/api/ios-quickstart#authentication
I follow their code as written and it runs/compiles, but doesn't authenticate. When requesting a login from the following bit of code:
(IBAction) login:(id) sender
{
SCLoginViewControllerCompletionHandler handler = ^(NSError *error) {
if (SC_CANCELED(error)) {
NSLog(#"Canceled!");
} else if (error) {
NSLog(#"Error: %#", [error localizedDescription]);
} else {
NSLog(#"Done!");
}
};
[SCSoundCloud requestAccessWithPreparedAuthorizationURLHandler:^(NSURL *preparedURL) {
SCLoginViewController *loginViewController;
loginViewController = [SCLoginViewController
loginViewControllerWithPreparedURL:preparedURL
completionHandler:handler];
[self presentModalViewController:loginViewController animated:YES];
}];
It returns with a console error of:
2013-12-26 16:11:23.902 SampleProject[14748:4717] -[NXOAuth2PostBodyStream open]
Stream has been reopened after close
2013-12-26 16:11:24.198 SampleProject[14748:70b] Done!
And then subsequent calls to [SCSoundCloud account] return nil.
During use of the app, the login views appear and I appear to have logged in successfully, but no account appears to have been saved / registered. Any advice?
Also, my initialization function with clientID / section / redirectURL are as directed in the tutorial and the app is registered.
Have a look at NXOAuth2Account.m where the user's client ID, client secret etc. are used to create the oauthClient.
You can also find in this file a method called description that should return everything you need to re-authenticate the user should you want to do so:
- (NSString *)description;
{
return [NSString stringWithFormat:#"<NXOAuth2Account identifier:'%#' accountType:'%#' accessToken:%# userData:%#>", self.identifier, self.accountType, self.accessToken, self.userData];
}

Resources