Text reply after watchOS notification is failing only when the corresponding app is installed on the watch - ios

I have an iOS9 app with a watchKit 1.0 Extension. Most functionality is working fine. One of the main features of the app is a private messaging feature, which is also working great.
I'm using UIUserNotificationActionBehaviorTextInput for iOS9+ devices so that when a user receives a notification on their watch, they will be able to use the built in reply feature.
This works great, but only if the watchKit app is NOT installed on the watch. Users are able to reply to a notification on their watch with canned responses, or dictate a response with no problems. Note, this does NOT launch the watchKit app - it just uses the built-in reply functionality of the watch.
When the watchKit app IS installed on the watch, the "Message" and "Dismiss" buttons appear as expected. But as soon as someone clicks the Message button, instead of being able to tap or dictate a response, it just immediately goes back to the watch face.
It is 100% reproducible using two separate sets of an iPhone 6 running iOS9.1 and Apple Watch running watchOS 2.0.1. Since notifications can't be tested in the simulator, this is a very difficult problem to troubleshoot.
I could really use some guidance in what steps to take next.

Related

WatchOS app not detecting companion iOS app

I am making an independent Apple Watch app (but with a companion iPhone app which is not necessary for the watch app to function.)
The app uses WatchConnectivity to sync data between devices if iPhone companion app is installed. I am able to call session.updateApplicationContext() on the iOS app and receive session(didReceiveApplicationContext) on the Watch app. But going the other way is not possible. I always get an NSError code of 7018 which means the iOS companion app is not installed.
I have made sure both watchOS and iOS app are installed in simulator (and tested on my actual devices, iPhone 11 & Watch series 5.) But getting the same failed results from watchOS -> iOS.
I noticed there is a new WCSession instance variable available for watchOS 6.0+ isCompanionAppInstalled. When I read this variable after my WCSession is activated on my watch app, it always return false.
Is there anything else I need to look out for? I am thinking maybe there is something I did wrong in all the different info.plist. But I have checked them multiple times.
my info.plist files:
In my watch app:
WKWatchKitApp is YES
WKCompanionAppBundleIdentifier is com.abc.myapp
In my watch extension:
App can run independently of companion iPhone app is YES
NSExtension
WKAppBundleIdentifier is com.abc.myapp.watchkitapp
NSExtensionPointIdentifier is com.apple.watchkit
iOS app bundle identifier is com.abc.myapp
watchOS app is com.abc.myapp.watchkitapp
watchOS app extension is com.abc.myapp.watchkitapp.watchkitextension
Is there anything else I might be overlooking?
Thank you very much for any help/insight you can offer into this.
Ok. I found a way to get rid of the error and have the watch connectivity work from watch to iPhone.
Originally I wanted the watch app to be independent so in the watch extension target in Xcode, the check box "Supports Running Without iOS App Installation" is checked. But as soon as I uncheck this box, WCSession.isCompanionAppInstalled returns true and error goes away. Syncing from watch to iPhone starts working.
So hopefully this is not intended behavior and will soon be fixed by Apple. (I filed a bug report.) But for now, I am just going to leave the independent watchOS app unchecked because I do want WatchConnectivity in case iPhone app is installed by user.
Thank you for reading and good luck with your programming.
If you have "App is only available as a standalone watchOS app" in Info.plist, delete it even if it is false. Leave only "App can run independently of companion iPhone app". Also don't forget to set "WKCompanionAppBundleIdentifier" for Watch App (not extension). At least it works on real device for me with these parameters.
This seems to be a bug. Sometimes when I start my WatchOS app, it gets WCSession.isCompanionAppInstalled = false all the time, even though the companion app on the iPhone is running, and other apps are able to communicate with the phone.
This seems to go away when I force-restart the app on the watch (press side button, then swipe the app to the left and press the big red button, then start the app again). After the restart, everything seems to work fine.
This has happened only on Testflight builds so far. If it happens in production builds, I'm going to file a bug.
My iOS app will not launch in the Simulator if I uncheck "Supports Running Without iOS App Installation".

Trigger apple watch application launch from iPhone [duplicate]

I would like to give a hint to the user, that my iOS app supports the Apple Watch.
So I would like to link/open the Apple Watch companion app from within my iOS app, very much similar to opening the Settings App using ([[UIApplication sharedApplication] openURL: [NSURL URLWithString:UIApplicationOpenSettingsURLString]];)
This shall enable the user to directly navigate to the Watch companion app to setup my app for the watch.
I could not find any URL which would open the companion app in general or specific to a section of the companion app.
If direct linking is not supported, I am also interested in alternative approaches for this use case.
Thanks in advance!
EDIT:
I checked the WatchKitSettings Info.plist file in the simulator to see if it registers any URL schema, but it does not.
I guess it's not possible to programmatically launch the watch companion app from iOS. The opposite way would be possible: to launch the iOS app in the background upon receiving a message from the watch. See WWDC talk Introducing Watch Connectivity.
You could check WCSession.defaultSession().watchAppInstalled and ask the user to launch the app if it is true.
Previously, it was not possible to launch the WatchKit App from the iPhone app, but the iPhone app could be launched—only in the background—with the openParentApplication method.
As of WatchOS 2, however, it is now not possible for either app to cause the other to launch. Instead, there are new methods for queueing changes to be picked up when the other app is launched in the future.
One partial solution for your use case could be displaying a local notification which could be tapped to open the watch app. The primary flaw in such an approach is I do not believe there is a way to limit this notification to the Watch only, so it would also appear on the iPhone where if tapped it would bring the iPhone app to the foreground. Messy if implemented like this, and therefore not worth it I'd have thought, even if it could pass app store review.

How to programmatically open Apple Watch companion app from iOS app

I would like to give a hint to the user, that my iOS app supports the Apple Watch.
So I would like to link/open the Apple Watch companion app from within my iOS app, very much similar to opening the Settings App using ([[UIApplication sharedApplication] openURL: [NSURL URLWithString:UIApplicationOpenSettingsURLString]];)
This shall enable the user to directly navigate to the Watch companion app to setup my app for the watch.
I could not find any URL which would open the companion app in general or specific to a section of the companion app.
If direct linking is not supported, I am also interested in alternative approaches for this use case.
Thanks in advance!
EDIT:
I checked the WatchKitSettings Info.plist file in the simulator to see if it registers any URL schema, but it does not.
I guess it's not possible to programmatically launch the watch companion app from iOS. The opposite way would be possible: to launch the iOS app in the background upon receiving a message from the watch. See WWDC talk Introducing Watch Connectivity.
You could check WCSession.defaultSession().watchAppInstalled and ask the user to launch the app if it is true.
Previously, it was not possible to launch the WatchKit App from the iPhone app, but the iPhone app could be launched—only in the background—with the openParentApplication method.
As of WatchOS 2, however, it is now not possible for either app to cause the other to launch. Instead, there are new methods for queueing changes to be picked up when the other app is launched in the future.
One partial solution for your use case could be displaying a local notification which could be tapped to open the watch app. The primary flaw in such an approach is I do not believe there is a way to limit this notification to the Watch only, so it would also appear on the iPhone where if tapped it would bring the iPhone app to the foreground. Messy if implemented like this, and therefore not worth it I'd have thought, even if it could pass app store review.

How can I avoid the error "Error Launching 'AppName' WatchKit Extension" when trying to build and run a WatchKit Extension on an actual Apple Watch?

When I try to build and run a WatchKit extension on my real Apple Watch, I sometimes get the following error message:
I've tried to build the parent application for the iPhone and then again for my WatchKit app but I still get the error message.
Does anyone know what causes this error message and how to deal with it?
This seems to happen when it takes a long time to install the WatchKit App on the actual watch and Xcode times out waiting for the process to start due to the long install time. It can take a long time for two reasons:
It sometimes takes a while for the Watch to "notice" the App needs updating before it begins the transfer.
If your Apple Watch app has a lot of images or other content it needs to transfer to the watch, the actual transfer over Bluetooth can take a long time.
If you want to avoid this error, here are some tips, adapting from this blog post, which can also show you how to speed up your app installs: http://www.sneakycrab.com/blog/2015/5/28/speeding-up-slow-install-times-when-debugging-on-a-real-apple-watch
Choose the iOS base scheme in Xcode to build and install on your phone. (Not the WatchKit App Extension)
Hit stop in Xcode.
Get iOS to notice it needs to begin installing the Watch app. There are two ways, either a) open the page for your app in the Apple Watch Companion App on your phone, or b) tapping on your app directly on the Watch (when you see the spinner, you can hit the crown to go back to the app icon screen, and you should see it start to load)
Once the app is installed on your watch, switch to the WatchKit Extension scheme and hit play, it will be waiting to attach debugging
Launch your app manually.
Make sure your iPhone bluetooth is turned on
Then I removed the app from my iPhone and re-launched it. That fixed it for me.

WatchKit app "Unlock to activate"

My IOS app reads the heart rate from a bluetooth heart rate sensor, the heart rate is displayed on the Apple Watch. Everything works fine. But in most cases the user will lock the iPhone and put it in his pocket.
Here is the problem:
The IOS app is still working in the background and reading the heart rate but I can no longer display the data on the Apple Watch because the simulator displays "Unlock to activate".
Is it not possible to continue with the WatchKit app when the iPhone is locked and the IOS app is in the background?
I found the correct answer at the Apple Developer Forum:
Q: If you would like to debug willActivate/didDeactivate in a specific Interface Controller in your WatchKit app or Glance, once it is showing in the iOS Simulator, you can choose Hardware > Lock from the iOS Simulator menu bar to trigger didDeactivate. Repeat to unlock and trigger willActivate.
I found this in beta4, but some confusion. Is it just a test function in simulator? The app on real watch would not be locked after iphone locked, right?
A: Correct, it's just for testing.
Q: Is there a way to test the watch app in the simulator while the phone is locked? It seems like this would be an important test case as well, but right now the watch only shows "unlock to activate" while the phone is locked.
A: Not currently.
Link: (but you mast have a developer account) https://devforums.apple.com/message/1106203#1106203
Did you try something like this: Easy way to update app content via apple watch
Does calling openParentApplication not work when the iphone is locked?
When it comes to getting the iPhone to perform things in the background, openParentApplication works very well. Essentially, openParentApplication will run while your phone is locked.
This link: http://www.bignerdranch.com/blog/watchKit-extensions-communicating-with-your-parent-application/
has one of the best and easiest to understand tutorials I've found. Really helped me out, hope that helps.
You should be able to grab your data using openParentApplication
Good luck
Active background mode to ensure that the parent app has time to send its reply. For a code example on how to use the background mode, refer to Calling parent application from Watch app.

Resources