Handling App Clips URL in React Native
In this post, We are going to explain the App Clips invocation URL in React Native.
Firstly, I wrote this article when App Clips was introduced. it was just an experimental, then I decided to explore more about App Clips' experiences.
If you checked Apple documentation about App Clips. the App Clips receives an invocation URL that determines what information appears on the App Clips card.
To configure an invocation URL for debugging:
- In Xcode, choose Product > Scheme > Edit Scheme and select your App Clip’s scheme.
- Select the Run action.
- In the Arguments tab, check whether the
_XCAppClipURL
environment variable is present. When you add an App Clips target to your project, Xcode adds this environment variable for you. If it’s missing, add the environment variable. - Set the environment variable’s value to the invocation URL you want to test.
- Enable the variable by checking the checkbox next to it.
- Build and run the App Clips to access the test URL you configured from an
NSUserActivity
object. For more information on accessing the invocation URL, see Responding to Invocations.
The following screenshot shows the sheet to configure an App Clips target’s Run action with a value for the _XCAppClipURL
environment variable:
To catch _XCAppClipURL
in the Debug console, We are going to implement some code. SceneDelegate have a method called willConnectToSession This method is called when your app creates or restores an instance of your user interface.
willConnectToSession method will look like this.
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
if (connectionOptions.userActivities && connectionOptions.userActivities.count > 0) {
NSUserActivity *userActivity = connectionOptions.userActivities.allObjects.firstObject;
NSLog(@"%@", userActivity.webpageURL.absoluteString);
self.initialLinkUrl = userActivity.webpageURL.absoluteString;
}
}
After that if you run project again you will see _XCAppClipURL
in Xcode Debug Console.
Okay. We got the _XCAppClipURL
but question is how to pass this url to React Native. Actually I tried Linking but got nothing. then I decided to write my own module to handle it.
I created AppClipLinkingManager.h and .m files inside AppClip target folder.
#import "AppClipLinkingManager.h"
#import "SceneDelegate.h"
@interface AppClipLinkingManager ()
@end
@implementation AppClipLinkingManager
- (dispatch_queue_t)methodQueue
{
return dispatch_get_main_queue();
}
RCT_EXPORT_MODULE();
- (NSArray<NSString *> *)supportedEvents {
return @[];
}
RCT_EXPORT_METHOD(getInitialLink:(RCTPromiseResolveBlock) resolve:(RCTPromiseRejectBlock)reject) {
UIScene *scene = UIApplication.sharedApplication.connectedScenes.allObjects.firstObject;
SceneDelegate *sceneDelegate = (SceneDelegate *)scene.delegate;
if (sceneDelegate.initialLinkUrl) {
resolve(sceneDelegate.initialLinkUrl);
} else {
reject(@"event_failure", @"no event id returned", nil);
}
}
@end
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
#import <Foundation/Foundation.h>
@interface AppClipLinkingManager : RCTEventEmitter <RCTBridgeModule>
@end
Also I added a object inside SceneDelegate
#import <UIKit/UIKit.h>
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
@interface SceneDelegate : UIResponder <UIWindowSceneDelegate>
@property (strong, nonatomic) UIWindow * window;
@property (strong, readwrite) NSString * initialLinkUrl;
@end
import React, {useState, useEffect} from 'react';
import {AppRegistry, Button, View, Text} from 'react-native';
import {NativeModules} from 'react-native';
const AppClip = () => {
const [url, setURL] = useState('');
const {AppClipLinkingManager} = NativeModules;
useEffect(() => {
AppClipLinkingManager.getInitialLink().then((link) => {
setURL(link);
});
}, []);
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Text style={{fontSize: 22}}>React Native App Clip {url}</Text>
<Button title="Learn More" color="#841584" />
</View>
);
};
AppRegistry.registerComponent('AppClip', () => AppClip);
When you run the app, first willConnectToSession will be called. it will set initialLinkUrl. when you call getInitialLink method from React Native side url will be returned from sceneDelegate
if you successfully do everything correctly. you will see link like below
If you liked this tutorial, please subscribe and share this with your community. Cheers!