Skip to content

Commit

Permalink
raise notification for applink insigths
Browse files Browse the repository at this point in the history
squashed
  • Loading branch information
Gen Wang committed Jul 17, 2014
1 parent 513935f commit 2d2ad8b
Show file tree
Hide file tree
Showing 12 changed files with 336 additions and 39 deletions.
12 changes: 12 additions & 0 deletions Bolts.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@
8EE768A81803E5DA009A53B1 /* BoltsVersion.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8E0B5CDA17E13B4C0066379B /* BoltsVersion.h */; };
8EE768A91803E5E0009A53B1 /* Bolts.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8EE768A61803E32F009A53B1 /* Bolts.h */; };
8EE768AA1803E5E5009A53B1 /* BoltsVersion.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8E0B5CDA17E13B4C0066379B /* BoltsVersion.h */; };
B24A9E26194FABF700603EBB /* BFMeasurementEvent.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = B2DEBAF4194668D4005EBEAA /* BFMeasurementEvent.h */; };
B2DEBAF6194668D4005EBEAA /* BFMeasurementEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = B2DEBAF5194668D4005EBEAA /* BFMeasurementEvent.m */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -102,6 +104,7 @@
1E45E47518DA7F0000D23509 /* BFAppLinkNavigation.h in CopyFiles */,
1E45E47618DA7F0000D23509 /* BFAppLinkResolving.h in CopyFiles */,
1E45E47718DA7F0000D23509 /* BFAppLinkTarget.h in CopyFiles */,
B24A9E26194FABF700603EBB /* BFMeasurementEvent.h in CopyFiles */,
1E45E47818DA7F0000D23509 /* BFURL.h in CopyFiles */,
1E45E47918DA7F0000D23509 /* BFWebViewAppLinkResolver.h in CopyFiles */,
8E42701F1805E5A1000B84ED /* BFExecutor.h in CopyFiles */,
Expand Down Expand Up @@ -199,6 +202,10 @@
8EB2CB411805DDDB00323385 /* BFExecutor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BFExecutor.m; sourceTree = "<group>"; };
8EDDA63517E17DDD00655F8A /* libMacBolts.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libMacBolts.a; sourceTree = BUILT_PRODUCTS_DIR; };
8EE768A61803E32F009A53B1 /* Bolts.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Bolts.h; sourceTree = "<group>"; };
B2112471194FCEA10001FF7A /* BFURL_Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BFURL_Internal.h; sourceTree = "<group>"; };
B28E0515194F818B00AC3740 /* BFAppLink_Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BFAppLink_Internal.h; sourceTree = "<group>"; };
B2DEBAF4194668D4005EBEAA /* BFMeasurementEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BFMeasurementEvent.h; sourceTree = "<group>"; };
B2DEBAF5194668D4005EBEAA /* BFMeasurementEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BFMeasurementEvent.m; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -338,6 +345,7 @@
isa = PBXGroup;
children = (
1E11AB7518C561E300522739 /* BFAppLink.h */,
B28E0515194F818B00AC3740 /* BFAppLink_Internal.h */,
1E11AB7618C561E300522739 /* BFAppLink.m */,
1E11AB7318C561E300522739 /* BFAppLinkNavigation.h */,
1E11AB7418C561E300522739 /* BFAppLinkNavigation.m */,
Expand All @@ -356,9 +364,12 @@
8E9C3D2017DEA35700427E62 /* BFTaskCompletionSource.h */,
8E9C3D2117DEA35700427E62 /* BFTaskCompletionSource.m */,
1E11AB7718C561E300522739 /* BFURL.h */,
B2112471194FCEA10001FF7A /* BFURL_Internal.h */,
1E11AB7818C561E300522739 /* BFURL.m */,
1EC3019418CDD8A500D06D07 /* BFWebViewAppLinkResolver.h */,
1EC3019518CDD8A500D06D07 /* BFWebViewAppLinkResolver.m */,
B2DEBAF4194668D4005EBEAA /* BFMeasurementEvent.h */,
B2DEBAF5194668D4005EBEAA /* BFMeasurementEvent.m */,
8EE768A61803E32F009A53B1 /* Bolts.h */,
8EA6BF661805CED500337041 /* Bolts.m */,
8E0B5CDA17E13B4C0066379B /* BoltsVersion.h */,
Expand Down Expand Up @@ -579,6 +590,7 @@
1EC3019618CDD8A500D06D07 /* BFWebViewAppLinkResolver.m in Sources */,
1E11AB7918C561E300522739 /* BFAppLinkNavigation.m in Sources */,
85D5138818E4E27700D19D87 /* BFAppLinkReturnToRefererView.m in Sources */,
B2DEBAF6194668D4005EBEAA /* BFMeasurementEvent.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
31 changes: 27 additions & 4 deletions Bolts/BFAppLink.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*
*/

