I have created a smaller project for Apple watch to communicate with it’s parent application it’s worked.
So I have created a Watch kit extension in my existing iOS project but when from Watch side it call openparent application in reply block it receives
“Error: Error Domain=FBSOpenApplicationErrorDomain Code=5 "The operation couldn’t be completed. (FBSOpenApplicationErrorDomain error 5.)”.
What does this error means? Is there any target issue? Please find the code below:
Watch kit side :
- (IBAction)satusButtonClicked {
NSLog(#"StausButtonClicked");
NSDictionary *senddict=[[NSDictionary alloc] initWithObjects:#[#"5",#"Two",#"Three"] forKeys:#[#"1",#"2",#"3"]];
[InterfaceController openParentApplication:senddict reply:^(NSDictionary *replyInfo, NSError *error) {
NSLog(#"ReplyReceived : %lu",(unsigned long)[replyInfo count]);
NSLog(#"Reply Info: %#", replyInfo);
NSLog(#"Error: %#", error);
}];
}
iOS side :
-(void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply
{
NSLog(#"Watckit call received");
reply(#{#"Score": #"234"});
In the info.plist, I had "Application Does Not Run in Background" set to YES. This caused the problem. Changing that setting to NO fixed it.
Answered from here:
iOS Error: FBSOpenApplicationErrorDomain error 5. What does this mean?
Related
I am Using Firebase phone number login authentication All things are perfect
1) Provisioning profile
2) certificate
3) Signing methods Enable
4) Project setting with .12 file
5) everything should perfect
Issue
When I send mobile number for the OTP using thins method using this code
NSString *phoneNumber = #"+919428936703";
[[FIRPhoneAuthProvider provider]
verifyPhoneNumber:phoneNumber
completion:^(NSString * verificationID,
NSError * error) {
NSLog(#"VARIFICATION CODE %#", verificationID);
NSLog(#"Error %#", error);
if (!error){
}else{
}
}];
Also get call methods
- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
// Pass device token to auth.
[[FIRAuth auth] setAPNSToken:deviceToken type:FIRAuthAPNSTokenTypeSandbox];
}
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)notification
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
NSLog(#"DATA OF AUTH %#", [FIRAuth auth]);
if ([[FIRAuth auth] canHandleNotification:notification]) {
NSLog(#"Handle by Firebase ");
completionHandler(UIBackgroundFetchResultNoData);
return;
}else{
NSLog(#"NOT HANDLE BY FIREBASE %#", notification);
}
}
but then after getting a crash with this error log
-[__NSCFString setFir_authPhoneNumber:]: unrecognized selector sent to instance 0x166388b0
It looks like you're not linking your app with -ObjC linker flag, which is part of the instructions for Integrate without CocoaPods.
setFir_authPhoneNumber: is implemented as a category, thus -ObjC linker flag must be used or the compiled .o from the library won't be linked into your app binary.
Im getting the following error when sending a message from Apple Watch to device
Error Domain=WCErrorDomain Code=7012 "Message reply took too long."
UserInfo={NSLocalizedDescription=Message reply took too long.,
NSLocalizedFailureReason=Reply timeout occured.}
#import <WatchConnectivity/WatchConnectivity.h> is in both watch and main app targets, and conforms to delegate methods on both watch and device
SEND MESSAGE FROM WATCH TO DEVICE
Session confirmed as Available
Session confirmed as Reachable
NSDictionary *applicationDict = [[NSDictionary alloc] initWithObjects:#[#"SomethingHere"] forKeys:#[#"valueKey"]];
if([[WCSession defaultSession] isReachable]) {
NSLog(#"Reachable"); //<---- Console shows reachable
[[WCSession defaultSession] sendMessage:applicationDict
replyHandler:^(NSDictionary *reply) {
NSLog(#"%#",reply);
}
errorHandler:^(NSError *error) {
NSLog(#"%#",error); //<--- returns error
}];
}
DEVICE
In appdelegate didFinishLaunching
// Watch kit session
if ([WCSession isSupported]) {
WCSession *session = [WCSession defaultSession];
session.delegate = self;
[session activateSession];
NSLog(#"\n\n - WatchKit Session Started - \n\n");
}
else{
NSLog(#"WatchKit Session Error");
}
Session confirmed as starting as expected
Receiving Message On Device
- (void)session:(nonnull WCSession *)session didReceiveMessage:(nonnull NSDictionary<NSString *,id> *)message replyHandler:(nonnull void (^)(NSDictionary<NSString *,id> * __nonnull))replyHandler {
NSLog(#"Data delagte");
dispatch_async(dispatch_get_main_queue(), ^{
resultFromWatch = [message objectForKey:#"resultDataValue"];
});
}
Update:
- (void) session:(nonnull WCSession *)session didReceiveApplicationContext:(nonnull NSDictionary<NSString *,id> *)message {
dispatch_async(dispatch_get_main_queue(), ^{
});
}
Stops the error message received as per ccjensen comment
Check these things:
1/ Make sure to implement the WCSessionDelegate properly on the phone side. (No idea if and/or how much you implemented so far)
In particular, make sure you implemented session(_:didReceiveMessage:replyHandler:).
2/ Make sure that you actually call the replyHandler in the WCSessionDelegate as highlighted in the doc: "You must execute the reply block as part of your implementation." WCSessionDelegate Protocol Reference
3/ Once you've checked these, make sur you run the latest version of the iPhone app before re-trying with the watch.
If these don't work, then it means your WCSessionDelegate implementation is too slow and therefore times out or you get a good old fashion network issue between the watch and the phone (unlikely in the sim, but bugs are possible).
Hope this helps.
Edit:
I missed to mention, that the counter part app must be active for it to respond. It means, the iPhone app must be at least in the background (launched once) for it to respond.
If it isn't, and after a while you will get a timeout.
Make sure you set WCSession delegate before you active the session.
HI i want to implement sample application on watch kit app. i want to show some information of parent application , which is running in iphone, now i want to get data in watch kit app from preform action from button click on watch kit . i have used delegate method for background communication with extension app but Am getting same error when i print error in
[InterfaceController openParentApplication:dict reply:^(NSDictionary *replyInfo, NSError *error)
{
NSLog(#"%#",[replyInfo objectForKey:#"Key"]);
NSLog(#"error:-%#",[error description]);
}
Getting the Error ....
Error: Error Domain=com.apple.watchkit.errors Code=2 "The UIApplicationDelegate in the iPhone App never called reply() in -[UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:]" UserInfo=0x7f8603227730 {NSLocalizedDescription=The UIApplicationDelegate in the iPhone App never called reply() in -[UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:]}
please suggest how can i get data in watch app from extention app.
Thanks in Advance.
In my watch app, I want to setup my mapview, so I ask my app for a location.
- (void)awakeWithContext:(id)context {
[super awakeWithContext:context];
// Configure interface objects here.
[WKInterfaceController openParentApplication:#{} reply:^(NSDictionary *replyInfo, NSError *error) {
if (replyInfo) {
[self.map setRegion:MKCoordinateRegionMake(CLLocationCoordinate2DMake([replyInfo[#"lat"] doubleValue], [replyInfo[#"lon"] doubleValue]), MKCoordinateSpanMake(0.05, 0.05))];
}
}];
}
Then I put back location from my app delegate:
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply
{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"http://www.google.com"]];
reply(#{#"lat": #"22.3175899",#"lon": #"114.2212058"});
}
How to open up the contacts of iPhone programmatically in watch extension as we do in iOS using AddressBook.
Thanks in advance
In general to communicate with iPhone from your WatchKit extension you use
+ (BOOL)openParentApplication:(NSDictionary *)userInfo reply:(void(^)(NSDictionary *replyInfo, NSError *error)) reply; // launches containing iOS application on the phone. userInfo must be non-nil
method of WKInterfaceController class.
So for example, you can attach IBAction from your button in Storyboard to this method
- (IBAction)callPhoneAppButtonTapped
{
NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys:#"text to display on iPhone", #"key", nil];
[InterfaceController openParentApplication:dictionary reply:^(NSDictionary *replyInfo, NSError *error) {
NSLog(#"Reply received by Watch app: %#", replyInfo);
}];
}
Note: In order to fetch data from Address Book user needs to grant your app permission. But app will be launched in background and user will be focused on Watch so it will be better to ask for this permission in your iPhone app.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
ABAddressBookRequestAccessWithCompletion(ABAddressBookCreateWithOptions(NULL, nil), ^(bool granted, CFErrorRef error) {
if (!granted){
NSLog(#"Access denied");
return;
}
NSLog(#"Access granted");
});
}
In order to handle message sent by openParentApplication:reply in your AppDelegate implement
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply
{
NSLog(#"Request received by iOS app");
NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys:#"your value to return to Apple Watch", #"key", nil];
// Here your app will be launch in background. Fetch AddressBook or other data you need.
// Remember to call reply block in the end.
// Example of saving data to Address Book
NSString *firstName;
NSString *lastName;
firstName = #"Maggie";
lastName = #"Peggie";
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, nil);
ABRecordRef contact = ABPersonCreate();
ABRecordSetValue(contact, kABPersonFirstNameProperty, (__bridge CFStringRef) firstName, nil);
ABRecordSetValue(contact, kABPersonLastNameProperty, (__bridge CFStringRef)lastName, nil);
ABAddressBookAddRecord(addressBookRef, contact, nil);
ABAddressBookSave(addressBookRef, nil);
reply(dictionary);
}
While the current versions of Apple Watch apps cannot themselves execute code, your WatchKit Extension runs on the phone and can access all of the iPhone APIs that a standard iOS application can. As developers, we are much more limited in how we can programmatically change the interface, but not in what is done in terms of accessing services.
Therefore, there is no technical requirement to access Address Book data via your iOS app—you could make these requests for Address Book data directly. If these methods execute rapidly, the choice of whether to do this directly in the Extension or in your iPhone app would come down to decisions about what would minimise code complexity and thus maximise code maintainability. Apple have indicated that latency in communication between the iPhone app and WatchKit Extension can largely be ignored as it will be trivial. (It is latency between the Extension, running on the phone, and the Watch app that we need to be focussed on.)
However, we have also been told that WatchKit Extensions may be immediately terminated when Watch apps are, and we need to be prepared for engagement time measured in seconds, not minutes. WatchKit Extensions are not given the kind of latitude that iPhone apps are to complete things in the background after the user interface has terminated. Therefore, the recommendation is that anything that may be more time consuming or which needs to be completed for data integrity should be run in the iPhone app. lvp's answer gives code that could assist with that.
Your app runs on the phone, so you can fetch the contacts and send it to watch
I am newbie to iphone technology,right now i m working with an application where i need to implement push notification.
I followed the link :
http://mobiforge.com/developing/story/programming-apple-push-notification-services#comment-7850
Also,Used the following code :
NSLog(#"Registering for push notifications...");
[[UIApplication sharedApplication]
registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeAlert |
UIRemoteNotificationTypeBadge |
UIRemoteNotificationTypeSound)];
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
NSString *str = [NSString stringWithFormat:#"Device Token=%#",deviceToken];
NSLog(str);
}
- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err
{
NSString *str = [NSString stringWithFormat: #"Error: %#", err];
NSLog(str);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
for (id key in userInfo)
{
NSLog(#"key: %#, value: %#", key, [userInfo objectForKey:key]);
}
}
Thing is,when i run the program,i should get device token in the debugger window,as per the code,instead i am getting error like :
" Error in registration. Error: Error
Domain=NSCocoaErrorDomain Code=3010
"remote notifications are not
supported in the simulator"
UserInfo=0x6e055a0
{NSLocalizedDescription=remote
notifications are not supported in the
simulator} "
How should i solve this problem?
Kindly help me out.
Thank you.
Because the simulator doesn't support it... In the example it displays the device identifier in the console. The console is displaying the feedback from the device. It isn't the console that is getting the information, but the device sending the information back. So, just because the console displays information on your Mac doesn't mean your Mac is capable of directly getting that information. Sometimes it must be sent by the device. Try running it on a device.
The error message is self explaining, you should try to debug the app on real device not on the simulator, as push notifications are not supported to be received on the simulators.