react-native-firebase/ios/RNFirebase/links/RNFirebaseLinks.m

288 lines
12 KiB
Mathematica
Raw Normal View History

#import "RNFirebaseLinks.h"
#if __has_include(<FirebaseDynamicLinks/FirebaseDynamicLinks.h>)
#import <Firebase.h>
2017-09-25 14:34:26 +00:00
#import "RNFirebaseEvents.h"
static void sendDynamicLink(NSURL *url, id sender) {
Fixed: attempt to insert nil object from objects[0] Fixed the issue that was causing a crash in my application: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0]' *** First throw call stack: ( 0 CoreFoundation 0x000000011310e12b __exceptionPreprocess + 171 1 libobjc.A.dylib 0x00000001127a6f41 objc_exception_throw + 48 2 CoreFoundation 0x000000011314e0cc _CFThrowFormattedException + 194 3 CoreFoundation 0x0000000113022951 -[__NSPlaceholderDictionary initWithObjects:forKeys:count:] + 321 4 CoreFoundation 0x00000001130227db +[NSDictionary dictionaryWithObjects:forKeys:count:] + 59 5 Mesghal 0x000000010ace08c2 sendDynamicLink + 226 6 Mesghal 0x000000010ace0d0f __71+[RNFirebaseLinks application:continueUserActivity:restorationHandler:]_block_invoke + 447 7 libdispatch.dylib 0x0000000113fcd2f7 _dispatch_call_block_and_release + 12 8 libdispatch.dylib 0x0000000113fce33d _dispatch_client_callout + 8 9 libdispatch.dylib 0x0000000113fd95f9 _dispatch_main_queue_callback_4CF + 628 10 CoreFoundation 0x00000001130d0e39 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9 11 CoreFoundation 0x0000000113095462 __CFRunLoopRun + 2402 12 CoreFoundation 0x0000000113094889 CFRunLoopRunSpecific + 409 13 GraphicsServices 0x00000001154d29c6 GSEventRunModal + 62 14 UIKit 0x000000010f60b5d6 UIApplicationMain + 159 15 Mesghal 0x000000010a6b688f main + 111 16 libdyld.dylib 0x000000011404ad81 start + 1 )
2018-01-06 00:43:02 +00:00
if (url) {
[[NSNotificationCenter defaultCenter] postNotificationName:LINKS_DYNAMIC_LINK_RECEIVED
object:sender
userInfo:@{@"url": url.absoluteString}];
NSLog(@"sendDynamicLink Success: %@", url.absoluteString);
}
}
@implementation RNFirebaseLinks
RCT_EXPORT_MODULE();
2017-09-25 14:34:26 +00:00
- (id)init {
self = [super init];
if (self != nil) {
NSLog(@"Setting up RNFirebaseLinks instance");
[self initialiseLinks];
2017-09-25 14:34:26 +00:00
}
return self;
}
- (void)initialiseLinks {
2017-09-25 14:34:26 +00:00
// Set up internal listener to send notification over bridge
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(sendDynamicLinkEvent:)
2017-09-25 14:34:26 +00:00
name:LINKS_DYNAMIC_LINK_RECEIVED
object:nil];
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
+ (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
2017-09-30 16:56:58 +00:00
return [self handleLinkFromCustomSchemeURL:url];
}
+ (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
2017-09-30 16:56:58 +00:00
annotation:(id)annotation {
return [self handleLinkFromCustomSchemeURL:url];
}
+ (BOOL)handleLinkFromCustomSchemeURL:(NSURL *)url {
FIRDynamicLink *dynamicLink =
[[FIRDynamicLinks dynamicLinks] dynamicLinkFromCustomSchemeURL:url];
if (dynamicLink && dynamicLink.url) {
NSURL* dynamicLinkUrl = dynamicLink.url;
sendDynamicLink(dynamicLinkUrl, self);
return YES;
}
return NO;
}
+ (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
2017-09-30 16:56:58 +00:00
restorationHandler:(void (^)(NSArray *))restorationHandler {
BOOL handled = [[FIRDynamicLinks dynamicLinks]
handleUniversalLink:userActivity.webpageURL
completion:^(FIRDynamicLink * _Nullable dynamicLink, NSError * _Nullable error) {
if (error != nil){
NSLog(@"Failed to handle universal link: %@", [error localizedDescription]);
}
else {
if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
NSURL* url = dynamicLink ? dynamicLink.url : userActivity.webpageURL;
sendDynamicLink(url, self);
}
}
}];
return handled;
}
- (NSArray<NSString *> *)supportedEvents {
return @[LINKS_DYNAMIC_LINK_RECEIVED];
}
- (void)sendDynamicLinkEvent:(NSNotification *)notification {
[self sendEventWithName:LINKS_DYNAMIC_LINK_RECEIVED body:notification.userInfo[@"url"]];
}
-(void)handleInitialLinkFromCustomSchemeURL:(NSURL*)url resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
FIRDynamicLink *dynamicLink =
[[FIRDynamicLinks dynamicLinks] dynamicLinkFromCustomSchemeURL:url];
NSString* urlString = dynamicLink ? dynamicLink.url.absoluteString : (id)kCFNull;
NSLog(@"initial link is: %@", urlString);
resolve(urlString);
}
-(void)handleInitialLinkFromUniversalLinkURL:(NSDictionary *)userActivityDictionary resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
NSUserActivity* userActivity = (NSUserActivity*) userActivityDictionary[@"UIApplicationLaunchOptionsUserActivityKey"];
if ([userActivityDictionary[UIApplicationLaunchOptionsUserActivityTypeKey] isEqual:NSUserActivityTypeBrowsingWeb])
{
[[FIRDynamicLinks dynamicLinks]
handleUniversalLink:userActivity.webpageURL
completion:^(FIRDynamicLink * _Nullable dynamicLink, NSError * _Nullable error) {
if (error != nil){
NSLog(@"Failed to handle universal link: %@", [error localizedDescription]);
reject(@"links/failure", @"Failed to handle universal link", error);
}
else {
NSString* urlString = dynamicLink ? dynamicLink.url.absoluteString : userActivity.webpageURL.absoluteString;
NSLog(@"initial link is: %@", urlString);
resolve(urlString);
}
}];
}
else {
NSLog(@"no initial link");
resolve((id)kCFNull);
}
}
RCT_EXPORT_METHOD(getInitialLink:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
if (self.bridge.launchOptions[UIApplicationLaunchOptionsURLKey]) {
NSURL* url = (NSURL*)self.bridge.launchOptions[UIApplicationLaunchOptionsURLKey];
[self handleInitialLinkFromCustomSchemeURL:url resolver:resolve rejecter:reject];
} else {
NSDictionary *userActivityDictionary =
self.bridge.launchOptions[UIApplicationLaunchOptionsUserActivityDictionaryKey];
[self handleInitialLinkFromUniversalLinkURL:userActivityDictionary resolver:resolve rejecter:reject];
}
}
2017-09-25 14:34:26 +00:00
RCT_EXPORT_METHOD(createDynamicLink: (NSDictionary *) metadata resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
@try {
FIRDynamicLinkComponents *components = [self getDynamicLinkComponentsFromMetadata:metadata];
if (components == nil) {
reject(@"links/failure", @"Failed to create Dynamic Link", nil);
} else {
NSURL *longLink = components.url;
NSLog(@"created long dynamic link: %@", longLink.absoluteString);
resolve(longLink.absoluteString);
}
}
@catch(NSException * e) {
NSLog(@"create dynamic link failure %@", e);
reject(@"links/failure",[e reason], nil);
}
}
RCT_EXPORT_METHOD(createShortDynamicLink: (NSDictionary *) metadata resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
@try {
FIRDynamicLinkComponents *components = [self getDynamicLinkComponentsFromMetadata:metadata];
[self setSuffixParameters:metadata components:components];
[components shortenWithCompletion:^(NSURL *_Nullable shortURL,
NSArray *_Nullable warnings,
NSError *_Nullable error) {
if (error) {
NSLog(@"create short dynamic link failure %@", [error localizedDescription]);
reject(@"links/failure", @"Failed to create Short Dynamic Link", error);
}
else {
NSURL *shortLink = shortURL;
NSLog(@"created short dynamic link: %@", shortLink.absoluteString);
resolve(shortLink.absoluteString);
}
}];
}
@catch(NSException * e) {
NSLog(@"create short dynamic link failure %@", e);
reject(@"links/failure",[e reason], nil);
}
}
2017-09-25 14:34:26 +00:00
- (FIRDynamicLinkComponents *)getDynamicLinkComponentsFromMetadata:(NSDictionary *)metadata {
@try {
NSURL *link = [NSURL URLWithString:metadata[@"link"]];
FIRDynamicLinkComponents *components =
[FIRDynamicLinkComponents componentsWithLink:link domain:metadata[@"dynamicLinkDomain"]];
[self setAndroidParameters:metadata components:components];
[self setIosParameters:metadata components:components];
[self setSocialMetaTagParameters:metadata components:components];
return components;
}
@catch(NSException * e) {
NSLog(@"error while building componets from meta data %@", e);
@throw;
}
}
- (void)setAndroidParameters:(NSDictionary *)metadata
components:(FIRDynamicLinkComponents *)components {
NSDictionary *androidParametersDict = metadata[@"androidInfo"];
if (androidParametersDict) {
FIRDynamicLinkAndroidParameters *androidParams = [FIRDynamicLinkAndroidParameters
parametersWithPackageName: androidParametersDict[@"androidPackageName"]];
if (androidParametersDict[@"androidFallbackLink"]) {
androidParams.fallbackURL = [NSURL URLWithString:androidParametersDict[@"androidFallbackLink"]];
}
if (androidParametersDict[@"androidMinPackageVersionCode"]) {
androidParams.minimumVersion = [androidParametersDict[@"androidMinPackageVersionCode"] integerValue];
}
components.androidParameters = androidParams;
}
}
- (void)setIosParameters:(NSDictionary *)metadata
components:(FIRDynamicLinkComponents *)components {
NSDictionary *iosParametersDict = metadata[@"iosInfo"];
if (iosParametersDict) {
FIRDynamicLinkIOSParameters *iOSParams = [FIRDynamicLinkIOSParameters
parametersWithBundleID:iosParametersDict[@"iosBundleId"]];
if (iosParametersDict[@"iosAppStoreId"]) {
iOSParams.appStoreID = iosParametersDict[@"iosAppStoreId"];
}
if (iosParametersDict[@"iosCustomScheme"]) {
iOSParams.customScheme = iosParametersDict[@"iosCustomScheme"];
}
if (iosParametersDict[@"iosFallbackLink"]) {
iOSParams.fallbackURL = [NSURL URLWithString:iosParametersDict[@"iosFallbackLink"]];
}
if (iosParametersDict[@"iosIpadBundleId"]) {
iOSParams.iPadBundleID = iosParametersDict[@"iosIpadBundleId"];
}
if (iosParametersDict[@"iosIpadFallbackLink"]) {
iOSParams.iPadFallbackURL = [NSURL URLWithString:iosParametersDict[@"iosIpadFallbackLink"]];
}
if (iosParametersDict[@"iosMinPackageVersionCode"]) {
iOSParams.minimumAppVersion = iosParametersDict[@"iosMinPackageVersionCode"];
}
components.iOSParameters = iOSParams;
}
}
- (void)setSocialMetaTagParameters:(NSDictionary *)metadata
components:(FIRDynamicLinkComponents *)components {
NSDictionary *socialParamsDict = metadata[@"socialMetaTagInfo"];
if (socialParamsDict) {
FIRDynamicLinkSocialMetaTagParameters *socialParams = [FIRDynamicLinkSocialMetaTagParameters parameters];
if (socialParamsDict[@"socialTitle"]) {
socialParams.title = socialParamsDict[@"socialTitle"];
}
if (socialParamsDict[@"socialDescription"]) {
socialParams.descriptionText = socialParamsDict[@"socialDescription"];
}
if (socialParamsDict[@"socialImageLink"]) {
socialParams.imageURL = [NSURL URLWithString:socialParamsDict[@"socialImageLink"]];
}
components.socialMetaTagParameters = socialParams;
}
}
- (void)setSuffixParameters:(NSDictionary *)metadata
components:(FIRDynamicLinkComponents *)components {
NSDictionary *suffixParametersDict = metadata[@"suffix"];
if (suffixParametersDict) {
FIRDynamicLinkComponentsOptions *options = [FIRDynamicLinkComponentsOptions options];
if ([suffixParametersDict[@"option"] isEqual: @"SHORT"]) {
options.pathLength = FIRShortDynamicLinkPathLengthShort;
}
else if ([suffixParametersDict[@"option"] isEqual: @"UNGUESSABLE"]) {
options.pathLength = FIRShortDynamicLinkPathLengthUnguessable;
}
components.options = options;
}
}
+ (BOOL)requiresMainQueueSetup
{
return YES;
}
@end
#else
@implementation RNFirebaseLinks
@end
#endif