diff --git a/extension-appsflyer/api/appsflyer.script_api b/extension-appsflyer/api/appsflyer.script_api index db9e89d..2bafd08 100644 --- a/extension-appsflyer/api/appsflyer.script_api +++ b/extension-appsflyer/api/appsflyer.script_api @@ -47,6 +47,16 @@ - name: event_params type: table +#***************************************************************************************************** + + - name: get_appsflyer_uid + type: function + + return: + - name: uid + type: string + desc: AppsFlyer's unique device ID + #***************************************************************************************************** - name: CONVERSION_DATA_SUCCESS diff --git a/extension-appsflyer/ext.manifest b/extension-appsflyer/ext.manifest index 7f6daa3..c644c66 100755 --- a/extension-appsflyer/ext.manifest +++ b/extension-appsflyer/ext.manifest @@ -1 +1,7 @@ -name: "AppsflyerExt" \ No newline at end of file +name: "AppsflyerExt" + +platforms: + ios: + context: + frameworks: ["iAd", "AdServices", "AdSupport", "AppTrackingTransparency", "AudioToolbox", "AVFoundation", "CoreGraphics", "CoreMedia", "CoreMotion", "CoreTelephony", "Foundation", "MessageUI", "SafariServices", "StoreKit", "SystemConfiguration", "UIKit", "WebKit"] + linkFlags: ["-ObjC"] \ No newline at end of file diff --git a/extension-appsflyer/lib/ios/AppsFlyerLib.framework/AppsFlyerLib b/extension-appsflyer/lib/ios/AppsFlyerLib.framework/AppsFlyerLib new file mode 100644 index 0000000..0c9475c Binary files /dev/null and b/extension-appsflyer/lib/ios/AppsFlyerLib.framework/AppsFlyerLib differ diff --git a/extension-appsflyer/lib/ios/AppsFlyerLib.framework/Headers/AppsFlyerCrossPromotionHelper.h b/extension-appsflyer/lib/ios/AppsFlyerLib.framework/Headers/AppsFlyerCrossPromotionHelper.h new file mode 100644 index 0000000..483f8f8 --- /dev/null +++ b/extension-appsflyer/lib/ios/AppsFlyerLib.framework/Headers/AppsFlyerCrossPromotionHelper.h @@ -0,0 +1,49 @@ +// +// CrossPromotionHelper.h +// AppsFlyerLib +// +// Created by Gil Meroz on 27/01/2017. +// +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + AppsFlyer allows you to log and attribute installs originating + from cross promotion campaigns of your existing apps. + Afterwards, you can optimize on your cross-promotion traffic to get even better results. + */ +@interface AppsFlyerCrossPromotionHelper : NSObject + +/** + To log an impression use the following API call. + Make sure to use the promoted App ID as it appears within the AppsFlyer dashboard. + + @param appID Promoted App ID + @param campaign A campaign name + @param parameters Additional params like `@{@"af_sub1": @"val", @"custom_param": @"val2" }` +*/ ++ (void)logCrossPromoteImpression:(nonnull NSString *)appID + campaign:(nullable NSString *)campaign + parameters:(nullable NSDictionary *)parameters; + +/** + iOS allows you to utilize the StoreKit component to open + the App Store while remaining in the context of your app. + More details at https://support.appsflyer.com/hc/en-us/articles/115004481946-Cross-Promotion-Tracking#tracking-cross-promotion-impressions + + @param appID Promoted App ID + @param campaign A campaign name + @param parameters Additional params like `@{@"af_sub1": @"val", @"custom_param": @"val2" }` + @param openStoreBlock Contains promoted `clickURL` + */ ++ (void)logAndOpenStore:(nonnull NSString *)appID + campaign:(nullable NSString *)campaign + parameters:(nullable NSDictionary *)parameters + openStore:(void (^)(NSURLSession *urlSession, NSURL *clickURL))openStoreBlock; + +@end + +NS_ASSUME_NONNULL_END diff --git a/extension-appsflyer/lib/ios/AppsFlyerLib.framework/Headers/AppsFlyerDeepLink.h b/extension-appsflyer/lib/ios/AppsFlyerLib.framework/Headers/AppsFlyerDeepLink.h new file mode 100644 index 0000000..f099ace --- /dev/null +++ b/extension-appsflyer/lib/ios/AppsFlyerLib.framework/Headers/AppsFlyerDeepLink.h @@ -0,0 +1,36 @@ +// +// AFSDKDeeplink.h +// AppsFlyerLib +// +// Created by Andrii Hahan on 20.08.2020. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +NS_SWIFT_NAME(DeepLink) +@interface AppsFlyerDeepLink : NSObject + +- (nonnull instancetype)init NS_UNAVAILABLE; ++ (nonnull instancetype)new NS_UNAVAILABLE; + +@property (readonly, nonnull) NSDictionary *clickEvent; +@property (readonly, nullable) NSString *deeplinkValue; +@property (readonly, nullable) NSString *matchType; +@property (readonly, nullable) NSString *clickHTTPReferrer; +@property (readonly, nullable) NSString *mediaSource; +@property (readonly, nullable) NSString *campaign; +@property (readonly, nullable) NSString *campaignId; +@property (readonly, nullable) NSString *afSub1; +@property (readonly, nullable) NSString *afSub2; +@property (readonly, nullable) NSString *afSub3; +@property (readonly, nullable) NSString *afSub4; +@property (readonly, nullable) NSString *afSub5; +@property (readonly) BOOL isDeferred; + +- (NSString *)toString; + +@end + +NS_ASSUME_NONNULL_END diff --git a/extension-appsflyer/lib/ios/AppsFlyerLib.framework/Headers/AppsFlyerDeepLinkResult.h b/extension-appsflyer/lib/ios/AppsFlyerLib.framework/Headers/AppsFlyerDeepLinkResult.h new file mode 100644 index 0000000..50d41d7 --- /dev/null +++ b/extension-appsflyer/lib/ios/AppsFlyerLib.framework/Headers/AppsFlyerDeepLinkResult.h @@ -0,0 +1,29 @@ +// +// AFSDKDeeplinkResult.h +// AppsFlyerLib +// +// Created by Andrii Hahan on 20.08.2020. +// + +#import + +@class AppsFlyerDeepLink; + +typedef NS_CLOSED_ENUM(NSUInteger, AFSDKDeepLinkResultStatus) { + AFSDKDeepLinkResultStatusNotFound, + AFSDKDeepLinkResultStatusFound, + AFSDKDeepLinkResultStatusFailure, +} NS_SWIFT_NAME(DeepLinkResultStatus); + +NS_SWIFT_NAME(DeepLinkResult) +@interface AppsFlyerDeepLinkResult : NSObject + +- (nonnull instancetype)init NS_UNAVAILABLE; ++ (nonnull instancetype)new NS_UNAVAILABLE; + +@property(readonly) AFSDKDeepLinkResultStatus status; + +@property(readonly, nullable) AppsFlyerDeepLink *deepLink; +@property(readonly, nullable) NSError *error; + +@end diff --git a/extension-appsflyer/lib/ios/AppsFlyerLib.framework/Headers/AppsFlyerLib.h b/extension-appsflyer/lib/ios/AppsFlyerLib.framework/Headers/AppsFlyerLib.h new file mode 100644 index 0000000..0b900a9 --- /dev/null +++ b/extension-appsflyer/lib/ios/AppsFlyerLib.framework/Headers/AppsFlyerLib.h @@ -0,0 +1,696 @@ +// +// AppsFlyerLib.h +// AppsFlyerLib +// +// AppsFlyer iOS SDK 6.10.1 (109) +// Copyright (c) 2012-2023 AppsFlyer Ltd. All rights reserved. +// + +#import + +#import +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +// In app event names constants +#define AFEventLevelAchieved @"af_level_achieved" +#define AFEventAddPaymentInfo @"af_add_payment_info" +#define AFEventAddToCart @"af_add_to_cart" +#define AFEventAddToWishlist @"af_add_to_wishlist" +#define AFEventCompleteRegistration @"af_complete_registration" +#define AFEventTutorial_completion @"af_tutorial_completion" +#define AFEventInitiatedCheckout @"af_initiated_checkout" +#define AFEventPurchase @"af_purchase" +#define AFEventRate @"af_rate" +#define AFEventSearch @"af_search" +#define AFEventSpentCredits @"af_spent_credits" +#define AFEventAchievementUnlocked @"af_achievement_unlocked" +#define AFEventContentView @"af_content_view" +#define AFEventListView @"af_list_view" +#define AFEventTravelBooking @"af_travel_booking" +#define AFEventShare @"af_share" +#define AFEventInvite @"af_invite" +#define AFEventLogin @"af_login" +#define AFEventReEngage @"af_re_engage" +#define AFEventUpdate @"af_update" +#define AFEventOpenedFromPushNotification @"af_opened_from_push_notification" +#define AFEventLocation @"af_location_coordinates" +#define AFEventCustomerSegment @"af_customer_segment" + +#define AFEventSubscribe @"af_subscribe" +#define AFEventStartTrial @"af_start_trial" +#define AFEventAdClick @"af_ad_click" +#define AFEventAdView @"af_ad_view" + +// In app event parameter names +#define AFEventParamContent @"af_content" +#define AFEventParamAchievementId @"af_achievement_id" +#define AFEventParamLevel @"af_level" +#define AFEventParamScore @"af_score" +#define AFEventParamSuccess @"af_success" +#define AFEventParamPrice @"af_price" +#define AFEventParamContentType @"af_content_type" +#define AFEventParamContentId @"af_content_id" +#define AFEventParamContentList @"af_content_list" +#define AFEventParamCurrency @"af_currency" +#define AFEventParamQuantity @"af_quantity" +#define AFEventParamRegistrationMethod @"af_registration_method" +#define AFEventParamPaymentInfoAvailable @"af_payment_info_available" +#define AFEventParamMaxRatingValue @"af_max_rating_value" +#define AFEventParamRatingValue @"af_rating_value" +#define AFEventParamSearchString @"af_search_string" +#define AFEventParamDateA @"af_date_a" +#define AFEventParamDateB @"af_date_b" +#define AFEventParamDestinationA @"af_destination_a" +#define AFEventParamDestinationB @"af_destination_b" +#define AFEventParamDescription @"af_description" +#define AFEventParamClass @"af_class" +#define AFEventParamEventStart @"af_event_start" +#define AFEventParamEventEnd @"af_event_end" +#define AFEventParamLat @"af_lat" +#define AFEventParamLong @"af_long" +#define AFEventParamCustomerUserId @"af_customer_user_id" +#define AFEventParamValidated @"af_validated" +#define AFEventParamRevenue @"af_revenue" +#define AFEventProjectedParamRevenue @"af_projected_revenue" +#define AFEventParamReceiptId @"af_receipt_id" +#define AFEventParamTutorialId @"af_tutorial_id" +#define AFEventParamVirtualCurrencyName @"af_virtual_currency_name" +#define AFEventParamDeepLink @"af_deep_link" +#define AFEventParamOldVersion @"af_old_version" +#define AFEventParamNewVersion @"af_new_version" +#define AFEventParamReviewText @"af_review_text" +#define AFEventParamCouponCode @"af_coupon_code" +#define AFEventParamOrderId @"af_order_id" +#define AFEventParam1 @"af_param_1" +#define AFEventParam2 @"af_param_2" +#define AFEventParam3 @"af_param_3" +#define AFEventParam4 @"af_param_4" +#define AFEventParam5 @"af_param_5" +#define AFEventParam6 @"af_param_6" +#define AFEventParam7 @"af_param_7" +#define AFEventParam8 @"af_param_8" +#define AFEventParam9 @"af_param_9" +#define AFEventParam10 @"af_param_10" +#define AFEventParamTouch @"af_touch_obj" + +#define AFEventParamDepartingDepartureDate @"af_departing_departure_date" +#define AFEventParamReturningDepartureDate @"af_returning_departure_date" +#define AFEventParamDestinationList @"af_destination_list" //array of string +#define AFEventParamCity @"af_city" +#define AFEventParamRegion @"af_region" +#define AFEventParamCountry @"af_country" + + +#define AFEventParamDepartingArrivalDate @"af_departing_arrival_date" +#define AFEventParamReturningArrivalDate @"af_returning_arrival_date" +#define AFEventParamSuggestedDestinations @"af_suggested_destinations" //array of string +#define AFEventParamTravelStart @"af_travel_start" +#define AFEventParamTravelEnd @"af_travel_end" +#define AFEventParamNumAdults @"af_num_adults" +#define AFEventParamNumChildren @"af_num_children" +#define AFEventParamNumInfants @"af_num_infants" +#define AFEventParamSuggestedHotels @"af_suggested_hotels" //array of string + +#define AFEventParamUserScore @"af_user_score" +#define AFEventParamHotelScore @"af_hotel_score" +#define AFEventParamPurchaseCurrency @"af_purchase_currency" + +#define AFEventParamPreferredStarRatings @"af_preferred_star_ratings" //array of int (basically a tuple (min,max) but we'll use array of int and instruct the developer to use two values) + +#define AFEventParamPreferredPriceRange @"af_preferred_price_range" //array of int (basically a tuple (min,max) but we'll use array of int and instruct the developer to use two values) +#define AFEventParamPreferredNeighborhoods @"af_preferred_neighborhoods" //array of string +#define AFEventParamPreferredNumStops @"af_preferred_num_stops" + +#define AFEventParamAdRevenueAdType @"af_adrev_ad_type" +#define AFEventParamAdRevenueNetworkName @"af_adrev_network_name" +#define AFEventParamAdRevenuePlacementId @"af_adrev_placement_id" +#define AFEventParamAdRevenueAdSize @"af_adrev_ad_size" +#define AFEventParamAdRevenueMediatedNetworkName @"af_adrev_mediated_network_name" + + +/// Mail hashing type +typedef enum { + /// None + EmailCryptTypeNone = 0, + /// SHA256 + EmailCryptTypeSHA256 = 3 +} EmailCryptType; + +typedef NS_CLOSED_ENUM (NSInteger ,AFSDKPlugin) { + AFSDKPluginIOSNative, + AFSDKPluginUnity, + AFSDKPluginFlutter, + AFSDKPluginReactNative, + AFSDKPluginAdobeAir, + AFSDKPluginAdobeMobile, + AFSDKPluginCocos2dx, + AFSDKPluginCordova, + AFSDKPluginMparticle, + AFSDKPluginNativeScript, + AFSDKPluginExpo, + AFSDKPluginUnreal, + AFSDKPluginXamarin, + AFSDKPluginCapacitor, + AFSDKPluginSegment, + AFSDKPluginAdobeSwiftAEP +} NS_SWIFT_NAME(Plugin); + +@class AFSDKPluginInfo; + +NS_SWIFT_NAME(DeepLinkDelegate) +@protocol AppsFlyerDeepLinkDelegate + +@optional +- (void)didResolveDeepLink:(AppsFlyerDeepLinkResult *_Nonnull)result; + +@end + +/** + Conform and subscribe to this protocol to allow getting data about conversion and + install attribution + */ +@protocol AppsFlyerLibDelegate + +/** + `conversionInfo` contains information about install. + Organic/non-organic, etc. + @param conversionInfo May contain null values for some keys. Please handle this case. + */ +- (void)onConversionDataSuccess:(NSDictionary *)conversionInfo; + +/** + Any errors that occurred during the conversion request. + */ +- (void)onConversionDataFail:(NSError *)error; + +@optional + +/** + `attributionData` contains information about OneLink, deeplink. + */ +- (void)onAppOpenAttribution:(NSDictionary *)attributionData; + +/** + Any errors that occurred during the attribution request. + */ +- (void)onAppOpenAttributionFailure:(NSError *)error; + +/** + @abstract Sets the HTTP header fields of the ESP resolving to the given + dictionary. + @discussion This method replaces all header fields that may have + existed before this method ESP resolving call. + To keep default SDK behavior - return nil; + */ +- (NSDictionary * _Nullable)allHTTPHeaderFieldsForResolveDeepLinkURL:(NSURL *)URL; + +@end + +/** + You can log installs, app updates, sessions and additional in-app events + (including in-app purchases, game levels, etc.) + to evaluate ROI and user engagement. + The iOS SDK is compatible with all iOS/tvOS devices with iOS version 7 and above. + + @see [SDK Integration Validator](https://support.appsflyer.com/hc/en-us/articles/207032066-AppsFlyer-SDK-Integration-iOS) + for more information. + + */ +@interface AppsFlyerLib : NSObject + +/** + Gets the singleton instance of the AppsFlyerLib class, creating it if + necessary. + + @return The singleton instance of AppsFlyerLib. + */ ++ (AppsFlyerLib *)shared; + + +- (void)setUpInteroperabilityObject:(id)object; + +/** + In case you use your own user ID in your app, you can set this property to that ID. + Enables you to cross-reference your own unique ID with AppsFlyer’s unique ID and the other devices’ IDs + */ +@property(nonatomic, strong, nullable) NSString * customerUserID; + +/** + In case you use custom data and you want to receive it in the raw reports. + + @see [Setting additional custom data](https://support.appsflyer.com/hc/en-us/articles/207032066-AppsFlyer-SDK-Integration-iOS#setting-additional-custom-data) for more information. + */ +@property(nonatomic, strong, nullable, setter = setAdditionalData:) NSDictionary * customData; + +/** + Use this property to set your AppsFlyer's dev key + */ +@property(nonatomic, strong) NSString * appsFlyerDevKey; + +/** + Use this property to set your app's Apple ID(taken from the app's page on iTunes Connect) + */ +@property(nonatomic, strong) NSString * appleAppID; + +#ifndef AFSDK_NO_IDFA +/** + AppsFlyer SDK collect Apple's `advertisingIdentifier` if the `AdSupport.framework` included in the SDK. + You can disable this behavior by setting the following property to YES +*/ +@property(nonatomic) BOOL disableAdvertisingIdentifier; + +@property(nonatomic, strong, readonly) NSString *advertisingIdentifier; + +/** + Waits for request user authorization to access app-related data + */ +- (void)waitForATTUserAuthorizationWithTimeoutInterval:(NSTimeInterval)timeoutInterval +NS_SWIFT_NAME(waitForATTUserAuthorization(timeoutInterval:)); + +#endif + +@property(nonatomic) BOOL disableSKAdNetwork; + +/** + In case of in app purchase events, you can set the currency code your user has purchased with. + The currency code is a 3 letter code according to ISO standards + + Objective-C: + +
+ [[AppsFlyerLib shared] setCurrencyCode:@"USD"];
+ 
+ + Swift: + +
+ AppsFlyerLib.shared().currencyCode = "USD"
+ 
+ */ +@property(nonatomic, strong, nullable) NSString *currencyCode; + +/** + Prints SDK messages to the console log. This property should only be used in `DEBUG` mode. + The default value is `NO` + */ +@property(nonatomic) BOOL isDebug; + +/** + Set this flag to `YES`, to collect the current device name(e.g. "My iPhone"). Default value is `NO` + */ +@property(nonatomic) BOOL shouldCollectDeviceName; + +/** + Set your `OneLink ID` from OneLink configuration. Used in User Invites to generate a OneLink. + */ +@property(nonatomic, strong, nullable, setter = setAppInviteOneLink:) NSString * appInviteOneLinkID; + +/** + Opt-out logging for specific user + */ +@property(atomic) BOOL anonymizeUser; + +/** + Opt-out for Apple Search Ads attributions + */ +@property(atomic) BOOL disableCollectASA; + +/** + Disable Apple Ads Attribution API +[AAAtribution attributionTokenWithError:] + */ +@property(nonatomic) BOOL disableAppleAdsAttribution; + +/** + AppsFlyer delegate. See `AppsFlyerLibDelegate` + */ +@property(weak, nonatomic) id delegate; + +@property(weak, nonatomic) id deepLinkDelegate; + +/** + In app purchase receipt validation Apple environment(production or sandbox). The default value is NO + */ +@property(nonatomic) BOOL useReceiptValidationSandbox; + +/** + Set this flag to test uninstall on Apple environment(production or sandbox). The default value is NO + */ +@property(nonatomic) BOOL useUninstallSandbox; + +/** + For advertisers who wrap OneLink within another Universal Link. + An advertiser will be able to deeplink from a OneLink wrapped within another Universal Link and also log this retargeting conversion. + + Objective-C: + +
+ [[AppsFlyerLib shared] setResolveDeepLinkURLs:@[@"domain.com", @"subdomain.domain.com"]];
+ 
+ */ +@property(nonatomic, nullable) NSArray *resolveDeepLinkURLs; + +/** + For advertisers who use vanity OneLinks. + + Objective-C: + +
+ [[AppsFlyerLib shared] oneLinkCustomDomains:@[@"domain.com", @"subdomain.domain.com"]];
+ 
+ */ +@property(nonatomic, nullable) NSArray *oneLinkCustomDomains; + +/* + * Set phone number for each `start` event. `phoneNumber` will be sent as SHA256 string + */ +@property(nonatomic, nullable) NSString *phoneNumber; + +- (NSString *)phoneNumber UNAVAILABLE_ATTRIBUTE; + +/** + To disable app's vendor identifier(IDFV), set disableIDFVCollection to true + */ +@property(nonatomic) BOOL disableIDFVCollection; + +/** + Set the language of the device. The data will be displayed in Raw Data Reports + Objective-C: + +
+ [[AppsFlyerLib shared] setCurrentDeviceLanguage:@"EN"]
+ 
+ + Swift: + +
+ AppsFlyerLib.shared().currentDeviceLanguage("EN")
+ 
+ */ +@property(nonatomic, nullable) NSString *currentDeviceLanguage; + +/** + Internal API. Please don't use. + */ +- (void)setPluginInfoWith:(AFSDKPlugin)plugin pluginVersion:(NSString *)version additionalParams:(NSDictionary * _Nullable)additionalParams +NS_SWIFT_NAME(setPluginInfo(plugin:version:additionalParams:)); +/** + Enable the collection of Facebook Deferred AppLinks + Requires Facebook SDK and Facebook app on target/client device. + This API must be invoked prior to initializing the AppsFlyer SDK in order to function properly. + + Objective-C: + +
+ [[AppsFlyerLib shared] enableFacebookDeferredApplinksWithClass:[FBSDKAppLinkUtility class]]
+ 
+ + Swift: + +
+ AppsFlyerLib.shared().enableFacebookDeferredApplinks(with: FBSDKAppLinkUtility.self)
+ 
+ + @param facebookAppLinkUtilityClass requeries method call `[FBSDKAppLinkUtility class]` as param. + */ +- (void)enableFacebookDeferredApplinksWithClass:(Class _Nullable)facebookAppLinkUtilityClass; + +/** + Use this to send the user's emails + + @param userEmails The list of strings that hold mails + @param type Hash algoritm + */ +- (void)setUserEmails:(NSArray * _Nullable)userEmails withCryptType:(EmailCryptType)type; + +/** + Start SDK session + Add the following method at the `applicationDidBecomeActive` in AppDelegate class + */ +- (void)start; + +- (void)startWithCompletionHandler:(void (^ _Nullable)(NSDictionary * _Nullable dictionary, NSError * _Nullable error))completionHandler; + +/** + Use this method to log an events with multiple values. See AppsFlyer's documentation for details. + + Objective-C: + +
+ [[AppsFlyerLib shared] logEvent:AFEventPurchase
+        withValues: @{AFEventParamRevenue  : @200,
+                      AFEventParamCurrency : @"USD",
+                      AFEventParamQuantity : @2,
+                      AFEventParamContentId: @"092",
+                      AFEventParamReceiptId: @"9277"}];
+ 
+ + Swift: + +
+ AppsFlyerLib.shared().logEvent(AFEventPurchase,
+        withValues: [AFEventParamRevenue  : "1200",
+                     AFEventParamContent  : "shoes",
+                     AFEventParamContentId: "123"])
+ 
+ + @param eventName Contains name of event that could be provided from predefined constants in `AppsFlyerLib.h` + @param values Contains dictionary of values for handling by backend + */ +- (void)logEvent:(NSString *)eventName withValues:(NSDictionary * _Nullable)values; + +- (void)logEventWithEventName:(NSString *)eventName + eventValues:(NSDictionary * _Nullable)eventValues + completionHandler:(void (^ _Nullable)(NSDictionary * _Nullable dictionary, NSError * _Nullable error))completionHandler +NS_SWIFT_NAME(logEvent(name:values:completionHandler:)); + +/** + To log and validate in app purchases you can call this method from the completeTransaction: method on + your `SKPaymentTransactionObserver`. + + @param productIdentifier The product identifier + @param price The product price + @param currency The product currency + @param transactionId The purchase transaction Id + @param params The additional param, which you want to receive it in the raw reports + @param successBlock The success callback + @param failedBlock The failure callback + */ +- (void)validateAndLogInAppPurchase:(NSString * _Nullable)productIdentifier + price:(NSString * _Nullable)price + currency:(NSString * _Nullable)currency + transactionId:(NSString * _Nullable)transactionId + additionalParameters:(NSDictionary * _Nullable)params + success:(void (^ _Nullable)(NSDictionary * response))successBlock + failure:(void (^ _Nullable)(NSError * _Nullable error, id _Nullable reponse))failedBlock NS_AVAILABLE(10_7, 7_0); + +/** + To log location for geo-fencing. Does the same as code below. + +
+ AppsFlyerLib.shared().logEvent(AFEventLocation, withValues: [AFEventParamLong:longitude, AFEventParamLat:latitude])
+ 
+ + @param longitude The location longitude + @param latitude The location latitude + */ +- (void)logLocation:(double)longitude latitude:(double)latitude NS_SWIFT_NAME(logLocation(longitude:latitude:)); + +/** + This method returns AppsFlyer's internal id(unique for your app) + + @return Internal AppsFlyer Id + */ +- (NSString *)getAppsFlyerUID; + +/** + In case you want to log deep linking. Does the same as `-handleOpenURL:sourceApplication:withAnnotation`. + + @warning Preferred to use `-handleOpenURL:sourceApplication:withAnnotation`. + + @param url The URL that was passed to your AppDelegate. + @param sourceApplication The sourceApplication that passed to your AppDelegate. + */ +- (void)handleOpenURL:(NSURL * _Nullable)url sourceApplication:(NSString * _Nullable)sourceApplication API_UNAVAILABLE(macos); + +/** + In case you want to log deep linking. + Call this method from inside your AppDelegate `-application:openURL:sourceApplication:annotation:` + + @param url The URL that was passed to your AppDelegate. + @param sourceApplication The sourceApplication that passed to your AppDelegate. + @param annotation The annotation that passed to your app delegate. + */ +- (void)handleOpenURL:(NSURL * _Nullable)url + sourceApplication:(NSString * _Nullable)sourceApplication + withAnnotation:(id _Nullable)annotation API_UNAVAILABLE(macos); + +/** + Call this method from inside of your AppDelegate `-application:openURL:options:` method. + This method is functionally the same as calling the AppsFlyer method + `-handleOpenURL:sourceApplication:withAnnotation`. + + @param url The URL that was passed to your app delegate + @param options The options dictionary that was passed to your AppDelegate. + */ +- (void)handleOpenUrl:(NSURL * _Nullable)url options:(NSDictionary * _Nullable)options API_UNAVAILABLE(macos); + +/** + Allow AppsFlyer to handle restoration from an NSUserActivity. + Use this method to log deep links with OneLink. + + @param userActivity The NSUserActivity that caused the app to be opened. + */ +- (BOOL)continueUserActivity:(NSUserActivity * _Nullable)userActivity + restorationHandler:(void (^ _Nullable)(NSArray * _Nullable))restorationHandler NS_AVAILABLE_IOS(9_0) API_UNAVAILABLE(macos); + +/** + Enable AppsFlyer to handle a push notification. + + @see [Learn more here](https://support.appsflyer.com/hc/en-us/articles/207364076-Measuring-Push-Notification-Re-Engagement-Campaigns) + + @warning To make it work - set data, related to AppsFlyer under key @"af". + + @param pushPayload The `userInfo` from received remote notification. One of root keys should be @"af". + */ +- (void)handlePushNotification:(NSDictionary * _Nullable)pushPayload; + + +/** + Register uninstall - you should register for remote notification and provide AppsFlyer the push device token. + + @param deviceToken The `deviceToken` from `-application:didRegisterForRemoteNotificationsWithDeviceToken:` + */ +- (void)registerUninstall:(NSData * _Nullable)deviceToken; + +/** + Get SDK version. + + @return The AppsFlyer SDK version info. + */ +- (NSString *)getSDKVersion; + +/** + This is for internal use. + */ +- (void)remoteDebuggingCallWithData:(NSString *)data; + +/** + Used to force the trigger `onAppOpenAttribution` delegate. + Notice, re-engagement, session and launch won't be counted. + Only for OneLink/UniversalLink/Deeplink resolving. + + @param URL The param to resolve into -[AppsFlyerLibDelegate onAppOpenAttribution:] + */ +- (void)performOnAppAttributionWithURL:(NSURL * _Nullable)URL; + +/** + @brief This property accepts a string value representing the host name for all endpoints. + Can be used to Zero rate your application’s data usage. Contact your CSM for more information. + + @warning To use `default` SDK endpoint – set value to `nil`. + + Objective-C: + +
+ [[AppsFlyerLib shared] setHost:@"example.com"];
+ 
+ + Swift: + +
+ AppsFlyerLib.shared().host = "example.com"
+ 
+ */ +@property(nonatomic, strong, readonly) NSString *host; + +/** + * This function set the host name and prefix host name for all the endpoints + **/ +- (void)setHost:(NSString *)host withHostPrefix:(NSString *)hostPrefix; + +/** + * This property accepts a string value representing the prefix host name for all endpoints. + * for example "test" prefix with default host name will have the address "host.appsflyer.com" + */ +@property(nonatomic, strong, readonly) NSString *hostPrefix; + +/** + This property is responsible for timeout between sessions in seconds. + Default value is 5 seconds. + */ +@property(atomic) NSUInteger minTimeBetweenSessions; + +/** + API to shut down all SDK activities. + + @warning This will disable all requests from AppsFlyer SDK. + */ +@property(atomic) BOOL isStopped; + +/** + API to set manually Facebook deferred app link + */ +@property(nonatomic, nullable) NSURL *facebookDeferredAppLink; + +/** + Block an events from being shared with ad networks and other 3rd party integrations + Must only include letters/digits or underscore, maximum length: 45 + */ +@property(nonatomic, nullable) NSArray *sharingFilter DEPRECATED_MSG_ATTRIBUTE("starting SDK version 6.4.0, please use `setSharingFilterForPartners:`"); + +@property(nonatomic) NSUInteger deepLinkTimeout; + +/** + Block an events from being shared with any partner + This method overwrite -[AppsFlyerLib setSharingFilter:] + */ +- (void)setSharingFilterForAllPartners DEPRECATED_MSG_ATTRIBUTE("starting SDK version 6.4.0, please use `setSharingFilterForPartners:`"); + +/** + Block an events from being shared with ad networks and other 3rd party integrations + Must only include letters/digits or underscore, maximum length: 45 + + The sharing filter is cleared in case if `nil` or empty array passed as a parameter. + "all" keyword sets sharing filter for ALL partners, it is case insencitive and has highest priority + if passed along with another values. For example, if ["all", "examplePartner1_int", "examplePartner2_int" ] passed, + the sharing filter will be set for ALL partners. + */ +- (void)setSharingFilterForPartners:(NSArray * _Nullable)sharingFilter; + +/** + Validate if URL contains certain string and append quiery + parameters to deeplink URL. In case if URL does not contain user-defined string, + parameters are not appended to the url. + + @param containsString string to check in URL. + @param parameters NSDictionary, which containins parameters to append to the deeplink url after it passed validation. + */ +- (void)appendParametersToDeepLinkingURLWithString:(NSString *)containsString + parameters:(NSDictionary *)parameters +NS_SWIFT_NAME(appendParametersToDeeplinkURL(contains:parameters:)); + +/** + Adds array of keys, which are used to compose key path + to resolve deeplink from push notification payload `userInfo`. + + @param deepLinkPath an array of strings which contains keys to search for deeplink in payload. + */ +- (void)addPushNotificationDeepLinkPath:(NSArray *)deepLinkPath; + +/** + * Allows sending custom data for partner integration purposes. + * + * @param partnerId ID of the partner (usually has "_int" suffix) + * @param partnerInfo customer data, depends on the integration nature with specific partner + */ + +- (void)setPartnerDataWithPartnerId:(NSString * _Nullable)partnerId partnerInfo:(NSDictionary * _Nullable)partnerInfo +NS_SWIFT_NAME(setPartnerData(partnerId:partnerInfo:)); + +@end + +NS_ASSUME_NONNULL_END diff --git a/extension-appsflyer/lib/ios/AppsFlyerLib.framework/Headers/AppsFlyerLinkGenerator.h b/extension-appsflyer/lib/ios/AppsFlyerLib.framework/Headers/AppsFlyerLinkGenerator.h new file mode 100644 index 0000000..b917074 --- /dev/null +++ b/extension-appsflyer/lib/ios/AppsFlyerLib.framework/Headers/AppsFlyerLinkGenerator.h @@ -0,0 +1,52 @@ +// +// LinkGenerator.h +// AppsFlyerLib +// +// Created by Gil Meroz on 27/01/2017. +// +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + Payload container for the `generateInviteUrlWithLinkGenerator:completionHandler:` from `AppsFlyerShareInviteHelper` + */ +@interface AppsFlyerLinkGenerator : NSObject + +/// Instance initialization is not allowed. Use generated instance +/// from `-[AppsFlyerShareInviteHelper generateInviteUrlWithLinkGenerator:completionHandler]` +- (instancetype)init NS_UNAVAILABLE; +/// Instance initialization is not allowed. Use generated instance +/// from `-[AppsFlyerShareInviteHelper generateInviteUrlWithLinkGenerator:completionHandler]` ++ (instancetype)new NS_UNAVAILABLE; + +@property(nonatomic, nullable) NSString *brandDomain; + +/// The channel through which the invite was sent (e.g. Facebook/Gmail/etc.). Usage: Recommended +- (void)setChannel :(nonnull NSString *)channel; +/// ReferrerCustomerId setter +- (void)setReferrerCustomerId:(nonnull NSString *)referrerCustomerId; +/// A campaign name. Usage: Optional +- (void)setCampaign :(nonnull NSString *)campaign; +/// ReferrerUID setter +- (void)setReferrerUID :(nonnull NSString *)referrerUID; +/// Referrer name +- (void)setReferrerName :(nonnull NSString *)referrerName; +/// The URL to referrer user avatar. Usage: Optional +- (void)setReferrerImageURL :(nonnull NSString *)referrerImageURL; +/// AppleAppID +- (void)setAppleAppID :(nonnull NSString *)appleAppID; +/// Deeplink path +- (void)setDeeplinkPath :(nonnull NSString *)deeplinkPath; +/// Base deeplink path +- (void)setBaseDeeplink :(nonnull NSString *)baseDeeplink; +/// A single key value custom parameter. Usage: Optional +- (void)addParameterValue :(nonnull NSString *)value forKey:(NSString *)key; +/// Multiple key value custom parameters. Usage: Optional +- (void)addParameters :(nonnull NSDictionary *)parameters; + +@end + +NS_ASSUME_NONNULL_END diff --git a/extension-appsflyer/lib/ios/AppsFlyerLib.framework/Headers/AppsFlyerShareInviteHelper.h b/extension-appsflyer/lib/ios/AppsFlyerLib.framework/Headers/AppsFlyerShareInviteHelper.h new file mode 100644 index 0000000..f55dbf9 --- /dev/null +++ b/extension-appsflyer/lib/ios/AppsFlyerLib.framework/Headers/AppsFlyerShareInviteHelper.h @@ -0,0 +1,35 @@ +// +// ShareInviteHelper.h +// AppsFlyerLib +// +// Created by Gil Meroz on 27/01/2017. +// +// + +#import +#import + +/** + AppsFlyerShareInviteHelper + */ +@interface AppsFlyerShareInviteHelper : NSObject + +NS_ASSUME_NONNULL_BEGIN + +/** + * The AppsFlyerShareInviteHelper class builds the invite URL according to various setter methods + * which allow passing on additional information on the click. + * This information is available through `onConversionDataReceived:` when the user accepts the invite and installs the app. + * In addition, campaign and channel parameters are visible within the AppsFlyer Dashboard. + */ ++ (void)generateInviteUrlWithLinkGenerator:(AppsFlyerLinkGenerator *(^)(AppsFlyerLinkGenerator *generator))generatorCreator completionHandler:(void (^)(NSURL *_Nullable url))completionHandler; + +/** + * It is recommended to generate an in-app event after the invite is sent to log the invites from the senders' perspective. + * This enables you to find the users that tend most to invite friends, and the media sources that get you these users. + */ ++ (void)logInvite:(nullable NSString *)channel parameters:(nullable NSDictionary *)parameters; + +@end + +NS_ASSUME_NONNULL_END diff --git a/extension-appsflyer/lib/ios/AppsFlyerLib.framework/Info.plist b/extension-appsflyer/lib/ios/AppsFlyerLib.framework/Info.plist new file mode 100644 index 0000000..968f409 Binary files /dev/null and b/extension-appsflyer/lib/ios/AppsFlyerLib.framework/Info.plist differ diff --git a/extension-appsflyer/lib/ios/AppsFlyerLib.framework/Modules/module.modulemap b/extension-appsflyer/lib/ios/AppsFlyerLib.framework/Modules/module.modulemap new file mode 100644 index 0000000..96f59b3 --- /dev/null +++ b/extension-appsflyer/lib/ios/AppsFlyerLib.framework/Modules/module.modulemap @@ -0,0 +1,6 @@ +framework module AppsFlyerLib { + umbrella header "AppsFlyerLib.h" + + export * + module * { export * } +} diff --git a/extension-appsflyer/manifests/android/.gradle/7.4.2/fileChanges/last-build.bin b/extension-appsflyer/manifests/android/.gradle/7.4.2/fileChanges/last-build.bin new file mode 100644 index 0000000..f76dd23 Binary files /dev/null and b/extension-appsflyer/manifests/android/.gradle/7.4.2/fileChanges/last-build.bin differ diff --git a/extension-appsflyer/manifests/android/build.gradle b/extension-appsflyer/manifests/android/build.gradle index 295088f..41b18f9 100644 --- a/extension-appsflyer/manifests/android/build.gradle +++ b/extension-appsflyer/manifests/android/build.gradle @@ -1,5 +1,8 @@ +repositories { + mavenCentral() +} dependencies { //make sure to use the latest SDK version: https://mvnrepository.com/artifact/com.appsflyer/af-android-sdk - implementation 'com.appsflyer:af-android-sdk:6.3.2' + implementation 'com.appsflyer:af-android-sdk:6.10.2' implementation 'com.android.installreferrer:installreferrer:2.2' } diff --git a/extension-appsflyer/manifests/ios/Info.plist b/extension-appsflyer/manifests/ios/Info.plist new file mode 100644 index 0000000..c3c3e09 --- /dev/null +++ b/extension-appsflyer/manifests/ios/Info.plist @@ -0,0 +1,8 @@ + + + + + NSAdvertisingAttributionReportEndpoint + https://appsflyer-skadnetwork.com/ + + \ No newline at end of file diff --git a/extension-appsflyer/res/android/com/appsflyer/internal/a- b/extension-appsflyer/res/android/com/appsflyer/internal/a- index 520c7df..dad4a68 100644 Binary files a/extension-appsflyer/res/android/com/appsflyer/internal/a- and b/extension-appsflyer/res/android/com/appsflyer/internal/a- differ diff --git a/extension-appsflyer/res/android/com/appsflyer/internal/b- b/extension-appsflyer/res/android/com/appsflyer/internal/b- index 9149aae..4fa7f17 100644 Binary files a/extension-appsflyer/res/android/com/appsflyer/internal/b- and b/extension-appsflyer/res/android/com/appsflyer/internal/b- differ diff --git a/extension-appsflyer/src/AppsFlyerAttribution.h b/extension-appsflyer/src/AppsFlyerAttribution.h new file mode 100644 index 0000000..79f4852 --- /dev/null +++ b/extension-appsflyer/src/AppsFlyerAttribution.h @@ -0,0 +1,34 @@ +// +// AppsFlyerAttribution.h +// UnityFramework +// +// Created by Margot Guetta on 11/04/2021. +// + +#ifndef AppsFlyerAttribution_h +#define AppsFlyerAttribution_h +#endif /* AppsFlyerAttribution_h */ +#if __has_include() +#import +#else +#import "AppsFlyerLib.h" +#endif + + +@interface AppsFlyerAttribution : NSObject +@property NSUserActivity*_Nullable userActivity; +@property (nonatomic, copy) void (^ _Nullable restorationHandler)(NSArray *_Nullable ); +@property NSURL * _Nullable url; +@property NSDictionary * _Nullable options; +@property NSString* _Nullable sourceApplication; +@property id _Nullable annotation; +@property BOOL isBridgeReady; + ++ (AppsFlyerAttribution *_Nullable)shared; +- (void) continueUserActivity: (NSUserActivity*_Nullable) userActivity restorationHandler: (void (^_Nullable)(NSArray * _Nullable))restorationHandler; +- (void) handleOpenUrl:(NSURL*_Nullable)url options:(NSDictionary*_Nullable) options; +- (void) handleOpenUrl: (NSURL *_Nonnull)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation; + +@end + +static NSString * _Nullable const AF_BRIDGE_SET = @"bridge is set"; \ No newline at end of file diff --git a/extension-appsflyer/src/AppsFlyerAttribution.m b/extension-appsflyer/src/AppsFlyerAttribution.m new file mode 100644 index 0000000..8d66b90 --- /dev/null +++ b/extension-appsflyer/src/AppsFlyerAttribution.m @@ -0,0 +1,79 @@ + +#import +#import "AppsFlyerAttribution.h" + +@implementation AppsFlyerAttribution + ++ (id)shared { + static AppsFlyerAttribution *shared = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + shared = [[self alloc] init]; + }); + return shared; +} + +- (id)init { + if (self = [super init]) { + self.options = nil; + self.restorationHandler = nil; + self.url = nil; + self.userActivity = nil; + self.annotation = nil; + self.sourceApplication = nil; + self.isBridgeReady = NO; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(receiveBridgeReadyNotification:) + name:AF_BRIDGE_SET + object:nil]; + } + return self; +} + +- (void) continueUserActivity: (NSUserActivity*_Nullable) userActivity restorationHandler: (void (^_Nullable)(NSArray * _Nullable))restorationHandler{ + if(self.isBridgeReady == YES){ + [[AppsFlyerLib shared] continueUserActivity:userActivity restorationHandler:restorationHandler]; + }else{ + [AppsFlyerAttribution shared].userActivity = userActivity; + [AppsFlyerAttribution shared].restorationHandler = restorationHandler; + } +} + +- (void) handleOpenUrl:(NSURL *)url options:(NSDictionary *)options{ + if(self.isBridgeReady == YES){ + [[AppsFlyerLib shared] handleOpenUrl:url options:options]; + }else{ + [AppsFlyerAttribution shared].url = url; + [AppsFlyerAttribution shared].options = options; + } +} + +- (void) handleOpenUrl:(NSURL *)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation{ + if(self.isBridgeReady == YES){ + [[AppsFlyerLib shared] handleOpenURL:url sourceApplication:sourceApplication withAnnotation:annotation]; + }else{ + [AppsFlyerAttribution shared].url = url; + [AppsFlyerAttribution shared].sourceApplication = sourceApplication; + [AppsFlyerAttribution shared].annotation = annotation; + } + +} + +- (void) receiveBridgeReadyNotification:(NSNotification *) notification +{ + if(self.url && self.sourceApplication){ + [[AppsFlyerLib shared] handleOpenURL:self.url sourceApplication:self.sourceApplication withAnnotation:self.annotation]; + self.url = nil; + self.sourceApplication = nil; + self.annotation = nil; + }else if(self.options && self.url){ + [[AppsFlyerLib shared] handleOpenUrl:self.url options:self.options]; + self.options = nil; + self.url = nil; + }else if(self.userActivity){ + [[AppsFlyerLib shared] continueUserActivity:self.userActivity restorationHandler:nil]; + self.userActivity = nil; + self.restorationHandler = nil; + } +} +@end \ No newline at end of file diff --git a/extension-appsflyer/src/AppsflyerAppDelegate.h b/extension-appsflyer/src/AppsflyerAppDelegate.h new file mode 100644 index 0000000..69ec9ae --- /dev/null +++ b/extension-appsflyer/src/AppsflyerAppDelegate.h @@ -0,0 +1,5 @@ +#import + +@interface AppsflyerAppDelegate : NSObject + +@end \ No newline at end of file diff --git a/extension-appsflyer/src/AppsflyerAppDelegate.mm b/extension-appsflyer/src/AppsflyerAppDelegate.mm new file mode 100644 index 0000000..87e7baf --- /dev/null +++ b/extension-appsflyer/src/AppsflyerAppDelegate.mm @@ -0,0 +1,30 @@ +#import "AppsflyerAppDelegate.h" +#import +#import "AppsFlyerAttribution.h" + + +@implementation AppsflyerAppDelegate + +- (void)applicationDidBecomeActive:(nonnull UIApplication *)application { +} + +// Reports app open from a Universal Link for iOS 9 or above +- (BOOL) application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray> *restorableObjects))restorationHandler { + [[AppsFlyerAttribution shared] continueUserActivity:userActivity restorationHandler:restorationHandler]; + return YES; + } + +// Reports app open from deep link from apps which do not support Universal Links (Twitter) and for iOS8 and below + - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation { + [[AppsFlyerAttribution shared] handleOpenUrl:url sourceApplication:sourceApplication annotation:annotation]; + return YES; + } + +// Reports app open from deep link for iOS 10 + - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url + options:(NSDictionary *) options { + [[AppsFlyerAttribution shared] handleOpenUrl:url options:options]; + return YES; + } + +@end \ No newline at end of file diff --git a/extension-appsflyer/src/DEFAFSDKDelegate.h b/extension-appsflyer/src/DEFAFSDKDelegate.h new file mode 100644 index 0000000..e6fa02c --- /dev/null +++ b/extension-appsflyer/src/DEFAFSDKDelegate.h @@ -0,0 +1,20 @@ +#if defined(DM_PLATFORM_IOS) + +#import +#if __has_include() +#import +#else +#import "AppsFlyerLib.h" +#endif +#include "appsflyer_private.h" +#import "appsflyer_callback_private.h" +#import "AppsFlyerAttribution.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface DEFAFSDKDelegate : NSObject +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/extension-appsflyer/src/DEFAFSDKDelegate.mm b/extension-appsflyer/src/DEFAFSDKDelegate.mm new file mode 100644 index 0000000..46a42b1 --- /dev/null +++ b/extension-appsflyer/src/DEFAFSDKDelegate.mm @@ -0,0 +1,82 @@ +#if defined(DM_PLATFORM_IOS) + +#import "DEFAFSDKDelegate.h" + + +@implementation DEFAFSDKDelegate + +void ForwardIOSEventAppsf(int type, NSString * json) +{ + const char *JsonCString = [json UTF8String]; + AddToQueueCallback((dmAppsflyer::MessageId)type, JsonCString); +} + +- (instancetype)init { + self = [super init]; + if (self) { + + } + return self; +} + +/** + `installData` contains information about install. + Organic/non-organic, etc. + */ +- (void)onConversionDataSuccess:(NSDictionary *)installData { + NSLog(@"AppsFlyer onConversionDataSuccess"); + NSData *data = [NSJSONSerialization dataWithJSONObject: installData options: 0 error: nil]; + NSString *serializedParameters = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding]; + ForwardIOSEventAppsf(1, serializedParameters); +} + +/** + Any errors that occurred during the conversion request. + */ +- (void)onConversionDataFail:(NSError *)error { + NSLog(@"AppsFlyer conversion data error %@", error); +} + +/** + `attributionData` contains information about OneLink, deeplink. + */ +- (void)onAppOpenAttribution:(NSDictionary *)attributionData { + + NSLog(@"AppsFlyer onAppOpenAttribution"); + NSData *data = [NSJSONSerialization dataWithJSONObject: attributionData options: 0 error: nil]; + NSString *serializedParameters = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding]; + ForwardIOSEventAppsf(3, serializedParameters); +} + +/** + Any errors that occurred during the attribution request. + */ +- (void)onAppOpenAttributionFailure:(NSError *)error { + NSLog(@"Appsflyer onAppOpenAttributionFailure %@", error); +} + +- (void)didResolveDeepLink:(AppsFlyerDeepLinkResult *)result{ + NSLog(@"Appsflyer didResolveDeepLink"); +} + ++ (NSDictionary *)dictionaryByReplacingNullsWithStrings:(NSDictionary *)dict { + const NSMutableDictionary *replaced = [dict mutableCopy]; + const id nul = [NSNull null]; + const NSString *blank = @""; + + for (NSString *key in dict) { + const id object = [dict objectForKey:key]; + if (object == nul) { + // pointer comparison is way faster than -isKindOfClass: + // since [NSNull null] is a singleton, they'll all point to the same + // location in memory. + [replaced setObject:blank + forKey:key]; + } + } + return [replaced copy]; +} + +@end + +#endif diff --git a/extension-appsflyer/src/appsflyer.cpp b/extension-appsflyer/src/appsflyer.cpp index 56c5574..3273703 100644 --- a/extension-appsflyer/src/appsflyer.cpp +++ b/extension-appsflyer/src/appsflyer.cpp @@ -8,7 +8,7 @@ #include -#if defined(DM_PLATFORM_ANDROID) +#if defined(DM_PLATFORM_ANDROID) || defined(DM_PLATFORM_IOS) #include #include "appsflyer_private.h" @@ -26,6 +26,13 @@ static int Lua_StartSDK(lua_State* L) return 0; } +static int Lua_GetAppsFlyerUID(lua_State* L) +{ + DM_LUA_STACK_CHECK(L, 1); + + return GetAppsFlyerUID(L); +} + static int Lua_SetCallback(lua_State* L) { DM_LUA_STACK_CHECK(L, 0); @@ -102,6 +109,7 @@ static const luaL_reg Module_methods[] = {"set_debug_log", Lua_SetDebugLog}, {"log_event", Lua_LogEvent}, {"set_customer_user_id", Lua_SetCustomerUserId}, + {"get_appsflyer_uid", Lua_GetAppsFlyerUID}, {0, 0} }; diff --git a/extension-appsflyer/src/appsflyer_android.cpp b/extension-appsflyer/src/appsflyer_android.cpp index c689d79..22785b2 100644 --- a/extension-appsflyer/src/appsflyer_android.cpp +++ b/extension-appsflyer/src/appsflyer_android.cpp @@ -23,6 +23,7 @@ struct Appsflyer jmethodID m_SetDebugLog; jmethodID m_LogEvent; jmethodID m_SetCustomerUserId; + jmethodID m_GetAppsFlyerUID; }; static Appsflyer g_appsflyer; @@ -44,6 +45,7 @@ static void InitJNIMethods(JNIEnv* env, jclass cls) g_appsflyer.m_SetDebugLog = env->GetMethodID(cls, "setDebugLog", "(Z)V"); g_appsflyer.m_LogEvent = env->GetMethodID(cls, "logEvent", "(Ljava/lang/String;Ljava/util/Map;)V"); g_appsflyer.m_SetCustomerUserId = env->GetMethodID(cls, "setCustomerUserId", "(Ljava/lang/String;)V"); + g_appsflyer.m_GetAppsFlyerUID = env->GetMethodID(cls, "getAppsFlyerUID", "()Ljava/lang/String;"); } void Initialize_Ext() @@ -72,6 +74,16 @@ void StartSDK() env->CallVoidMethod(g_appsflyer.m_AppsflyerJNI, g_appsflyer.m_StartSDK); } +int GetAppsFlyerUID(lua_State* L) +{ + dmAndroid::ThreadAttacher threadAttacher; + JNIEnv* env = threadAttacher.GetEnv(); + jstring jni_device_uid = (jstring)env->CallObjectMethod(g_appsflyer.m_AppsflyerJNI, g_appsflyer.m_GetAppsFlyerUID); + lua_pushstring(L, env->GetStringUTFChars(jni_device_uid, 0)); + env->DeleteLocalRef(jni_device_uid); + return 1; +} + void SetDebugLog(bool is_debug) { dmAndroid::ThreadAttacher threadAttacher; diff --git a/extension-appsflyer/src/appsflyer_callback.cpp b/extension-appsflyer/src/appsflyer_callback.cpp index 3a1405d..b36d62f 100644 --- a/extension-appsflyer/src/appsflyer_callback.cpp +++ b/extension-appsflyer/src/appsflyer_callback.cpp @@ -1,4 +1,4 @@ -#if defined(DM_PLATFORM_ANDROID) +#if defined(DM_PLATFORM_ANDROID) || defined(DM_PLATFORM_IOS) #include "appsflyer_callback_private.h" #include "utils/lua_util.h" diff --git a/extension-appsflyer/src/appsflyer_callback_private.h b/extension-appsflyer/src/appsflyer_callback_private.h index d72243c..da3a364 100644 --- a/extension-appsflyer/src/appsflyer_callback_private.h +++ b/extension-appsflyer/src/appsflyer_callback_private.h @@ -1,4 +1,4 @@ -#if defined(DM_PLATFORM_ANDROID) +#if defined(DM_PLATFORM_ANDROID) || defined(DM_PLATFORM_IOS) #pragma once #include "appsflyer_private.h" diff --git a/extension-appsflyer/src/appsflyer_ios.mm b/extension-appsflyer/src/appsflyer_ios.mm new file mode 100644 index 0000000..ddf8754 --- /dev/null +++ b/extension-appsflyer/src/appsflyer_ios.mm @@ -0,0 +1,91 @@ +#if defined(DM_PLATFORM_IOS) + + +#include +// AppDelegate.h +#import +#include "appsflyer_private.h" +#import "appsflyer_callback_private.h" +#import "DEFAFSDKDelegate.h" +#import "AppsFlyerAttribution.h" +#import "AppsflyerAppDelegate.h" + +namespace dmAppsflyer { + + +struct AppsflyerAppDelegateRegister +{ + AppsflyerAppDelegate* m_Delegate; + + AppsflyerAppDelegateRegister() { + m_Delegate = [[AppsflyerAppDelegate alloc] init]; + dmExtension::RegisteriOSUIApplicationDelegate(m_Delegate); + } + + ~AppsflyerAppDelegateRegister() { + dmExtension::UnregisteriOSUIApplicationDelegate(m_Delegate); + [m_Delegate release]; + } +}; + + +AppsflyerAppDelegateRegister g_appDelegate; + +void Initialize_Ext(){ +} + +void Finalize_Ext(){ +} + + +void InitializeSDK(const char* key, const char* appleAppID){ + NSLog(@"AppsFlyer InitializeSDK"); + [AppsFlyerLib shared].isDebug = true; + DEFAFSDKDelegate *delegate = [[DEFAFSDKDelegate alloc] init]; + [AppsFlyerAttribution shared].isBridgeReady = YES; + [[NSNotificationCenter defaultCenter] postNotificationName:AF_BRIDGE_SET object: [AppsFlyerAttribution shared]]; + [[AppsFlyerLib shared] setAppsFlyerDevKey:[NSString stringWithUTF8String: key]]; + [[AppsFlyerLib shared] setAppleAppID:[NSString stringWithUTF8String: appleAppID]]; + [[AppsFlyerLib shared] setDelegate:delegate]; + [[AppsFlyerLib shared] setDeepLinkDelegate:delegate]; + // [[AppsFlyerLib shared] addPushNotificationDeepLinkPath:@[@"af_push_link"]]; +} + +void StartSDK(){ + [[AppsFlyerLib shared] start]; +} + +void SetDebugLog(bool is_debug){ + [AppsFlyerLib shared].isDebug = is_debug; +} + +void LogEvent(const char* eventName, dmArray* trackData){ + @autoreleasepool { + NSMutableDictionary* newDict = [NSMutableDictionary dictionary]; + NSString* key; + NSString* value; + NSString* event = [NSString stringWithUTF8String: eventName]; + TrackData data; + for(uint32_t i = 0; i != trackData->Size(); i++) + { + data = (*trackData)[i]; + key = [NSString stringWithUTF8String: data.key]; + value = [NSString stringWithUTF8String: data.value]; + newDict[key] = value; + } + [[AppsFlyerLib shared] logEvent: event withValues: newDict]; + } +} + +void SetCustomerUserId(const char* userId){ + [AppsFlyerLib shared].customerUserID = [NSString stringWithUTF8String: userId]; +} + +int GetAppsFlyerUID(lua_State* L){ + lua_pushstring(L, [[[AppsFlyerLib shared] getAppsFlyerUID] UTF8String]); + return 1; +} + + }// namespace + +#endif // platform \ No newline at end of file diff --git a/extension-appsflyer/src/appsflyer_private.h b/extension-appsflyer/src/appsflyer_private.h index a5d57ca..8143cad 100644 --- a/extension-appsflyer/src/appsflyer_private.h +++ b/extension-appsflyer/src/appsflyer_private.h @@ -1,4 +1,4 @@ -#if defined(DM_PLATFORM_ANDROID) +#if defined(DM_PLATFORM_ANDROID) || defined(DM_PLATFORM_IOS) #pragma once @@ -13,12 +13,14 @@ struct TrackData }; void Initialize_Ext(); +void Finalize_Ext(); void InitializeSDK(const char* key, const char* appleAppID); void StartSDK(); void SetDebugLog(bool is_debug); void LogEvent(const char* eventName, dmArray* trackData); void SetCustomerUserId(const char* userId); +int GetAppsFlyerUID(lua_State* L); } // namespace diff --git a/extension-appsflyer/src/java/com/defold/appsflyer/AppsflyerJNI.java b/extension-appsflyer/src/java/com/defold/appsflyer/AppsflyerJNI.java index 9b9b9d0..6a17bb2 100644 --- a/extension-appsflyer/src/java/com/defold/appsflyer/AppsflyerJNI.java +++ b/extension-appsflyer/src/java/com/defold/appsflyer/AppsflyerJNI.java @@ -90,4 +90,8 @@ public void setCustomerUserId(String userId) { Log.d(TAG, "Set customer user id: " + userId); AppsFlyerLib.getInstance().setCustomerUserId(userId); } + + public String getAppsFlyerUID() { + return AppsFlyerLib.getInstance().getAppsFlyerUID(activity); + } }