How to open a killed React Native app from background service on iOS?

Viewed 1015

I am developing a React Native app which uses Agora.io for making calls. Target platforms are Android and iOS. Costs and time are limited, so native (Swift + Java/Kotlin) way is not acceptable. As a trade-off, I am using react-native-callkeep to get as close to native call UI as possible.

Basically, the flow is:

  1. User A presses "Call" button, then he/she is taken to Call Screen, and push notification is sent to User B (callee).
  2. User B receives the push.
    • 2.1. User B's app is in foreground. Native call UI is shown using react-native-callkeep, user presses "Answer", then he is redirected to Call Screen. This scenario works fine.
    • 2.2. User B's app is in background. The push is handled by a background service (I know it may be called different on iOS/Android, but hope you get what I mean). Then, on Android I use the following code to bring app to foreground:
// In a native module:

@ReactMethod
public void launchMainActivity(String uri) {
    String packageName = reactContext.getPackageName();
    Intent launchIntent = reactContext.getPackageManager().getLaunchIntentForPackage(packageName);
    String className = launchIntent.getComponent().getClassName();

    try {
        Class<?> activityClass = Class.forName(className);
        Intent activityIntent;
        if (uri != null) {
            activityIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri), reactContext, activityClass);
        } else {
            activityIntent = new Intent(reactContext, activityClass);
        }
        activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        reactContext.startActivity(activityIntent);
    } catch(Exception e) {
        return;
    }
}
MyModule.launchMainActivity(`https://myapp.com/CallScreen?parameter=${value}`); // Link is simplified

This opens the app and tells react-navigation what screen I want to open and what params I want to pass to it. This works fine on Android.

Now I want the same on iOS. I was not able to find any example of how to do the same on iOS. So I tried to use deep links, but no success. I have added this to AppDelegate.m:

#import <React/RCTLinkingManager.h>

- (BOOL)application:(UIApplication *)application
   openURL:(NSURL *)url
   options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
  return [RCTLinkingManager application:application openURL:url options:options];
}

- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
  restorationHandler:(void(^)(NSArray * __nullable restorableObjects))restorationHandler
{
  return [RNCallKeep application:application
           continueUserActivity:userActivity
             restorationHandler:restorationHandler];
}

and to Info.plist:

<key>CFBundleURLTypes</key>
<array>
 <dict>
  <key>CFBundleURLSchemes</key>
  <array>
   <string>myapp</string>
  </array>
 </dict>
</array>

This is how I use it:

Linking.openURL(`myapp://CallScreen?parameter=${value}`); // Link is simplified

And it says that it can not handle this link. But, if I just type the link in the browser, it suggests to open it in my app (and opens it, I get redirected to Call Screen).

So, finally, the question: how can I open my app on iOS from background service, if it is in background/killed? A way similar to how it is done on Android is highly preferred over linking.

BTW, this is how background service is registered (firebase is used):

import messaging from '@react-native-firebase/messaging';

messaging().setBackgroundMessageHandler(async message => {
  // Here we go
});

P.S.:

  1. Background messaging itself works fine on iOS/Android.
  2. react-native-callkeep works on iOS/Android.
  3. Call flow works fine when app is in foreground on iOS/Android.
  4. I have configured react-navigation for linking (and linking itself works on both iOS/Android).
0 Answers
Related