react-native-watch-connectivity
react-native-watch-connectivity copied to clipboard
Wake up iPhone app when a Watch message arrives
Apple's WatchKit and WatchConnectivity libraries have the feature that a message from the Watch app can wake up the iPhone app in the background. This way, the iPhone app can provide some information to the Watch app, without the user noticing it on the iPhone.
I do not know the details of such a background activity on the iPhone app. All I can say is that I got such an example running as follows (if you do know the details of such a background activity, then skip down to my question):
- In your iPhone app, open
AppDelegate.mand add the following five lines, starting at line 38:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
#if defined(FB_SONARKIT_ENABLED) && __has_include(<FlipperKit/FlipperClient.h>)
InitializeFlipper(application);
#endif
NSLog(@"activating WCSession"); // <<<=== add these five lines (here is line 38)
if ([WCSession isSupported]) {
[WCSession defaultSession].delegate = self;
[[WCSession defaultSession] activateSession];
} // <<<=== until here
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"main" init
- Again in
AppDelegate.m, add the following three lines, starting at line 64:
[super application:application didFinishLaunchingWithOptions:launchOptions];
return YES;
}
- (void)session:(WCSession *)session didReceiveMessage:(NSDictionary<NSString *,id> *)message replyHandler:(void (^)(NSDictionary<NSString *,id> *replyMessage))replyHandler { // <<<=== add these three lines
replyHandler(@{@"message": @"replying from the background"});
} // <<<=== until here
- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge
{
- Now build the app for a real device (Apple Watch simulator seems very buggy when working with connectivity) and open the app on both the iPhone and the Watch.
- Now kill the app on the iPhone (you have to swipe it up in the recent-apps list, so that the app's process is terminated).
- Now send a message from the Watch to the iPhone.
- The iPhone answers with a
{ "message": "replying from the background" }message object.
My question is, does react-native-watch-connectivity support such a use case?
If it supports it (or will support it sometime), then I wonder how the interaction with our React Javascript code will look like when the app is in the background. Since there is no UI in the background, I suppose there will not be much React stuff. But our business logic (e.g. Redux reducers), we surely need it to run in order to be able to provide the Watch app with the information it needs.
Any ideas?
@yolpsoftware did you ever get anywhere with this issue?
I think you're probably on the right track in that the JavaScript side isn't initialised.
RN has the concept of Headless JS but unfortunately it only applies to android...
I'm wondering if perhaps we can somehow detect the app is in background from within session:didReceiveMessage and store any "missed" messages. When the app then comes to foreground we can forward those messages on over the bridge (probably using the same event handlers?).
I didn't really get answers to my questions. When I install a companion app on the Watch, it seems this app gets immediately started in the background, and sends something over to the iPhone, which makes the Phone app start in the background. If you open the iPhone app half a minute after you have installed the companion app, you won't get a splash screen, as the app is already running.
However, I could not detect in a consistent way how much of the React Javascript is ran in such a scenario. It all seems very foggy to me, there isn't much documentation around the topic (even for non-RN scenarios), and if you try to find it out by just trying, it does not seem a very consistent experience.
I tried to detect the background scenario within session:didReceiveMessage, but AFAIR it was not possible - the didReceiveMessage is fired in the same way as if the app was running in the foreground.
So I gave up, because this is not an important topic for my app. But sure, if someone finds out more, I'd be very interested.
I think both are different functionalities altogether. @yolpsoftware is talking about waking up companion app when message arrives and send reply back without user intervention.
@mtford90 I'm more interested in what you're explaining above. It will be good if we can somehow store messages which cannot be delivered when the companion app is not reachable and send them once it is reachable again. How can we achieve this? Any idea? I'm working on this one.... Please lemme know if there's anything we can do... TIA
@NagashreeNMeda what you want to do can be achieved with updateApplicationContext. It is supported by this library as of now. You don't need any Headless JS or Background App Startups or anything.
@yolpsoftware did you have any luck with this?
I am looking to receive the pending userInfo when the application is in the background.
I think this can also work: https://www.npmjs.com/package/react-native-background-fetch, but it will not be real-time, and as far as I can tell, there is no way to get the pending userInfo.
@cip123 no luck when I tried it back then. Keep me posted if you find a way to do this.