#import "BFAppLink.h"
#import "BFAppLink_Internal.h"

NSString *const BFAppLinkDataParameterName = @"al_applink_data";
NSString *const BFAppLinkTargetKeyName = @"target_url";
Expand All @@ -20,16 +20,39 @@
NSString *const BFAppLinkVersionKeyName = @"version";
NSString *const BFAppLinkVersion = @"1.0";

@implementation BFAppLink
@implementation BFAppLink {
BOOL _isBackToReferrer;
}

+ (instancetype)appLinkWithSourceURL:(NSURL *)sourceURL
targets:(NSArray *)targets
webURL:(NSURL *)webURL {
BFAppLink *link = [[self alloc] init];
webURL:(NSURL *)webURL
isBackToReferrer:(BOOL)isBackToReferrer {
BFAppLink *link = [[self alloc] initWithIsBackToReferrer:isBackToReferrer];
link->_sourceURL = sourceURL;
link->_targets = [NSArray arrayWithArray:targets];
link->_webURL = webURL;
return link;
}

+ (instancetype)appLinkWithSourceURL:(NSURL *)sourceURL
targets:(NSArray *)targets
webURL:(NSURL *)webURL {
return [self appLinkWithSourceURL:sourceURL
targets:targets
webURL:webURL
isBackToReferrer:NO];
}

- (BOOL)isBackToReferrer {
return _isBackToReferrer;
}

- (BFAppLink *)initWithIsBackToReferrer:(BOOL)isBackToReferrer {
if ((self = [super init])) {
_isBackToReferrer = isBackToReferrer;
}
return self;
}

@end
7 changes: 7 additions & 0 deletions Bolts/BFAppLinkNavigation.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ typedef NS_ENUM(NSInteger, BFAppLinkNavigationType) {
BFAppLinkNavigationTypeApp
};

/*! Bolts Events raised by BFMeasurementEvent for Applink */
/* The event raised when the user navigates from your app to other apps */
FOUNDATION_EXPORT NSString *const BFAppLinkNavigateOutEventName;
/* The event raised when the user navigates out from your app and back to the referrer app.
e.g when the user leaves your app after tapping the back-to-referrer navigation bar */
FOUNDATION_EXPORT NSString *const BFAppLinkNavigateBackToReferrerEventName;

@protocol BFAppLinkResolving;
@class BFTask;

Expand Down
114 changes: 89 additions & 25 deletions Bolts/BFAppLinkNavigation.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,20 @@
#import "BFWebViewAppLinkResolver.h"
#import "BFExecutor.h"
#import "BFTask.h"
#import "BFMeasurementEvent.h"
#import "BFAppLink_Internal.h"

FOUNDATION_EXPORT NSString *const BFAppLinkDataParameterName;
FOUNDATION_EXPORT NSString *const BFAppLinkTargetKeyName;
FOUNDATION_EXPORT NSString *const BFAppLinkUserAgentKeyName;
FOUNDATION_EXPORT NSString *const BFAppLinkExtrasKeyName;
FOUNDATION_EXPORT NSString *const BFAppLinkVersionKeyName;

static id<BFAppLinkResolving> defaultResolver;

@interface BFAppLinkNavigation ()
/*! AppLink events raised in this class */
NSString *const BFAppLinkNavigateOutEventName = @"al_nav_out";
NSString *const BFAppLinkNavigateBackToReferrerEventName = @"al_ref_back_out";

@end
static id<BFAppLinkResolving> defaultResolver;

@implementation BFAppLinkNavigation

Expand Down Expand Up @@ -97,43 +99,105 @@ - (BFAppLinkNavigationType)navigate:(NSError **)error {
}
}

