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..a02e5ee 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.13.0"; // 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 */