iOS Universal Links - NSUserActivity is nil - ios

I am trying to use Universal Links. On clicking the link app launches on the iPad but in the delegate call continueUserActivity: userActivity variable is nil. Here is my code in AppDelegate.
- (BOOL)application:(UIApplication *)application willContinueUserActivityWithType:(NSString *)userActivityType
{
if ([userActivityType isEqualToString: NSUserActivityTypeBrowsingWeb])
{
}
return true;
}
-(BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler
{
if ([userActivity.activityType isEqualToString: NSUserActivityTypeBrowsingWeb]) {
NSURL *url = userActivity.webpageURL;
NSString *msg = [self getQueryComponentWithName:#"msg" fromURL:url];
}
return YES;
}

I was using Debug build. It works when I use release mode. To build in release mode please use following steps:
Go to Product menu
Select Scheme
Edit Scheme
In Build Configuration Select Release.

Related

Firebase custom domain doesn't survive App Store installation iOS

I'm having an issue getting my React Native iOS app Firebase Dynamic Link to survive the App Store installation process. This link works fine when the app is installation and works perfectly in Android. Dynamic Link urls also work perfectly with Google branded urls such as page.link or goo.gl.
I created a couple of custom domains, properly set the custom url, associated domains, and added them to the FirebaseDynamicLinksCustomDomains array in the plist and still can't get them to work from an app store launch. I also added some logs to the AppDelegate file to see if the url is getting lost somewhere, but I don't see it coming in the native iOS code. I do, however, see the dynamic links showing up when the app is installed and or I use a Google branded domain like page.link. I also tested my domains with Firebase's quickstart app and they don't work unless the app is installed.
The custom domain does work when the app preview screen is enabled, but I would prefer not to use it see there's a branded interstitial page that redirects the user to the App Store if the app isn't installed.
I am using react-native-firebase/analytics 11.1.2, react-native-firebase/app 11.1.2, react-native-firebase/dynamic-links 11.1.2, and react-native-firebase/messaging 11.1.2. I don't know if this is a third party issue or a Firebase SDK issue.
I'm testing for the presence of the url in the native and React code here:
- (BOOL)application:(UIApplication *)application
continueUserActivity:(nonnull NSUserActivity *)userActivity
restorationHandler:
#if defined(__IPHONE_12_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_12_0)
(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> *_Nullable))restorationHandler {
#else
(nonnull void (^)(NSArray *_Nullable))restorationHandler {
#endif // __IPHONE_12_0
BOOL handled = [[FIRDynamicLinks dynamicLinks] handleUniversalLink:userActivity.webpageURL
completion:^(FIRDynamicLink * _Nullable dynamicLink,
NSError * _Nullable error) {
if (dynamicLink.url) {
NSString *message = [NSString stringWithFormat:#"Foreground deep link iOS native %#", dynamicLink.url.absoluteString];
[SentrySDK captureMessage:message];
} else {
[SentrySDK captureMessage:#"Foreground deep link iOS native no deep link found"];
}
}];
return handled;
}
- (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary<NSString *, id> *)options {
return [self application:app
openURL:url
sourceApplication:options[UIApplicationOpenURLOptionsSourceApplicationKey]
annotation:options[UIApplicationOpenURLOptionsAnnotationKey]];
}
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
FIRDynamicLink *dynamicLink = [[FIRDynamicLinks dynamicLinks] dynamicLinkFromCustomSchemeURL:url];
if (dynamicLink) {
if (dynamicLink.url) {
NSString *message = [NSString stringWithFormat:#"Background deep link iOS native %#", dynamicLink.url.absoluteString];
[SentrySDK captureMessage:message];
} else {
[SentrySDK captureMessage:#"Background deep link iOS native no deep link found"];
}
return YES;
}
return NO;
}
And testing for the url in the React code in the App.js file:
useEffect(() => {
dynamicLinks()
.getInitialLink()
.then((link) => {
const deepLink = link ?? 'no deep link available';
logSentryMessage(JSON.stringify(deepLink), 'Deep link from background');
if (isNil(link) || isNil(link.url)) {
return;
}
setUrl(link.url);
});
}, []);
/**
* AppLink handler
*
* #param link
*/
const handleDynamicLink = useCallback(
(link: FirebaseDynamicLinksTypes.DynamicLink) => {
const deepLink = link ?? 'no deep link available';
logSentryMessage(JSON.stringify(deepLink), 'Deep link from foreground');
if (isNil(link.url)) {
return;
}
setUrl(link.url);
},
[],
);
useEffect(() => {
const unsubscribe = dynamicLinks().onLink(handleDynamicLink);
return () => unsubscribe();
}, [handleDynamicLink]);

Can we add or use handleOpenURL other app delegate

I'm building SDK for my product and there will be no app delegate class. I used Dropbox Integration in my SDK, so I'm bound to use following method.
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
NSString *stringUrl = [url absoluteString];
if ([stringUrl containsString:#"cancel"]) {
// Handle if user cancelled the login
[[NSNotificationCenter defaultCenter] postNotificationName:#"dropboxRegistrationCancel" object:self];
return NO;
}
if ([[DBSession sharedSession] handleOpenURL:url]) {
if ([[DBSession sharedSession] isLinked]) {
NSLog(#"App linked successfully!");
// At this point you can start making API calls
[[NSNotificationCenter defaultCenter] postNotificationName:ApplicationComeBackFromDropBoxLoginPage object:self];
}
return YES;
}
// Add whatever other url handling code your app requires here
return NO;
}
So Issue is there is no app delegate than how can use above method?
Or any alternate solution for this to use this in another class (like to inherit UIResponder class).
Looking for help.
If you are building a SDK with no appDelegate, then well, you have nothing to do. It will be in your project where you will be using your sdk that you will have to add this line.
By the way, the line NSString *stringUrl = [url absoluteString]; is absolutly useless since you are not using stringUrl later on, and the
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
// NSString *stringUrl = [url absoluteString];
return YES;
}
just means: yes you can quit my app to open another app when the user click on a link.
No biggy....

Universal Links IOS9

Seems that Apple is moving away from the custom scheme mechanism for opening apps via linking.
With custom schemes if you were to try to open an custom scheme registered by your app, the applications would open and the javascript function handleOpenURL would handle the call.
Does worklight support the new "Universal Links" method in IOS9?
In our project worklight didn't trigger handleOpenURL function for Universal Links functionality out of the box.
So, we used the following solution:
1) Native layer plugin
MyAppDelegate+UniversalLinksPlugin.h
#import "rr.h"
#interface MyAppDelegate (UniversalLinksPlugin)
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler;
#end
MyAppDelegate+UniversalLinksPlugin.m
#import "rr.h"
#import <objc/runtime.h>
#implementation MyAppDelegate (UniversalLinksPlugin)
- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler {
NSLog(#"Universal links plugin: starting application launch handling.");
// ignore activities that are not for Universal Links
if (![userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb] || userActivity.webpageURL == nil) {
return NO;
}
NSString* url = [userActivity.webpageURL absoluteString];
NSLog(#"Universal links plugin: the following url is used for the application launch %#", url);
NSMutableDictionary *data = [[NSMutableDictionary alloc] init];
[data setValue:url forKey:#"url"];
[[WL sharedInstance] sendActionToJS:#"handleURL" withData:data];
return YES;
}
#end
2) config.xml update:
<feature name="UniversalLinksPlugin">
<param name="ios-package" value="UniversalLinksPlugin"/>
</feature>
3) iphone/js/main.js update:
/**
* UL links handling
*/
document.addEventListener("deviceready", function() {
WL.App.addActionReceiver ("ULReceiver", function(received) {
if (received.action === "handleURL") {
WL.Logger.debug('Inside handle URL action receiver. Provided url: ' + received.data.url);
handleOpenURL(received.data.url);
}
});
}, false);
This is it. I really hope that this will help to someone )
Universal Linking was not tested as part of iOS 9 support. If linking is required continue to work with the custom scheme option for the time being.
Edit: tested and found to be working.

Handoff icon not disappearing from the phone

I create a handoff request for my apple watch app with the following code:
[self updateUserActivity:#"..." userInfo:selectedTopic webpageURL:[NSURL URLWithString:nil]];
And I handle the request in the phone AppDelegate with the following code:
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *))restorationHandler
{
BOOL handled = NO;
[userActivity becomeCurrent];
NSString *type = [userActivity activityType];
NSDictionary *userInfo = [userActivity userInfo];
if ([type isEqualToString:#"..."]) {
//does action
[userActivity invalidate];
handled = YES;
}
return handled;
}
The issue is the handoff icon does not go away even though this code is executed. What am I doing wrong here? Why will the handoff icon not disappear?
I've seen this behaviour on other applications. The only applications I see with the correct behaviour are native apps.

iOS - How to implement Deep Linking to open App or go to itunes link using URL scheme

I have an issue with URL Scheme in plist file as "m.zameen.com"
but i type this in iPhone's safari browser not op[en but when i open using :// it opened
// In AppDelegate.m file
-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
if([[url host] isEqualToString:#"page"]){
if([[url path] isEqualToString:#"/main"]){
[self.mainController setViewControllers:#[[[DLViewController alloc] init]] animated:YES];
}
else if([[url path] isEqualToString:#"/page1"]){
[self.mainController pushViewController:[[Page1ViewController alloc] init] animated:YES];
}
return YES;
}
else{
return NO;
}
}
// In DLViewController.m file
- (IBAction)page1Clicked:(id)sender {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"m.zameen.com://page/page1"]];
}
// In Page1ViewController.m file
- (IBAction)mainPageClicked:(id)sender {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"m.zameen.com://page/main"]];
}
In your project Info tab, add a new URL Type with the scheme you want to use to open the app, for example 'myAwesomeAppScheme', using your app bundle identifier 'com.myCompany.myAwesomeApp' in the identifier field and the scheme you want in the URL Schemes field:
Then in you app delegate you can check if the opened url has your scheme with something like this
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
if ([url.scheme isEqualToString:#"myAwesomeAppScheme"]) {
...
}
}
And finally to open the app from an external app, the link has to be something like myAwesomeAppScheme://parameters/for/opening/viewcontrollers?otherParam=blahblah

Resources