NSURL *appLinkURLToOpen = nil;
NSError *encodingError = nil;
BFAppLinkNavigationType retType = BFAppLinkNavigationTypeFailure;
if (eligibleTarget) {
NSError *encodingError = nil;
NSURL *appLinkURL = [self appLinkURLWithTargetURL:eligibleTarget.URL error:&encodingError];
if (encodingError || !appLinkURL) {
// If there was an error encoding the app link data, fail hard.
NSURL *appLinkAppURL = [self appLinkURLWithTargetURL:eligibleTarget.URL error:&encodingError];
if (encodingError || !appLinkAppURL) {
if (error) {
*error = encodingError;
}
return BFAppLinkNavigationTypeFailure;
}
// Attempt to navigate
if ([[UIApplication sharedApplication] openURL:appLinkURL]) {
return BFAppLinkNavigationTypeApp;
} else if ([[UIApplication sharedApplication] canOpenURL:appLinkAppURL]) {
retType = BFAppLinkNavigationTypeApp;
appLinkURLToOpen = appLinkAppURL;
}
}

// Fall back to opening the url in the browser if available.
if (self.appLink.webURL) {
NSError *encodingError = nil;
NSURL *appLinkURL = [self appLinkURLWithTargetURL:self.appLink.webURL error:&encodingError];
if (encodingError || !appLinkURL) {
if (!appLinkURLToOpen && self.appLink.webURL) {
// Fall back to opening the url in the browser if available.
NSURL *appLinkBrowserURL = [self appLinkURLWithTargetURL:self.appLink.webURL error:&encodingError];
if (encodingError || !appLinkBrowserURL) {
// If there was an error encoding the app link data, fail hard.
if (error) {
*error = encodingError;
}
return BFAppLinkNavigationTypeFailure;
}
// Attempt to navigate
if ([[UIApplication sharedApplication] openURL:appLinkURL]) {
} else if ([[UIApplication sharedApplication] canOpenURL:appLinkBrowserURL]) {
// This was a browser navigation.
return BFAppLinkNavigationTypeBrowser;
retType = BFAppLinkNavigationTypeBrowser;
appLinkURLToOpen = appLinkBrowserURL;
}
}


[self postAppLinkNavigateEventNotificationWithTargetURL:appLinkURLToOpen
error:error ? *error : nil
type:retType];
if (appLinkURLToOpen) {
[[UIApplication sharedApplication] openURL:appLinkURLToOpen];
}
// Otherwise, navigation fails.
return BFAppLinkNavigationTypeFailure;
return retType;
}

- (void) postAppLinkNavigateEventNotificationWithTargetURL:(NSURL *)outputURL error:(NSError *)error type:(BFAppLinkNavigationType)type{
NSString *const EVENT_YES_VAL = @"1";
NSString *const EVENT_NO_VAL = @"0";
NSMutableDictionary *logData = [[NSMutableDictionary alloc] init];

NSString *outputURLScheme = [outputURL scheme];
NSString *outputURLString = [outputURL absoluteString];
if (outputURLScheme) {
logData[@"outputURLScheme"] = outputURLScheme;
}
if (outputURLString) {
logData[@"outputURL"] = outputURLString;
}

NSString *sourceURLString = [self.appLink.sourceURL absoluteString];
NSString *sourceURLHost = [self.appLink.sourceURL host];
NSString *sourceURLScheme = [self.appLink.sourceURL scheme];
if (sourceURLString) {
logData[@"sourceURL"] = sourceURLString;
}
if (sourceURLHost) {
logData[@"sourceHost"] = sourceURLHost;
}
if (sourceURLScheme) {
logData[@"sourceScheme"] = sourceURLScheme;
}
if ([error localizedDescription]) {
logData[@"error"] = [error localizedDescription];
}
NSString *success = nil; //no
NSString *linkType = nil; // unknown;
switch (type) {
case BFAppLinkNavigationTypeFailure:
success = EVENT_NO_VAL;
linkType = @"fail";
break;
case BFAppLinkNavigationTypeBrowser:
success = EVENT_YES_VAL;
linkType = @"web";
break;
case BFAppLinkNavigationTypeApp:
success = EVENT_YES_VAL;
linkType = @"app";
break;
default:
break;
}
if (success) {
logData[@"success"] = success;
}
if (linkType) {
logData[@"type"] = linkType;
}

if ([self.appLink isBackToReferrer]) {
[BFMeasurementEvent postNotificationForEventName:BFAppLinkNavigateBackToReferrerEventName args:logData];
} else {
[BFMeasurementEvent postNotificationForEventName:BFAppLinkNavigateOutEventName args:logData];
}
}

+ (BFTask *)resolveAppLinkInBackground:(NSURL *)destination resolver:(id)resolver {
Expand Down
14 changes: 10 additions & 4 deletions Bolts/BFAppLinkReturnToRefererController.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

#import "BFAppLink.h"
#import "BFAppLinkReturnToRefererView_Internal.h"
#import "BFURL.h"
#import "BFURL_Internal.h"

static const CFTimeInterval kBFViewAnimationDuration = 0.25f;

Expand All @@ -22,7 +22,10 @@ @interface BFAppLinkReturnToRefererController ()

@end

@implementation BFAppLinkReturnToRefererController
@implementation BFAppLinkReturnToRefererController {
BFURL *_lastShownBFUrl;
NSURL *_lastShownUrl;
}

@synthesize view = _view;

Expand Down Expand Up @@ -112,8 +115,11 @@ - (void)showViewForRefererAppLink:(BFAppLink *)refererAppLink {
}

- (void)showViewForRefererURL:(NSURL *)url {
BFURL *bfurl = [BFURL URLWithURL:url];
[self showViewForRefererAppLink:bfurl.appLinkReferer];
if (![_lastShownUrl isEqual:url]) {
_lastShownUrl = [url copy];
_lastShownBFUrl = [BFURL URLForRenderBackToReferrerBarURL:url];
}
[self showViewForRefererAppLink:_lastShownBFUrl.appLinkReferer];
}

- (void)removeFromNavController {
Expand Down
23 changes: 23 additions & 0 deletions Bolts/BFAppLink_Internal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/

#import "BFAppLink.h"

@interface BFAppLink (Internal)

+ (instancetype)appLinkWithSourceURL:(NSURL *)sourceURL
targets:(NSArray *)targets
webURL:(NSURL *)webURL
isBackToReferrer:(BOOL)isBackToReferrer;

/*! return if this AppLink is to go back to referrer. */
- (BOOL)isBackToReferrer;

@end
27 changes: 27 additions & 0 deletions Bolts/BFMeasurementEvent.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/

#import <Foundation/Foundation.h>

/*! The name of the notification posted by BFMeasurementEvent */
FOUNDATION_EXPORT NSString *const BFMeasurementEventNotificationName;

/*! Defines keys in the userInfo object for the notification named BFMeasurementEventNotificationName */
FOUNDATION_EXPORT NSString *const BFMeasurementEventNameKey;
FOUNDATION_EXPORT NSString *const BFMeasurementEventArgsKey;

/*!
* Provides methods for posting notifications from the Bolts framework
*/
@interface BFMeasurementEvent : NSObject

+ (void) postNotificationForEventName:(NSString *)name args:(NSDictionary *)args;

@end
Loading

0 comments on commit 2d2ad8b

Please sign in to comment.