Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wake up iPhone app when a Watch message arrives #68

Open
yolpsoftware opened this issue Nov 13, 2021 · 6 comments
Open

Wake up iPhone app when a Watch message arrives #68

yolpsoftware opened this issue Nov 13, 2021 · 6 comments

Comments

@yolpsoftware
Copy link
Collaborator

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):

  1. In your iPhone app, open AppDelegate.m and 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
  1. 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
{
  1. 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.
  2. 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).
  3. Now send a message from the Watch to the iPhone.
  4. 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?

@mtford90
Copy link
Collaborator

mtford90 commented Jun 8, 2022

@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?).

@yolpsoftware
Copy link
Collaborator Author

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.

@NagashreeNMeda
Copy link

NagashreeNMeda commented Nov 23, 2022

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

@yolpsoftware
Copy link
Collaborator Author

@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.

@cip123
Copy link

cip123 commented Mar 7, 2024

@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.

@yolpsoftware
Copy link
Collaborator Author

@cip123 no luck when I tried it back then. Keep me posted if you find a way to do this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants