diff --git a/AppIcon.xcassets/Contents.json b/AppIcon.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/AppIcon.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AppIcon.xcassets/Icon-180.imageset/Contents.json b/AppIcon.xcassets/Icon-180.imageset/Contents.json new file mode 100644 index 0000000..31ff961 --- /dev/null +++ b/AppIcon.xcassets/Icon-180.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Icon-180.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "original" + } +} diff --git a/AppIcon.xcassets/Icon-180.imageset/Icon-180.png b/AppIcon.xcassets/Icon-180.imageset/Icon-180.png new file mode 100644 index 0000000..d4bc531 Binary files /dev/null and b/AppIcon.xcassets/Icon-180.imageset/Icon-180.png differ diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e6b56c..609836b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,13 @@ project(${APP_NAME}) set(COCOS2DX_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cocos2d) set(CMAKE_MODULE_PATH ${COCOS2DX_ROOT_PATH}/cmake/Modules/) +# Print the values +message(STATUS "CMAKE_CURRENT_SOURCE_DIR: ${CMAKE_CURRENT_SOURCE_DIR}") +message(STATUS "COCOS2DX_ROOT_PATH: ${COCOS2DX_ROOT_PATH}") +message(STATUS "CMAKE_MODULE_PATH: ${CMAKE_MODULE_PATH}") +message(STATUS "COCOS2DX_ROOT_PATH: ${COCOS2DX_ROOT_PATH}") +message(STATUS "Is ANDROID?: ${ANDROID}") + include(CocosBuildSet) add_subdirectory(${COCOS2DX_ROOT_PATH}/cocos ${ENGINE_BINARY_PATH}/cocos/core) @@ -49,22 +56,28 @@ endif() # add cross-platforms source files and header files list(APPEND GAME_SOURCE Classes/AppsFlyer/AppsFlyerX.cpp - Classes/AppsFlyer/AppsFlyerXAndroid.cpp - Classes/AppsFlyer/AppsFlyerProxyX.cpp Classes/AppDelegate.cpp Classes/HelloWorldScene.cpp Classes/AppsFlyer/AppsFlyerXDeepLinkResult.cpp ) list(APPEND GAME_HEADER Classes/AppsFlyer/AppsFlyerX.h - Classes/AppsFlyer/AppsFlyerXAndroid.h - Classes/AppsFlyer/AppsFlyerProxyX.h Classes/AppDelegate.h Classes/HelloWorldScene.h Classes/AppsFlyer/AppsFlyerXDeepLinkResult.h ) if(ANDROID) + list(APPEND GAME_SOURCE + Classes/AppsFlyer/AppsFlyerXAndroid.cpp + Classes/AppsFlyer/AppsFlyerProxyX.cpp + ) + + list(APPEND GAME_HEADER + Classes/AppsFlyer/AppsFlyerXAndroid.h + Classes/AppsFlyer/AppsFlyerProxyX.h + ) + # change APP_NAME to the share library name for Android, it's value depend on AndroidManifest.xml set(APP_NAME MyGame) list(APPEND GAME_SOURCE @@ -90,11 +103,13 @@ elseif(APPLE) proj.ios_mac/ios/AppController.h proj.ios_mac/ios/RootViewController.h ) + set(APP_UI_RES proj.ios_mac/ios/LaunchScreen.storyboard proj.ios_mac/ios/LaunchScreenBackground.png proj.ios_mac/ios/Images.xcassets ) + list(APPEND GAME_SOURCE proj.ios_mac/ios/main.m proj.ios_mac/ios/AppController.mm @@ -145,7 +160,7 @@ if(APPLE) ) elseif(IOS) cocos_pak_xcode(${APP_NAME} INFO_PLIST "iOSBundleInfo.plist.in") - set_xcode_property(${APP_NAME} ASSETCATALOG_COMPILER_APPICON_NAME "AppIcon") + # set_xcode_property(${APP_NAME} ASSETCATALOG_COMPILER_APPICON_NAME "AppIcon") set_xcode_property(${APP_NAME} DEVELOPMENT_TEAM "") set_xcode_property(${APP_NAME} CODE_SIGN_IDENTITY "iPhone Developer") endif() diff --git a/Classes/AppsFlyer/AFSDKXPurchaseDetails.cpp b/Classes/AppsFlyer/AFSDKXPurchaseDetails.cpp new file mode 100644 index 0000000..0539aac --- /dev/null +++ b/Classes/AppsFlyer/AFSDKXPurchaseDetails.cpp @@ -0,0 +1,86 @@ +// +// AFSDKXPurchaseDetails.cpp +// MyGame +// +// Created by ivan.obodovskyi on 02.10.2024. +// + +#include +#include "AFSDKXPurchaseDetails.h" + +AFSDKXPurchaseDetails::AFSDKXPurchaseDetails(const AFXPurchaseType &purchaseType, + const std::string &purchaseToken, + const std::string &productId, + const std::string &price, + const std::string ¤cy, + const std::string &transactionId) + :purchaseType_(purchaseType), + purchaseToken_(purchaseToken), + productId_(productId), + price_(price), + currency_(currency), + transactionId_(transactionId) { +} + +std::string AFSDKXPurchaseDetails::getProductId() const { + return productId_; +} + +void AFSDKXPurchaseDetails::setProductId(const std::string &productId) { + productId_ = productId; +} + +std::string AFSDKXPurchaseDetails::getPrice() const { + return price_; +} + +void AFSDKXPurchaseDetails::setPrice(const std::string &price) { + price_ = price; +} + +std::string AFSDKXPurchaseDetails::getCurrency() const { + return currency_; +} + +void AFSDKXPurchaseDetails::setCurrency(const std::string ¤cy) { + currency_ = currency; +} + +std::string AFSDKXPurchaseDetails::getTransactionId() const { + return transactionId_; +} + +void AFSDKXPurchaseDetails::setTransactionId(const std::string &transactionId) { + transactionId_ = transactionId; +} + +std::string AFSDKXPurchaseDetails::getPurchaseToken() const { + return purchaseToken_; +} + +void AFSDKXPurchaseDetails::setPurchaseToken(const std::string &purchaseToken) { + purchaseToken_ = purchaseToken; +} + +std::string AFSDKXPurchaseDetails::getPurchaseType() const { + std::string purchaseTypeStr = purchaseTypeToString(); + return purchaseTypeStr; +} + +void AFSDKXPurchaseDetails::setPurchaseType(AFXPurchaseType &purchaseType) { + purchaseType_ = purchaseType; +} + +// Function to get the string value of the enum +std::string AFSDKXPurchaseDetails::purchaseTypeToString() const{ + switch (purchaseType_) { + case AFXPurchaseType::SUBSCRIPTION: + return "subscription"; + case AFXPurchaseType::ONE_TIME_PURCHASE: + return "one_time_purchase"; + case AFXPurchaseType::APPLE: + return ""; + default: + return ""; + } +} diff --git a/Classes/AppsFlyer/AFSDKXPurchaseDetails.h b/Classes/AppsFlyer/AFSDKXPurchaseDetails.h new file mode 100644 index 0000000..2f24148 --- /dev/null +++ b/Classes/AppsFlyer/AFSDKXPurchaseDetails.h @@ -0,0 +1,74 @@ +// +// AFSDKXPurchaseDetails.h +// MyGame +// +// Created by ivan.obodovskyi on 02.10.2024. +// + +#ifndef AFSDKXPurchaseDetails_h +#define AFSDKXPurchaseDetails_h + +#include +#include "cocos2d.h" +#include "AFSDKXValidateAndLogResult.h" + +enum class AFXPurchaseType { + SUBSCRIPTION, + ONE_TIME_PURCHASE, + APPLE +}; + + +class AFSDKXPurchaseDetails { +public: + // Deleted default constructor to prevent usage. + AFSDKXPurchaseDetails() = delete; + + // Constructor with parameters to initialize the properties. + AFSDKXPurchaseDetails(const AFXPurchaseType &purchaseType, + const std::string &purchaseToken, + const std::string &productId, + const std::string &price, + const std::string ¤cy, + const std::string &transactionId); + + // Default destructor. + virtual ~AFSDKXPurchaseDetails() = default; + + // Public assignment and copy constructors + AFSDKXPurchaseDetails(const AFSDKXPurchaseDetails &) = default; + AFSDKXPurchaseDetails &operator=(const AFSDKXPurchaseDetails &) = default; + + // Getters and setters for private member variables. + std::string getProductId() const; + void setProductId(const std::string &productId); + + std::string getPrice() const; + void setPrice(const std::string &price); + + std::string getCurrency() const; + void setCurrency(const std::string ¤cy); + + std::string getTransactionId() const; + void setTransactionId(const std::string &transactionId); + + // Propperties related to Android impl + // For Apple implementation, please pass APPLE, it will be interpreted as an empty string + std::string purchaseTypeToString() const; + std::string getPurchaseType() const; + void setPurchaseType(AFXPurchaseType &purchaseType); + + // Android purchase token, for iOS impl, please use empty string + std::string getPurchaseToken() const; + void setPurchaseToken(const std::string &purchaseToken); + +private: + // Private member variables. + std::string productId_; + std::string price_; + std::string currency_; + std::string transactionId_; + std::string purchaseToken_; + AFXPurchaseType purchaseType_; +}; +#endif /* AFSDKXPurchaseDetails_h */ diff --git a/Classes/AppsFlyer/AFSDKXValidateAndLogResult.cpp b/Classes/AppsFlyer/AFSDKXValidateAndLogResult.cpp new file mode 100644 index 0000000..9b31f7f --- /dev/null +++ b/Classes/AppsFlyer/AFSDKXValidateAndLogResult.cpp @@ -0,0 +1,50 @@ +// +// AFSDKXValidateAndLogResult.cpp +// MyGame +// +// Created by ivan.obodovskyi on 03.10.2024. +// + +#include +#include "AFSDKXValidateAndLogResult.h" + +// Constructor implementation. +AFSDKXValidateAndLogResult::AFSDKXValidateAndLogResult( + AFSDKXValidateAndLogStatus status, + const cocos2d::ValueMap& result, + const cocos2d::ValueMap& errorData, + const cocos2d::ValueMap& error) + : status_(status), result_(result), errorData_(errorData), error_(error) { +} + +// Getter methods implementation. +AFSDKXValidateAndLogStatus AFSDKXValidateAndLogResult::getStatus() const { + return status_; +} + +cocos2d::ValueMap AFSDKXValidateAndLogResult::getResult() const { + return result_; +} + +cocos2d::ValueMap AFSDKXValidateAndLogResult::getErrorData() const { + return errorData_; +} + +cocos2d::ValueMap AFSDKXValidateAndLogResult::getError() const { + return error_; +} + +// Function to map Objective-C enum to C++ enum +AFSDKXValidateAndLogStatus AFSDKXValidateAndLogResult::objcEnumToCppEnum(int objcStatus) { + switch (objcStatus) { + case 0: + return AFSDKXValidateAndLogStatus::Success; + case 1: + return AFSDKXValidateAndLogStatus::Failure; + case 2: + return AFSDKXValidateAndLogStatus::Error; + default: + // Handle unknown cases, or return a default value + return AFSDKXValidateAndLogStatus::Error; + } +} diff --git a/Classes/AppsFlyer/AFSDKXValidateAndLogResult.h b/Classes/AppsFlyer/AFSDKXValidateAndLogResult.h new file mode 100644 index 0000000..1136b1e --- /dev/null +++ b/Classes/AppsFlyer/AFSDKXValidateAndLogResult.h @@ -0,0 +1,54 @@ +// +// AFSDKXValidateAndLogResult.h +// MyGame +// +// Created by ivan.obodovskyi on 03.10.2024. +// + +#ifndef AFSDKXValidateAndLogResult_h +#define AFSDKXValidateAndLogResult_h + +#include +#include +#include +#include +#include + +// Assuming an error class similar to NSError exists in your C++ code. +class Error; + +// Enum to represent validation status +enum class AFSDKXValidateAndLogStatus { + Success, + Failure, + Error +}; + +class AFSDKXValidateAndLogResult { +public: + // Deleting default constructor to prevent usage. + AFSDKXValidateAndLogResult() = delete; + + // Constructor with initialization list. + AFSDKXValidateAndLogResult(AFSDKXValidateAndLogStatus status, + const cocos2d::ValueMap& result, + const cocos2d::ValueMap& errorData, + const cocos2d::ValueMap& error); + + // Getter methods + AFSDKXValidateAndLogStatus getStatus() const; + static AFSDKXValidateAndLogStatus objcEnumToCppEnum(int objcStatus); + cocos2d::ValueMap getResult() const; + cocos2d::ValueMap getErrorData() const; + cocos2d::ValueMap getError() const; + + +private: + // Member variables. + AFSDKXValidateAndLogStatus status_; + cocos2d::ValueMap result_; + cocos2d::ValueMap errorData_; + cocos2d::ValueMap error_; +}; + +#endif /* AFSDKXValidateAndLogResult_h */ diff --git a/Classes/AppsFlyer/AFXAdRevenueData.cpp b/Classes/AppsFlyer/AFXAdRevenueData.cpp new file mode 100644 index 0000000..ded3ac3 --- /dev/null +++ b/Classes/AppsFlyer/AFXAdRevenueData.cpp @@ -0,0 +1,76 @@ +// +// AFXAdRevenueData.cpp +// MyGame +// +// Created by ivan.obodovskyi on 04.10.2024. +// + +#include +#include "AFXAdRevenueData.h" + +// Constructor definition +AFXAdRevenueData::AFXAdRevenueData(const std::string& monetizationNetwork, + AppsFlyerXAdRevenueMediationNetworkType mediationNetwork, + const std::string& currencyIso4217Code, + double eventRevenue) + : monetizationNetwork(monetizationNetwork), + mediationNetwork(mediationNetwork), + currencyIso4217Code(currencyIso4217Code), + eventRevenue(eventRevenue) { +} + +// Getters implementation +std::string AFXAdRevenueData::getMonetizationNetwork() const { + return monetizationNetwork; +} + +AppsFlyerXAdRevenueMediationNetworkType AFXAdRevenueData::getMediationNetwork() const { + return mediationNetwork; +} + +std::string AFXAdRevenueData::meditationNetworkString() const { + switch (mediationNetwork) { + case AppsFlyerXAdRevenueMediationNetworkType::GoogleAdMob: + return "GOOGLE_ADMOB"; + case AppsFlyerXAdRevenueMediationNetworkType::IronSource: + return "IRONSOURCE"; + case AppsFlyerXAdRevenueMediationNetworkType::ApplovinMax: + return "APPLOVIN_MAX"; + case AppsFlyerXAdRevenueMediationNetworkType::Fyber: + return "FYBER"; + case AppsFlyerXAdRevenueMediationNetworkType::Appodeal: + return "APPODEAL"; + case AppsFlyerXAdRevenueMediationNetworkType::Admost: + return "ADMOST"; + case AppsFlyerXAdRevenueMediationNetworkType::Topon: + return "TOPON"; + case AppsFlyerXAdRevenueMediationNetworkType::Tradplus: + return "TRADPLUS"; + case AppsFlyerXAdRevenueMediationNetworkType::Yandex: + return "YANDEX"; + case AppsFlyerXAdRevenueMediationNetworkType::ChartBoost: + return "CHARTBOOST"; + case AppsFlyerXAdRevenueMediationNetworkType::Unity: + return "UNITY"; + case AppsFlyerXAdRevenueMediationNetworkType::ToponPte: + return "TOPON_PTE"; + case AppsFlyerXAdRevenueMediationNetworkType::Custom: + return "CUSTOM_MEDIATION"; + case AppsFlyerXAdRevenueMediationNetworkType::DirectMonetization: + return "DIRECT_MONETIZATION_NETWORK"; + default: + return "unknown"; + } +}; + +std::string AFXAdRevenueData::getCurrencyIso4217Code() const { + return currencyIso4217Code; +} + +double AFXAdRevenueData::getEventRevenue() const { + return eventRevenue; +} + +int convertMeditationType(AppsFlyerXAdRevenueMediationNetworkType a) { + return static_cast(static_cast(a)); +} diff --git a/Classes/AppsFlyer/AFXAdRevenueData.h b/Classes/AppsFlyer/AFXAdRevenueData.h new file mode 100644 index 0000000..d045d6f --- /dev/null +++ b/Classes/AppsFlyer/AFXAdRevenueData.h @@ -0,0 +1,77 @@ +// +// AFXAdRevenueData.h +// MyGame +// +// Created by ivan.obodovskyi on 04.10.2024. +// + +#include + +#ifndef AFXAdRevenueData_h +#define AFXAdRevenueData_h + +enum class AppsFlyerXAdRevenueMediationNetworkType { + GoogleAdMob = 1, + IronSource = 2, + ApplovinMax = 3, + Fyber = 4, + Appodeal = 5, + Admost = 6, + Topon = 7, + Tradplus = 8, + Yandex = 9, + ChartBoost = 10, + Unity = 11, + ToponPte = 12, + Custom = 13, + DirectMonetization = 14 +}; + +#define kAppsFlyerAdRevenueMonetizationNetwork @"monetization_network" +#define kAppsFlyerAdRevenueMediationNetwork @"mediation_network" +#define kAppsFlyerAdRevenueEventRevenue @"event_revenue" +#define kAppsFlyerAdRevenueEventRevenueCurrency @"event_revenue_currency" +#define kAppsFlyerAdRevenueCustomParameters @"custom_parameters" +#define kAFADRWrapperTypeGeneric @"adrevenue_sdk" + +//Pre-defined keys for non-mandatory dictionary + +//Code ISO 3166-1 format +#define kAppsFlyerAdRevenueCountry @"country" + +//ID of the ad unit for the impression +#define kAppsFlyerAdRevenueAdUnit @"ad_unit" + +//Format of the ad +#define kAppsFlyerAdRevenueAdType @"ad_type" + +//ID of the ad placement for the impression +#define kAppsFlyerAdRevenuePlacement @"placement" + + +class AFXAdRevenueData { +public: + // Constructor with initialization parameters + AFXAdRevenueData(const std::string& monetizationNetwork, + AppsFlyerXAdRevenueMediationNetworkType mediationNetwork, + const std::string& currencyIso4217Code, + double eventRevenue); + + // Getter functions for each property + std::string getMonetizationNetwork() const; + AppsFlyerXAdRevenueMediationNetworkType getMediationNetwork() const; + std::string getCurrencyIso4217Code() const; + double getEventRevenue() const; + int convertMeditationType(AppsFlyerXAdRevenueMediationNetworkType a); + std::string meditationNetworkString() const; + +private: + // Private member variables + std::string monetizationNetwork; + AppsFlyerXAdRevenueMediationNetworkType mediationNetwork; + std::string currencyIso4217Code; + double eventRevenue; +}; + + +#endif /* AFXAdRevenueData_h */ diff --git a/Classes/AppsFlyer/AppsFlyerX+AppController.h b/Classes/AppsFlyer/AppsFlyerX+AppController.h index 55ba6d2..b8f3d65 100644 --- a/Classes/AppsFlyer/AppsFlyerX+AppController.h +++ b/Classes/AppsFlyer/AppsFlyerX+AppController.h @@ -5,7 +5,7 @@ // Created by AndreyG-AF on 10/17/17. // -#import "AppController.h" + @interface AppController (AppsFlyerX) diff --git a/Classes/AppsFlyer/AppsFlyerX+AppController.m b/Classes/AppsFlyer/AppsFlyerX+AppController.m index 418a8dc..874809a 100644 --- a/Classes/AppsFlyer/AppsFlyerX+AppController.m +++ b/Classes/AppsFlyer/AppsFlyerX+AppController.m @@ -7,7 +7,7 @@ #import "AppsFlyerX+AppController.h" #import -#import "AppsFlyerLib.h" +#import "AppsFlyer/libAppsFlyer/AppsFlyerLib.h" @implementation AppController (AppsFlyerX) diff --git a/Classes/AppsFlyer/AppsFlyerX.cpp b/Classes/AppsFlyer/AppsFlyerX.cpp index c1b4224..74312a8 100644 --- a/Classes/AppsFlyer/AppsFlyerX.cpp +++ b/Classes/AppsFlyer/AppsFlyerX.cpp @@ -332,6 +332,25 @@ void AppsFlyerX::validateAndLogInAppPurchase(const std::string& publicKey, #endif } +void AppsFlyerX::logAdRevenue(AFXAdRevenueData adRevenueData, cocos2d::ValueMap additionalParameters) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + // Android implementation + CCLOGWARN("Log AdRevenue Android"); + AppsFlyerXAndroid::logAdRevenue(adRevenueData, additionalParameters); +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + AppsFlyerXApple::logAdRevenue(adRevenueData, additionalParameters); +#endif +} + +void AppsFlyerX::validateAndLogInAppPurchase(AFSDKXPurchaseDetails &details, cocos2d::ValueMap params, std::function completionHandler) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + // Android implementation + AppsFlyerXAndroid::validateAndLogInAppPurchase(details, std::move(params), std::move(completionHandler)); +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + AppsFlyerXApple::validateAndLogInAppPurchase(details, params, completionHandler); +#endif +} + std::string AppsFlyerX::getAppsFlyerUID() { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) diff --git a/Classes/AppsFlyer/AppsFlyerX.h b/Classes/AppsFlyer/AppsFlyerX.h index 0998fae..316acb3 100644 --- a/Classes/AppsFlyer/AppsFlyerX.h +++ b/Classes/AppsFlyer/AppsFlyerX.h @@ -16,6 +16,8 @@ #include "AppsFlyerXMacro.h" #include "AppsFlyerXDeepLinkResult.h" #include "AppsFlyerXConsent.cpp" +#include "AFSDKXPurchaseDetails.h" +#include "AFXAdRevenueData.h" class AppsFlyerX { @@ -74,6 +76,8 @@ class AppsFlyerX { static void logEvent(const std::string& eventName, cocos2d::ValueMap values); + static void logAdRevenue(AFXAdRevenueData adRevenueData, cocos2d::ValueMap additionalParameters); + static void validateAndLogInAppPurchase(const std::string& productIdentifier, const std::string& price, const std::string& currency, @@ -88,6 +92,9 @@ class AppsFlyerX { const std::string& price, const std::string& currency, cocos2d::ValueMap additionalParameters); + + + static void validateAndLogInAppPurchase(AFSDKXPurchaseDetails &details, cocos2d::ValueMap params, std::function completionHandler); static void logLocation(double longitude, double latitude); diff --git a/Classes/AppsFlyer/AppsFlyerXAndroid.cpp b/Classes/AppsFlyer/AppsFlyerXAndroid.cpp index 5d05f54..34369e6 100644 --- a/Classes/AppsFlyer/AppsFlyerXAndroid.cpp +++ b/Classes/AppsFlyer/AppsFlyerXAndroid.cpp @@ -5,6 +5,7 @@ #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) #include +#include "stdlib.h" #include "AppsFlyerXAndroid.h" #include "AppsFlyerProxyX.h" @@ -12,7 +13,7 @@ std::string afDevKey; bool isConveriosnListenerInitialized = false; bool isSubscribedForDeepLink = false; -const char *pluginVersion = "6.13.0"; +const char *pluginVersion = "6.15.1"; // Headers void initConvertionCallback(); @@ -396,10 +397,6 @@ void callSetPluginInfo(jobject extensionObject) { } } -void AppsFlyerXAndroid::logEvent(const std::string &eventName, const std::string &value) { - -} - void AppsFlyerXAndroid::logEvent(const std::string &eventName, cocos2d::ValueMap values) { cocos2d::JniMethodInfo jniGetInstance = getAppsFlyerInstance(); @@ -443,6 +440,77 @@ void AppsFlyerXAndroid::logEvent(const std::string &eventName, cocos2d::ValueMap } } + +void AppsFlyerXAndroid::logAdRevenue(const AFXAdRevenueData &adRevenueData, cocos2d::ValueMap params) { + cocos2d::JniMethodInfo jniGetInstance = getAppsFlyerInstance(); + + jobject afInstance = (jobject) jniGetInstance.env->CallStaticObjectMethod( + jniGetInstance.classID, jniGetInstance.methodID); + + std::string appsFlyerUid; + + cocos2d::JniMethodInfo miGetContext; + + if (!cocos2d::JniHelper::getStaticMethodInfo(miGetContext, "org/cocos2dx/lib/Cocos2dxActivity", + "getContext", "()Landroid/content/Context;")) { + return; + } + jobject jContext = (jobject) miGetContext.env->CallStaticObjectMethod(miGetContext.classID, + miGetContext.methodID); + + jobject hashMapObj = valueMapToHashMap(jniGetInstance, params); + + if (NULL != afInstance) { + // CCLOG("%s", "com/appsflyer/AppsFlyerLib is loaded"); + jclass afAdRevenueDataClass = jniGetInstance.env->FindClass( + "com/appsflyer/AFAdRevenueData"); + jmethodID afAdRevenueDataMethodId = jniGetInstance.env->GetMethodID(afAdRevenueDataClass, + "", + "(Ljava/lang/String;Lcom/appsflyer/MediationNetwork;Ljava/lang/String;D)V"); + + jclass mediationNetworkClass = jniGetInstance.env->FindClass("com/appsflyer/MediationNetwork"); + + // Get the enum value by name (e.g., "IRONSOURCE", "APPLOVIN_MAX") + jmethodID valueOfMethod = jniGetInstance.env->GetStaticMethodID(mediationNetworkClass, "valueOf", "(Ljava/lang/String;)Lcom/appsflyer/MediationNetwork;"); + + // Check if the valueOf method was found + if (valueOfMethod == nullptr) { + // Handle error, method not found + return; + } + + jstring enumNameString = jniGetInstance.env->NewStringUTF(adRevenueData.meditationNetworkString().c_str()); + + jobject jMediationNetworkEnumObject = jniGetInstance.env->CallStaticObjectMethod(mediationNetworkClass, valueOfMethod, enumNameString); + jobject jMonetizationNetwork = jniGetInstance.env->NewStringUTF(adRevenueData.getMonetizationNetwork().c_str()); + jobject jCurrencyCode = jniGetInstance.env->NewStringUTF(adRevenueData.getCurrencyIso4217Code().c_str()); + + jobject afAdRevenueDataObject = jniGetInstance.env->NewObject(afAdRevenueDataClass, afAdRevenueDataMethodId, + jMonetizationNetwork, + jMediationNetworkEnumObject, + jCurrencyCode, + adRevenueData.getEventRevenue()); + + jclass cls = jniGetInstance.env->GetObjectClass(afInstance); + + jmethodID methodId = jniGetInstance.env->GetMethodID(cls, "logAdRevenue", + "(Lcom/appsflyer/AFAdRevenueData;" + "Ljava/util/Map;)V"); + + jniGetInstance.env->CallVoidMethod(afInstance, methodId, afAdRevenueDataObject, hashMapObj); + + // cleanup + jniGetInstance.env->DeleteLocalRef(enumNameString); + jniGetInstance.env->DeleteLocalRef(afAdRevenueDataObject); + jniGetInstance.env->DeleteLocalRef(jMediationNetworkEnumObject); + jniGetInstance.env->DeleteLocalRef(jMonetizationNetwork); + jniGetInstance.env->DeleteLocalRef(jCurrencyCode); + jniGetInstance.env->DeleteLocalRef(afInstance); + } else { + CCLOGWARN("com/appsflyer/AppsFlyerLib is not loaded"); + } +} + void AppsFlyerXAndroid::setUserEmails(std::vector userEmails, EmailCryptTypeX type) { } @@ -512,6 +580,10 @@ void AppsFlyerXAndroid::setAppsFlyerDevKey(const std::string &appsFlyerDevKey) { jContext); jniGetInstance.env->DeleteLocalRef(afInstance); + jniGetInstance.env->DeleteLocalRef(plugin); + jniGetInstance.env->DeleteLocalRef(version); + jniGetInstance.env->DeleteLocalRef(extensionObject); + jniGetInstance.env->DeleteLocalRef(jContext); jniGetInstance.env->DeleteLocalRef(jniGetInstance.classID); } } @@ -634,6 +706,99 @@ void AppsFlyerXAndroid::validateAndLogInAppPurchase(const std::string &publicKey } } +void AppsFlyerXAndroid::validateAndLogInAppPurchase(AFSDKXPurchaseDetails &details, cocos2d::ValueMap params, std::function completionHandler) { + cocos2d::JniMethodInfo jniGetInstance = getAppsFlyerInstance(); + + jobject afInstance = (jobject) jniGetInstance.env->CallStaticObjectMethod( + jniGetInstance.classID, jniGetInstance.methodID); + + cocos2d::JniMethodInfo miGetContext; + + if (!cocos2d::JniHelper::getStaticMethodInfo(miGetContext, "org/cocos2dx/lib/Cocos2dxActivity", + "getContext", "()Landroid/content/Context;")) { + return; + } + jobject jContext = (jobject) miGetContext.env->CallStaticObjectMethod(miGetContext.classID, + miGetContext.methodID); + + std::string jPurchaseTypeString = details.getPurchaseType(); + jstring jPurchaseToken = jniGetInstance.env->NewStringUTF(details.getPurchaseToken().c_str()); + jstring jProductId = jniGetInstance.env->NewStringUTF(details.getProductId().c_str()); + jstring jPrice = jniGetInstance.env->NewStringUTF(details.getPrice().c_str()); + jstring jCurrency = jniGetInstance.env->NewStringUTF(details.getCurrency().c_str()); + + jobject hashMapObj = valueMapToHashMap(jniGetInstance, params); + + + if (NULL != afInstance) { + jclass afPurchaseDetailsClass = jniGetInstance.env->FindClass("com/appsflyer/AFPurchaseDetails"); + jmethodID purchaseDetails = jniGetInstance.env->GetMethodID(afPurchaseDetailsClass, "", + "(Lcom/appsflyer/AFPurchaseType;" + "Ljava/lang/String;" + "Ljava/lang/String;" + "Ljava/lang/String;" + "Ljava/lang/String;)V"); + + jclass afPurchaseTypeClass = jniGetInstance.env->FindClass("com/appsflyer/AFPurchaseType"); + + jmethodID afPurchaseTypeMethodId = jniGetInstance.env->GetStaticMethodID(afPurchaseTypeClass, "values", "()[Lcom/appsflyer/AFPurchaseType;"); + jobjectArray afPurchaseTypeArray = (jobjectArray) jniGetInstance.env->CallStaticObjectMethod(afPurchaseTypeClass, afPurchaseTypeMethodId); + if (afPurchaseTypeArray == nullptr) { + CCLOG("Error: Call to values() returned null."); + return; + } + + jsize arrayLength = jniGetInstance.env->GetArrayLength(afPurchaseTypeArray); + + jobject selectedPurchaseType; + if (jPurchaseTypeString.compare("subscription") == 0) { + CCLOG("Purchase type is 'subscription'."); + selectedPurchaseType = jniGetInstance.env->GetObjectArrayElement(afPurchaseTypeArray, 0); + CCLOG("First enum constant (SUBSCRIPTION): %p", selectedPurchaseType); + } else if (jPurchaseTypeString.compare("one_time_purchase") == 0) { + CCLOG("Purchase type is 'one_time_purchase'."); + selectedPurchaseType = jniGetInstance.env->GetObjectArrayElement(afPurchaseTypeArray, 1); + CCLOG("Second enum constant (ONE_TIME_PURCHASE): %p", selectedPurchaseType); + } else { + CCLOG("Error: Unknown purchase type."); + return; + } + + CCLOG("afPurchaseTypeClass: %p", afPurchaseTypeClass); + jobject jPurchaseDetails = jniGetInstance.env->NewObject(afPurchaseDetailsClass, + purchaseDetails, + selectedPurchaseType, + jPurchaseToken, + jProductId, + jPrice, + jCurrency); + + CCLOG("Purchase details: %p", jPurchaseDetails); + jclass cls = jniGetInstance.env->GetObjectClass(afInstance); + jmethodID methodId = jniGetInstance.env->GetMethodID( + cls, + "validateAndLogInAppPurchase", + "(Lcom/appsflyer/AFPurchaseDetails;" + "Ljava/util/Map;" + "Lcom/appsflyer/AppsFlyerInAppPurchaseValidationCallback;)V" + ); + + jniGetInstance.env->CallVoidMethod(afInstance, methodId, jPurchaseDetails, hashMapObj, + nullptr); + + jniGetInstance.env->DeleteLocalRef(hashMapObj); + jniGetInstance.env->DeleteLocalRef(afInstance); + jniGetInstance.env->DeleteLocalRef(jniGetInstance.classID); + + jniGetInstance.env->DeleteLocalRef(jPurchaseToken); + jniGetInstance.env->DeleteLocalRef(jProductId); + jniGetInstance.env->DeleteLocalRef(jPrice); + jniGetInstance.env->DeleteLocalRef(jCurrency); + } else { + CCLOGERROR("%s", "'AppsFlyerLib' is not loaded"); + } +} + //Sharing data filter void AppsFlyerXAndroid::sharingFilter(std::vector partners){ cocos2d::JniMethodInfo jniGetInstance = getAppsFlyerInstance(); diff --git a/Classes/AppsFlyer/AppsFlyerXAndroid.h b/Classes/AppsFlyer/AppsFlyerXAndroid.h index fc273c5..1e2c5e1 100644 --- a/Classes/AppsFlyer/AppsFlyerXAndroid.h +++ b/Classes/AppsFlyer/AppsFlyerXAndroid.h @@ -75,12 +75,14 @@ class AppsFlyerXAndroid { static void start(); - static void logEvent(const std::string& eventName, const std::string& value); - static void logEvent(const std::string& eventName, cocos2d::ValueMap values); + static void logAdRevenue(const AFXAdRevenueData& adRevenueData, cocos2d::ValueMap params); + static void validateAndLogInAppPurchase(std::string productIdentifier, std::string price, std::string currency, std::string tranactionId, cocos2d::ValueMap params, void (*successBlock)(cocos2d::ValueMap response), void (*failedBlock)(void* error, void* responce)); + static void validateAndLogInAppPurchase(AFSDKXPurchaseDetails &details, cocos2d::ValueMap params, std::function completionHandler); + static void logLocation(double longitude, double latitude); static std::string getAppsFlyerUID(); diff --git a/Classes/AppsFlyer/AppsFlyerXApple.h b/Classes/AppsFlyer/AppsFlyerXApple.h index 7bead4d..7fd76ad 100644 --- a/Classes/AppsFlyer/AppsFlyerXApple.h +++ b/Classes/AppsFlyer/AppsFlyerXApple.h @@ -16,6 +16,8 @@ //#include "AppsFlyerXAppleDelegate.h" //#include "EmailCryptTypeX.h" #include "AppsFlyerXDeepLinkResult.h" +#include "AFSDKXPurchaseDetails.h" +#include "AFSDKXValidateAndLogResult.h" class AppsFlyerXApple { private: @@ -91,28 +93,26 @@ class AppsFlyerXApple { std::function successBlock, std::function failureBlock); + static void validateAndLogInAppPurchase(AFSDKXPurchaseDetails &details, + cocos2d::ValueMap params, + std::function completionHandler); + + static void logAdRevenue(AFXAdRevenueData adRevenueData, cocos2d::ValueMap additionalParameters); + static void logLocation(double longitude, double latitude); static std::string getAppsFlyerUID(); - static void handleOpenURL(const std::string& url, const std::string& sourceApplication); static void handleOpenURL(std::string url, std::string sourceApplication, void* annotation); static void handleOpenURL(std::string url, cocos2d::ValueMap options); - /* - - (BOOL) continueUserActivity:(NSUserActivity *) userActivity restorationHandler:(void (^)(NSArray *))restorationHandler NS_AVAILABLE_IOS(9_0); - - (void) didUpdateUserActivity:(NSUserActivity *)userActivity NS_AVAILABLE_IOS(9_0); - */ - static void handlePushNotification(cocos2d::ValueMap pushPayload); static void registerUninstall(void* deviceToken, unsigned long length); - // static std::string getSDKVersion(); - static void remoteDebuggingCallWithData(const std::string& data); static void setHost(const std::string& host); @@ -124,7 +124,7 @@ class AppsFlyerXApple { static void stop(bool stop); - // Delegates methods proxy + // MARK: - AppsFlyerLib delegate proxy methods static void setOnConversionDataReceived(void(*callback)(cocos2d::ValueMap installData)); static void setOnConversionDataRequestFailure(void(*callback)(cocos2d::ValueMap error)); static void setOnAppOpenAttribution(void(*callback)(cocos2d::ValueMap attributionData)); diff --git a/Classes/AppsFlyer/AppsFlyerXApple.mm b/Classes/AppsFlyer/AppsFlyerXApple.mm index 0e31954..e0c5400 100644 --- a/Classes/AppsFlyer/AppsFlyerXApple.mm +++ b/Classes/AppsFlyer/AppsFlyerXApple.mm @@ -12,7 +12,10 @@ #include "AppsFlyerXAppleHelper.h" #include "AppsFlyerXAppleDelegate.h" #include "AppsFlyerXAppleDeepLinkDelegate.h" +#include "AFSDKXPurchaseDetails.h" +#include "AFSDKXValidateAndLogResult.h" #import "libAppsFlyer/AppsFlyerLib.h" +#import "libAppsFlyer/AFSDKPurchaseDetails.h" #import @@ -74,7 +77,7 @@ static AppsFlyerXApple *xApple = nil; static AppsFlyerXAppleDelegate *delegate = nil; [[AppsFlyerLib shared] setPluginInfoWith: AFSDKPluginCocos2dx - pluginVersion:@"6.13.0" + pluginVersion:@"6.15.3" additionalParams:nil]; dispatch_once(&onceToken, ^{ @@ -249,6 +252,54 @@ }]; } + +void AppsFlyerXApple::validateAndLogInAppPurchase(AFSDKXPurchaseDetails &details, + cocos2d::ValueMap params, + std::function completionHandler) { + + NSString *productId = [NSString stringWithUTF8String:details.getProductId().c_str()]; + NSString *price = [NSString stringWithUTF8String:details.getPrice().c_str()]; + NSString *transactionId = [NSString stringWithUTF8String:details.getTransactionId().c_str()]; + NSString *currency = [NSString stringWithUTF8String:details.getCurrency().c_str()]; + NSDictionary *lParams = AppsFlyerXAppleHelper::valueMap2nsDictionary(params); + + AFSDKPurchaseDetails *afPurchaseDetails = [[AFSDKPurchaseDetails alloc] initWithProductId:productId + price:price + currency:currency + transactionId:transactionId]; + + [[AppsFlyerLib shared] validateAndLogInAppPurchase:afPurchaseDetails extraEventValues:lParams completionHandler:^(AFSDKValidateAndLogResult * _Nullable result) { + // TODO: - add result to completionHandler + NSLog(@"[ValidateAndLog] Result: %@", result); + AFSDKXValidateAndLogStatus status = AFSDKXValidateAndLogResult::objcEnumToCppEnum(result.status); + cocos2d::ValueMap resultX = AppsFlyerXAppleHelper::nsDictionary2ValueMap(result.result); + cocos2d::ValueMap errorData = AppsFlyerXAppleHelper::nsDictionary2ValueMap(result.errorData); + + NSMutableDictionary *errorDictionary = [NSMutableDictionary dictionary]; + if (result.error) { + errorDictionary[@"errorCode"] = [NSNumber numberWithInteger:result.error.code]; + errorDictionary[@"errorDescription"] = result.error.localizedDescription; + } + AFSDKXValidateAndLogResult validateResult = AFSDKXValidateAndLogResult(status, resultX, errorData, AppsFlyerXAppleHelper::nsDictionary2ValueMap(errorDictionary)); + + completionHandler(validateResult); + }]; +} + +void AppsFlyerXApple::logAdRevenue(AFXAdRevenueData adRevenueData, + cocos2d::ValueMap additionalParameters) { + NSDictionary *lParams = AppsFlyerXAppleHelper::valueMap2nsDictionary(additionalParameters); + + NSString * monetizationNetwork = [NSString stringWithUTF8String:adRevenueData.getMonetizationNetwork().c_str()]; + AppsFlyerAdRevenueMediationNetworkType mediationNetwork = static_cast(adRevenueData.getMediationNetwork()); + NSString * currencyIso4217Code = [NSString stringWithUTF8String:adRevenueData.getCurrencyIso4217Code().c_str()]; + NSNumber *eventRevenue = [NSNumber numberWithDouble:adRevenueData.getEventRevenue()]; + + AFAdRevenueData *appsflyerAdRevenueData = [[AFAdRevenueData alloc] initWithMonetizationNetwork:monetizationNetwork mediationNetwork:mediationNetwork currencyIso4217Code:currencyIso4217Code eventRevenue:eventRevenue]; + + [[AppsFlyerLib shared] logAdRevenue:appsflyerAdRevenueData additionalParameters:lParams]; +} + void AppsFlyerXApple::logLocation(double longitude, double latitude) { [[AppsFlyerLib shared] logLocation:longitude latitude:latitude]; } diff --git a/Classes/AppsFlyer/AppsFlyerXAppleDelegate.h b/Classes/AppsFlyer/AppsFlyerXAppleDelegate.h index 0f998c7..a91910f 100644 --- a/Classes/AppsFlyer/AppsFlyerXAppleDelegate.h +++ b/Classes/AppsFlyer/AppsFlyerXAppleDelegate.h @@ -7,7 +7,7 @@ #ifndef AppsFlyerXAppleDelegate_h #define AppsFlyerXAppleDelegate_h -#import "AppsFlyerLib.h" +#import "AppsFlyer/libAppsFlyer/AppsFlyerLib.h" @interface AppsFlyerXAppleDelegate: NSObject diff --git a/Classes/AppsFlyer/AppsFlyerXAppleHelper.h b/Classes/AppsFlyer/AppsFlyerXAppleHelper.h index e5661d7..2dd362c 100644 --- a/Classes/AppsFlyer/AppsFlyerXAppleHelper.h +++ b/Classes/AppsFlyer/AppsFlyerXAppleHelper.h @@ -12,6 +12,7 @@ #include #include "AppsFlyerXDeepLinkResult.h" #import "libAppsFlyer/AppsFlyerLib.h" +#import //#import diff --git a/Classes/AppsFlyer/AppsFlyerXAppleHelper.mm b/Classes/AppsFlyer/AppsFlyerXAppleHelper.mm index 4b3d76e..f78efff 100644 --- a/Classes/AppsFlyer/AppsFlyerXAppleHelper.mm +++ b/Classes/AppsFlyer/AppsFlyerXAppleHelper.mm @@ -9,6 +9,7 @@ #include "AppsFlyerXDeepLinkResult.h" + cocos2d::ValueMap AppsFlyerXAppleHelper::nsDictionary2ValueMap(NSDictionary *dic) { cocos2d::ValueMap vm; nsDictionary2ValueMap(dic, vm); diff --git a/Classes/AppsFlyer/AppsFlyerXMacro.h b/Classes/AppsFlyer/AppsFlyerXMacro.h index 5fea9f3..3149375 100644 --- a/Classes/AppsFlyer/AppsFlyerXMacro.h +++ b/Classes/AppsFlyer/AppsFlyerXMacro.h @@ -114,6 +114,12 @@ #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" + #endif /* AppsFlyerXMacro_h */ diff --git a/Classes/AppsFlyer/libAppsFlyer/AFAdRevenueData.h b/Classes/AppsFlyer/libAppsFlyer/AFAdRevenueData.h new file mode 100644 index 0000000..2025468 --- /dev/null +++ b/Classes/AppsFlyer/libAppsFlyer/AFAdRevenueData.h @@ -0,0 +1,68 @@ +// +// AFAdRevenueData.h +// AppsFlyerLib +// +// Created by Veronica Belyakov on 26/06/2024. +// + +typedef NS_CLOSED_ENUM(NSUInteger, AppsFlyerAdRevenueMediationNetworkType) { + AppsFlyerAdRevenueMediationNetworkTypeGoogleAdMob = 1, + AppsFlyerAdRevenueMediationNetworkTypeIronSource = 2, + AppsFlyerAdRevenueMediationNetworkTypeApplovinMax= 3, + AppsFlyerAdRevenueMediationNetworkTypeFyber = 4, + AppsFlyerAdRevenueMediationNetworkTypeAppodeal = 5, + AppsFlyerAdRevenueMediationNetworkTypeAdmost = 6, + AppsFlyerAdRevenueMediationNetworkTypeTopon = 7, + AppsFlyerAdRevenueMediationNetworkTypeTradplus = 8, + AppsFlyerAdRevenueMediationNetworkTypeYandex = 9, + AppsFlyerAdRevenueMediationNetworkTypeChartBoost = 10, + AppsFlyerAdRevenueMediationNetworkTypeUnity = 11, + AppsFlyerAdRevenueMediationNetworkTypeToponPte = 12, + AppsFlyerAdRevenueMediationNetworkTypeCustom = 13, + AppsFlyerAdRevenueMediationNetworkTypeDirectMonetization = 14 +} NS_SWIFT_NAME(MediationNetworkType); + +#define kAppsFlyerAdRevenueMonetizationNetwork @"monetization_network" +#define kAppsFlyerAdRevenueMediationNetwork @"mediation_network" +#define kAppsFlyerAdRevenueEventRevenue @"event_revenue" +#define kAppsFlyerAdRevenueEventRevenueCurrency @"event_revenue_currency" +#define kAppsFlyerAdRevenueCustomParameters @"custom_parameters" +#define kAFADRWrapperTypeGeneric @"adrevenue_sdk" + +//Pre-defined keys for non-mandatory dictionary + +//Code ISO 3166-1 format +#define kAppsFlyerAdRevenueCountry @"country" + +//ID of the ad unit for the impression +#define kAppsFlyerAdRevenueAdUnit @"ad_unit" + +//Format of the ad +#define kAppsFlyerAdRevenueAdType @"ad_type" + +//ID of the ad placement for the impression +#define kAppsFlyerAdRevenuePlacement @"placement" + + +@interface AFAdRevenueData : NSObject + +- (nonnull instancetype)init NS_UNAVAILABLE; ++ (nonnull instancetype)new NS_UNAVAILABLE; + +@property (strong, nonnull, nonatomic) NSString *monetizationNetwork; +@property AppsFlyerAdRevenueMediationNetworkType mediationNetwork; +@property (strong, nonnull, nonatomic) NSString *currencyIso4217Code; +@property (strong, nonnull, nonatomic) NSNumber *eventRevenue; + +/** +* @param monetizationNetwork network which monetized the impression (@"facebook") +* @param mediationNetwork mediation source that mediated the monetization network for the impression (AppsFlyerAdRevenueMediationNetworkTypeGoogleAdMob) +* @param currencyIso4217Code reported impression’s revenue currency ISO 4217 format (@"USD") +* @param eventRevenue reported impression’s revenue (@(0.001994303)) +*/ +- (instancetype _Nonnull )initWithMonetizationNetwork:(NSString *_Nonnull)monetizationNetwork + mediationNetwork:(AppsFlyerAdRevenueMediationNetworkType)mediationNetwork + currencyIso4217Code:(NSString *_Nonnull)currencyIso4217Code + eventRevenue:(NSNumber *_Nonnull)eventRevenue; + +@end diff --git a/Classes/AppsFlyer/libAppsFlyer/AFSDKPurchaseDetails.h b/Classes/AppsFlyer/libAppsFlyer/AFSDKPurchaseDetails.h new file mode 100644 index 0000000..89af8a7 --- /dev/null +++ b/Classes/AppsFlyer/libAppsFlyer/AFSDKPurchaseDetails.h @@ -0,0 +1,23 @@ +// +// AFSDKPurchaseDetails.h +// AppsFlyerLib +// +// Created by Moris Gateno on 13/03/2024. +// + +@interface AFSDKPurchaseDetails : NSObject + +- (nonnull instancetype)init NS_UNAVAILABLE; ++ (nonnull instancetype)new NS_UNAVAILABLE; + +@property (strong, nullable, nonatomic) NSString *productId; +@property (strong, nullable, nonatomic) NSString *price; +@property (strong, nullable, nonatomic) NSString *currency; +@property (strong, nullable, nonatomic) NSString *transactionId; + +- (instancetype _Nonnull )initWithProductId:(NSString *_Nullable)productId + price:(NSString *_Nullable)price + currency:(NSString *_Nullable)currency + transactionId:(NSString *_Nullable)transactionId; + +@end diff --git a/Classes/AppsFlyer/libAppsFlyer/AFSDKValidateAndLogResult.h b/Classes/AppsFlyer/libAppsFlyer/AFSDKValidateAndLogResult.h new file mode 100644 index 0000000..1ddb9f2 --- /dev/null +++ b/Classes/AppsFlyer/libAppsFlyer/AFSDKValidateAndLogResult.h @@ -0,0 +1,35 @@ +// +// AFSDKValidateAndLogResult.h +// AppsFlyerLib +// +// Created by Moris Gateno on 13/03/2024. +// + + +typedef NS_CLOSED_ENUM(NSUInteger, AFSDKValidateAndLogStatus) { + AFSDKValidateAndLogStatusSuccess, + AFSDKValidateAndLogStatusFailure, + AFSDKValidateAndLogStatusError +} NS_SWIFT_NAME(ValidateAndLogStatus); + +NS_SWIFT_NAME(ValidateAndLogResult) +@interface AFSDKValidateAndLogResult: NSObject + +- (nonnull instancetype)init NS_UNAVAILABLE; ++ (nonnull instancetype)new NS_UNAVAILABLE; + +- (instancetype _Nonnull )initWithStatus:(AFSDKValidateAndLogStatus)status + result:(NSDictionary *_Nullable)result + errorData:(NSDictionary *_Nullable)errorData + error:(NSError *_Nullable)error; + +@property(readonly) AFSDKValidateAndLogStatus status; +// Success case +@property(readonly, nullable) NSDictionary *result; +// Server 200 with validation failure +@property(readonly, nullable) NSDictionary *errorData; +// for the error case +@property(readonly, nullable) NSError *error; + +@end + diff --git a/Classes/AppsFlyer/libAppsFlyer/AppsFlyerLib-Swift.h b/Classes/AppsFlyer/libAppsFlyer/AppsFlyerLib-Swift.h new file mode 100644 index 0000000..1f1b87e --- /dev/null +++ b/Classes/AppsFlyer/libAppsFlyer/AppsFlyerLib-Swift.h @@ -0,0 +1,311 @@ +#if 0 +#elif defined(__arm64__) && __arm64__ +// Generated by Apple Swift version 5.9 (swiftlang-5.9.0.128.108 clang-1500.0.40.1) +#ifndef APPSFLYERLIB_SWIFT_H +#define APPSFLYERLIB_SWIFT_H +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wgcc-compat" + +#if !defined(__has_include) +# define __has_include(x) 0 +#endif +#if !defined(__has_attribute) +# define __has_attribute(x) 0 +#endif +#if !defined(__has_feature) +# define __has_feature(x) 0 +#endif +#if !defined(__has_warning) +# define __has_warning(x) 0 +#endif + +#if __has_include() +# include +#endif + +#pragma clang diagnostic ignored "-Wauto-import" +#if defined(__OBJC__) +#include +#endif +#if defined(__cplusplus) +#include +#include +#include +#include +#include +#include +#include +#else +#include +#include +#include +#include +#endif +#if defined(__cplusplus) +#if defined(__arm64e__) && __has_include() +# include +#else +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreserved-macro-identifier" +# ifndef __ptrauth_swift_value_witness_function_pointer +# define __ptrauth_swift_value_witness_function_pointer(x) +# endif +# ifndef __ptrauth_swift_class_method_pointer +# define __ptrauth_swift_class_method_pointer(x) +# endif +#pragma clang diagnostic pop +#endif +#endif + +#if !defined(SWIFT_TYPEDEFS) +# define SWIFT_TYPEDEFS 1 +# if __has_include() +# include +# elif !defined(__cplusplus) +typedef uint_least16_t char16_t; +typedef uint_least32_t char32_t; +# endif +typedef float swift_float2 __attribute__((__ext_vector_type__(2))); +typedef float swift_float3 __attribute__((__ext_vector_type__(3))); +typedef float swift_float4 __attribute__((__ext_vector_type__(4))); +typedef double swift_double2 __attribute__((__ext_vector_type__(2))); +typedef double swift_double3 __attribute__((__ext_vector_type__(3))); +typedef double swift_double4 __attribute__((__ext_vector_type__(4))); +typedef int swift_int2 __attribute__((__ext_vector_type__(2))); +typedef int swift_int3 __attribute__((__ext_vector_type__(3))); +typedef int swift_int4 __attribute__((__ext_vector_type__(4))); +typedef unsigned int swift_uint2 __attribute__((__ext_vector_type__(2))); +typedef unsigned int swift_uint3 __attribute__((__ext_vector_type__(3))); +typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4))); +#endif + +#if !defined(SWIFT_PASTE) +# define SWIFT_PASTE_HELPER(x, y) x##y +# define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y) +#endif +#if !defined(SWIFT_METATYPE) +# define SWIFT_METATYPE(X) Class +#endif +#if !defined(SWIFT_CLASS_PROPERTY) +# if __has_feature(objc_class_property) +# define SWIFT_CLASS_PROPERTY(...) __VA_ARGS__ +# else +# define SWIFT_CLASS_PROPERTY(...) +# endif +#endif +#if !defined(SWIFT_RUNTIME_NAME) +# if __has_attribute(objc_runtime_name) +# define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X))) +# else +# define SWIFT_RUNTIME_NAME(X) +# endif +#endif +#if !defined(SWIFT_COMPILE_NAME) +# if __has_attribute(swift_name) +# define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X))) +# else +# define SWIFT_COMPILE_NAME(X) +# endif +#endif +#if !defined(SWIFT_METHOD_FAMILY) +# if __has_attribute(objc_method_family) +# define SWIFT_METHOD_FAMILY(X) __attribute__((objc_method_family(X))) +# else +# define SWIFT_METHOD_FAMILY(X) +# endif +#endif +#if !defined(SWIFT_NOESCAPE) +# if __has_attribute(noescape) +# define SWIFT_NOESCAPE __attribute__((noescape)) +# else +# define SWIFT_NOESCAPE +# endif +#endif +#if !defined(SWIFT_RELEASES_ARGUMENT) +# if __has_attribute(ns_consumed) +# define SWIFT_RELEASES_ARGUMENT __attribute__((ns_consumed)) +# else +# define SWIFT_RELEASES_ARGUMENT +# endif +#endif +#if !defined(SWIFT_WARN_UNUSED_RESULT) +# if __has_attribute(warn_unused_result) +# define SWIFT_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +# else +# define SWIFT_WARN_UNUSED_RESULT +# endif +#endif +#if !defined(SWIFT_NORETURN) +# if __has_attribute(noreturn) +# define SWIFT_NORETURN __attribute__((noreturn)) +# else +# define SWIFT_NORETURN +# endif +#endif +#if !defined(SWIFT_CLASS_EXTRA) +# define SWIFT_CLASS_EXTRA +#endif +#if !defined(SWIFT_PROTOCOL_EXTRA) +# define SWIFT_PROTOCOL_EXTRA +#endif +#if !defined(SWIFT_ENUM_EXTRA) +# define SWIFT_ENUM_EXTRA +#endif +#if !defined(SWIFT_CLASS) +# if __has_attribute(objc_subclassing_restricted) +# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA +# define SWIFT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# else +# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# define SWIFT_CLASS_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# endif +#endif +#if !defined(SWIFT_RESILIENT_CLASS) +# if __has_attribute(objc_class_stub) +# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME) __attribute__((objc_class_stub)) +# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_class_stub)) SWIFT_CLASS_NAMED(SWIFT_NAME) +# else +# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME) +# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) SWIFT_CLASS_NAMED(SWIFT_NAME) +# endif +#endif +#if !defined(SWIFT_PROTOCOL) +# define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA +# define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA +#endif +#if !defined(SWIFT_EXTENSION) +# define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__) +#endif +#if !defined(OBJC_DESIGNATED_INITIALIZER) +# if __has_attribute(objc_designated_initializer) +# define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) +# else +# define OBJC_DESIGNATED_INITIALIZER +# endif +#endif +#if !defined(SWIFT_ENUM_ATTR) +# if __has_attribute(enum_extensibility) +# define SWIFT_ENUM_ATTR(_extensibility) __attribute__((enum_extensibility(_extensibility))) +# else +# define SWIFT_ENUM_ATTR(_extensibility) +# endif +#endif +#if !defined(SWIFT_ENUM) +# define SWIFT_ENUM(_type, _name, _extensibility) enum _name : _type _name; enum SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type +# if __has_feature(generalized_swift_name) +# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type +# else +# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) SWIFT_ENUM(_type, _name, _extensibility) +# endif +#endif +#if !defined(SWIFT_UNAVAILABLE) +# define SWIFT_UNAVAILABLE __attribute__((unavailable)) +#endif +#if !defined(SWIFT_UNAVAILABLE_MSG) +# define SWIFT_UNAVAILABLE_MSG(msg) __attribute__((unavailable(msg))) +#endif +#if !defined(SWIFT_AVAILABILITY) +# define SWIFT_AVAILABILITY(plat, ...) __attribute__((availability(plat, __VA_ARGS__))) +#endif +#if !defined(SWIFT_WEAK_IMPORT) +# define SWIFT_WEAK_IMPORT __attribute__((weak_import)) +#endif +#if !defined(SWIFT_DEPRECATED) +# define SWIFT_DEPRECATED __attribute__((deprecated)) +#endif +#if !defined(SWIFT_DEPRECATED_MSG) +# define SWIFT_DEPRECATED_MSG(...) __attribute__((deprecated(__VA_ARGS__))) +#endif +#if !defined(SWIFT_DEPRECATED_OBJC) +# if __has_feature(attribute_diagnose_if_objc) +# define SWIFT_DEPRECATED_OBJC(Msg) __attribute__((diagnose_if(1, Msg, "warning"))) +# else +# define SWIFT_DEPRECATED_OBJC(Msg) SWIFT_DEPRECATED_MSG(Msg) +# endif +#endif +#if defined(__OBJC__) +#if !defined(IBSegueAction) +# define IBSegueAction +#endif +#endif +#if !defined(SWIFT_EXTERN) +# if defined(__cplusplus) +# define SWIFT_EXTERN extern "C" +# else +# define SWIFT_EXTERN extern +# endif +#endif +#if !defined(SWIFT_CALL) +# define SWIFT_CALL __attribute__((swiftcall)) +#endif +#if !defined(SWIFT_INDIRECT_RESULT) +# define SWIFT_INDIRECT_RESULT __attribute__((swift_indirect_result)) +#endif +#if !defined(SWIFT_CONTEXT) +# define SWIFT_CONTEXT __attribute__((swift_context)) +#endif +#if !defined(SWIFT_ERROR_RESULT) +# define SWIFT_ERROR_RESULT __attribute__((swift_error_result)) +#endif +#if defined(__cplusplus) +# define SWIFT_NOEXCEPT noexcept +#else +# define SWIFT_NOEXCEPT +#endif +#if !defined(SWIFT_C_INLINE_THUNK) +# if __has_attribute(always_inline) +# if __has_attribute(nodebug) +# define SWIFT_C_INLINE_THUNK inline __attribute__((always_inline)) __attribute__((nodebug)) +# else +# define SWIFT_C_INLINE_THUNK inline __attribute__((always_inline)) +# endif +# else +# define SWIFT_C_INLINE_THUNK inline +# endif +#endif +#if defined(_WIN32) +#if !defined(SWIFT_IMPORT_STDLIB_SYMBOL) +# define SWIFT_IMPORT_STDLIB_SYMBOL __declspec(dllimport) +#endif +#else +#if !defined(SWIFT_IMPORT_STDLIB_SYMBOL) +# define SWIFT_IMPORT_STDLIB_SYMBOL +#endif +#endif +#if defined(__OBJC__) +#if __has_feature(objc_modules) +#if __has_warning("-Watimport-in-framework-header") +#pragma clang diagnostic ignored "-Watimport-in-framework-header" +#endif +#endif + +#endif +#pragma clang diagnostic ignored "-Wproperty-attribute-mismatch" +#pragma clang diagnostic ignored "-Wduplicate-method-arg" +#if __has_warning("-Wpragma-clang-attribute") +# pragma clang diagnostic ignored "-Wpragma-clang-attribute" +#endif +#pragma clang diagnostic ignored "-Wunknown-pragmas" +#pragma clang diagnostic ignored "-Wnullability" +#pragma clang diagnostic ignored "-Wdollar-in-identifier-extension" + +#if __has_attribute(external_source_symbol) +# pragma push_macro("any") +# undef any +# pragma clang attribute push(__attribute__((external_source_symbol(language="Swift", defined_in="AppsFlyerLib",generated_declaration))), apply_to=any(function,enum,objc_interface,objc_category,objc_protocol)) +# pragma pop_macro("any") +#endif + +#if defined(__OBJC__) +#endif +#if __has_attribute(external_source_symbol) +# pragma clang attribute pop +#endif +#if defined(__cplusplus) +#endif +#pragma clang diagnostic pop +#endif + +#else +#error unsupported Swift architecture +#endif diff --git a/Classes/AppsFlyer/libAppsFlyer/AppsFlyerLib.h b/Classes/AppsFlyer/libAppsFlyer/AppsFlyerLib.h index 3ed2d29..d7319a4 100644 --- a/Classes/AppsFlyer/libAppsFlyer/AppsFlyerLib.h +++ b/Classes/AppsFlyer/libAppsFlyer/AppsFlyerLib.h @@ -2,7 +2,7 @@ // AppsFlyerLib.h // AppsFlyerLib // -// AppsFlyer iOS SDK 6.13.1 (150) +// AppsFlyer iOS SDK 6.15.3 (217) // Copyright (c) 2012-2023 AppsFlyer Ltd. All rights reserved. // @@ -13,6 +13,9 @@ #import "AppsFlyerDeepLinkResult.h" #import "AppsFlyerDeepLink.h" #import "AppsFlyerConsent.h" +#import "AFSDKPurchaseDetails.h" +#import "AFSDKValidateAndLogResult.h" +#import "AFAdRevenueData.h" NS_ASSUME_NONNULL_BEGIN @@ -490,6 +493,28 @@ NS_SWIFT_NAME(logEvent(name:values:completionHandler:)); success:(void (^ _Nullable)(NSDictionary * response))successBlock failure:(void (^ _Nullable)(NSError * _Nullable error, id _Nullable reponse))failedBlock NS_AVAILABLE(10_7, 7_0); +typedef void (^AFSDKValidateAndLogCompletion)(AFSDKValidateAndLogResult * _Nullable result); + +/** + To log and validate in app purchases you can call this method from the completeTransaction: method on + your `SKPaymentTransactionObserver`. + + @param details The product details + @param extraEventValues The additional param, which you want to receive it in the raw reports + @param completionHandler The callback + */ +- (void)validateAndLogInAppPurchase:(AFSDKPurchaseDetails *)details + extraEventValues:(NSDictionary * _Nullable)extraEventValues + completionHandler:(AFSDKValidateAndLogCompletion)completionHandler NS_AVAILABLE(10_7, 7_0); + +/** + An API to provide the data from the impression payload to AdRevenue. + + @param adRevenueData object used to hold all mandatory parameters of AdRevenue event. + @param additionalParameters non-mandatory dictionary which can include pre-defined keys (kAppsFlyerAdRevenueCountry, etc) + */ +- (void)logAdRevenue:(AFAdRevenueData *)adRevenueData additionalParameters:(NSDictionary * _Nullable)additionalParameters; + /** To log location for geo-fencing. Does the same as code below. diff --git a/Classes/AppsFlyer/libAppsFlyer/libAppsFlyerLib.a b/Classes/AppsFlyer/libAppsFlyer/libAppsFlyerLib.a index 7dbcd1a..d94e352 100644 Binary files a/Classes/AppsFlyer/libAppsFlyer/libAppsFlyerLib.a and b/Classes/AppsFlyer/libAppsFlyer/libAppsFlyerLib.a differ diff --git a/Classes/HelloWorldScene.cpp b/Classes/HelloWorldScene.cpp index 36c0fe6..1fd69d0 100644 --- a/Classes/HelloWorldScene.cpp +++ b/Classes/HelloWorldScene.cpp @@ -111,14 +111,10 @@ bool HelloWorld::init() std::cout << "Log event raised" << std::endl; ValueMap params; - AppsFlyerX::validateAndLogInAppPurchase("1", "2", "USD", "3", params, [&](cocos2d::ValueMap result) { - for (auto& t : result) - std::cout << t.first << " " - << t.second.asString() << "\n"; - }, [&](cocos2d::ValueMap error) { - for (auto& t : error) - std::cout << t.first << " " - << t.second.asString() << "\n"; + AFSDKXPurchaseDetails details = AFSDKXPurchaseDetails(AFXPurchaseType::SUBSCRIPTION, "public", "customId", "price", "curr", "transactionId"); + AppsFlyerX::validateAndLogInAppPurchase(details, params, [](const AFSDKXValidateAndLogResult& result) { + std::cout << "Result Status: " << static_cast(result.getStatus()) << std::endl; + }); break; } diff --git a/Classes/Strict/AppsFlyer/AFSDKXPurchaseDetails.cpp b/Classes/Strict/AppsFlyer/AFSDKXPurchaseDetails.cpp new file mode 100644 index 0000000..bc8294e --- /dev/null +++ b/Classes/Strict/AppsFlyer/AFSDKXPurchaseDetails.cpp @@ -0,0 +1,51 @@ +// +// AFSDKXPurchaseDetails.cpp +// MyGame +// +// Created by ivan.obodovskyi on 02.10.2024. +// + +#include +#include "AFSDKXPurchaseDetails.h" + +AFSDKXPurchaseDetails::AFSDKXPurchaseDetails(const std::string &productId, + const std::string &price, + const std::string ¤cy, + const std::string &transactionId) + : productId_(productId), + price_(price), + currency_(currency), + transactionId_(transactionId) { +} + +std::string AFSDKXPurchaseDetails::getProductId() const { + return productId_; +} + +void AFSDKXPurchaseDetails::setProductId(const std::string &productId) { + productId_ = productId; +} + +std::string AFSDKXPurchaseDetails::getPrice() const { + return price_; +} + +void AFSDKXPurchaseDetails::setPrice(const std::string &price) { + price_ = price; +} + +std::string AFSDKXPurchaseDetails::getCurrency() const { + return currency_; +} + +void AFSDKXPurchaseDetails::setCurrency(const std::string ¤cy) { + currency_ = currency; +} + +std::string AFSDKXPurchaseDetails::getTransactionId() const { + return transactionId_; +} + +void AFSDKXPurchaseDetails::setTransactionId(const std::string &transactionId) { + transactionId_ = transactionId; +} diff --git a/Classes/Strict/AppsFlyer/AFSDKXPurchaseDetails.h b/Classes/Strict/AppsFlyer/AFSDKXPurchaseDetails.h new file mode 100644 index 0000000..275542c --- /dev/null +++ b/Classes/Strict/AppsFlyer/AFSDKXPurchaseDetails.h @@ -0,0 +1,54 @@ +// +// AFSDKXPurchaseDetails.h +// MyGame +// +// Created by ivan.obodovskyi on 02.10.2024. +// + +#ifndef AFSDKXPurchaseDetails_h +#define AFSDKXPurchaseDetails_h + +#include +#include "cocos2d.h" +#include "AFSDKXValidateAndLogResult.h" + + +class AFSDKXPurchaseDetails { +public: + // Deleted default constructor to prevent usage. + AFSDKXPurchaseDetails() = delete; + + // Constructor with parameters to initialize the properties. + AFSDKXPurchaseDetails(const std::string &productId, + const std::string &price, + const std::string ¤cy, + const std::string &transactionId); + + // Default destructor. + virtual ~AFSDKXPurchaseDetails() = default; + + // Public assignment and copy constructors + AFSDKXPurchaseDetails(const AFSDKXPurchaseDetails &) = default; + AFSDKXPurchaseDetails &operator=(const AFSDKXPurchaseDetails &) = default; + + // Getters and setters for private member variables. + std::string getProductId() const; + void setProductId(const std::string &productId); + + std::string getPrice() const; + void setPrice(const std::string &price); + + std::string getCurrency() const; + void setCurrency(const std::string ¤cy); + + std::string getTransactionId() const; + void setTransactionId(const std::string &transactionId); + +private: + // Private member variables. + std::string productId_; + std::string price_; + std::string currency_; + std::string transactionId_; +}; +#endif /* AFSDKXPurchaseDetails_h */ diff --git a/Classes/Strict/AppsFlyer/AFSDKXValidateAndLogResult.cpp b/Classes/Strict/AppsFlyer/AFSDKXValidateAndLogResult.cpp new file mode 100644 index 0000000..729320a --- /dev/null +++ b/Classes/Strict/AppsFlyer/AFSDKXValidateAndLogResult.cpp @@ -0,0 +1,35 @@ +// +// AFSDKXValidateAndLogResult.cpp +// MyGame +// +// Created by ivan.obodovskyi on 03.10.2024. +// + +#include +#include "AFSDKXValidateAndLogResult.h" + +// Constructor implementation. +AFSDKXValidateAndLogResult::AFSDKXValidateAndLogResult( + AFSDKXValidateAndLogStatus status, + const cocos2d::ValueMap& result, + const cocos2d::ValueMap& errorData, + const std::shared_ptr& error) + : status_(status), result_(result), errorData_(errorData), error_(error) { +} + +// Getter methods implementation. +AFSDKXValidateAndLogStatus AFSDKXValidateAndLogResult::getStatus() const { + return status_; +} + +cocos2d::ValueMap AFSDKXValidateAndLogResult::getResult() const { + return result_; +} + +cocos2d::ValueMap AFSDKXValidateAndLogResult::getErrorData() const { + return errorData_; +} + +std::shared_ptr AFSDKXValidateAndLogResult::getError() const { + return error_; +} diff --git a/Classes/Strict/AppsFlyer/AFSDKXValidateAndLogResult.h b/Classes/Strict/AppsFlyer/AFSDKXValidateAndLogResult.h new file mode 100644 index 0000000..60c0d31 --- /dev/null +++ b/Classes/Strict/AppsFlyer/AFSDKXValidateAndLogResult.h @@ -0,0 +1,52 @@ +// +// AFSDKXValidateAndLogResult.h +// MyGame +// +// Created by ivan.obodovskyi on 03.10.2024. +// + +#ifndef AFSDKXValidateAndLogResult_h +#define AFSDKXValidateAndLogResult_h + +#include +#include +#include +#include +#include + +// Assuming an error class similar to NSError exists in your C++ code. +class Error; + +// Enum to represent validation status +enum class AFSDKXValidateAndLogStatus { + Success, + Failure, + Error +}; + +class AFSDKXValidateAndLogResult { +public: + // Deleting default constructor to prevent usage. + AFSDKXValidateAndLogResult() = delete; + + // Constructor with initialization list. + AFSDKXValidateAndLogResult(AFSDKXValidateAndLogStatus status, + const cocos2d::ValueMap& result, + const cocos2d::ValueMap& errorData, + const std::shared_ptr& error); + + // Getter methods + AFSDKXValidateAndLogStatus getStatus() const; + cocos2d::ValueMap getResult() const; + cocos2d::ValueMap getErrorData() const; + std::shared_ptr getError() const; + +private: + // Member variables. + AFSDKXValidateAndLogStatus status_; + cocos2d::ValueMap result_; + cocos2d::ValueMap errorData_; + std::shared_ptr error_; +}; + +#endif /* AFSDKXValidateAndLogResult_h */ diff --git a/Classes/Strict/AppsFlyer/AFXAdRevenueData.cpp b/Classes/Strict/AppsFlyer/AFXAdRevenueData.cpp new file mode 100644 index 0000000..ceb2250 --- /dev/null +++ b/Classes/Strict/AppsFlyer/AFXAdRevenueData.cpp @@ -0,0 +1,41 @@ +// +// AFXAdRevenueData.cpp +// MyGame +// +// Created by ivan.obodovskyi on 04.10.2024. +// + +#include +#include "AFXAdRevenueData.h" + +// Constructor definition +AFXAdRevenueData::AFXAdRevenueData(const std::string& monetizationNetwork, + AppsFlyerXAdRevenueMediationNetworkType mediationNetwork, + const std::string& currencyIso4217Code, + double eventRevenue) + : monetizationNetwork(monetizationNetwork), + mediationNetwork(mediationNetwork), + currencyIso4217Code(currencyIso4217Code), + eventRevenue(eventRevenue) { +} + +// Getters implementation +std::string AFXAdRevenueData::getMonetizationNetwork() const { + return monetizationNetwork; +} + +AppsFlyerXAdRevenueMediationNetworkType AFXAdRevenueData::getMediationNetwork() const { + return mediationNetwork; +} + +std::string AFXAdRevenueData::getCurrencyIso4217Code() const { + return currencyIso4217Code; +} + +double AFXAdRevenueData::getEventRevenue() const { + return eventRevenue; +} + +int convertMeditationType(AppsFlyerXAdRevenueMediationNetworkType a) { + return static_cast(static_cast(a)); +} diff --git a/Classes/Strict/AppsFlyer/AFXAdRevenueData.h b/Classes/Strict/AppsFlyer/AFXAdRevenueData.h new file mode 100644 index 0000000..9fe0a61 --- /dev/null +++ b/Classes/Strict/AppsFlyer/AFXAdRevenueData.h @@ -0,0 +1,76 @@ +// +// AFXAdRevenueData.h +// MyGame +// +// Created by ivan.obodovskyi on 04.10.2024. +// + +#include + +#ifndef AFXAdRevenueData_h +#define AFXAdRevenueData_h + +enum class AppsFlyerXAdRevenueMediationNetworkType { + GoogleAdMob = 1, + IronSource = 2, + ApplovinMax = 3, + Fyber = 4, + Appodeal = 5, + Admost = 6, + Topon = 7, + Tradplus = 8, + Yandex = 9, + ChartBoost = 10, + Unity = 11, + ToponPte = 12, + Custom = 13, + DirectMonetization = 14 +}; + +#define kAppsFlyerAdRevenueMonetizationNetwork @"monetization_network" +#define kAppsFlyerAdRevenueMediationNetwork @"mediation_network" +#define kAppsFlyerAdRevenueEventRevenue @"event_revenue" +#define kAppsFlyerAdRevenueEventRevenueCurrency @"event_revenue_currency" +#define kAppsFlyerAdRevenueCustomParameters @"custom_parameters" +#define kAFADRWrapperTypeGeneric @"adrevenue_sdk" + +//Pre-defined keys for non-mandatory dictionary + +//Code ISO 3166-1 format +#define kAppsFlyerAdRevenueCountry @"country" + +//ID of the ad unit for the impression +#define kAppsFlyerAdRevenueAdUnit @"ad_unit" + +//Format of the ad +#define kAppsFlyerAdRevenueAdType @"ad_type" + +//ID of the ad placement for the impression +#define kAppsFlyerAdRevenuePlacement @"placement" + + +class AFXAdRevenueData { +public: + // Constructor with initialization parameters + AFXAdRevenueData(const std::string& monetizationNetwork, + AppsFlyerXAdRevenueMediationNetworkType mediationNetwork, + const std::string& currencyIso4217Code, + double eventRevenue); + + // Getter functions for each property + std::string getMonetizationNetwork() const; + AppsFlyerXAdRevenueMediationNetworkType getMediationNetwork() const; + std::string getCurrencyIso4217Code() const; + double getEventRevenue() const; + int convertMeditationType(AppsFlyerXAdRevenueMediationNetworkType a); + +private: + // Private member variables + std::string monetizationNetwork; + AppsFlyerXAdRevenueMediationNetworkType mediationNetwork; + std::string currencyIso4217Code; + double eventRevenue; +}; + + +#endif /* AFXAdRevenueData_h */ diff --git a/Classes/Strict/AppsFlyer/AppsFlyerX+AppController.h b/Classes/Strict/AppsFlyer/AppsFlyerX+AppController.h index 55ba6d2..b8f3d65 100644 --- a/Classes/Strict/AppsFlyer/AppsFlyerX+AppController.h +++ b/Classes/Strict/AppsFlyer/AppsFlyerX+AppController.h @@ -5,7 +5,7 @@ // Created by AndreyG-AF on 10/17/17. // -#import "AppController.h" + @interface AppController (AppsFlyerX) diff --git a/Classes/Strict/AppsFlyer/AppsFlyerX+AppController.m b/Classes/Strict/AppsFlyer/AppsFlyerX+AppController.m index 418a8dc..874809a 100644 --- a/Classes/Strict/AppsFlyer/AppsFlyerX+AppController.m +++ b/Classes/Strict/AppsFlyer/AppsFlyerX+AppController.m @@ -7,7 +7,7 @@ #import "AppsFlyerX+AppController.h" #import -#import "AppsFlyerLib.h" +#import "AppsFlyer/libAppsFlyer/AppsFlyerLib.h" @implementation AppController (AppsFlyerX) diff --git a/Classes/Strict/AppsFlyer/AppsFlyerX.cpp b/Classes/Strict/AppsFlyer/AppsFlyerX.cpp index e62f6f9..c85ff80 100644 --- a/Classes/Strict/AppsFlyer/AppsFlyerX.cpp +++ b/Classes/Strict/AppsFlyer/AppsFlyerX.cpp @@ -16,6 +16,28 @@ #include "AppsFlyerXApple.h" #endif +bool AppsFlyerX::manualStart = false; + +void AppsFlyerX::setManualStart(bool isManualStart) { + manualStart = isManualStart; +} + +//static void enableTCFDataCollection(bool shouldCollectConsentData); +void AppsFlyerX::enableTCFDataCollection(bool shouldCollectConsentData) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + AppsFlyerXAndroid::enableTCFDataCollection(shouldCollectConsentData); +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + AppsFlyerXApple::enableTCFDataCollection(shouldCollectConsentData); +#endif +} + +void AppsFlyerX::setConsentData(const AppsFlyerXConsent& consentData){ +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + AppsFlyerXAndroid::setConsentData(consentData); +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + AppsFlyerXApple::setConsentData(consentData); +#endif +} void AppsFlyerX::setCustomerUserID(const std::string& customerUserID) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) @@ -310,6 +332,22 @@ void AppsFlyerX::validateAndLogInAppPurchase(const std::string& publicKey, #endif } +void AppsFlyerX::logAdRevenue(AFXAdRevenueData adRevenueData, cocos2d::ValueMap additionalParameters) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + // Android implementation +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + AppsFlyerXApple::logAdRevenue(adRevenueData, additionalParameters); +#endif +} + +void AppsFlyerX::validateAndLogInAppPurchase(AFSDKXPurchaseDetails &details, cocos2d::ValueMap params, std::function completionHandler) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + // Android implementation +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + AppsFlyerXApple::validateAndLogInAppPurchase(details, params, completionHandler); +#endif +} + std::string AppsFlyerX::getAppsFlyerUID() { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) @@ -595,3 +633,12 @@ void AppsFlyerX::generateUserInviteLink(cocos2d::ValueMap parameters, std::funct AppsFlyerXApple::generateUserInviteLink(parameters, callback); #endif } + +void AppsFlyerX::setDisableNetworkData(bool disable){ +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + AppsFlyerXAndroid::setDisableNetworkData(disable); +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + //not supported for iOS + CCLOGWARN("%s", "setDisableNetworkData is not supported for iOS"); +#endif +} diff --git a/Classes/Strict/AppsFlyer/AppsFlyerX.h b/Classes/Strict/AppsFlyer/AppsFlyerX.h index 5c0409c..316acb3 100644 --- a/Classes/Strict/AppsFlyer/AppsFlyerX.h +++ b/Classes/Strict/AppsFlyer/AppsFlyerX.h @@ -15,11 +15,20 @@ #include "EmailCryptTypeX.h" #include "AppsFlyerXMacro.h" #include "AppsFlyerXDeepLinkResult.h" +#include "AppsFlyerXConsent.cpp" +#include "AFSDKXPurchaseDetails.h" +#include "AFXAdRevenueData.h" class AppsFlyerX { public: - + static bool manualStart; + static void setManualStart(bool isManualStart); + + static void enableTCFDataCollection(bool shouldCollectConsentData); + + static void setConsentData(const AppsFlyerXConsent& consentData); + static void setCustomerUserID(const std::string& customerUserID); static std::string customerUserID(); @@ -67,6 +76,8 @@ class AppsFlyerX { static void logEvent(const std::string& eventName, cocos2d::ValueMap values); + static void logAdRevenue(AFXAdRevenueData adRevenueData, cocos2d::ValueMap additionalParameters); + static void validateAndLogInAppPurchase(const std::string& productIdentifier, const std::string& price, const std::string& currency, @@ -81,6 +92,9 @@ class AppsFlyerX { const std::string& price, const std::string& currency, cocos2d::ValueMap additionalParameters); + + + static void validateAndLogInAppPurchase(AFSDKXPurchaseDetails &details, cocos2d::ValueMap params, std::function completionHandler); static void logLocation(double longitude, double latitude); @@ -152,6 +166,7 @@ class AppsFlyerX { static void generateUserInviteLink(cocos2d::ValueMap parameters,void(*onResponse)(std::string url), void(*onResponseError)(std::string url)); static void generateUserInviteLink(cocos2d::ValueMap parameters, std::function callback); + static void setDisableNetworkData(bool disable); }; #endif /* A;ppsFlyerX_h */ diff --git a/Classes/Strict/AppsFlyer/AppsFlyerXAndroid.cpp b/Classes/Strict/AppsFlyer/AppsFlyerXAndroid.cpp index 33766ad..94fb753 100644 --- a/Classes/Strict/AppsFlyer/AppsFlyerXAndroid.cpp +++ b/Classes/Strict/AppsFlyer/AppsFlyerXAndroid.cpp @@ -12,7 +12,7 @@ std::string afDevKey; bool isConveriosnListenerInitialized = false; bool isSubscribedForDeepLink = false; -const char *pluginVersion = "6.10.3"; +const char *pluginVersion = "6.15.1"; // Headers void initConvertionCallback(); @@ -50,6 +50,72 @@ cocos2d::JniMethodInfo getAppsFlyerInstance() { return jniGetInstance; } +/* + * AppsFlyerLib.getInstance().enableTCFDataCollection(true); + */ + +void AppsFlyerXAndroid::enableTCFDataCollection(bool shouldCollectConsentData) { + callVoidMethodWithBoolParam(shouldCollectConsentData, "enableTCFDataCollection", "(Z)V"); +} + +void AppsFlyerXAndroid::setConsentData(const AppsFlyerXConsent& consentData){ + cocos2d::JniMethodInfo jniGetConsentInstance; + jobject resultConsent; + + if (consentData.IsUserSubjectToGDPR()) { + bool hasConsentForDataUsage = consentData.HasConsentForDataUsage(); + bool hasConsentForAdsPersonalization = consentData.HasConsentForAdsPersonalization(); + jboolean jHasConsentForDataUsage = (jboolean)hasConsentForDataUsage; + jboolean jHasConsentForAdsPersonalization = (jboolean)hasConsentForAdsPersonalization; + if (cocos2d::JniHelper::getStaticMethodInfo(jniGetConsentInstance, + "com/appsflyer/AppsFlyerConsent", + "forGDPRUser", + "(ZZ)Lcom/appsflyer/AppsFlyerConsent;")) { + + resultConsent = (jobject) jniGetConsentInstance. + env->CallStaticObjectMethod(jniGetConsentInstance.classID, jniGetConsentInstance.methodID, + jHasConsentForDataUsage, + jHasConsentForAdsPersonalization); + } + else{ + CCLOG("%s", "'AppsFlyerConsent' is not loaded"); + return; + } + } + else{ + if (cocos2d::JniHelper::getStaticMethodInfo(jniGetConsentInstance, + "com/appsflyer/AppsFlyerConsent", + "forNonGDPRUser", + "()Lcom/appsflyer/AppsFlyerConsent;")) { + resultConsent = (jobject) jniGetConsentInstance. + env->CallStaticObjectMethod(jniGetConsentInstance.classID, jniGetConsentInstance.methodID); + } + else{ + CCLOG("%s", "'AppsFlyerConsent' is not loaded"); + return; + } + } + cocos2d::JniMethodInfo jniGetInstance = getAppsFlyerInstance(); + + jobject afInstance = (jobject) jniGetInstance.env->CallStaticObjectMethod( + jniGetInstance.classID, jniGetInstance.methodID); + + if (NULL != afInstance) { + + jclass cls = jniGetInstance.env->GetObjectClass(afInstance); + + jmethodID methodId = jniGetInstance.env->GetMethodID(cls, "setConsentData", "(Lcom/appsflyer/AppsFlyerConsent;)V"); + + jniGetInstance.env->CallVoidMethod(afInstance, methodId, resultConsent); + + jniGetInstance.env->DeleteLocalRef(resultConsent); + jniGetInstance.env->DeleteLocalRef(afInstance); + jniGetInstance.env->DeleteLocalRef(jniGetInstance.classID); + } else { + CCLOGERROR("%s", "'AppsFlyerLib' is not loaded"); + } + +} void AppsFlyerXAndroid::stop(bool shouldStop) { @@ -277,26 +343,8 @@ void AppsFlyerXAndroid::start() { jniGetInstance.classID, jniGetInstance.methodID); if (NULL != afInstance) { - //CCLOG("%s", "com/appsflyer/AppsFlyerLib is loaded"); - jclass cls = jniGetInstance.env->GetObjectClass(afInstance); - jclass clsExtension = jniGetInstance.env->FindClass("com/appsflyer/internal/platform_extension/PluginInfo"); - - - - jmethodID extensionConstructor = jniGetInstance.env->GetMethodID(clsExtension, - "","(Lcom/appsflyer/internal/platform_extension/Plugin;Ljava/lang/String;)V"); - - jclass enumClass = jniGetInstance.env->FindClass("com/appsflyer/internal/platform_extension/Plugin"); - jfieldID fid = jniGetInstance.env->GetStaticFieldID(enumClass, "COCOS_2DX","Lcom/appsflyer/internal/platform_extension/Plugin;"); - jobject plugin = jniGetInstance.env->GetStaticObjectField(enumClass, fid); - jstring version = jniGetInstance.env->NewStringUTF(pluginVersion); - jobject extensionObject = jniGetInstance.env->NewObject(clsExtension, extensionConstructor, plugin, version); - - callSetPluginInfo(extensionObject); - - cocos2d::JniMethodInfo jniGetContext; if (!cocos2d::JniHelper::getStaticMethodInfo(jniGetContext, @@ -312,17 +360,6 @@ void AppsFlyerXAndroid::start() { jstring jAppsFlyerDevKey = jniGetInstance.env->NewStringUTF(afDevKey.c_str()); - // call Init if no GCD registered - if (!isConveriosnListenerInitialized) { - jmethodID initMethodId = jniGetInstance.env->GetMethodID(cls, - "init", - "(Ljava/lang/String;Lcom/appsflyer/AppsFlyerConversionListener;Landroid/content/Context;)Lcom/appsflyer/AppsFlyerLib;"); - - // This is what we actually do: afLib.init(appsFlyerDevKey, null) - jniGetInstance.env->CallObjectMethod(afInstance, initMethodId, jAppsFlyerDevKey, NULL, jContext); - } - - //public void trackAppLaunch(Context ctx, String devKey) jmethodID startTrackingMethodId = jniGetInstance.env->GetMethodID(cls, "start", "(Landroid/content/Context;Ljava/lang/String;)V"); @@ -412,6 +449,75 @@ void AppsFlyerXAndroid::setUserEmails(std::vector userEmails, Email void AppsFlyerXAndroid::setAppsFlyerDevKey(const std::string &appsFlyerDevKey) { afDevKey = appsFlyerDevKey; + + if (afDevKey.empty()) { + CCLOGWARN("%s", "AppsFlyer Dev Key is not provided"); + return; + } + + cocos2d::JniMethodInfo jniGetInstance = getAppsFlyerInstance(); + + //AppsFlyerLib afLib instance + jobject afInstance = (jobject) jniGetInstance.env->CallStaticObjectMethod( + jniGetInstance.classID, jniGetInstance.methodID); + + if (NULL != afInstance) { + //CCLOG("%s", "com/appsflyer/AppsFlyerLib is loaded"); + + jclass cls = jniGetInstance.env->GetObjectClass(afInstance); + + jclass clsExtension = jniGetInstance.env->FindClass( + "com/appsflyer/internal/platform_extension/PluginInfo"); + + + jmethodID extensionConstructor = jniGetInstance.env->GetMethodID(clsExtension, + "", + "(Lcom/appsflyer/internal/platform_extension/Plugin;Ljava/lang/String;)V"); + + jclass enumClass = jniGetInstance.env->FindClass( + "com/appsflyer/internal/platform_extension/Plugin"); + jfieldID fid = jniGetInstance.env->GetStaticFieldID(enumClass, "COCOS_2DX", + "Lcom/appsflyer/internal/platform_extension/Plugin;"); + jobject plugin = jniGetInstance.env->GetStaticObjectField(enumClass, fid); + jstring version = jniGetInstance.env->NewStringUTF(pluginVersion); + jobject extensionObject = jniGetInstance.env->NewObject(clsExtension, extensionConstructor, + plugin, version); + + callSetPluginInfo(extensionObject); + + + cocos2d::JniMethodInfo jniGetContext; + + if (!cocos2d::JniHelper::getStaticMethodInfo(jniGetContext, + "org/cocos2dx/lib/Cocos2dxActivity", + "getContext", + "()Landroid/content/Context;")) { + return; + } + + jobject jContext = (jobject) jniGetContext.env->CallStaticObjectMethod( + jniGetContext.classID, jniGetContext.methodID); + + + jstring jAppsFlyerDevKey = jniGetInstance.env->NewStringUTF(afDevKey.c_str()); + + // call Init if no GCD registered + if (!isConveriosnListenerInitialized) { + jmethodID initMethodId = jniGetInstance.env->GetMethodID(cls, + "init", + "(Ljava/lang/String;Lcom/appsflyer/AppsFlyerConversionListener;Landroid/content/Context;)Lcom/appsflyer/AppsFlyerLib;"); + + // This is what we actually do: afLib.init(appsFlyerDevKey, null) + jniGetInstance.env->CallObjectMethod(afInstance, initMethodId, jAppsFlyerDevKey, NULL, + jContext); + + jniGetInstance.env->DeleteLocalRef(afInstance); + jniGetInstance.env->DeleteLocalRef(jniGetInstance.classID); + } + } + else { + CCLOGERROR("%s", "'AppsFlyerLib' is not loaded"); + } } std::string AppsFlyerXAndroid::appsFlyerDevKey() { @@ -1313,4 +1419,8 @@ void AppsFlyerXAndroid::logInvite(const std::string& channel, cocos2d::ValueMap } } -#endif \ No newline at end of file + +void AppsFlyerXAndroid::setDisableNetworkData(bool disable) { + callVoidMethodWithBoolParam(disable, "setDisableNetworkData", "(Z)V"); +} +#endif diff --git a/Classes/Strict/AppsFlyer/AppsFlyerXAndroid.h b/Classes/Strict/AppsFlyer/AppsFlyerXAndroid.h index fe6dbd2..fc273c5 100644 --- a/Classes/Strict/AppsFlyer/AppsFlyerXAndroid.h +++ b/Classes/Strict/AppsFlyer/AppsFlyerXAndroid.h @@ -10,6 +10,8 @@ #include "EmailCryptTypeX.h" #include "AppsFlyerXDeepLinkResult.h" +#include "AppsFlyerX.h" + class AppsFlyerXAndroid { private: @@ -24,6 +26,10 @@ class AppsFlyerXAndroid { static AppsFlyerXAndroid* getInstance(); + static void enableTCFDataCollection(bool shouldCollectConsentData); + + static void setConsentData(const AppsFlyerXConsent& consentData); + static void didEnterBackground(); static void setCustomerUserID(const std::string& customerUserID); @@ -136,6 +142,8 @@ class AppsFlyerXAndroid { static void generateInviteUrl(cocos2d::ValueMap parameter, void(*onResponse)(std::string url), void(*onResponseError)(std::string url)); static void logInvite(const std::string& channel,cocos2d::ValueMap parameters); + + static void setDisableNetworkData(bool disable); }; diff --git a/Classes/Strict/AppsFlyer/AppsFlyerXApple.h b/Classes/Strict/AppsFlyer/AppsFlyerXApple.h index c8e5fdf..7fd76ad 100644 --- a/Classes/Strict/AppsFlyer/AppsFlyerXApple.h +++ b/Classes/Strict/AppsFlyer/AppsFlyerXApple.h @@ -16,6 +16,8 @@ //#include "AppsFlyerXAppleDelegate.h" //#include "EmailCryptTypeX.h" #include "AppsFlyerXDeepLinkResult.h" +#include "AFSDKXPurchaseDetails.h" +#include "AFSDKXValidateAndLogResult.h" class AppsFlyerXApple { private: @@ -34,6 +36,10 @@ class AppsFlyerXApple { static AppsFlyerXApple* getInstance(); + static void enableTCFDataCollection(bool shouldCollectConsentData); + + static void setConsentData(const AppsFlyerXConsent& consentData); + static void setCustomerUserID(const std::string& customerUserID); static std::string customerUserID(); @@ -87,28 +93,26 @@ class AppsFlyerXApple { std::function successBlock, std::function failureBlock); + static void validateAndLogInAppPurchase(AFSDKXPurchaseDetails &details, + cocos2d::ValueMap params, + std::function completionHandler); + + static void logAdRevenue(AFXAdRevenueData adRevenueData, cocos2d::ValueMap additionalParameters); + static void logLocation(double longitude, double latitude); static std::string getAppsFlyerUID(); - static void handleOpenURL(const std::string& url, const std::string& sourceApplication); static void handleOpenURL(std::string url, std::string sourceApplication, void* annotation); static void handleOpenURL(std::string url, cocos2d::ValueMap options); - /* - - (BOOL) continueUserActivity:(NSUserActivity *) userActivity restorationHandler:(void (^)(NSArray *))restorationHandler NS_AVAILABLE_IOS(9_0); - - (void) didUpdateUserActivity:(NSUserActivity *)userActivity NS_AVAILABLE_IOS(9_0); - */ - static void handlePushNotification(cocos2d::ValueMap pushPayload); static void registerUninstall(void* deviceToken, unsigned long length); - // static std::string getSDKVersion(); - static void remoteDebuggingCallWithData(const std::string& data); static void setHost(const std::string& host); @@ -120,7 +124,7 @@ class AppsFlyerXApple { static void stop(bool stop); - // Delegates methods proxy + // MARK: - AppsFlyerLib delegate proxy methods static void setOnConversionDataReceived(void(*callback)(cocos2d::ValueMap installData)); static void setOnConversionDataRequestFailure(void(*callback)(cocos2d::ValueMap error)); static void setOnAppOpenAttribution(void(*callback)(cocos2d::ValueMap attributionData)); diff --git a/Classes/Strict/AppsFlyer/AppsFlyerXApple.mm b/Classes/Strict/AppsFlyer/AppsFlyerXApple.mm index 3d37391..ca1098d 100644 --- a/Classes/Strict/AppsFlyer/AppsFlyerXApple.mm +++ b/Classes/Strict/AppsFlyer/AppsFlyerXApple.mm @@ -7,12 +7,17 @@ // - +#include "AppsFlyerX.h" #include "AppsFlyerXApple.h" #include "AppsFlyerXAppleHelper.h" #include "AppsFlyerXAppleDelegate.h" #include "AppsFlyerXAppleDeepLinkDelegate.h" +#include "AFSDKXPurchaseDetails.h" +#include "AFSDKXValidateAndLogResult.h" #import "libAppsFlyer/AppsFlyerLib.h" +#import "libAppsFlyer/AFSDKPurchaseDetails.h" +#import + /* Null, because instance will be initialized on demand. */ AppsFlyerXApple* AppsFlyerXApple::instance = 0; @@ -37,6 +42,19 @@ AppsFlyerXApple::AppsFlyerXApple() {} +void AppsFlyerXApple::enableTCFDataCollection(bool shouldCollectConsentData){ + [[AppsFlyerLib shared] enableTCFDataCollection:shouldCollectConsentData]; +} + +void AppsFlyerXApple::setConsentData(const AppsFlyerXConsent& consentData){ + if (consentData.IsUserSubjectToGDPR()){ + [[AppsFlyerLib shared] setConsentData:[[AppsFlyerConsent alloc] initForGDPRUserWithHasConsentForDataUsage:consentData.HasConsentForDataUsage() hasConsentForAdsPersonalization:consentData.HasConsentForAdsPersonalization()]]; + } + else{ + [[AppsFlyerLib shared] setConsentData:[[AppsFlyerConsent alloc] initNonGDPRUser]]; + } +} + void AppsFlyerXApple::setCustomerUserID(const std::string& customerUserID) { [[AppsFlyerLib shared] setCustomerUserID: [NSString stringWithUTF8String:customerUserID.c_str()]]; } @@ -58,7 +76,9 @@ static dispatch_once_t onceToken; static AppsFlyerXApple *xApple = nil; static AppsFlyerXAppleDelegate *delegate = nil; - + [[AppsFlyerLib shared] setPluginInfoWith: AFSDKPluginCocos2dx + pluginVersion:@"6.15.3" + additionalParams:nil]; dispatch_once(&onceToken, ^{ xApple = AppsFlyerXApple::getInstance(); @@ -69,7 +89,9 @@ object: nil queue: nil usingBlock: ^ (NSNotification * note) { - [[AppsFlyerLib shared] start]; + if (AppsFlyerX::manualStart == false) { + [[AppsFlyerLib shared] start]; + } }]; }); @@ -230,6 +252,42 @@ }]; } + +void AppsFlyerXApple::validateAndLogInAppPurchase(AFSDKXPurchaseDetails &details, + cocos2d::ValueMap params, + std::function completionHandler) { + + NSString *productId = [NSString stringWithUTF8String:details.getProductId().c_str()]; + NSString *price = [NSString stringWithUTF8String:details.getPrice().c_str()]; + NSString *transactionId = [NSString stringWithUTF8String:details.getTransactionId().c_str()]; + NSString *currency = [NSString stringWithUTF8String:details.getCurrency().c_str()]; + NSDictionary *lParams = AppsFlyerXAppleHelper::valueMap2nsDictionary(params); + + AFSDKPurchaseDetails *afPurchaseDetails = [[AFSDKPurchaseDetails alloc] initWithProductId:productId + price:price + currency:currency + transactionId:transactionId]; + + [[AppsFlyerLib shared] validateAndLogInAppPurchase:afPurchaseDetails extraEventValues:lParams completionHandler:^(AFSDKValidateAndLogResult * _Nullable result) { + // TODO: - add result to completionHandler + NSLog(@"[ValidateAndLog] Result: %@", result); + }]; +} + +void AppsFlyerXApple::logAdRevenue(AFXAdRevenueData adRevenueData, + cocos2d::ValueMap additionalParameters) { + NSDictionary *lParams = AppsFlyerXAppleHelper::valueMap2nsDictionary(additionalParameters); + + NSString * monetizationNetwork = [NSString stringWithUTF8String:adRevenueData.getMonetizationNetwork().c_str()]; + AppsFlyerAdRevenueMediationNetworkType mediationNetwork = static_cast(adRevenueData.getMediationNetwork()); + NSString * currencyIso4217Code = [NSString stringWithUTF8String:adRevenueData.getCurrencyIso4217Code().c_str()]; + NSNumber *eventRevenue = [NSNumber numberWithDouble:adRevenueData.getEventRevenue()]; + + AFAdRevenueData *appsflyerAdRevenueData = [[AFAdRevenueData alloc] initWithMonetizationNetwork:monetizationNetwork mediationNetwork:mediationNetwork currencyIso4217Code:currencyIso4217Code eventRevenue:eventRevenue]; + + [[AppsFlyerLib shared] logAdRevenue:appsflyerAdRevenueData additionalParameters:lParams]; +} + void AppsFlyerXApple::logLocation(double longitude, double latitude) { [[AppsFlyerLib shared] logLocation:longitude latitude:latitude]; } diff --git a/Classes/Strict/AppsFlyer/AppsFlyerXAppleDelegate.h b/Classes/Strict/AppsFlyer/AppsFlyerXAppleDelegate.h index 0f998c7..a91910f 100644 --- a/Classes/Strict/AppsFlyer/AppsFlyerXAppleDelegate.h +++ b/Classes/Strict/AppsFlyer/AppsFlyerXAppleDelegate.h @@ -7,7 +7,7 @@ #ifndef AppsFlyerXAppleDelegate_h #define AppsFlyerXAppleDelegate_h -#import "AppsFlyerLib.h" +#import "AppsFlyer/libAppsFlyer/AppsFlyerLib.h" @interface AppsFlyerXAppleDelegate: NSObject diff --git a/Classes/Strict/AppsFlyer/AppsFlyerXAppleHelper.h b/Classes/Strict/AppsFlyer/AppsFlyerXAppleHelper.h index e5661d7..2dd362c 100644 --- a/Classes/Strict/AppsFlyer/AppsFlyerXAppleHelper.h +++ b/Classes/Strict/AppsFlyer/AppsFlyerXAppleHelper.h @@ -12,6 +12,7 @@ #include #include "AppsFlyerXDeepLinkResult.h" #import "libAppsFlyer/AppsFlyerLib.h" +#import //#import diff --git a/Classes/Strict/AppsFlyer/AppsFlyerXAppleHelper.mm b/Classes/Strict/AppsFlyer/AppsFlyerXAppleHelper.mm index 4b3d76e..f78efff 100644 --- a/Classes/Strict/AppsFlyer/AppsFlyerXAppleHelper.mm +++ b/Classes/Strict/AppsFlyer/AppsFlyerXAppleHelper.mm @@ -9,6 +9,7 @@ #include "AppsFlyerXDeepLinkResult.h" + cocos2d::ValueMap AppsFlyerXAppleHelper::nsDictionary2ValueMap(NSDictionary *dic) { cocos2d::ValueMap vm; nsDictionary2ValueMap(dic, vm); diff --git a/Classes/Strict/AppsFlyer/AppsFlyerXConsent.cpp b/Classes/Strict/AppsFlyer/AppsFlyerXConsent.cpp new file mode 100644 index 0000000..b51fced --- /dev/null +++ b/Classes/Strict/AppsFlyer/AppsFlyerXConsent.cpp @@ -0,0 +1,39 @@ +// +// AppsFlyerXConsent.h +// install_test_2 +// +// Created by Moris Gateno on 04/03/2024. +// + +#ifndef AppsFlyerXConsent_h +#define AppsFlyerXConsent_h + +class AppsFlyerXConsent{ +private: + bool isUserSubjectToGDPR; + bool hasConsentForDataUsage; + bool hasConsentForAdsPersonalization; + + AppsFlyerXConsent(bool isConsentForDataUsage, bool isConsentForAdsPersonalization): isUserSubjectToGDPR(true), hasConsentForDataUsage(isConsentForDataUsage), hasConsentForAdsPersonalization(isConsentForAdsPersonalization){} + + AppsFlyerXConsent(): isUserSubjectToGDPR(false), + hasConsentForDataUsage(false), hasConsentForAdsPersonalization(false) {} + +public: +// methods to get the private fields + bool IsUserSubjectToGDPR() const { return isUserSubjectToGDPR; } + bool HasConsentForDataUsage() const { return hasConsentForDataUsage; } + bool HasConsentForAdsPersonalization() const { return hasConsentForAdsPersonalization; } + + static AppsFlyerXConsent initNonGDPRUser() { + AppsFlyerXConsent c; + return c; + } + + static AppsFlyerXConsent initForGDPRUser(bool hasConsentForDataUsage, bool hasConsentForAdsPersonalization) { + AppsFlyerXConsent b(hasConsentForDataUsage, hasConsentForAdsPersonalization); + return b; + } +}; + +#endif /* AppsFlyerXConsent_h */ diff --git a/Classes/Strict/AppsFlyer/AppsFlyerXMacro.h b/Classes/Strict/AppsFlyer/AppsFlyerXMacro.h index 5fea9f3..3149375 100644 --- a/Classes/Strict/AppsFlyer/AppsFlyerXMacro.h +++ b/Classes/Strict/AppsFlyer/AppsFlyerXMacro.h @@ -114,6 +114,12 @@ #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" + #endif /* AppsFlyerXMacro_h */ diff --git a/Classes/Strict/AppsFlyer/libAppsFlyer/AFAdRevenueData.h b/Classes/Strict/AppsFlyer/libAppsFlyer/AFAdRevenueData.h new file mode 100644 index 0000000..2025468 --- /dev/null +++ b/Classes/Strict/AppsFlyer/libAppsFlyer/AFAdRevenueData.h @@ -0,0 +1,68 @@ +// +// AFAdRevenueData.h +// AppsFlyerLib +// +// Created by Veronica Belyakov on 26/06/2024. +// + +typedef NS_CLOSED_ENUM(NSUInteger, AppsFlyerAdRevenueMediationNetworkType) { + AppsFlyerAdRevenueMediationNetworkTypeGoogleAdMob = 1, + AppsFlyerAdRevenueMediationNetworkTypeIronSource = 2, + AppsFlyerAdRevenueMediationNetworkTypeApplovinMax= 3, + AppsFlyerAdRevenueMediationNetworkTypeFyber = 4, + AppsFlyerAdRevenueMediationNetworkTypeAppodeal = 5, + AppsFlyerAdRevenueMediationNetworkTypeAdmost = 6, + AppsFlyerAdRevenueMediationNetworkTypeTopon = 7, + AppsFlyerAdRevenueMediationNetworkTypeTradplus = 8, + AppsFlyerAdRevenueMediationNetworkTypeYandex = 9, + AppsFlyerAdRevenueMediationNetworkTypeChartBoost = 10, + AppsFlyerAdRevenueMediationNetworkTypeUnity = 11, + AppsFlyerAdRevenueMediationNetworkTypeToponPte = 12, + AppsFlyerAdRevenueMediationNetworkTypeCustom = 13, + AppsFlyerAdRevenueMediationNetworkTypeDirectMonetization = 14 +} NS_SWIFT_NAME(MediationNetworkType); + +#define kAppsFlyerAdRevenueMonetizationNetwork @"monetization_network" +#define kAppsFlyerAdRevenueMediationNetwork @"mediation_network" +#define kAppsFlyerAdRevenueEventRevenue @"event_revenue" +#define kAppsFlyerAdRevenueEventRevenueCurrency @"event_revenue_currency" +#define kAppsFlyerAdRevenueCustomParameters @"custom_parameters" +#define kAFADRWrapperTypeGeneric @"adrevenue_sdk" + +//Pre-defined keys for non-mandatory dictionary + +//Code ISO 3166-1 format +#define kAppsFlyerAdRevenueCountry @"country" + +//ID of the ad unit for the impression +#define kAppsFlyerAdRevenueAdUnit @"ad_unit" + +//Format of the ad +#define kAppsFlyerAdRevenueAdType @"ad_type" + +//ID of the ad placement for the impression +#define kAppsFlyerAdRevenuePlacement @"placement" + + +@interface AFAdRevenueData : NSObject + +- (nonnull instancetype)init NS_UNAVAILABLE; ++ (nonnull instancetype)new NS_UNAVAILABLE; + +@property (strong, nonnull, nonatomic) NSString *monetizationNetwork; +@property AppsFlyerAdRevenueMediationNetworkType mediationNetwork; +@property (strong, nonnull, nonatomic) NSString *currencyIso4217Code; +@property (strong, nonnull, nonatomic) NSNumber *eventRevenue; + +/** +* @param monetizationNetwork network which monetized the impression (@"facebook") +* @param mediationNetwork mediation source that mediated the monetization network for the impression (AppsFlyerAdRevenueMediationNetworkTypeGoogleAdMob) +* @param currencyIso4217Code reported impression’s revenue currency ISO 4217 format (@"USD") +* @param eventRevenue reported impression’s revenue (@(0.001994303)) +*/ +- (instancetype _Nonnull )initWithMonetizationNetwork:(NSString *_Nonnull)monetizationNetwork + mediationNetwork:(AppsFlyerAdRevenueMediationNetworkType)mediationNetwork + currencyIso4217Code:(NSString *_Nonnull)currencyIso4217Code + eventRevenue:(NSNumber *_Nonnull)eventRevenue; + +@end diff --git a/Classes/Strict/AppsFlyer/libAppsFlyer/AFSDKPurchaseDetails.h b/Classes/Strict/AppsFlyer/libAppsFlyer/AFSDKPurchaseDetails.h new file mode 100644 index 0000000..89af8a7 --- /dev/null +++ b/Classes/Strict/AppsFlyer/libAppsFlyer/AFSDKPurchaseDetails.h @@ -0,0 +1,23 @@ +// +// AFSDKPurchaseDetails.h +// AppsFlyerLib +// +// Created by Moris Gateno on 13/03/2024. +// + +@interface AFSDKPurchaseDetails : NSObject + +- (nonnull instancetype)init NS_UNAVAILABLE; ++ (nonnull instancetype)new NS_UNAVAILABLE; + +@property (strong, nullable, nonatomic) NSString *productId; +@property (strong, nullable, nonatomic) NSString *price; +@property (strong, nullable, nonatomic) NSString *currency; +@property (strong, nullable, nonatomic) NSString *transactionId; + +- (instancetype _Nonnull )initWithProductId:(NSString *_Nullable)productId + price:(NSString *_Nullable)price + currency:(NSString *_Nullable)currency + transactionId:(NSString *_Nullable)transactionId; + +@end diff --git a/Classes/Strict/AppsFlyer/libAppsFlyer/AFSDKValidateAndLogResult.h b/Classes/Strict/AppsFlyer/libAppsFlyer/AFSDKValidateAndLogResult.h new file mode 100644 index 0000000..94ef0f4 --- /dev/null +++ b/Classes/Strict/AppsFlyer/libAppsFlyer/AFSDKValidateAndLogResult.h @@ -0,0 +1,35 @@ +// +// AFSDKValidateAndLogResult.h +// AppsFlyerLib +// +// Created by Moris Gateno on 13/03/2024. +// + + +typedef NS_CLOSED_ENUM(NSUInteger, AFSDKValidateAndLogStatus) { + AFSDKValidateAndLogStatusSuccess, + AFSDKValidateAndLogStatusFailure, + AFSDKValidateAndLogStatusError +} NS_SWIFT_NAME(ValidateAndLogStatus); + +NS_SWIFT_NAME(ValidateAndLogResult) +@interface AFSDKValidateAndLogResult : NSObject + +- (nonnull instancetype)init NS_UNAVAILABLE; ++ (nonnull instancetype)new NS_UNAVAILABLE; + +- (instancetype _Nonnull )initWithStatus:(AFSDKValidateAndLogStatus)status + result:(NSDictionary *_Nullable)result + errorData:(NSDictionary *_Nullable)errorData + error:(NSError *_Nullable)error; + +@property(readonly) AFSDKValidateAndLogStatus status; +// Success case +@property(readonly, nullable) NSDictionary *result; +// Server 200 with validation failure +@property(readonly, nullable) NSDictionary *errorData; +// for the error case +@property(readonly, nullable) NSError *error; + +@end + diff --git a/Classes/Strict/AppsFlyer/libAppsFlyer/AppsFlyerConsent.h b/Classes/Strict/AppsFlyer/libAppsFlyer/AppsFlyerConsent.h new file mode 100644 index 0000000..564912a --- /dev/null +++ b/Classes/Strict/AppsFlyer/libAppsFlyer/AppsFlyerConsent.h @@ -0,0 +1,26 @@ +// +// AppsFlyerConsent.h +// AppsFlyerLib +// +// Created by Veronica Belyakov on 14/01/2024. +// +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface AppsFlyerConsent : NSObject + +@property (nonatomic, readonly, assign) BOOL isUserSubjectToGDPR; +@property (nonatomic, readonly, assign) BOOL hasConsentForDataUsage; +@property (nonatomic, readonly, assign) BOOL hasConsentForAdsPersonalization; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +- (instancetype)initForGDPRUserWithHasConsentForDataUsage:(BOOL)hasConsentForDataUsage + hasConsentForAdsPersonalization:(BOOL)hasConsentForAdsPersonalization NS_DESIGNATED_INITIALIZER; +- (instancetype)initNonGDPRUser NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Classes/Strict/AppsFlyer/libAppsFlyer/AppsFlyerLib-Swift.h b/Classes/Strict/AppsFlyer/libAppsFlyer/AppsFlyerLib-Swift.h new file mode 100644 index 0000000..1f1b87e --- /dev/null +++ b/Classes/Strict/AppsFlyer/libAppsFlyer/AppsFlyerLib-Swift.h @@ -0,0 +1,311 @@ +#if 0 +#elif defined(__arm64__) && __arm64__ +// Generated by Apple Swift version 5.9 (swiftlang-5.9.0.128.108 clang-1500.0.40.1) +#ifndef APPSFLYERLIB_SWIFT_H +#define APPSFLYERLIB_SWIFT_H +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wgcc-compat" + +#if !defined(__has_include) +# define __has_include(x) 0 +#endif +#if !defined(__has_attribute) +# define __has_attribute(x) 0 +#endif +#if !defined(__has_feature) +# define __has_feature(x) 0 +#endif +#if !defined(__has_warning) +# define __has_warning(x) 0 +#endif + +#if __has_include() +# include +#endif + +#pragma clang diagnostic ignored "-Wauto-import" +#if defined(__OBJC__) +#include +#endif +#if defined(__cplusplus) +#include +#include +#include +#include +#include +#include +#include +#else +#include +#include +#include +#include +#endif +#if defined(__cplusplus) +#if defined(__arm64e__) && __has_include() +# include +#else +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreserved-macro-identifier" +# ifndef __ptrauth_swift_value_witness_function_pointer +# define __ptrauth_swift_value_witness_function_pointer(x) +# endif +# ifndef __ptrauth_swift_class_method_pointer +# define __ptrauth_swift_class_method_pointer(x) +# endif +#pragma clang diagnostic pop +#endif +#endif + +#if !defined(SWIFT_TYPEDEFS) +# define SWIFT_TYPEDEFS 1 +# if __has_include() +# include +# elif !defined(__cplusplus) +typedef uint_least16_t char16_t; +typedef uint_least32_t char32_t; +# endif +typedef float swift_float2 __attribute__((__ext_vector_type__(2))); +typedef float swift_float3 __attribute__((__ext_vector_type__(3))); +typedef float swift_float4 __attribute__((__ext_vector_type__(4))); +typedef double swift_double2 __attribute__((__ext_vector_type__(2))); +typedef double swift_double3 __attribute__((__ext_vector_type__(3))); +typedef double swift_double4 __attribute__((__ext_vector_type__(4))); +typedef int swift_int2 __attribute__((__ext_vector_type__(2))); +typedef int swift_int3 __attribute__((__ext_vector_type__(3))); +typedef int swift_int4 __attribute__((__ext_vector_type__(4))); +typedef unsigned int swift_uint2 __attribute__((__ext_vector_type__(2))); +typedef unsigned int swift_uint3 __attribute__((__ext_vector_type__(3))); +typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4))); +#endif + +#if !defined(SWIFT_PASTE) +# define SWIFT_PASTE_HELPER(x, y) x##y +# define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y) +#endif +#if !defined(SWIFT_METATYPE) +# define SWIFT_METATYPE(X) Class +#endif +#if !defined(SWIFT_CLASS_PROPERTY) +# if __has_feature(objc_class_property) +# define SWIFT_CLASS_PROPERTY(...) __VA_ARGS__ +# else +# define SWIFT_CLASS_PROPERTY(...) +# endif +#endif +#if !defined(SWIFT_RUNTIME_NAME) +# if __has_attribute(objc_runtime_name) +# define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X))) +# else +# define SWIFT_RUNTIME_NAME(X) +# endif +#endif +#if !defined(SWIFT_COMPILE_NAME) +# if __has_attribute(swift_name) +# define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X))) +# else +# define SWIFT_COMPILE_NAME(X) +# endif +#endif +#if !defined(SWIFT_METHOD_FAMILY) +# if __has_attribute(objc_method_family) +# define SWIFT_METHOD_FAMILY(X) __attribute__((objc_method_family(X))) +# else +# define SWIFT_METHOD_FAMILY(X) +# endif +#endif +#if !defined(SWIFT_NOESCAPE) +# if __has_attribute(noescape) +# define SWIFT_NOESCAPE __attribute__((noescape)) +# else +# define SWIFT_NOESCAPE +# endif +#endif +#if !defined(SWIFT_RELEASES_ARGUMENT) +# if __has_attribute(ns_consumed) +# define SWIFT_RELEASES_ARGUMENT __attribute__((ns_consumed)) +# else +# define SWIFT_RELEASES_ARGUMENT +# endif +#endif +#if !defined(SWIFT_WARN_UNUSED_RESULT) +# if __has_attribute(warn_unused_result) +# define SWIFT_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +# else +# define SWIFT_WARN_UNUSED_RESULT +# endif +#endif +#if !defined(SWIFT_NORETURN) +# if __has_attribute(noreturn) +# define SWIFT_NORETURN __attribute__((noreturn)) +# else +# define SWIFT_NORETURN +# endif +#endif +#if !defined(SWIFT_CLASS_EXTRA) +# define SWIFT_CLASS_EXTRA +#endif +#if !defined(SWIFT_PROTOCOL_EXTRA) +# define SWIFT_PROTOCOL_EXTRA +#endif +#if !defined(SWIFT_ENUM_EXTRA) +# define SWIFT_ENUM_EXTRA +#endif +#if !defined(SWIFT_CLASS) +# if __has_attribute(objc_subclassing_restricted) +# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA +# define SWIFT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# else +# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# define SWIFT_CLASS_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# endif +#endif +#if !defined(SWIFT_RESILIENT_CLASS) +# if __has_attribute(objc_class_stub) +# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME) __attribute__((objc_class_stub)) +# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_class_stub)) SWIFT_CLASS_NAMED(SWIFT_NAME) +# else +# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME) +# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) SWIFT_CLASS_NAMED(SWIFT_NAME) +# endif +#endif +#if !defined(SWIFT_PROTOCOL) +# define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA +# define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA +#endif +#if !defined(SWIFT_EXTENSION) +# define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__) +#endif +#if !defined(OBJC_DESIGNATED_INITIALIZER) +# if __has_attribute(objc_designated_initializer) +# define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) +# else +# define OBJC_DESIGNATED_INITIALIZER +# endif +#endif +#if !defined(SWIFT_ENUM_ATTR) +# if __has_attribute(enum_extensibility) +# define SWIFT_ENUM_ATTR(_extensibility) __attribute__((enum_extensibility(_extensibility))) +# else +# define SWIFT_ENUM_ATTR(_extensibility) +# endif +#endif +#if !defined(SWIFT_ENUM) +# define SWIFT_ENUM(_type, _name, _extensibility) enum _name : _type _name; enum SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type +# if __has_feature(generalized_swift_name) +# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type +# else +# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) SWIFT_ENUM(_type, _name, _extensibility) +# endif +#endif +#if !defined(SWIFT_UNAVAILABLE) +# define SWIFT_UNAVAILABLE __attribute__((unavailable)) +#endif +#if !defined(SWIFT_UNAVAILABLE_MSG) +# define SWIFT_UNAVAILABLE_MSG(msg) __attribute__((unavailable(msg))) +#endif +#if !defined(SWIFT_AVAILABILITY) +# define SWIFT_AVAILABILITY(plat, ...) __attribute__((availability(plat, __VA_ARGS__))) +#endif +#if !defined(SWIFT_WEAK_IMPORT) +# define SWIFT_WEAK_IMPORT __attribute__((weak_import)) +#endif +#if !defined(SWIFT_DEPRECATED) +# define SWIFT_DEPRECATED __attribute__((deprecated)) +#endif +#if !defined(SWIFT_DEPRECATED_MSG) +# define SWIFT_DEPRECATED_MSG(...) __attribute__((deprecated(__VA_ARGS__))) +#endif +#if !defined(SWIFT_DEPRECATED_OBJC) +# if __has_feature(attribute_diagnose_if_objc) +# define SWIFT_DEPRECATED_OBJC(Msg) __attribute__((diagnose_if(1, Msg, "warning"))) +# else +# define SWIFT_DEPRECATED_OBJC(Msg) SWIFT_DEPRECATED_MSG(Msg) +# endif +#endif +#if defined(__OBJC__) +#if !defined(IBSegueAction) +# define IBSegueAction +#endif +#endif +#if !defined(SWIFT_EXTERN) +# if defined(__cplusplus) +# define SWIFT_EXTERN extern "C" +# else +# define SWIFT_EXTERN extern +# endif +#endif +#if !defined(SWIFT_CALL) +# define SWIFT_CALL __attribute__((swiftcall)) +#endif +#if !defined(SWIFT_INDIRECT_RESULT) +# define SWIFT_INDIRECT_RESULT __attribute__((swift_indirect_result)) +#endif +#if !defined(SWIFT_CONTEXT) +# define SWIFT_CONTEXT __attribute__((swift_context)) +#endif +#if !defined(SWIFT_ERROR_RESULT) +# define SWIFT_ERROR_RESULT __attribute__((swift_error_result)) +#endif +#if defined(__cplusplus) +# define SWIFT_NOEXCEPT noexcept +#else +# define SWIFT_NOEXCEPT +#endif +#if !defined(SWIFT_C_INLINE_THUNK) +# if __has_attribute(always_inline) +# if __has_attribute(nodebug) +# define SWIFT_C_INLINE_THUNK inline __attribute__((always_inline)) __attribute__((nodebug)) +# else +# define SWIFT_C_INLINE_THUNK inline __attribute__((always_inline)) +# endif +# else +# define SWIFT_C_INLINE_THUNK inline +# endif +#endif +#if defined(_WIN32) +#if !defined(SWIFT_IMPORT_STDLIB_SYMBOL) +# define SWIFT_IMPORT_STDLIB_SYMBOL __declspec(dllimport) +#endif +#else +#if !defined(SWIFT_IMPORT_STDLIB_SYMBOL) +# define SWIFT_IMPORT_STDLIB_SYMBOL +#endif +#endif +#if defined(__OBJC__) +#if __has_feature(objc_modules) +#if __has_warning("-Watimport-in-framework-header") +#pragma clang diagnostic ignored "-Watimport-in-framework-header" +#endif +#endif + +#endif +#pragma clang diagnostic ignored "-Wproperty-attribute-mismatch" +#pragma clang diagnostic ignored "-Wduplicate-method-arg" +#if __has_warning("-Wpragma-clang-attribute") +# pragma clang diagnostic ignored "-Wpragma-clang-attribute" +#endif +#pragma clang diagnostic ignored "-Wunknown-pragmas" +#pragma clang diagnostic ignored "-Wnullability" +#pragma clang diagnostic ignored "-Wdollar-in-identifier-extension" + +#if __has_attribute(external_source_symbol) +# pragma push_macro("any") +# undef any +# pragma clang attribute push(__attribute__((external_source_symbol(language="Swift", defined_in="AppsFlyerLib",generated_declaration))), apply_to=any(function,enum,objc_interface,objc_category,objc_protocol)) +# pragma pop_macro("any") +#endif + +#if defined(__OBJC__) +#endif +#if __has_attribute(external_source_symbol) +# pragma clang attribute pop +#endif +#if defined(__cplusplus) +#endif +#pragma clang diagnostic pop +#endif + +#else +#error unsupported Swift architecture +#endif diff --git a/Classes/Strict/AppsFlyer/libAppsFlyer/AppsFlyerLib.h b/Classes/Strict/AppsFlyer/libAppsFlyer/AppsFlyerLib.h index f7afacf..e916b2d 100644 --- a/Classes/Strict/AppsFlyer/libAppsFlyer/AppsFlyerLib.h +++ b/Classes/Strict/AppsFlyer/libAppsFlyer/AppsFlyerLib.h @@ -2,16 +2,22 @@ // AppsFlyerLib.h // AppsFlyerLib // -// AppsFlyer iOS SDK 6.9.1 (92) -// Copyright (c) 2012-2020 AppsFlyer Ltd. All rights reserved. +// AppsFlyer iOS SDK 6.15.3 (217) +// Copyright (c) 2012-2023 AppsFlyer Ltd. All rights reserved. // #import -#import -#import -#import -#import + +#import "AppsFlyerCrossPromotionHelper.h" +#import "AppsFlyerShareInviteHelper.h" +#import "AppsFlyerDeepLinkResult.h" +#import "AppsFlyerDeepLink.h" +#import "AppsFlyerConsent.h" +#import "AFSDKPurchaseDetails.h" +#import "AFSDKValidateAndLogResult.h" +#import "AFAdRevenueData.h" + NS_ASSUME_NONNULL_BEGIN @@ -131,7 +137,6 @@ NS_ASSUME_NONNULL_BEGIN #define AFEventParamAdRevenueAdSize @"af_adrev_ad_size" #define AFEventParamAdRevenueMediatedNetworkName @"af_adrev_mediated_network_name" - /// Mail hashing type typedef enum { /// None @@ -140,6 +145,26 @@ typedef enum { 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); + + NS_SWIFT_NAME(DeepLinkDelegate) @protocol AppsFlyerDeepLinkDelegate @@ -298,6 +323,9 @@ NS_SWIFT_NAME(waitForATTUserAuthorization(timeoutInterval:)); */ @property(atomic) BOOL disableCollectASA; +/** + Disable Apple Ads Attribution API +[AAAtribution attributionTokenWithError:] + */ @property(nonatomic) BOOL disableAppleAdsAttribution; /** @@ -327,7 +355,7 @@ NS_SWIFT_NAME(waitForATTUserAuthorization(timeoutInterval:)); [[AppsFlyerLib shared] setResolveDeepLinkURLs:@[@"domain.com", @"subdomain.domain.com"]]; */ -@property(nonatomic, nullable) NSArray *resolveDeepLinkURLs; +@property(nonatomic, nullable, copy) NSArray *resolveDeepLinkURLs; /** For advertisers who use vanity OneLinks. @@ -338,12 +366,12 @@ NS_SWIFT_NAME(waitForATTUserAuthorization(timeoutInterval:)); [[AppsFlyerLib shared] oneLinkCustomDomains:@[@"domain.com", @"subdomain.domain.com"]]; */ -@property(nonatomic, nullable) NSArray *oneLinkCustomDomains; +@property(nonatomic, nullable, copy) NSArray *oneLinkCustomDomains; /* * Set phone number for each `start` event. `phoneNumber` will be sent as SHA256 string */ -@property(nonatomic, nullable) NSString *phoneNumber; +@property(nonatomic, nullable, copy) NSString *phoneNumber; - (NSString *)phoneNumber UNAVAILABLE_ATTRIBUTE; @@ -366,7 +394,15 @@ NS_SWIFT_NAME(waitForATTUserAuthorization(timeoutInterval:)); AppsFlyerLib.shared().currentDeviceLanguage("EN") */ -@property(nonatomic, nullable) NSString *currentDeviceLanguage; +@property(nonatomic, nullable, copy) 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 @@ -458,6 +494,28 @@ NS_SWIFT_NAME(logEvent(name:values:completionHandler:)); success:(void (^ _Nullable)(NSDictionary * response))successBlock failure:(void (^ _Nullable)(NSError * _Nullable error, id _Nullable reponse))failedBlock NS_AVAILABLE(10_7, 7_0); +typedef void (^AFSDKValidateAndLogCompletion)(AFSDKValidateAndLogResult * _Nullable result); + +/** + To log and validate in app purchases you can call this method from the completeTransaction: method on + your `SKPaymentTransactionObserver`. + + @param details The product details + @param extraEventValues The additional param, which you want to receive it in the raw reports + @param completionHandler The callback + */ +- (void)validateAndLogInAppPurchase:(AFSDKPurchaseDetails *)details + extraEventValues:(NSDictionary * _Nullable)extraEventValues + completionHandler:(AFSDKValidateAndLogCompletion)completionHandler NS_AVAILABLE(10_7, 7_0); + +/** + An API to provide the data from the impression payload to AdRevenue. + + @param adRevenueData object used to hold all mandatory parameters of AdRevenue event. + @param additionalParameters non-mandatory dictionary which can include pre-defined keys (kAppsFlyerAdRevenueCountry, etc) + */ +- (void)logAdRevenue:(AFAdRevenueData *)adRevenueData additionalParameters:(NSDictionary * _Nullable)additionalParameters; + /** To log location for geo-fencing. Does the same as code below. @@ -549,6 +607,11 @@ NS_SWIFT_NAME(logEvent(name:values:completionHandler:)); */ - (void)remoteDebuggingCallWithData:(NSString *)data; +/** + This is for internal use. + */ +- (void)remoteDebuggingCallV2WithData:(NSString *)dataAsString; + /** Used to force the trigger `onAppOpenAttribution` delegate. Notice, re-engagement, session and launch won't be counted. @@ -605,13 +668,13 @@ NS_SWIFT_NAME(logEvent(name:values:completionHandler:)); /** API to set manually Facebook deferred app link */ -@property(nonatomic, nullable) NSURL *facebookDeferredAppLink; +@property(nonatomic, nullable, copy) 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, nullable, copy) NSArray *sharingFilter DEPRECATED_MSG_ATTRIBUTE("starting SDK version 6.4.0, please use `setSharingFilterForPartners:`"); @property(nonatomic) NSUInteger deepLinkTimeout; @@ -632,6 +695,27 @@ NS_SWIFT_NAME(logEvent(name:values:completionHandler:)); */ - (void)setSharingFilterForPartners:(NSArray * _Nullable)sharingFilter; + +/** + Sets or updates the user consent data related to GDPR and DMA regulations for advertising and data usage + purposes within the application. This method must be invoked with the user's current consent status each + time the app starts or whenever there is a change in the user's consent preferences. + + Note that this method does not persist the consent data across app sessions; it only applies for the + duration of the current app session. If you wish to stop providing the consent data, you should + cease calling this method. + + @param consent an instance of AppsFlyerConsent that encapsulates the user's consent information. + */ +- (void)setConsentData:(AppsFlyerConsent *)consent; + +/** + Enable the SDK to collect and send TCF data + + @param shouldCollectConsentData indicates if the TCF data collection is enabled. + */ +- (void)enableTCFDataCollection:(BOOL)shouldCollectConsentData; + /** Validate if URL contains certain string and append quiery parameters to deeplink URL. In case if URL does not contain user-defined string, diff --git a/Classes/Strict/AppsFlyer/libAppsFlyer/AppsFlyerLinkGenerator.h b/Classes/Strict/AppsFlyer/libAppsFlyer/AppsFlyerLinkGenerator.h index b917074..d3ec8f4 100644 --- a/Classes/Strict/AppsFlyer/libAppsFlyer/AppsFlyerLinkGenerator.h +++ b/Classes/Strict/AppsFlyer/libAppsFlyer/AppsFlyerLinkGenerator.h @@ -22,7 +22,7 @@ NS_ASSUME_NONNULL_BEGIN /// from `-[AppsFlyerShareInviteHelper generateInviteUrlWithLinkGenerator:completionHandler]` + (instancetype)new NS_UNAVAILABLE; -@property(nonatomic, nullable) NSString *brandDomain; +@property(nonatomic, nullable, copy) NSString *brandDomain; /// The channel through which the invite was sent (e.g. Facebook/Gmail/etc.). Usage: Recommended - (void)setChannel :(nonnull NSString *)channel; diff --git a/Classes/Strict/AppsFlyer/libAppsFlyer/libAppsFlyerLib.a b/Classes/Strict/AppsFlyer/libAppsFlyer/libAppsFlyerLib.a index fa4959f..0aaa14a 100644 Binary files a/Classes/Strict/AppsFlyer/libAppsFlyer/libAppsFlyerLib.a and b/Classes/Strict/AppsFlyer/libAppsFlyer/libAppsFlyerLib.a differ diff --git a/README.md b/README.md index 0ad4f96..c9fd5ce 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,8 @@ In order for us to provide optimal support, we would kindly ask you to submit an - [setSharingFilterForPartners](#SharingFilterForPartners) - [setDisableNetworkData](#disableNetworkID) *(android only)* - [Send consent for DMA compliance](#dma_support) +- [validateAndLog](#validate_and_log_2.0) +- [logAdrevenue](#logAdrevenue) ### This plugin is built for @@ -198,17 +200,76 @@ AppsFlyerX::stop(false); // or false AppsFlyerX::sharingFilter(partners); ``` --- - ##### **`sharingFilterForAllPartners();`** Use to prevent sharing data with all networks/integrated partners. +```cpp +AppsFlyerX::sharingFilterForAllPartners(); +``` +___ + +##### **`Validate and log 2.0 API`** + +| Property | Type | Description | Platform | +| ------------- | ------------------------------ | ----------------------------------------------------------------- | ------------ | +| purchaseType | `AFXPurchaseType` | Purchase type of the event. For Apple implementation, use `APPLE` | Android only | +| purchaseToken | `std::string` | Field required to validate the purchase | Android only | +| transactionId | `std::string` | Transaction ID of the Apple purchase | iOS only | +| productId | `std::string` | ID of the purchased product | Android/iOS | +| price | `std::string` | Price of the product | Android/iOS | +| currency | `std::string` | Currency according to the ISO format (ISO 4217) | Android/iOS | + +*Description:* +The `validateAndLogInAppPurchase` method is part of the receipt validation flow, which enables your app to validate in-app purchase events generated by Google Play and Apple. + + +`AFSDXPurchaseDetails` encapsulates all purchase necessary data for Android and iOS. +* `AFXPurchaseType` is used for Android only, so for iOS, be sure to use `APPLE` option, which is empty string and will be omitted by the implementation. +* `purchaseToken` is the Android propperty, for Apple impl, please use empty string; +* The `transactionId`is used by Apple implementation, Android omits this propperty; + *Example:* +```cpp +ValueMap params; // Additional parameters you want to pass to the API +AFSDKXPurchaseDetails details = AFSDKXPurchaseDetails(AFXPurchaseType::SUBSCRIPTION, "", "customId", "6.99", "USD", "transactionId"); + +AppsFlyerX::validateAndLogInAppPurchase(details, params, [](const AFSDKXValidateAndLogResult& result) { + // Your implementation of the completion/callback block; +}); +``` + +**Note:** For Android SDK, the callback block does not return anything for now, it will be supported in the next update; + +--- + + +##### **`Log AdRevenue API`** + +*Description:* + +When an impression with revenue occurs, invoke the logAdRevenue method with the revenue details of the impression. + +`AFXAdRevenueData` object encapsulates all data related to the AdRevenue event: + +| Property | Type | Description | +| ----------------------- | ------------------------------------------- | ------------------------------------------------- | +| monetizationNetwork | `std::string` | The name of the monetization network | +| mediationNetwork | `AppsFlyerXAdRevenueMediationNetworkType` | The type of mediation network being used | +| currencyIso4217Code | `std::string` | Currency code according to the ISO format (ISO 4217) | +| eventRevenue | `double` | Revenue generated from the ad event | + + +*Example:* ```cpp -AppsFlyerX::sharingFilterForAllPartners(); +ValueMap params; // Additional parameters you want to pass to the API +AFXAdRevenueData data = AFXAdRevenueData("someVal", AppsFlyerXAdRevenueMediationNetworkType::ApplovinMax, "USD", 7.99); + +AppsFlyerX::logAdRevenue(data, params); ``` + --- ##### **`trackEvent(eventName, eventValues): void`** (optional) @@ -772,6 +833,23 @@ Used by advertisers to set some (one or more) networks/integrated partners to ex --- +##### **`setSharingFilterForPartners(partners);`** +Used by advertisers to set some (one or more) networks/integrated partners to exclude from getting data. + +| parameter | type | description | +| ----------- |-----------------------------|--------------| +| `partners` | `std::vector` | partners to exclude from getting data + + +*Example:* + +```cpp + +``` + +--- + + ##### **`setDisableNetworkData(disable);`** Use to opt-out of collecting the network operator name (carrier) and sim operator name from the device. diff --git a/proj.android-studio/app/AndroidManifest.xml b/proj.android-studio/app/AndroidManifest.xml index a97bcb7..3748764 100644 --- a/proj.android-studio/app/AndroidManifest.xml +++ b/proj.android-studio/app/AndroidManifest.xml @@ -1,9 +1,11 @@ - + + + + + package="com.example.yourapp"> - -#import "AppsFlyerLib.h" +#import "AppsFlyer/libAppsFlyer/AppsFlyerLib.h" @class RootViewController; diff --git a/proj.ios_mac/ios/Images.xcassets/Contents.json b/proj.ios_mac/ios/Images.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/proj.ios_mac/ios/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-100.imageset/Contents.json b/proj.ios_mac/ios/Images.xcassets/Icon-100.imageset/Contents.json new file mode 100644 index 0000000..6407691 --- /dev/null +++ b/proj.ios_mac/ios/Images.xcassets/Icon-100.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Icon-100.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "original" + } +} diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-100.imageset/Icon-100.png b/proj.ios_mac/ios/Images.xcassets/Icon-100.imageset/Icon-100.png new file mode 100644 index 0000000..ef38d45 Binary files /dev/null and b/proj.ios_mac/ios/Images.xcassets/Icon-100.imageset/Icon-100.png differ diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-114.imageset/Contents.json b/proj.ios_mac/ios/Images.xcassets/Icon-114.imageset/Contents.json new file mode 100644 index 0000000..311f877 --- /dev/null +++ b/proj.ios_mac/ios/Images.xcassets/Icon-114.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Icon-114.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "original" + } +} diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-114.imageset/Icon-114.png b/proj.ios_mac/ios/Images.xcassets/Icon-114.imageset/Icon-114.png new file mode 100644 index 0000000..c380786 Binary files /dev/null and b/proj.ios_mac/ios/Images.xcassets/Icon-114.imageset/Icon-114.png differ diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-120.imageset/Contents.json b/proj.ios_mac/ios/Images.xcassets/Icon-120.imageset/Contents.json new file mode 100644 index 0000000..a627971 --- /dev/null +++ b/proj.ios_mac/ios/Images.xcassets/Icon-120.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Icon-120.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "original" + } +} diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-120.imageset/Icon-120.png b/proj.ios_mac/ios/Images.xcassets/Icon-120.imageset/Icon-120.png new file mode 100644 index 0000000..a5b49cc Binary files /dev/null and b/proj.ios_mac/ios/Images.xcassets/Icon-120.imageset/Icon-120.png differ diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-144.imageset/Contents.json b/proj.ios_mac/ios/Images.xcassets/Icon-144.imageset/Contents.json new file mode 100644 index 0000000..b32edc4 --- /dev/null +++ b/proj.ios_mac/ios/Images.xcassets/Icon-144.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Icon-144.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "original" + } +} diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-144.imageset/Icon-144.png b/proj.ios_mac/ios/Images.xcassets/Icon-144.imageset/Icon-144.png new file mode 100644 index 0000000..1526615 Binary files /dev/null and b/proj.ios_mac/ios/Images.xcassets/Icon-144.imageset/Icon-144.png differ diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-152.imageset/Contents.json b/proj.ios_mac/ios/Images.xcassets/Icon-152.imageset/Contents.json new file mode 100644 index 0000000..8edcba4 --- /dev/null +++ b/proj.ios_mac/ios/Images.xcassets/Icon-152.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Icon-152.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "original" + } +} diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-152.imageset/Icon-152.png b/proj.ios_mac/ios/Images.xcassets/Icon-152.imageset/Icon-152.png new file mode 100644 index 0000000..8aa8250 Binary files /dev/null and b/proj.ios_mac/ios/Images.xcassets/Icon-152.imageset/Icon-152.png differ diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-180.imageset/Contents.json b/proj.ios_mac/ios/Images.xcassets/Icon-180.imageset/Contents.json new file mode 100644 index 0000000..31ff961 --- /dev/null +++ b/proj.ios_mac/ios/Images.xcassets/Icon-180.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Icon-180.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "original" + } +} diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-180.imageset/Icon-180.png b/proj.ios_mac/ios/Images.xcassets/Icon-180.imageset/Icon-180.png new file mode 100644 index 0000000..d4bc531 Binary files /dev/null and b/proj.ios_mac/ios/Images.xcassets/Icon-180.imageset/Icon-180.png differ diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-29.imageset/Contents.json b/proj.ios_mac/ios/Images.xcassets/Icon-29.imageset/Contents.json new file mode 100644 index 0000000..599ced6 --- /dev/null +++ b/proj.ios_mac/ios/Images.xcassets/Icon-29.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Icon-29.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "original" + } +} diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-29.imageset/Icon-29.png b/proj.ios_mac/ios/Images.xcassets/Icon-29.imageset/Icon-29.png new file mode 100644 index 0000000..0500184 Binary files /dev/null and b/proj.ios_mac/ios/Images.xcassets/Icon-29.imageset/Icon-29.png differ diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-40.imageset/Contents.json b/proj.ios_mac/ios/Images.xcassets/Icon-40.imageset/Contents.json new file mode 100644 index 0000000..d3ed7d6 --- /dev/null +++ b/proj.ios_mac/ios/Images.xcassets/Icon-40.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Icon-40.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "original" + } +} diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-40.imageset/Icon-40.png b/proj.ios_mac/ios/Images.xcassets/Icon-40.imageset/Icon-40.png new file mode 100644 index 0000000..775685d Binary files /dev/null and b/proj.ios_mac/ios/Images.xcassets/Icon-40.imageset/Icon-40.png differ diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-50.imageset/Contents.json b/proj.ios_mac/ios/Images.xcassets/Icon-50.imageset/Contents.json new file mode 100644 index 0000000..80bdc86 --- /dev/null +++ b/proj.ios_mac/ios/Images.xcassets/Icon-50.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Icon-50.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "original" + } +} diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-50.imageset/Icon-50.png b/proj.ios_mac/ios/Images.xcassets/Icon-50.imageset/Icon-50.png new file mode 100644 index 0000000..ac381bc Binary files /dev/null and b/proj.ios_mac/ios/Images.xcassets/Icon-50.imageset/Icon-50.png differ diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-57.imageset/Contents.json b/proj.ios_mac/ios/Images.xcassets/Icon-57.imageset/Contents.json new file mode 100644 index 0000000..bfda1d1 --- /dev/null +++ b/proj.ios_mac/ios/Images.xcassets/Icon-57.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Icon-57.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "original" + } +} diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-57.imageset/Icon-57.png b/proj.ios_mac/ios/Images.xcassets/Icon-57.imageset/Icon-57.png new file mode 100644 index 0000000..4fcc6fd Binary files /dev/null and b/proj.ios_mac/ios/Images.xcassets/Icon-57.imageset/Icon-57.png differ diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-58.imageset/Contents.json b/proj.ios_mac/ios/Images.xcassets/Icon-58.imageset/Contents.json new file mode 100644 index 0000000..5a8dc53 --- /dev/null +++ b/proj.ios_mac/ios/Images.xcassets/Icon-58.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Icon-58.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "original" + } +} diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-58.imageset/Icon-58.png b/proj.ios_mac/ios/Images.xcassets/Icon-58.imageset/Icon-58.png new file mode 100644 index 0000000..f0f8b7f Binary files /dev/null and b/proj.ios_mac/ios/Images.xcassets/Icon-58.imageset/Icon-58.png differ diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-72.imageset/Contents.json b/proj.ios_mac/ios/Images.xcassets/Icon-72.imageset/Contents.json new file mode 100644 index 0000000..44a55ac --- /dev/null +++ b/proj.ios_mac/ios/Images.xcassets/Icon-72.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Icon-72.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "original" + } +} diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-72.imageset/Icon-72.png b/proj.ios_mac/ios/Images.xcassets/Icon-72.imageset/Icon-72.png new file mode 100644 index 0000000..2c573c8 Binary files /dev/null and b/proj.ios_mac/ios/Images.xcassets/Icon-72.imageset/Icon-72.png differ diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-76.imageset/Contents.json b/proj.ios_mac/ios/Images.xcassets/Icon-76.imageset/Contents.json new file mode 100644 index 0000000..7034b1a --- /dev/null +++ b/proj.ios_mac/ios/Images.xcassets/Icon-76.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Icon-76.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "original" + } +} diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-76.imageset/Icon-76.png b/proj.ios_mac/ios/Images.xcassets/Icon-76.imageset/Icon-76.png new file mode 100644 index 0000000..8a1fa18 Binary files /dev/null and b/proj.ios_mac/ios/Images.xcassets/Icon-76.imageset/Icon-76.png differ diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-80.imageset/Contents.json b/proj.ios_mac/ios/Images.xcassets/Icon-80.imageset/Contents.json new file mode 100644 index 0000000..3077ba5 --- /dev/null +++ b/proj.ios_mac/ios/Images.xcassets/Icon-80.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Icon-80.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "original" + } +} diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-80.imageset/Icon-80.png b/proj.ios_mac/ios/Images.xcassets/Icon-80.imageset/Icon-80.png new file mode 100644 index 0000000..d9c7ab4 Binary files /dev/null and b/proj.ios_mac/ios/Images.xcassets/Icon-80.imageset/Icon-80.png differ diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-87.imageset/Contents.json b/proj.ios_mac/ios/Images.xcassets/Icon-87.imageset/Contents.json new file mode 100644 index 0000000..58ba493 --- /dev/null +++ b/proj.ios_mac/ios/Images.xcassets/Icon-87.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Icon-87.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "original" + } +} diff --git a/proj.ios_mac/ios/Images.xcassets/Icon-87.imageset/Icon-87.png b/proj.ios_mac/ios/Images.xcassets/Icon-87.imageset/Icon-87.png new file mode 100644 index 0000000..8968cf4 Binary files /dev/null and b/proj.ios_mac/ios/Images.xcassets/Icon-87.imageset/Icon-87.png differ