watchOS Send Message not getting called - ios

Hi I'm having an issue with my code it looks like send message isn't getting called for some reason, thanks
if ([[WCSession defaultSession] isReachable]) {
NSLog(#"Initiating WCSession to Read iPhone Data");
[[WCSession defaultSession] sendMessage:watchData replyHandler:^(NSDictionary *dataFromPhone) {
NSLog(#"Sending Empty Write Data Array to iPhone...%#", watchData);
}
errorHandler:^(NSError *error) {
// Log error
NSLog(#"Error: %#", error);
}];
} else {
//we aren't in range of the phone, they didn't bring it on their run
NSLog(#"Unable to connect to iPhone");
}

From what I see this is the code that runs on iOS, which controls whether the Apple Watch is reachable, but you have to remember (if you have not done of course) to enable the session from either device with the following code, so enable the communication system
if (WCSession.isSupported()) {
let session = WCSession.defaultSession()
session.delegate = self
session.activateSession()
}

Related

CallDirectory Extension beginRequestWithExtensionContext not called

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?

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.

OpenTok Session Delegate Callback Has nil Connection

I'm using OpenTok to create a video conference between 2 iOS devices. I want to send information about a user (i.e. a userID) to the other member of the conference so once I get the callback that a user is connected, I send that connection that information:
//Start Call - Session is already created with a valid session ID.
-(void) startCall{
OTError* error = nil;
self.session connectWithToken:myToken error:&error];
if (error){
NSLog(#"Session signal Error: %#", error);
}
}
//Session delegate methods
– (void) session:(OTSession*) session connectionCreated:(OTConnection*) connection{
OTError* error = nil;
[session signalWithType:#"UserInfo" string:self.user.userID connection:connection error:&error];
if (error){
NSLog(#"Session signal Error: %#", error);
}
}
-(void) session:(OTSession*) session receivedSignalType:(NSString*) type fromConnection:(OTConnection*) connection withString:(NSString*) string{
if ([type isEqualToString:#"UserInfo"]){
self.remoteUser.userID = string;
}
}
The problem is that in some cases, the OTConnection I bet back in the – session:receivedSignalType:fromConnection:withString: is nil. Not only that but when I put a breakpoint in that callback my local session's connection is also nil. I assume this means that my local session is not connected yet when I receive that signal but I wouldn't have thought it was possible to receive a signal if my local session is not connected. Additionally I don't send the signal until the connection is created, so how is it nil on the other device?
Has anyone else seen this or come up with a way to prevent it?
Thanks for any help.

how can I use WCSessionUserInfoTransfer in watchos?

is anywhere a simple tutorial, how I can use the WCSessionUserInfoTransfer to change data between my watch and iOS ?
And what must be written in the delegate of the iOS -App?
in my old programming I used:
[WKInterfaceController openParentApplication:#{#"Kommando":#"Radius"} reply:^(NSDictionary *replyInfo, NSError *error) {
if (error) {
NSLog(#"Error from parent: %#", error);
} else {
NSLog(#"Radius from parent: %#", [replyInfo objectForKey:#"Radius"]);
}
}];
The first thing you need to do is to define a WCSession. This must be defined and activated in every class that you're planning on transferring data to and receiving data from. To use WCSession, make sure it's supported, and then activate the default session as shown below.
#import <WatchConnectivity/WatchConnectivity.h>
if ([WCSession isSupported]) {
WCSession *session = [WCSession defaultSession];
session.delegate = self;
[session activateSession];
}
From here, you can use transferUserInfo where ever you need to send data (from the watch or the iOS app):
[[WCSession defaultSession] transferUserInfo:#{#"Kommando":#"Radius"}];
On the receiving end, you would use session:didReceiveUserInfo. Note that this does NOT need to be in the app delegate anymore on the iOS app side, unlike handleWatchKitExtensionRequest. You can use this where ever you need to receive the data. Make sure to activate WCSession, as shown above, in the class where you have didReceiveUserInfo also.
- (void)session:(nonnull WCSession *)session didReceiveUserInfo:(nonnull NSDictionary<NSString *,id> *)userInfo {
NSLog(#"Radius from parent: %#", [userInfo objectForKey:#"Radius"]);
}

Can´t receive AppMessage from Pebble on iOS

On the Watch i send an AppMessage like this
DictionaryIterator *iter;
app_message_outbox_begin(&iter);
Tuplet value = TupletInteger(MESSAGE_TYPE, MESSAGETYPE_REFRESH);
dict_write_tuplet(iter, &value);
app_message_outbox_send();
I set the background modes and protocols for my app as described in the tutorial.
In iOS i set the listeners like this:
[PBPebbleCentral defaultCentral].delegate = self;
self.watch = [PBPebbleCentral defaultCentral].lastConnectedWatch;
NSLog(#"Pebble name: %#", _watch.name);
NSLog(#"Pebble serial number: %#", _watch.serialNumber);
[_watch appMessagesAddReceiveUpdateHandler:^BOOL(PBWatch *watch, NSDictionary *update) {
NSLog(#"Update received!");
return YES;
}];
[_watch appMessagesAddReceiveAllUpdatesHandler:^BOOL(PBWatch *watch, NSUUID *uuid, NSDictionary *update) {
NSLog(#"AllUpdate received!");
return YES;
}];
[_watch appMessagesAddAppLifecycleUpdateHandler:^(PBWatch *watch, NSUUID *uuid, PBAppState newAppState) {
NSLog(#"AppLifecycleUpdate received!");
}];
I already did send messages from the phone to the watch. So that way it works. But the listeners for incoming messages on the phone wont get called.
On the clock i get APP_MSG_SEND_TIMEOUT as error code. What did i wrong?
Do you have src/js/pebble-js-app.js in your watch app? I had the same problem and when i removed this generated file it started working.
Check to make sure you are using
appMessagesAddReceiveUpdateHandler:withUUID:
instead of
appMessagesAddReceiveUpdateHandler:
Pay attention to where you put the listener. For example if you are using the WeatherDemo app (provided by Pebble) you should do that after setting the the app UUID.
// Test if the Pebble's firmware supports AppMessages / Weather:
[watch appMessagesGetIsSupported:^(PBWatch *watch, BOOL isAppMessagesSupported) {
if (isAppMessagesSupported) {
...
[_targetWatch appMessagesAddReceiveUpdateHandler:^BOOL(PBWatch *watch, NSDictionary *update) {
NSLog(#"Received message: %#", update);
return YES;
}];
} else {
....
Another thing to pay attention is not to put it under
- (void)pebbleCentral:(PBPebbleCentral*)central watchDidConnect:(PBWatch*)watch isNew:(BOOL)isNew
because this function isn't called if the device is already connected.

Resources