diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d389536..e789df48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,25 @@ +### Version 4.37.0 (22nd January 2024) +#### Added +- Added support for SKAD 4.0. +- Added ability to verify purchase events. +- Added ability to read App Set ID on Android platform in case you opt in by adding the `com.google.android.gms:play-services-appset` dependency to your Android app. +- Added ability to delay SDK start on iOS platform in order to wait for an answer to the ATT dialog. You can set the number of seconds to wait (capped internally to 120) by calling the `setAttConsentWaitingInterval` method of the `AdjustConfig2dx` instance. +- Added support for SigV3 library. Update authorization header building logic to use `adj_signing_id`. +- Added ability to indicate if only final Android attribution is needed in attribution callback (by default attribution callback return intermediate attribution as well before final attribution if not enabled with this setter method) calling the `setFinalAttributionEnabled` method of the `AdjustConfig2dx` instance. +- Added ability to get IDFV value of the iOS device. You can achieve this by invoking `getIdfv()` method of the `Adjust2dx` instance. +- Added support for Meta install referrer. +- Added support for Google Play Games on PC. +- Added support for `TopOn` and `AD(X)` ad revenue tracking. +- Added `setReadDeviceInfoOnceEnabled` method to `AdjustConfig2dx` to indicate if device info should be read only once. +- Added ability to process shortened deep links and provide the unshortened link back as a response. You can achieve this by invoking `processDeeplink` method of the `Adjust2dx` instance. +- Added support for setting a new China URL strategy (with fallback to other endpoints) and China only URL strategy (without fallbacks). You can choose this setting by calling `setUrlStrategy` method of `AdjustConfig2dx` instance with `AdjustUrlStrategyCn` / `AdjustUrlStrategyCnOnly` parameter. + +#### Native SDKs +- [iOS@v4.37.0][ios_sdk_v4.37.0] +- [Android@v4.38.0][android_sdk_v4.38.0] + +--- + ### Version 4.32.0 (20th October 2022) #### Added - Added ability to mark your app as COPPA compliant. You can enable this setting by calling `setCoppaCompliantEnabled` method of `AdjustConfig2dx` instance with boolean parameter `true`. @@ -392,6 +414,7 @@ [ios_sdk_v4.28.0]: https://github.com/adjust/ios_sdk/tree/v4.28.0 [ios_sdk_v4.29.6]: https://github.com/adjust/ios_sdk/tree/v4.29.6 [ios_sdk_v4.32.1]: https://github.com/adjust/ios_sdk/tree/v4.32.1 +[ios_sdk_v4.37.0]: https://github.com/adjust/ios_sdk/tree/v4.37.0 [android_sdk_v4.0.8]: https://github.com/adjust/android_sdk/tree/v4.0.8 [android_sdk_v4.1.0]: https://github.com/adjust/android_sdk/tree/v4.1.0 @@ -415,5 +438,6 @@ [android_sdk_v4.27.0]: https://github.com/adjust/android_sdk/tree/v4.27.0 [android_sdk_v4.28.4]: https://github.com/adjust/android_sdk/tree/v4.28.4 [android_sdk_v4.33.0]: https://github.com/adjust/android_sdk/tree/v4.33.0 +[android_sdk_v4.38.0]: https://github.com/adjust/android_sdk/tree/v4.38.0 [windows_sdk_v4.0.3]: https://github.com/adjust/windows_sdk/tree/v4.0.3 diff --git a/README.md b/README.md index bdd81c9b..4ee18574 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ This is the Cocos2d-x SDK of Adjust™. You can read more about Adjust™ at [Ad * [Huawei Referrer API](#android-huawei-referrer-api) * [[iOS] Frameworks](#ios-frameworks) * [[iOS] Additional linker flags](#ios-linker-flags) + * [[iOS] Additional source files](#ios-additional-source-files) * [Integrate the SDK into your app](#sdk-integrate) * [Adjust logging](#sdk-logging) * [Android session tracking](#sdk-android-session-tracking) @@ -27,11 +28,13 @@ This is the Cocos2d-x SDK of Adjust™. You can read more about Adjust™ at [Ad * [App-tracking authorisation wrapper](#ata-wrapper) * [Get current authorisation status](#ata-getter) * [Check for ATT status change](#att-status-change) + * [Custom ATT prompt timing](#att-delay) * [SKAdNetwork framework](#skadn-framework) * [Update SKAdNetwork conversion value](#skadn-update-conversion-value) * [Conversion value updated callback](#skadn-cv-updated-callback) * [Event tracking](#event-tracking) * [Revenue tracking](#revenue-tracking) + * [Purchase verification](#purchase-verification) * [Revenue deduplication](#revenue-deduplication) * [Callback parameters](#callback-parameters) * [Partner parameters](#partner-parameters) @@ -55,6 +58,7 @@ This is the Cocos2d-x SDK of Adjust™. You can read more about Adjust™ at [Ad * [Background tracking](#background-tracking) * [Device IDs](#device-ids) * [iOS advertising identifier](#di-idfa) + * [iOS identifier for vendors](#di-idfv) * [Google Play Services advertising identifier](#di-gps-adid) * [Amazon advertising identifier](#di-fire-adid) * [Adjust device identifier](#di-adid) @@ -70,6 +74,7 @@ This is the Cocos2d-x SDK of Adjust™. You can read more about Adjust™ at [Ad * [Data residency](#data-residency) * [COPPA compliance](#coppa-compliance) * [Play Store Kids Apps](#play-store-kids-apps) + * [Meta install referrer](#meta-install-referrer) * [License](#license) ## Basic integration @@ -82,7 +87,7 @@ Download the latest version from our [releases page][releases]. Extract the arch ### Add the SDK to your project -Take the C++ source files from the `src` folder and add them to your Cocos2d-x project. +Take the C++ source files from the `dist` folder and add them to your Cocos2d-x project. Inside Android Studio project, you need to add the paths of the Adjust C++ files to the `LOCAL_SRC_FILES` section in your `Android.mk` file: @@ -100,6 +105,8 @@ $(LOCAL_PATH)/../../../Classes/Adjust/AdjustAppStoreSubscription2dx.cpp \ $(LOCAL_PATH)/../../../Classes/Adjust/AdjustPlayStoreSubscription2dx.cpp \ $(LOCAL_PATH)/../../../Classes/Adjust/AdjustThirdPartySharing2dx.cpp \ $(LOCAL_PATH)/../../../Classes/Adjust/AdjustAdRevenue2dx.cpp +$(LOCAL_PATH)/../../../Classes/Adjust/AdjustAppStorePurchase2dx.cpp \ +$(LOCAL_PATH)/../../../Classes/Adjust/AdjustPlayStorePurchase2dx.cpp \ ``` ### Adjust project settings @@ -144,26 +151,11 @@ Since August 1, 2014, apps in the Google Play Store must use the [Google adverti Open the `build.gradle` file of your app and find the `dependencies` block. Add the following line: ``` -implementation 'com.google.android.gms:play-services-analytics:16.0.1' +implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1' ``` To check whether the analytics part of the Google Play Services library has been successfully added to your app, you should start your app by configuring the SDK to run in **sandbox** mode and set the log level to **verbose**. After that, track a session or some events in your app and observe the list of parameters in the verbose logs which are being read once the session or event has been tracked. If you see a parameter called `gps_adid` in there, you have successfully added the analytics part of the Google Play Services library to your app and our SDK is reading the necessary information from it. -**If you are using Eclipse as your IDE:** - -In order to add Google Play Services to your project, you should add `google-play-services_lib` from Android SDK folder into your app project in Eclipse. `google-play-services_lib` is part of the Android SDK, which you may already have installed. - -There are two main ways to download the Android SDK. If you are using any tool which has the `Android SDK Manager`, you should download `Android SDK Tools`. Once installed, you can find the libraries in the `SDK_FOLDER/extras/google/google_play_services/libproject/` folder. - -If you are not using any tool which has Android SDK Manager, you should download the standalone version of Android SDK from [official page][android-sdk-download]. By downloading this, you will have only a basic version of the Android SDK which doesn't include the Android SDK Tools. There are more detailed instructions on how to download these in the readme file provided by Google, called `SDK Readme.txt`, which is placed in Android SDK folder. - -After this, open the `AndroidManifest.xml` file of your Android project and add the following `meta-data` tag inside the `` element: - -```xml - -``` - ### [Android] Proguard settings If you are using Proguard, add these lines to your Proguard file: @@ -235,7 +227,7 @@ As of v4.22.0, the Adjust SDK supports install tracking on Huawei devices with H Select your project in the Project Navigator. In the left hand side of the main view, select your target. In the tab `Build Phases`, expand the group `Link Binary with Libraries`. On the bottom of that section click on the `+` button. Select below mentined frameworks and make sure to change the `Status` of frameworks to `Optional`. Adjust SDK uses these frameworks with following purpose: -* `iAd.framework` - to support Apple Search Ads campaigns +* `AdjustSdk.framework` - having native Adjust SDK framework is a must (you can download it from the release page of each Cocos2d-x SDK release) * `AdServices.framework` - to support Apple Search Ads campaigns * `AdSupport.framework` - to read iOS Advertising Id (IDFA) value * `StoreKit.framework` - to communicate with `SKAdNetwork` framework @@ -245,6 +237,10 @@ Select your project in the Project Navigator. In the left hand side of the main In order to support categories from the `AdjustSdk.framework`, you should add a linker flag. Go to the `Build Settings` part of Project Settings and look for the `Other Linker Flags` option. Add an `-ObjC` flag to it. +### [iOS] Additional source files + +In order to complete the iOS setup, please make sure (next to adding C++ sourrce files) to add all the Objective-C++ (`.h` and `.mm`) files to your Xcode project and make sure that the `.mm` files are listed inside of the `Build Phases` -> `Compile Sources` section. + ### Integrate the SDK into your app In the Project Navigator, open the source file of your application delegate. Add the import statement at the top of the file, then add the following call to Adjust in the `applicationDidFinishLaunching` method of your app delegate: @@ -294,6 +290,7 @@ std::string environment = AdjustEnvironmentSandbox2dx; AdjustConfig2dx adjustConfig = AdjustConfig2dx(appToken, environment, true); adjustConfig.setLogLevel(AdjustLogLevel2dxSuppress); +Adjust2dx::start(adjustConfig); ``` ### Android session tracking @@ -416,6 +413,16 @@ In cases where you are not using [Adjust app-tracking authorization wrapper](#at Adjust2dx::checkForNewAttStatus(); ``` +### Custom ATT prompt timing + +If your app includes an onboarding process or a tutorial, you may want to delay sending your user's ATT consent status until after the user has completed this process. To do this, you can set the attConsentWaitingInterval property to delay the sending of data for up to `120 seconds` to give the user time to complete the initial onboarding. After the timeout ends or the user sets their consent status, the SDK sends all information it has recorded during the delay to Adjust's servers along with the user's consent status. + +```cpp +adjustConfig.setAttConsentWaitingInterval = 30; +``` + +**Note**: If the user closes the app before the timeout ends, or before they select their consent status, the timeout restarts when they reopen the app. + ### SKAdNetwork framework **Note**: This feature exists only in iOS platform. @@ -432,10 +439,28 @@ adjustConfig.deactivateSKAdNetworkHandling(); **Note**: This feature exists only in iOS platform. -You can use Adjust SDK wrapper method `updateConversionValue` to update SKAdNetwork conversion value for your user: +The Adjust SDK is providing you with an out-of-the-box wrappers of the [native SKAdNetwork methods](https://developer.apple.com/documentation/storekit/skadnetwork?language=objc) for updating the conversion values. Feel free to use the one that suits your needs (depending on SKAN version you're using) and have in mind that as of iOS / iPadOS 15.4, the `updateConversionValue` method has been deprecated by Apple: -```js +```cpp +// pass just the conversion value (deprecated method) Adjust2dx::updateConversionValue(6); + +// pass the conversion value and a callback to receive a message about potential error +Adjust2dx::updatePostbackConversionValue(6, [](std::string error) { + std::cout << "Error while updating conversion value: " << error; +}); + +// SKAN 4.0 +// pass the conversion value, coarse value and a callback to receive a message about potential error +Adjust2dx::updatePostbackConversionValue(6, "low", [](std::string error) { + std::cout << "Error while updating conversion value: " << error; +}); + +// SKAN 4.0 +// pass the conversion value, coarse value, lock window and a callback to receive a message about potential error +Adjust2dx::updatePostbackConversionValue(6, "low", false, [](std::string error) { + std::cout << "Error while updating conversion value: " << error; +}); ``` ### Conversion value updated callback @@ -449,10 +474,24 @@ You can register callback to get notified each time when Adjust SDK updates conv // ... -static void conversionValueUpdatedCallbackMethod(int conversionValue) { - CCLOG("\nConversion value updated!"); - CCLOG("\nConversion value: %d", conversionValue); +bool AppDelegate::applicationDidFinishLaunching() { + std::string appToken = "{YourAppToken}"; + std::string environment = AdjustEnvironmentSandbox2dx; + + AdjustConfig2dx adjustConfig = AdjustConfig2dx(appToken, environment); + adjustConfig.setLogLevel(AdjustLogLevel2dxVerbose); + adjustConfig.setConversionValueUpdatedCallback(conversionValueUpdatedCallbackMethod); + adjustConfig.setConversionValueUpdatedCallback([](int conversionValue) { + std::cout << "\nConversion value: " << conversionValue; + }); + Adjust2dx::start(adjustConfig); } +``` + +As of SKAN 4.0, next to conversion value, there are a couple of additional endpoint one can set when updating conversion value for the user: coarse and lock window values. If you are running SKAN 4.0 (or later) campaigns and would like to get information about these values as well, then make sure to implement a callback for that purpose: + +```cpp +#include "Adjust/Adjust2dx.h" // ... @@ -462,10 +501,14 @@ bool AppDelegate::applicationDidFinishLaunching() { AdjustConfig2dx adjustConfig = AdjustConfig2dx(appToken, environment); adjustConfig.setLogLevel(AdjustLogLevel2dxVerbose); - adjustConfig.setConversionValueUpdatedCallback(conversionValueUpdatedCallbackMethod); + adjustConfig.setPostbackConversionValueUpdatedCallback([](int conversionValue, + std::string coarseValue, + bool lockWindow) { + std::cout << "\nConversion value: " << conversionValue; + std::cout << "\nCoarse value: " << coarseValue; + std::cout << "\nLock window: " << lockWindow; + }); Adjust2dx::start(adjustConfig); - - // ... } ``` @@ -494,6 +537,44 @@ When you set a currency token, Adjust will automatically convert the incoming re You can read more about revenue and event tracking in the [event tracking guide][event-tracking]. +### Purchase verification + +If you've enabled [purchase verification](https://help.adjust.com/en/article/purchase-verification), you must can additional information with your purchase events to verify them. When Adjust's servers receive this information in an event object, they forward it to Apple / Google to verify the purchase. + +In order to verify the purchase on iOS platform: + +```cpp +AdjustEvent2dx adjustEvent = AdjustEvent2dx("abc123"); +adjustEvent.setRevenue(0.01, "EUR"); +adjustEvent.setProductId("productId"); +adjustEvent.setTransactionId("transactionId"); +adjustEvent.setReceipt("receipt"); +Adjust2dx::trackEvent(adjustEvent); +``` + +Parameters needed for the iOS verification: + +- `transactionId` (std::string): The [`transactionIdentifier` value](https://developer.apple.com/documentation/storekit/skpaymenttransaction/1411288-transactionidentifier) of the successfully completed purchase +- `productId` (std::string): The product identifier of the item that was successfully purchased +- `receipt` (std::string): The [signed receipt](https://developer.apple.com/documentation/foundation/bundle/1407276-appstorereceipturl) containing the information about the successfully completed purchase (not base64 encoded) + +In order to verify the purchase on Android platform: + +```cpp +AdjustEvent2dx adjustEvent = AdjustEvent2dx("abc123"); +adjustEvent.setRevenue(0.01, "EUR"); +adjustEvent.setProductId("productId"); +adjustEvent.setPurchaseToken("purchaseToken"); +Adjust2dx::trackEvent(adjustEvent); +``` + +Parameters needed for the Android verification: + +- `productId` (std::string): The product identifier ([`SKU`](https://developer.android.com/reference/com/android/billingclient/api/SkuDetails#getSku())) of the item that was successfully purchased +- `purchaseToken` (std::string): The [`purchase token`](https://developer.android.com/reference/com/android/billingclient/api/Purchase#getPurchaseToken()) of the successfully completed purchase + +**Note:** All the links for the parameters that are needed for the purchase verification are linking to native iOS / Android API which is not the API you will be using inside of your Cocos2d-x app. You will most probably be using some plugin in Cocos2d-x that is wrapping native iOS and Android in-app purchase flows and is encapsulating all these things for you in some way. Depending on the plugin you are using for in-app purchases, you will need to understand how to extract these parameters from the response that you are getting from your library. In case you need assistance with this, feel free to get in touch with us to help you with that. + ### Revenue deduplication You can also add an optional transaction ID to avoid tracking duplicate revenues. The last ten transaction IDs are remembered, and revenue events with duplicate transaction IDs are skipped. This is especially useful for in-app purchase tracking. You can see an example below. @@ -557,6 +638,8 @@ adjustEvent.setCallbackId("Your-Custom-Id"); Adjust2dx::trackEvent(adjustEvent); ``` + + ### Subscription tracking **Note**: This feature is only available in the SDK v4.22.0 and above. @@ -1087,6 +1170,14 @@ You can access the IDFA value on an iOS device by invoking the `getIdfa()` metho std::string idfa = Adjust2dx::getIdfa(); ``` +### iOS Identifier For Vendors + +You can access the IDFV value on an iOS device by invoking the `getIdfv()` method of the `Adjust2dx` instance. + +```cpp +std::string idfv = Adjust2dx::getIdfv(); +``` + ### Google Play Services advertising identifier The Google Play Services Advertising Identifier (Google advertising ID) is a unique identifier for a device. Users can opt out of sharing their Google advertising ID by toggling the "Opt out of Ads Personalization" setting on their device. When a user has enabled this setting, the Adjust SDK returns a string of zeros when trying to read the Google advertising ID. @@ -1283,6 +1374,29 @@ By default Adjust SDK doesn't mark Android app as Play Store Kids App. In order adjustConfig.setPlayStoreKidsAppEnabled(true); ``` +### Meta install referrer + +The Adjust SDK supports the [Meta Install Referrer](https://developers.facebook.com/docs/app-ads/install-referrer/) in v4.37.0 and above. To enable this feature: + +- Find your Meta app ID in your [App Dashboard](https://developers.facebook.com/apps). See Meta's [App Dashboard documentation](https://developers.facebook.com/docs/development/create-an-app/app-dashboard) for more information. +- Pass your `App ID` as a string argument to the `AdjustConfig`'s `setFbAppId` method. + +```cpp +adjustConfig.setFbAppId("your-fb-app-id"); +``` + +- Make sure to add additional `queries` entries to the root of your `AndroidManifest.xml` file: + +```xml + + + + + + +``` + + [adjust]: http://adjust.com [dashboard]: http://adjust.com [adjust.com]: http://adjust.com diff --git a/VERSION b/VERSION index eed4df59..69c42762 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.32.0 +4.37.0 diff --git a/dist/ADJAdjust2dx.h b/dist/ADJAdjust2dx.h index f61af0ad..dd5ed106 100755 --- a/dist/ADJAdjust2dx.h +++ b/dist/ADJAdjust2dx.h @@ -16,6 +16,7 @@ #include "ADJAppStoreSubscription2dx.h" #include "ADJThirdPartySharing2dx.h" #include "ADJAdRevenue2dx.h" +#include "ADJAppStorePurchase2dx.h" #include "AdjustAttribution2dx.h" extern const std::string ADJEnvironmentSandbox2dx; @@ -53,8 +54,14 @@ class ADJAdjust2dx { static void trackThirdPartySharing(ADJThirdPartySharing2dx thirdPartySharing); static void trackMeasurementConsent(bool measurementConsent); static void updateConversionValue(int conversionValue); + static void updatePostbackConversionValue(int conversionValue, void (*errorCallback)(std::string error)); + static void updatePostbackConversionValue(int conversionValue, std::string coarseValue, void (*errorCallback)(std::string error)); + static void updatePostbackConversionValue(int conversionValue, std::string coarseValue, bool lockWindow, void (*errorCallback)(std::string error)); static void checkForNewAttStatus(); static std::string getLastDeeplink(); + static void verifyAppStorePurchase(ADJAppStorePurchase2dx purchase, void (*verificationCallback)(std::string verificationStatus, int code, std::string message)); + static std::string getIdfv(); + static void processDeeplink(std::string url, void (*resolvedLinkCallback)(std::string resolvedLink)); // For testing purposes only. static void setTestOptions(std::map testOptionsMap); static void teardown(); diff --git a/dist/ADJAdjust2dx.mm b/dist/ADJAdjust2dx.mm index 85deb35b..accd0021 100755 --- a/dist/ADJAdjust2dx.mm +++ b/dist/ADJAdjust2dx.mm @@ -21,28 +21,33 @@ BOOL isSessionFailureCallbackImplemented = NULL != adjustConfig.getSessionFailureCallback() ? YES : NO; BOOL isDeferredDeeplinkCallbackImplemented = NULL != adjustConfig.getDeferredDeeplinkCallback() ? YES : NO; BOOL isConversionValueUpdatedListenerImplemented = NULL != adjustConfig.getConversionValueUpdatedCallback() ? YES : NO; - + BOOL isPostbackConversionValueUpdatedCallbackImplemented = NULL != adjustConfig.getPostbackConversionValueUpdatedCallback() ? YES : NO; + if (isAttributionCallbackImplemented || isEventSuccessCallbackImplemented || isEventFailureCallbackImplemented || isSessionSuccessCallbackImplemented || isSessionFailureCallbackImplemented || isDeferredDeeplinkCallbackImplemented - || isConversionValueUpdatedListenerImplemented) { - ((ADJConfig *)adjustConfig.getConfig()).delegate = [ADJDelegate2dx getInstanceWithSwizzleOfAttributionCallback:isAttributionCallbackImplemented - swizzleOfEventSuccessCallback:isEventSuccessCallbackImplemented - swizzleOfEventFailureCallback:isEventFailureCallbackImplemented - swizzleOfSessionSuccessCallback:isSessionSuccessCallbackImplemented - swizzleOfSessionFailureCallback:isSessionFailureCallbackImplemented - swizzleOfDeferredDeeplinkCallback:isDeferredDeeplinkCallbackImplemented - swizzleOfConversionValueUpdatedCallback:isConversionValueUpdatedListenerImplemented - andAttributionCallbackId:adjustConfig.getAttributionCallback() - eventSuccessCallbackId:adjustConfig.getEventSuccessCallback() - eventFailureCallbackId:adjustConfig.getEventFailureCallback() - sessionSuccessCallbackId:adjustConfig.getSessionSuccessCallback() - sessionFailureCallbackId:adjustConfig.getSessionFailureCallback() - deferredDeeplinkCallbackId:adjustConfig.getDeferredDeeplinkCallback() - conversionValueUpdatedCallbackId:adjustConfig.getConversionValueUpdatedCallback()]; + || isConversionValueUpdatedListenerImplemented + || isPostbackConversionValueUpdatedCallbackImplemented) { + ((ADJConfig *)adjustConfig.getConfig()).delegate = + [ADJDelegate2dx getInstanceWithSwizzleOfAttributionCallback:isAttributionCallbackImplemented + swizzleOfEventSuccessCallback:isEventSuccessCallbackImplemented + swizzleOfEventFailureCallback:isEventFailureCallbackImplemented + swizzleOfSessionSuccessCallback:isSessionSuccessCallbackImplemented + swizzleOfSessionFailureCallback:isSessionFailureCallbackImplemented + swizzleOfDeferredDeeplinkCallback:isDeferredDeeplinkCallbackImplemented + swizzleOfConversionValueUpdatedCallback:isConversionValueUpdatedListenerImplemented + swizzleOfPostbackConversionValueUpdatedCallback:isPostbackConversionValueUpdatedCallbackImplemented + andAttributionCallbackId:adjustConfig.getAttributionCallback() + eventSuccessCallbackId:adjustConfig.getEventSuccessCallback() + eventFailureCallbackId:adjustConfig.getEventFailureCallback() + sessionSuccessCallbackId:adjustConfig.getSessionSuccessCallback() + sessionFailureCallbackId:adjustConfig.getSessionFailureCallback() + deferredDeeplinkCallbackId:adjustConfig.getDeferredDeeplinkCallback() + conversionValueUpdatedCallbackId:adjustConfig.getConversionValueUpdatedCallback() + postbackConversionValueUpdatedCallbackId:adjustConfig.getPostbackConversionValueUpdatedCallback()]; } [Adjust appDidLaunch:(ADJConfig *)adjustConfig.getConfig()]; @@ -56,6 +61,16 @@ [Adjust trackSubscription:(ADJSubscription *)subscription.getSubscription()]; } +void ADJAdjust2dx::verifyAppStorePurchase(ADJAppStorePurchase2dx purchase, void (*verificationCallback)(std::string verificationStatus, int code, std::string message)) { + [Adjust verifyPurchase:(ADJPurchase *)purchase.getPurchase() completionHandler:^(ADJPurchaseVerificationResult * _Nonnull verificationResult) { + if (verificationCallback != NULL) { + verificationCallback(std::string([verificationResult.verificationStatus UTF8String]), + verificationResult.code, + std::string([verificationResult.message UTF8String])); + } + }]; +} + void ADJAdjust2dx::trackSubsessionStart() { [Adjust trackSubsessionStart]; } @@ -132,12 +147,13 @@ } std::string ADJAdjust2dx::getIdfa() { - if (nil == [Adjust idfa]) { + NSString *idfa = [Adjust idfa]; + if (nil == idfa) { return ""; } - std::string idfa = std::string([[Adjust idfa] UTF8String]); - return idfa; + std::string strIdfa = std::string([idfa UTF8String]); + return strIdfa; } std::string ADJAdjust2dx::getAdid() { @@ -227,7 +243,9 @@ void ADJAdjust2dx::requestTrackingAuthorizationWithCompletionHandler(void (*trackingStatusCallback)(int status)) { [Adjust requestTrackingAuthorizationWithCompletionHandler:^(NSUInteger status) { - trackingStatusCallback((int)status); + if (trackingStatusCallback != NULL) { + trackingStatusCallback((int)status); + } }]; } @@ -239,6 +257,35 @@ [Adjust updateConversionValue:conversionValue]; } +void ADJAdjust2dx::updatePostbackConversionValue(int conversionValue, void (*errorCallback)(std::string error)) { + [Adjust updatePostbackConversionValue:conversionValue completionHandler:^(NSError * _Nullable error) { + if (errorCallback != NULL) { + errorCallback(std::string([error.localizedDescription UTF8String])); + } + }]; +} + +void ADJAdjust2dx::updatePostbackConversionValue(int conversionValue, std::string coarseValue, void (*errorCallback)(std::string error)) { + [Adjust updatePostbackConversionValue:conversionValue + coarseValue:[NSString stringWithUTF8String:coarseValue.c_str()] + completionHandler:^(NSError * _Nullable error) { + if (errorCallback != NULL) { + errorCallback(std::string([error.localizedDescription UTF8String])); + } + }]; +} + +void ADJAdjust2dx::updatePostbackConversionValue(int conversionValue, std::string coarseValue, bool lockWindow, void (*errorCallback)(std::string error)) { + [Adjust updatePostbackConversionValue:conversionValue + coarseValue:[NSString stringWithUTF8String:coarseValue.c_str()] + lockWindow:lockWindow + completionHandler:^(NSError * _Nullable error) { + if (errorCallback != NULL) { + errorCallback(std::string([error.localizedDescription UTF8String])); + } + }]; +} + void ADJAdjust2dx::trackThirdPartySharing(ADJThirdPartySharing2dx thirdPartySharing) { [Adjust trackThirdPartySharing:(ADJThirdPartySharing *)thirdPartySharing.getThirdPartySharing()]; } @@ -265,11 +312,35 @@ return stdStrLastDeeplink; } +std::string ADJAdjust2dx::getIdfv() { + NSString *idfv = [Adjust idfv]; + if (nil == idfv) { + return ""; + } + + std::string strIdfv = std::string([idfv UTF8String]); + return strIdfv; +} + +void ADJAdjust2dx::processDeeplink(std::string url, void (*resolvedLinkCallback)(std::string resolvedLink)) { + NSURL *pUrl = [NSURL URLWithString:[NSString stringWithUTF8String:url.c_str()]]; + [Adjust processDeeplink:pUrl completionHandler:^(NSString * _Nonnull resolvedLink) { + if (resolvedLinkCallback != NULL) { + if (resolvedLink != nil) { + resolvedLinkCallback(std::string([resolvedLink UTF8String])); + } else { + resolvedLinkCallback(""); + } + } + }]; +} + void ADJAdjust2dx::setTestOptions(std::map testOptionsMap) { AdjustTestOptions *testOptions = [[AdjustTestOptions alloc] init]; testOptions.baseUrl = [NSString stringWithUTF8String:testOptionsMap["baseUrl"].c_str()]; testOptions.gdprUrl = [NSString stringWithUTF8String:testOptionsMap["gdprUrl"].c_str()]; testOptions.subscriptionUrl = [NSString stringWithUTF8String:testOptionsMap["subscriptionUrl"].c_str()]; + testOptions.purchaseVerificationUrl = [NSString stringWithUTF8String:testOptionsMap["purchaseVerificationUrl"].c_str()]; if (testOptionsMap.find("extraPath") != testOptionsMap.end()) { testOptions.extraPath = [NSString stringWithUTF8String:testOptionsMap["extraPath"].c_str()]; @@ -311,13 +382,6 @@ testOptions.noBackoffWait = YES; } } - testOptions.iAdFrameworkEnabled = NO; - if (testOptionsMap.find("iAdFrameworkEnabled") != testOptionsMap.end()) { - NSString *iAdFrameworkEnabled = [NSString stringWithUTF8String:testOptionsMap["iAdFrameworkEnabled"].c_str()]; - if ([iAdFrameworkEnabled isEqualToString:@"true"]) { - testOptions.iAdFrameworkEnabled = YES; - } - } testOptions.adServicesFrameworkEnabled = NO; if (testOptionsMap.find("adServicesFrameworkEnabled") != testOptionsMap.end()) { NSString *adServicesFrameworkEnabled = [NSString stringWithUTF8String:testOptionsMap["adServicesFrameworkEnabled"].c_str()]; diff --git a/dist/ADJAppStorePurchase2dx.h b/dist/ADJAppStorePurchase2dx.h new file mode 100755 index 00000000..9ac50edb --- /dev/null +++ b/dist/ADJAppStorePurchase2dx.h @@ -0,0 +1,28 @@ +// +// ADJAppStorePurchase2dx.h +// Adjust SDK +// +// Created by Uglješa Erceg (@uerceg) on 17th January 2024. +// Copyright © 2015-Present Adjust GmbH. All rights reserved. +// + +#ifndef _ADJUST_ADJAPPSTOREPURCHASE2DX_H_ +#define _ADJUST_ADJAPPSTOREPURCHASE2DX_H_ + +#include + +class ADJAppStorePurchase2dx { +private: + void* purchase; + void initPurchase(std::string productId, std::string transactionId, std::string receipt); + +public: + ADJAppStorePurchase2dx() {} + ADJAppStorePurchase2dx(std::string productId, std::string transactionId, std::string receipt) { + initPurchase(productId, transactionId, receipt); + } + + void* getPurchase(); +}; + +#endif /* _ADJUST_ADJAPPSTOREPURCHASE2DX_H_ */ diff --git a/dist/ADJAppStorePurchase2dx.mm b/dist/ADJAppStorePurchase2dx.mm new file mode 100755 index 00000000..b5b66216 --- /dev/null +++ b/dist/ADJAppStorePurchase2dx.mm @@ -0,0 +1,23 @@ +// +// ADJAppStorePurchase2dx.mm +// Adjust SDK +// +// Created by Uglješa Erceg (@uerceg) on 17th January 2024. +// Copyright © 2015-Present Adjust GmbH. All rights reserved. +// + +#include "ADJAppStorePurchase2dx.h" +#include + +void ADJAppStorePurchase2dx::initPurchase(std::string productId, std::string transactionId, std::string receipt) { + NSString *strProductId = [NSString stringWithUTF8String:productId.c_str()]; + NSString *strTransactionId = [NSString stringWithUTF8String:transactionId.c_str()]; + NSString *strReceipt = [NSString stringWithUTF8String:receipt.c_str()]; + purchase = [[ADJPurchase alloc] initWithTransactionId:strTransactionId + productId:strProductId + andReceipt:[strReceipt dataUsingEncoding:NSUTF8StringEncoding]]; +} + +void* ADJAppStorePurchase2dx::getPurchase() { + return purchase; +} diff --git a/dist/ADJConfig2dx.h b/dist/ADJConfig2dx.h index bec20897..676854fc 100755 --- a/dist/ADJConfig2dx.h +++ b/dist/ADJConfig2dx.h @@ -36,6 +36,7 @@ class ADJConfig2dx { void (*sessionFailureCallback)(AdjustSessionFailure2dx sessionFailure) = NULL; bool (*deferredDeeplinkCallback)(std::string deeplink) = NULL; void (*conversionValueUpdatedCallback)(int conversionValue) = NULL; + void (*postbackConversionValueUpdatedCallback)(int conversionValue, std::string coarseValue, bool lockWindow) = NULL; void initConfig(std::string appToken, std::string environment, bool allowSuppressLogLevel, std::string sdkPrefix); public: @@ -64,6 +65,7 @@ class ADJConfig2dx { void deactivateSkAdNetworkHandling(); void setCoppaCompliantEnabled(bool isEnabled); void setLinkMeEnabled(bool isEnabled); + void setAttConsentWaitingInterval(int numberOfSeconds); void setAttributionCallback(void(*callbackMethod)(AdjustAttribution2dx attribution)); void setEventSuccessCallback(void(*callbackMethod)(AdjustEventSuccess2dx eventSuccess)); void setEventFailureCallback(void(*callbackMethod)(AdjustEventFailure2dx eventFailure)); @@ -71,6 +73,8 @@ class ADJConfig2dx { void setSessionFailureCallback(void(*callbackMethod)(AdjustSessionFailure2dx sessionFailure)); void setDeferredDeeplinkCallback(bool(*callbackMethod)(std::string deeplink)); void setConversionValueUpdatedCallback(void(*callbackMethod)(int conversionValue)); + void setPostbackConversionValueUpdatedCallback(void(*callbackMethod)(int conversionValue, std::string coarseValue, bool lockWindow)); + void setReadDeviceInfoOnceEnabled(bool isEnabled); void* getConfig(); void(*getAttributionCallback())(AdjustAttribution2dx); void(*getEventSuccessCallback())(AdjustEventSuccess2dx); @@ -79,6 +83,7 @@ class ADJConfig2dx { void(*getSessionFailureCallback())(AdjustSessionFailure2dx); bool(*getDeferredDeeplinkCallback())(std::string); void(*getConversionValueUpdatedCallback())(int); + void(*getPostbackConversionValueUpdatedCallback())(int, std::string, bool); }; #endif /* _ADJUST_ADJCONFIG2DX_H_ */ diff --git a/dist/ADJConfig2dx.mm b/dist/ADJConfig2dx.mm index c0cc3845..318d9a95 100755 --- a/dist/ADJConfig2dx.mm +++ b/dist/ADJConfig2dx.mm @@ -38,7 +38,8 @@ } void ADJConfig2dx::setAllowiAdInfoReading(bool isAllowed) { - ((ADJConfig *)config).allowiAdInfoReading = isAllowed; + // deprecated + // ((ADJConfig *)config).allowiAdInfoReading = isAllowed; } void ADJConfig2dx::setAllowAdServicesInfoReading(bool isAllowed) { @@ -67,6 +68,10 @@ ((ADJConfig *)config).urlStrategy = ADJUrlStrategyChina; } else if ([strUrlStrategy isEqualToString:@"india"]) { ((ADJConfig *)config).urlStrategy = ADJUrlStrategyIndia; + } else if ([strUrlStrategy isEqualToString:@"cn"]) { + ((ADJConfig *)config).urlStrategy = ADJUrlStrategyCn; + } else if ([strUrlStrategy isEqualToString:@"cn-only"]) { + ((ADJConfig *)config).urlStrategy = ADJUrlStrategyCnOnly; } else if ([strUrlStrategy isEqualToString:@"data-residency-eu"]) { ((ADJConfig *)config).urlStrategy = ADJDataResidencyEU; } else if ([strUrlStrategy isEqualToString:@"data-residency-tr"]) { @@ -88,6 +93,10 @@ ((ADJConfig *)config).linkMeEnabled = isEnabled; } +void ADJConfig2dx::setAttConsentWaitingInterval(int numberOfSeconds) { + ((ADJConfig *)config).attConsentWaitingInterval = numberOfSeconds; +} + void ADJConfig2dx::setAttributionCallback(void (*callbackMethod)(AdjustAttribution2dx attribution)) { attributionCallback = callbackMethod; } @@ -116,6 +125,10 @@ conversionValueUpdatedCallback = callbackMethod; } +void ADJConfig2dx::setPostbackConversionValueUpdatedCallback(void(*callbackMethod)(int conversionValue, std::string coarseValue, bool lockWindow)) { + postbackConversionValueUpdatedCallback = callbackMethod; +} + void* ADJConfig2dx::getConfig() { return config; } @@ -128,6 +141,10 @@ [((ADJConfig *)config) setIsDeviceKnown:isDeviceKnown]; } +void ADJConfig2dx::setReadDeviceInfoOnceEnabled(bool isEnabled) { + ((ADJConfig *)config).readDeviceInfoOnceEnabled = isEnabled; +} + void(*ADJConfig2dx::getAttributionCallback())(AdjustAttribution2dx) { return attributionCallback; } @@ -155,3 +172,7 @@ void(*ADJConfig2dx::getConversionValueUpdatedCallback())(int) { return conversionValueUpdatedCallback; } + +void(*ADJConfig2dx::getPostbackConversionValueUpdatedCallback())(int, std::string, bool) { + return postbackConversionValueUpdatedCallback; +} diff --git a/dist/ADJDelegate2dx.h b/dist/ADJDelegate2dx.h index 3f931108..5f781a9b 100644 --- a/dist/ADJDelegate2dx.h +++ b/dist/ADJDelegate2dx.h @@ -17,6 +17,7 @@ @property (nonatomic) void (*sessionFailureCallbackMethod)(AdjustSessionFailure2dx sessionFailure); @property (nonatomic) bool (*deferredDeeplinkCallbackMethod)(std::string deeplink); @property (nonatomic) void (*conversionValueUpdatedCallbackMethod)(int conversionValue); +@property (nonatomic) void (*postbackConversionValueUpdatedCallbackMethod)(int conversionValue, std::string coarseValue, bool lockWindow); + (id)getInstanceWithSwizzleOfAttributionCallback:(BOOL)swizzleAttributionCallback swizzleOfEventSuccessCallback:(BOOL)swizzleEventSuccessCallback @@ -25,13 +26,15 @@ swizzleOfSessionFailureCallback:(BOOL)swizzleSessionFailureCallback swizzleOfDeferredDeeplinkCallback:(BOOL)swizzleDeferredDeeplinkCallback swizzleOfConversionValueUpdatedCallback:(BOOL)swizzleConversionValueUpdatedCallback - andAttributionCallbackId:(void (*)(AdjustAttribution2dx attribution))attributionCallbackId + swizzleOfPostbackConversionValueUpdatedCallback:(BOOL)swizzlePostbackConversionValueUpdatedCallback + andAttributionCallbackId:(void (*)(AdjustAttribution2dx attribution))attributionCallbackId eventSuccessCallbackId:(void (*)(AdjustEventSuccess2dx eventSuccess))eventSuccessCallbackId eventFailureCallbackId:(void (*)(AdjustEventFailure2dx eventFailure))eventFailureCallbackId sessionSuccessCallbackId:(void (*)(AdjustSessionSuccess2dx sessionSuccess))sessionSuccessCallbackId sessionFailureCallbackId:(void (*)(AdjustSessionFailure2dx sessionFailure))sessionFailureCallbackId - deferredDeeplinkCallbackId:(bool (*)(std::string deeplink))deferredDeeplinkCallbackId - conversionValueUpdatedCallbackId:(void (*)(int conversionValue))conversionValueUpdatedCallbackId; + deferredDeeplinkCallbackId:(bool (*)(std::string deeplink))deferredDeeplinkCallbackId + conversionValueUpdatedCallbackId:(void (*)(int conversionValue))conversionValueUpdatedCallbackId + postbackConversionValueUpdatedCallbackId:(void (*)(int conversionValue, std::string coarseValue, bool lockWindow))postbackConversionValueUpdatedCallbackId; + (void)teardown; @end diff --git a/dist/ADJDelegate2dx.mm b/dist/ADJDelegate2dx.mm index 4dbee598..85f80a23 100644 --- a/dist/ADJDelegate2dx.mm +++ b/dist/ADJDelegate2dx.mm @@ -22,13 +22,15 @@ + (id)getInstanceWithSwizzleOfAttributionCallback:(BOOL)swizzleAttributionCallba swizzleOfSessionFailureCallback:(BOOL)swizzleSessionFailureCallback swizzleOfDeferredDeeplinkCallback:(BOOL)swizzleDeferredDeeplinkCallback swizzleOfConversionValueUpdatedCallback:(BOOL)swizzleConversionValueUpdatedCallback + swizzleOfPostbackConversionValueUpdatedCallback:(BOOL)swizzlePostbackConversionValueUpdatedCallback andAttributionCallbackId:(void (*)(AdjustAttribution2dx attribution))attributionCallbackId eventSuccessCallbackId:(void (*)(AdjustEventSuccess2dx eventSuccess))eventSuccessCallbackId eventFailureCallbackId:(void (*)(AdjustEventFailure2dx eventFailure))eventFailureCallbackId sessionSuccessCallbackId:(void (*)(AdjustSessionSuccess2dx sessionSuccess))sessionSuccessCallbackId sessionFailureCallbackId:(void (*)(AdjustSessionFailure2dx sessionFailure))sessionFailureCallbackId deferredDeeplinkCallbackId:(bool (*)(std::string deeplink))deferredDeeplinkCallbackId - conversionValueUpdatedCallbackId:(void (*)(int conversionValue))conversionValueUpdatedCallbackId { + conversionValueUpdatedCallbackId:(void (*)(int conversionValue))conversionValueUpdatedCallbackId + postbackConversionValueUpdatedCallbackId:(void (*)(int conversionValue, std::string coarseValue, bool lockWindow))postbackConversionValueUpdatedCallbackId { dispatch_once(&onceToken, ^{ defaultInstance = [[ADJDelegate2dx alloc] init]; @@ -61,7 +63,11 @@ + (id)getInstanceWithSwizzleOfAttributionCallback:(BOOL)swizzleAttributionCallba [defaultInstance swizzleCallbackMethod:@selector(adjustConversionValueUpdated:) swizzledSelector:@selector(adjustConversionValueUpdatedWannabe:)]; } - + if (swizzlePostbackConversionValueUpdatedCallback) { + [defaultInstance swizzleCallbackMethod:@selector(adjustConversionValueUpdated:coarseValue:lockWindow:) + swizzledSelector:@selector(adjustConversionValueUpdatedWannabe:coarseValue:lockWindow:)]; + } + [defaultInstance setAttributionCallbackMethod:attributionCallbackId]; [defaultInstance setEventSuccessCallbackMethod:eventSuccessCallbackId]; [defaultInstance setEventFailureCallbackMethod:eventFailureCallbackId]; @@ -69,6 +75,7 @@ + (id)getInstanceWithSwizzleOfAttributionCallback:(BOOL)swizzleAttributionCallba [defaultInstance setSessionFailureCallbackMethod:sessionFailureCallbackId]; [defaultInstance setDeferredDeeplinkCallbackMethod:deferredDeeplinkCallbackId]; [defaultInstance setConversionValueUpdatedCallbackMethod:conversionValueUpdatedCallbackId]; + [defaultInstance setPostbackConversionValueUpdatedCallbackMethod:postbackConversionValueUpdatedCallbackId]; }); return defaultInstance; @@ -266,6 +273,17 @@ - (void)adjustConversionValueUpdatedWannabe:(NSNumber *)conversionValue { _conversionValueUpdatedCallbackMethod([conversionValue intValue]); } +- (void)adjustConversionValueUpdatedWannabe:(NSNumber *)fineValue + coarseValue:(NSString *)coarseValue + lockWindow:(NSNumber *)lockWindow { + if (fineValue == nil || coarseValue == nil || lockWindow == nil) { + return; + } + _postbackConversionValueUpdatedCallbackMethod([fineValue intValue], + std::string([coarseValue UTF8String]), + [lockWindow boolValue]); +} + - (void)swizzleCallbackMethod:(SEL)originalSelector swizzledSelector:(SEL)swizzledSelector { Class cls = [self class]; diff --git a/dist/ADJEvent2dx.h b/dist/ADJEvent2dx.h index 707124c6..dfef757b 100755 --- a/dist/ADJEvent2dx.h +++ b/dist/ADJEvent2dx.h @@ -28,6 +28,8 @@ class ADJEvent2dx { void setTransactionId(std::string transactionId); void setCallbackId(std::string callbackId); void setReceipt(std::string receipt, std::string transactionId); + void setProductId(std::string productId); + void setReceipt(std::string receipt); bool isValid(); void* getEvent(); }; diff --git a/dist/ADJEvent2dx.mm b/dist/ADJEvent2dx.mm index 818e83d4..cf666a58 100755 --- a/dist/ADJEvent2dx.mm +++ b/dist/ADJEvent2dx.mm @@ -43,6 +43,14 @@ transactionId:[NSString stringWithUTF8String:transactionId.c_str()]]; } +void ADJEvent2dx::setProductId(std::string productId) { + [((ADJEvent *)event) setProductId:[NSString stringWithUTF8String:productId.c_str()]]; +} + +void ADJEvent2dx::setReceipt(std::string receipt) { + [((ADJEvent *)event) setReceipt:[[NSString stringWithUTF8String:receipt.c_str()] dataUsingEncoding:NSUTF8StringEncoding]]; +} + bool ADJEvent2dx::isValid() { return [((ADJEvent *)event) isValid]; } diff --git a/dist/Adjust2dx.cpp b/dist/Adjust2dx.cpp index e8e44cbd..b26c1b90 100755 --- a/dist/Adjust2dx.cpp +++ b/dist/Adjust2dx.cpp @@ -55,6 +55,12 @@ void Adjust2dx::trackAppStoreSubscription(AdjustAppStoreSubscription2dx subscrip #endif } +void Adjust2dx::verifyAppStorePurchase(AdjustAppStorePurchase2dx purchase, void (*verificationCallback)(std::string verificationStatus, int code, std::string message)) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + ADJAdjust2dx::verifyAppStorePurchase(purchase.getPurchase(), verificationCallback); +#endif +} + void Adjust2dx::trackPlayStoreSubscription(AdjustPlayStoreSubscription2dx subscription) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) cocos2d::JniMethodInfo jmiTrackPlayStoreSubscription; @@ -65,6 +71,21 @@ void Adjust2dx::trackPlayStoreSubscription(AdjustPlayStoreSubscription2dx subscr #endif } +void Adjust2dx::verifyPlayStorePurchase(AdjustPlayStorePurchase2dx purchase, void (*verificationCallback)(std::string verificationStatus, int code, std::string message)) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + setPurchaseVerificationResultCallbackMethod(verificationCallback); + cocos2d::JniMethodInfo jmiVerifyPlayStorePurchase; + if (!cocos2d::JniHelper::getStaticMethodInfo(jmiVerifyPlayStorePurchase, "com/adjust/sdk/Adjust", "verifyPurchase", "(Lcom/adjust/sdk/AdjustPurchase;Lcom/adjust/sdk/OnPurchaseVerificationFinishedListener;)V")) { + return; + } + jclass clsAdjust2dxPurchaseVerificationResultCallback = jmiVerifyPlayStorePurchase.env->FindClass("com/adjust/sdk/Adjust2dxPurchaseVerificationResultCallback"); + jmethodID jmidInit = jmiVerifyPlayStorePurchase.env->GetMethodID(clsAdjust2dxPurchaseVerificationResultCallback, "", "()V"); + jobject jCallbackProxy = jmiVerifyPlayStorePurchase.env->NewObject(clsAdjust2dxPurchaseVerificationResultCallback, jmidInit); + jmiVerifyPlayStorePurchase.env->CallStaticVoidMethod(jmiVerifyPlayStorePurchase.classID, jmiVerifyPlayStorePurchase.methodID, purchase.getPurchase(), jCallbackProxy); + jmiVerifyPlayStorePurchase.env->DeleteLocalRef(jCallbackProxy); +#endif +} + void Adjust2dx::setEnabled(bool isEnabled) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) cocos2d::JniMethodInfo jmiSetEnabled; @@ -577,6 +598,36 @@ void Adjust2dx::trackAdRevenueNew(AdjustAdRevenue2dx adRevenue) { #endif } +void Adjust2dx::processDeeplink(std::string url, void (*resolvedLinkCallback)(std::string resolvedLink)) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + ADJAdjust2dx::processDeeplink(url, resolvedLinkCallback); +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + setResolvedLinkCallbackMethod(resolvedLinkCallback); + cocos2d::JniMethodInfo jmiProcessDeeplink; + if (!cocos2d::JniHelper::getStaticMethodInfo(jmiProcessDeeplink, "com/adjust/sdk/Adjust", "processDeeplink", "(Landroid/net/Uri;Landroid/content/Context;Lcom/adjust/sdk/OnDeeplinkResolvedListener;)V")) { + return; + } + cocos2d::JniMethodInfo jmiGetContext; + if (!cocos2d::JniHelper::getStaticMethodInfo(jmiGetContext, "org/cocos2dx/lib/Cocos2dxActivity", "getContext", "()Landroid/content/Context;")) { + return; + } + + jclass jcUri = jmiProcessDeeplink.env->FindClass("android/net/Uri"); + jmethodID midParse = jmiProcessDeeplink.env->GetStaticMethodID(jcUri, "parse", "(Ljava/lang/String;)Landroid/net/Uri;"); + jstring jUrl = jmiProcessDeeplink.env->NewStringUTF(url.c_str()); + jobject jUri = jmiProcessDeeplink.env->CallStaticObjectMethod(jcUri, midParse, jUrl); + jobject jContext = (jobject)jmiGetContext.env->CallStaticObjectMethod(jmiGetContext.classID, jmiGetContext.methodID); + jclass clsAdjust2dxResolvedLinkCallback = jmiProcessDeeplink.env->FindClass("com/adjust/sdk/Adjust2dxResolvedLinkCallback"); + jmethodID jmidInit = jmiProcessDeeplink.env->GetMethodID(clsAdjust2dxResolvedLinkCallback, "", "()V"); + jobject jCallbackProxy = jmiProcessDeeplink.env->NewObject(clsAdjust2dxResolvedLinkCallback, jmidInit); + jmiProcessDeeplink.env->CallStaticVoidMethod(jmiProcessDeeplink.classID, jmiProcessDeeplink.methodID, jUri, jContext, jCallbackProxy); + jmiProcessDeeplink.env->DeleteLocalRef(jUrl); + jmiProcessDeeplink.env->DeleteLocalRef(jUri); + jmiGetContext.env->DeleteLocalRef(jContext); + jmiProcessDeeplink.env->DeleteLocalRef(jCallbackProxy); +#endif +} + void Adjust2dx::setReferrer(std::string referrer) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) cocos2d::JniMethodInfo jmiSetReferrer; @@ -702,6 +753,24 @@ void Adjust2dx::updateConversionValue(int conversionValue) { #endif } +void Adjust2dx::updatePostbackConversionValue(int conversionValue, void (*errorCallback)(std::string error)) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + ADJAdjust2dx::updatePostbackConversionValue(conversionValue, errorCallback); +#endif +} + +void Adjust2dx::updatePostbackConversionValue(int conversionValue, std::string coarseValue, void (*errorCallback)(std::string error)) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + ADJAdjust2dx::updatePostbackConversionValue(conversionValue, coarseValue, errorCallback); +#endif +} + +void Adjust2dx::updatePostbackConversionValue(int conversionValue, std::string coarseValue, bool lockWindow, void (*errorCallback)(std::string error)) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + ADJAdjust2dx::updatePostbackConversionValue(conversionValue, coarseValue, lockWindow, errorCallback); +#endif +} + void Adjust2dx::checkForNewAttStatus() { #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) return ADJAdjust2dx::checkForNewAttStatus(); @@ -716,6 +785,14 @@ std::string Adjust2dx::getLastDeeplink() { #endif } +std::string Adjust2dx::getIdfv() { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + return ADJAdjust2dx::getIdfv(); +#else + return ""; +#endif +} + #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) jobject getTestOptions(std::map testOptions) { cocos2d::JniMethodInfo jmiInit; @@ -770,6 +847,11 @@ jobject getTestOptions(std::map testOptions) { jfieldID jfidSubscriptionUrl = jmiInit.env->GetFieldID(jclsTestOptions, "subscriptionUrl", "Ljava/lang/String;"); jmiInit.env->SetObjectField(jTestOptions, jfidSubscriptionUrl, jsSubscriptionUrl); + // Purchase verification URL. + jstring jsPurchaseVerificationUrl = jmiInit.env->NewStringUTF(testOptions["purchaseVerificationUrl"].c_str()); + jfieldID jfidPurchaseVerificationUrl = jmiInit.env->GetFieldID(jclsTestOptions, "purchaseVerificationUrl", "Ljava/lang/String;"); + jmiInit.env->SetObjectField(jTestOptions, jfidPurchaseVerificationUrl, jsPurchaseVerificationUrl); + // Base path. if (testOptions.find("basePath") != testOptions.end()) { jstring jsBasePath = jmiInit.env->NewStringUTF(testOptions["basePath"].c_str()); @@ -784,13 +866,20 @@ jobject getTestOptions(std::map testOptions) { jmiInit.env->SetObjectField(jTestOptions, jfidGdprPath, jsGdprPath); } - // GDPR path. + // Subscription path. if (testOptions.find("subscriptionPath") != testOptions.end()) { jstring jsSubscriptionPath = jmiInit.env->NewStringUTF(testOptions["subscriptionPath"].c_str()); jfieldID jfidSubscriptionPath = jmiInit.env->GetFieldID(jclsTestOptions, "subscriptionPath", "Ljava/lang/String;"); jmiInit.env->SetObjectField(jTestOptions, jfidSubscriptionPath, jsSubscriptionPath); } + // Purchase verification path. + if (testOptions.find("purchaseVerificationPath") != testOptions.end()) { + jstring jsPurchaseVerificationPath = jmiInit.env->NewStringUTF(testOptions["purchaseVerificationPath"].c_str()); + jfieldID jfidPurchaseVerificationPath = jmiInit.env->GetFieldID(jclsTestOptions, "purchaseVerificationPath", "Ljava/lang/String;"); + jmiInit.env->SetObjectField(jTestOptions, jfidPurchaseVerificationPath, jsPurchaseVerificationPath); + } + // Use test connection options. if (testOptions.find("useTestConnectionOptions") != testOptions.end()) { jboolean jUseTestConnectionOptions = testOptions["useTestConnectionOptions"] == "true" ? JNI_TRUE : JNI_FALSE; diff --git a/dist/Adjust2dx.h b/dist/Adjust2dx.h index 6307e65f..50d75453 100755 --- a/dist/Adjust2dx.h +++ b/dist/Adjust2dx.h @@ -18,6 +18,8 @@ #include "AdjustPlayStoreSubscription2dx.h" #include "AdjustThirdPartySharing2dx.h" #include "AdjustAdRevenue2dx.h" +#include "AdjustPlayStorePurchase2dx.h" +#include "AdjustAppStorePurchase2dx.h" extern const std::string AdjustEnvironmentSandbox2dx; extern const std::string AdjustEnvironmentProduction2dx; @@ -47,6 +49,7 @@ class Adjust2dx { static std::string getSdkVersion(); static AdjustAttribution2dx getAttribution(); static void trackAdRevenueNew(AdjustAdRevenue2dx adRevenue); + static void processDeeplink(std::string url, void (*resolvedLinkCallback)(std::string resolvedLink)); // Android specific methods. static void setReferrer(std::string referrer); static void getGoogleAdId(void (*adIdCallback)(std::string adId)); @@ -54,14 +57,20 @@ class Adjust2dx { static void onResume(); static void onPause(); static void trackPlayStoreSubscription(AdjustPlayStoreSubscription2dx subscription); + static void verifyPlayStorePurchase(AdjustPlayStorePurchase2dx purchase, void (*verificationCallback)(std::string verificationStatus, int code, std::string message)); // iOS specific methods. static std::string getIdfa(); static void trackAppStoreSubscription(AdjustAppStoreSubscription2dx subscription); static void requestTrackingAuthorizationWithCompletionHandler(void (*trackingStatusCallback)(int status)); static int getAppTrackingAuthorizationStatus(); static void updateConversionValue(int conversionValue); + static void updatePostbackConversionValue(int conversionValue, void (*errorCallback)(std::string error)); + static void updatePostbackConversionValue(int conversionValue, std::string coarseValue, void (*errorCallback)(std::string error)); + static void updatePostbackConversionValue(int conversionValue, std::string coarseValue, bool lockWindow, void (*errorCallback)(std::string error)); static void checkForNewAttStatus(); static std::string getLastDeeplink(); + static void verifyAppStorePurchase(AdjustAppStorePurchase2dx purchase, void (*verificationCallback)(std::string verificationStatus, int code, std::string message)); + static std::string getIdfv(); // For testing purposes only. static void setTestOptions(std::map testOptions); #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) diff --git a/dist/AdjustAppStorePurchase2dx.cpp b/dist/AdjustAppStorePurchase2dx.cpp new file mode 100755 index 00000000..ac20291c --- /dev/null +++ b/dist/AdjustAppStorePurchase2dx.cpp @@ -0,0 +1,28 @@ +// +// AdjustAppStorePurchase2dx.cpp +// Adjust SDK +// +// Created by Uglješa Erceg (@uerceg) on 17th January 2024. +// Copyright © 2015-Present Adjust GmbH. All rights reserved. +// + +#include "AdjustAppStorePurchase2dx.h" + +void AdjustAppStorePurchase2dx::initPurchase( + std::string productId, + std::string transactionId, + std::string receipt +) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + purchase = ADJAppStorePurchase2dx(productId, transactionId, receipt); + isPurchaseSet = true; +#endif +} + +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) +ADJAppStorePurchase2dx AdjustAppStorePurchase2dx::getPurchase() { + return purchase; +} +#endif diff --git a/dist/AdjustAppStorePurchase2dx.h b/dist/AdjustAppStorePurchase2dx.h new file mode 100755 index 00000000..a8efefa6 --- /dev/null +++ b/dist/AdjustAppStorePurchase2dx.h @@ -0,0 +1,44 @@ +// +// AdjustAppStorePurchase2dx.h +// Adjust SDK +// +// Created by Uglješa Erceg (@uerceg) on 17th January 2024. +// Copyright © 2015-Present Adjust GmbH. All rights reserved. +// + +#ifndef ADJUST_ADJUSTAPPSTOREPURCHASE2DX_H_ +#define ADJUST_ADJUSTAPPSTOREPURCHASE2DX_H_ + +#include "cocos2d.h" +#include + +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) +#include "ADJAppStorePurchase2dx.h" +#endif + +class AdjustAppStorePurchase2dx { +private: +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + bool isPurchaseSet; + ADJAppStorePurchase2dx purchase; +#endif + void initPurchase(std::string productId, std::string transactionId, std::string receipt); + +public: + AdjustAppStorePurchase2dx(std::string productId, std::string transactionId, std::string receipt) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + isPurchaseSet = false; + initPurchase(productId, transactionId, receipt); +#endif + } + +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + ADJAppStorePurchase2dx getPurchase(); +#endif +}; + +#endif /* ADJUST_ADJUSTAPPSTOREPURCHASE2DX_H_ */ diff --git a/dist/AdjustConfig2dx.cpp b/dist/AdjustConfig2dx.cpp index 39fa4fc7..6974a9e2 100755 --- a/dist/AdjustConfig2dx.cpp +++ b/dist/AdjustConfig2dx.cpp @@ -12,9 +12,11 @@ #include "AdjustProxy2dx.h" #endif -const std::string AdjustSdkPrefix2dx = "cocos2d-x4.32.0"; +const std::string AdjustSdkPrefix2dx = "cocos2d-x4.37.0"; const std::string AdjustUrlStrategyChina = "china"; const std::string AdjustUrlStrategyIndia = "india"; +const std::string AdjustUrlStrategyCn = "cn"; +const std::string AdjustUrlStrategyCnOnly = "cn-only"; const std::string AdjustDataResidencyEU = "data-residency-eu"; const std::string AdjustDataResidencyTR = "data-residency-tr"; const std::string AdjustDataResidencyUS = "data-residency-us"; @@ -26,6 +28,8 @@ const std::string AdjustAdRevenueSourceAdMostSource = "admost_sdk"; const std::string AdjustAdRevenueSourceUnity = "unity_sdk"; const std::string AdjustAdRevenueSourceHeliumChartboost = "helium_chartboost_sdk"; const std::string AdjustAdRevenueSourcePublisher = "publisher_sdk"; +const std::string AdjustAdRevenueSourceTopOn = "topon_sdk"; +const std::string AdjustAdRevenueSourceAdx = "adx_sdk"; void AdjustConfig2dx::initConfig(std::string appToken, std::string environment, bool allowSuppressLogLevel) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) @@ -303,6 +307,18 @@ void AdjustConfig2dx::setUrlStrategy(std::string urlStrategy) { jstring jUrlStrategyIndia = (jstring)jmiSetUrlStrategy.env->GetStaticObjectField(jclsAdjustConfig, jfidUrlStrategyIndia); jmiSetUrlStrategy.env->CallVoidMethod(config, jmiSetUrlStrategy.methodID, jUrlStrategyIndia); jmiSetUrlStrategy.env->DeleteLocalRef(jUrlStrategyIndia); + } else if (urlStrategy.compare(AdjustUrlStrategyCn) == 0) { + jclass jclsAdjustConfig = jmiSetUrlStrategy.env->FindClass("com/adjust/sdk/AdjustConfig"); + jfieldID jfidUrlStrategyCn = jmiSetUrlStrategy.env->GetStaticFieldID(jclsAdjustConfig, "URL_STRATEGY_CN", "Ljava/lang/String;"); + jstring jUrlStrategyCn = (jstring)jmiSetUrlStrategy.env->GetStaticObjectField(jclsAdjustConfig, jfidUrlStrategyCn); + jmiSetUrlStrategy.env->CallVoidMethod(config, jmiSetUrlStrategy.methodID, jUrlStrategyCn); + jmiSetUrlStrategy.env->DeleteLocalRef(jUrlStrategyCn); + } else if (urlStrategy.compare(AdjustUrlStrategyCnOnly) == 0) { + jclass jclsAdjustConfig = jmiSetUrlStrategy.env->FindClass("com/adjust/sdk/AdjustConfig"); + jfieldID jfidUrlStrategyCnOnly = jmiSetUrlStrategy.env->GetStaticFieldID(jclsAdjustConfig, "URL_STRATEGY_CN_ONLY", "Ljava/lang/String;"); + jstring jUrlStrategyCnOnly = (jstring)jmiSetUrlStrategy.env->GetStaticObjectField(jclsAdjustConfig, jfidUrlStrategyCnOnly); + jmiSetUrlStrategy.env->CallVoidMethod(config, jmiSetUrlStrategy.methodID, jUrlStrategyCnOnly); + jmiSetUrlStrategy.env->DeleteLocalRef(jUrlStrategyCnOnly); } else if (urlStrategy.compare(AdjustDataResidencyEU) == 0) { jclass jclsAdjustConfig = jmiSetUrlStrategy.env->FindClass("com/adjust/sdk/AdjustConfig"); jfieldID jfidDataResidencyEU = jmiSetUrlStrategy.env->GetStaticFieldID(jclsAdjustConfig, "DATA_RESIDENCY_EU", "Ljava/lang/String;"); @@ -615,6 +631,15 @@ void AdjustConfig2dx::setConversionValueUpdatedCallback(void(*conversionValueUpd #endif } +void AdjustConfig2dx::setPostbackConversionValueUpdatedCallback(void(*postbackConversionValueUpdatedCallback)(int conversionValue, std::string coarseValue, bool lockWindow)) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + if (isConfigSet) { + config.setPostbackConversionValueUpdatedCallback(postbackConversionValueUpdatedCallback); + } +#endif +} + void AdjustConfig2dx::setCoppaCompliantEnabled(bool isEnabled) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) if (config == NULL) { @@ -632,6 +657,23 @@ void AdjustConfig2dx::setCoppaCompliantEnabled(bool isEnabled) { #endif } +void AdjustConfig2dx::setReadDeviceInfoOnceEnabled(bool isEnabled) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + if (config == NULL) { + return; + } + cocos2d::JniMethodInfo jmiSetReadDeviceInfoOnceEnabled; + if (!cocos2d::JniHelper::getMethodInfo(jmiSetReadDeviceInfoOnceEnabled, "com/adjust/sdk/AdjustConfig", "setReadDeviceInfoOnceEnabled", "(Z)V")) { + return; + } + jmiSetReadDeviceInfoOnceEnabled.env->CallVoidMethod(config, jmiSetReadDeviceInfoOnceEnabled.methodID, isEnabled); +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + if (isConfigSet) { + config.setReadDeviceInfoOnceEnabled(isEnabled); + } +#endif +} + void AdjustConfig2dx::setPlayStoreKidsAppEnabled(bool isEnabled) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) if (config == NULL) { @@ -646,6 +688,37 @@ void AdjustConfig2dx::setPlayStoreKidsAppEnabled(bool isEnabled) { #endif } +void AdjustConfig2dx::setFinalAttributionEnabled(bool isEnabled) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + if (config == NULL) { + return; + } + cocos2d::JniMethodInfo jmiSetFinalAttributionEnabled; + if (!cocos2d::JniHelper::getMethodInfo(jmiSetFinalAttributionEnabled, "com/adjust/sdk/AdjustConfig", "setFinalAttributionEnabled", "(Z)V")) { + return; + } + jmiSetFinalAttributionEnabled.env->CallVoidMethod(config, jmiSetFinalAttributionEnabled.methodID, isEnabled); +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) +#endif +} + +void AdjustConfig2dx::setFbAppId(std::string fbAppId) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + if (config == NULL) { + return; + } + cocos2d::JniMethodInfo jmiSetFbAppId; + if (!cocos2d::JniHelper::getMethodInfo(jmiSetFbAppId, "com/adjust/sdk/AdjustConfig", "setFbAppId", "(Ljava/lang/String;)V")) { + return; + } + + jstring jFbAppId = jmiSetFbAppId.env->NewStringUTF(fbAppId.c_str()); + jmiSetFbAppId.env->CallVoidMethod(config, jmiSetFbAppId.methodID, jFbAppId); + jmiSetFbAppId.env->DeleteLocalRef(jFbAppId); +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) +#endif +} + void AdjustConfig2dx::setLinkMeEnabled(bool isEnabled) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) #elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) @@ -655,6 +728,15 @@ void AdjustConfig2dx::setLinkMeEnabled(bool isEnabled) { #endif } +void AdjustConfig2dx::setAttConsentWaitingInterval(int numberOfSeconds) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + if (isConfigSet) { + config.setAttConsentWaitingInterval(numberOfSeconds); + } +#endif +} + #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) jobject AdjustConfig2dx::getConfig() { return config; diff --git a/dist/AdjustConfig2dx.h b/dist/AdjustConfig2dx.h index f9c3ee5c..aafbbaff 100755 --- a/dist/AdjustConfig2dx.h +++ b/dist/AdjustConfig2dx.h @@ -26,6 +26,8 @@ extern const std::string AdjustSdkPrefix2dx; extern const std::string AdjustUrlStrategyChina; extern const std::string AdjustUrlStrategyIndia; +extern const std::string AdjustUrlStrategyCn; +extern const std::string AdjustUrlStrategyCnOnly; extern const std::string AdjustDataResidencyEU; extern const std::string AdjustDataResidencyTR; extern const std::string AdjustDataResidencyUS; @@ -37,6 +39,8 @@ extern const std::string AdjustAdRevenueSourceAdMostSource; extern const std::string AdjustAdRevenueSourceUnity; extern const std::string AdjustAdRevenueSourceHeliumChartboost; extern const std::string AdjustAdRevenueSourcePublisher; +extern const std::string AdjustAdRevenueSourceTopOn; +extern const std::string AdjustAdRevenueSourceAdx; enum AdjustLogLevel2dx { AdjustLogLevel2dxVerbose = 1, @@ -98,18 +102,23 @@ class AdjustConfig2dx { void setSessionFailureCallback(void(*sessionFailureCallback)(AdjustSessionFailure2dx sessionFailure)); void setDeferredDeeplinkCallback(bool(*deferredDeeplinkCallback)(std::string deeplink)); void setCoppaCompliantEnabled(bool isEnabled); + void setReadDeviceInfoOnceEnabled(bool isEnabled); // iOS only void deactivateSkAdNetworkHandling(); void setAllowIdfaReading(bool isAllowed); void setAllowiAdInfoReading(bool isAllowed); void setAllowAdServicesInfoReading(bool isAllowed); void setConversionValueUpdatedCallback(void(*conversionValueUpdatedCallback)(int conversionValue)); + void setPostbackConversionValueUpdatedCallback(void(*postbackConversionValueUpdatedCallback)(int conversionValue, std::string coarseValue, bool lockWindow)); void setLinkMeEnabled(bool isEnabled); + void setAttConsentWaitingInterval(int numberOfSeconds); // Android only void setReadMobileEquipmentIdentity(bool readMobileEquipmentIdentity); void setPreinstallTrackingEnabled(bool isEnabled); void setPreinstallFilePath(std::string filePath); void setPlayStoreKidsAppEnabled(bool isEnabled); + void setFinalAttributionEnabled(bool isEnabled); + void setFbAppId(std::string fbAppId); #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) jobject getConfig(); diff --git a/dist/AdjustEvent2dx.cpp b/dist/AdjustEvent2dx.cpp index 30cea812..c319e00f 100755 --- a/dist/AdjustEvent2dx.cpp +++ b/dist/AdjustEvent2dx.cpp @@ -135,14 +135,6 @@ void AdjustEvent2dx::setCallbackId(std::string callbackId) { #endif } -#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) -void AdjustEvent2dx::setReceipt(std::string receipt, std::string transactionId) { - if (isEventSet) { - event.setReceipt(receipt, transactionId); - } -} -#endif - bool AdjustEvent2dx::isValid() { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) if (event == NULL) { @@ -166,11 +158,57 @@ bool AdjustEvent2dx::isValid() { #endif } +void AdjustEvent2dx::setProductId(std::string productId) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + if (isEventSet) { + event.setProductId(productId); + } +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + if (event == NULL) { + return; + } + cocos2d::JniMethodInfo jmiSetProductId; + if (!cocos2d::JniHelper::getMethodInfo(jmiSetProductId, "com/adjust/sdk/AdjustEvent", "setProductId", "(Ljava/lang/String;)V")) { + return; + } + + jstring jProductId = jmiSetProductId.env->NewStringUTF(productId.c_str()); + jmiSetProductId.env->CallVoidMethod(event, jmiSetProductId.methodID, jProductId); + jmiSetProductId.env->DeleteLocalRef(jProductId); +#endif +} + #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) +void AdjustEvent2dx::setPurchaseToken(std::string purchaseToken) { + if (event == NULL) { + return; + } + cocos2d::JniMethodInfo jmiSetPurchaseToken; + if (!cocos2d::JniHelper::getMethodInfo(jmiSetPurchaseToken, "com/adjust/sdk/AdjustEvent", "setPurchaseToken", "(Ljava/lang/String;)V")) { + return; + } + + jstring jPurchaseToken = jmiSetPurchaseToken.env->NewStringUTF(purchaseToken.c_str()); + jmiSetPurchaseToken.env->CallVoidMethod(event, jmiSetPurchaseToken.methodID, jPurchaseToken); + jmiSetPurchaseToken.env->DeleteLocalRef(jPurchaseToken); +} + jobject AdjustEvent2dx::getEvent() { return event; } #elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) +void AdjustEvent2dx::setReceipt(std::string receipt, std::string transactionId) { + if (isEventSet) { + event.setReceipt(receipt, transactionId); + } +} + +void AdjustEvent2dx::setReceipt(std::string receipt) { + if (isEventSet) { + event.setReceipt(receipt); + } +} + ADJEvent2dx AdjustEvent2dx::getEvent() { return event; } diff --git a/dist/AdjustEvent2dx.h b/dist/AdjustEvent2dx.h index bbf0eca0..b1608281 100755 --- a/dist/AdjustEvent2dx.h +++ b/dist/AdjustEvent2dx.h @@ -44,11 +44,14 @@ class AdjustEvent2dx { void setCallbackId(std::string callbackId); void addCallbackParameter(std::string key, std::string value); void addPartnerParameter(std::string key, std::string value); + void setProductId(std::string productId); #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) jobject getEvent(); + void setPurchaseToken(std::string purchaseToken); #elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) ADJEvent2dx getEvent(); void setReceipt(std::string receipt, std::string transactionId); + void setReceipt(std::string receipt); #endif }; diff --git a/dist/AdjustPlayStorePurchase2dx.cpp b/dist/AdjustPlayStorePurchase2dx.cpp new file mode 100755 index 00000000..557b934e --- /dev/null +++ b/dist/AdjustPlayStorePurchase2dx.cpp @@ -0,0 +1,37 @@ +// +// AdjustPlayStorePurchase2dx.cpp +// Adjust SDK +// +// Created by Uglješa Erceg (@uerceg) on 17th January 2024. +// Copyright © 2015-Present Adjust GmbH. All rights reserved. +// + +#include "AdjustPlayStorePurchase2dx.h" + +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) +#include +#include "platform/android/jni/JniHelper.h" +#endif + +void AdjustPlayStorePurchase2dx::initPurchase(std::string productId, std::string purchaseToken) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + cocos2d::JniMethodInfo jmiInit; + if (!cocos2d::JniHelper::getMethodInfo(jmiInit, "com/adjust/sdk/AdjustPurchase", "", "(Ljava/lang/String;Ljava/lang/String;)V")) { + return; + } + + jclass jclsAdjustPurchase = jmiInit.env->FindClass("com/adjust/sdk/AdjustPurchase"); + jmethodID jmidInit = jmiInit.env->GetMethodID(jclsAdjustPurchase, "", "(Ljava/lang/String;Ljava/lang/String;)V"); + jstring jProductId = jmiInit.env->NewStringUTF(productId.c_str()); + jstring jPurchaseToken = jmiInit.env->NewStringUTF(purchaseToken.c_str()); + purchase = jmiInit.env->NewObject(jclsAdjustPurchase, jmidInit, jProductId, jPurchaseToken); + jmiInit.env->DeleteLocalRef(jProductId); + jmiInit.env->DeleteLocalRef(jPurchaseToken); +#endif +} + +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) +jobject AdjustPlayStorePurchase2dx::getPurchase() { + return purchase; +} +#endif diff --git a/dist/AdjustPlayStorePurchase2dx.h b/dist/AdjustPlayStorePurchase2dx.h new file mode 100755 index 00000000..10ae10eb --- /dev/null +++ b/dist/AdjustPlayStorePurchase2dx.h @@ -0,0 +1,38 @@ +// +// AdjustPlayStorePurchase2dx.h +// Adjust SDK +// +// Created by Uglješa Erceg (@uerceg) on 17th January 2024. +// Copyright © 2015-Present Adjust GmbH. All rights reserved. +// + +#ifndef ADJUST_ADJUSTPLAYSTOREPURCHASE2DX_H_ +#define ADJUST_ADJUSTPLAYSTOREPURCHASE2DX_H_ + +#include "cocos2d.h" +#include + +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) +#include +#endif + +class AdjustPlayStorePurchase2dx { +private: +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + jobject purchase; +#endif + void initPurchase(std::string productId, std::string purchaseToken); + +public: + AdjustPlayStorePurchase2dx(std::string productId, std::string purchaseToken) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + initPurchase(productId, purchaseToken); +#endif + } + +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + jobject getPurchase(); +#endif +}; + +#endif /* ADJUST_ADJUSTPLAYSTOREPURCHASE2DX_H_ */ diff --git a/dist/AdjustProxy2dx.cpp b/dist/AdjustProxy2dx.cpp index 75497b29..ce4375c1 100755 --- a/dist/AdjustProxy2dx.cpp +++ b/dist/AdjustProxy2dx.cpp @@ -556,21 +556,6 @@ JNIEXPORT void JNICALL Java_com_adjust_sdk_Adjust2dxSessionTrackingSucceededCall sessionTrackingSucceededCallbackMethod(sessionSuccess); } -JNIEXPORT void JNICALL Java_com_adjust_sdk_Adjust2dxAdIdCallback_adIdRead -(JNIEnv *env, jobject obj, jstring jAdId) { - if (NULL == adIdCallbackMethod) { - return; - } - if (NULL == jAdId) { - return; - } - - const char *adIdCStr = env->GetStringUTFChars(jAdId, NULL); - std::string adId = std::string(adIdCStr); - adIdCallbackMethod(adId); - env->ReleaseStringUTFChars(jAdId, adIdCStr); -} - JNIEXPORT bool JNICALL Java_com_adjust_sdk_Adjust2dxDeferredDeeplinkCallback_deferredDeeplinkReceived (JNIEnv *env, jobject obj, jstring jDeeplink) { if (NULL == deferredDeeplinkCallbackMethod) { @@ -586,6 +571,51 @@ JNIEXPORT bool JNICALL Java_com_adjust_sdk_Adjust2dxDeferredDeeplinkCallback_def return deferredDeeplinkCallbackMethod(deeplink); } +JNIEXPORT void JNICALL Java_com_adjust_sdk_Adjust2dxAdIdCallback_adIdRead +(JNIEnv *env, jobject obj, jstring jAdId) { + if (NULL == adIdCallbackMethod) { + return; + } + if (NULL == jAdId) { + return; + } + + const char *adIdCStr = env->GetStringUTFChars(jAdId, NULL); + std::string adId = std::string(adIdCStr); + adIdCallbackMethod(adId); + env->ReleaseStringUTFChars(jAdId, adIdCStr); +} + +JNIEXPORT void JNICALL Java_com_adjust_sdk_Adjust2dxResolvedLinkCallback_resolvedLink +(JNIEnv *env, jobject obj, jstring jResolvedLink) { + if (NULL == resolvedLinkCallbackMethod) { + return; + } + if (NULL == jResolvedLink) { + return; + } + + const char *resolvedLinkCStr = env->GetStringUTFChars(jResolvedLink, NULL); + std::string resolvedLink = std::string(resolvedLinkCStr); + resolvedLinkCallbackMethod(resolvedLink); + env->ReleaseStringUTFChars(jResolvedLink, resolvedLinkCStr); +} + +JNIEXPORT void JNICALL Java_com_adjust_sdk_Adjust2dxPurchaseVerificationResultCallback_verificationResult +(JNIEnv *env, jobject obj, jstring jVerificationStatus, int jCode, jstring jMessage) { + if (NULL == purchaseVerificationResultCallbackMethod) { + return; + } + + const char *verificationStatusCStr = env->GetStringUTFChars(jVerificationStatus, NULL); + std::string verificationStatus = std::string(verificationStatusCStr); + const char *messageCStr = env->GetStringUTFChars(jMessage, NULL); + std::string message = std::string(messageCStr); + purchaseVerificationResultCallbackMethod(verificationStatus, jCode, message); + env->ReleaseStringUTFChars(jVerificationStatus, verificationStatusCStr); + env->ReleaseStringUTFChars(jMessage, messageCStr); +} + void setExecuteTestLibCommandCallbackMethod(void(*callbackMethod)(std::string className, std::string methodName, std::string jsonParameters)) { if (NULL == executeTestLibCommandCallbackMethod) { executeTestLibCommandCallbackMethod = callbackMethod; @@ -594,7 +624,7 @@ void setExecuteTestLibCommandCallbackMethod(void(*callbackMethod)(std::string cl void setAttributionCallbackMethod(void (*callbackMethod)(AdjustAttribution2dx attribution)) { if (NULL == attributionCallbackMethod) { - attributionCallbackMethod = callbackMethod; + attributionCallbackMethod = callbackMethod; } } @@ -629,8 +659,21 @@ void setDeferredDeeplinkCallbackMethod(bool (*callbackMethod)(std::string deepli } void setAdIdCallbackMethod(void (*callbackMethod)(std::string adId)) { - if (NULL == adIdCallbackMethod) { - adIdCallbackMethod = callbackMethod; - } + if (NULL == adIdCallbackMethod) { + adIdCallbackMethod = callbackMethod; + } +} + +void setResolvedLinkCallbackMethod(void (*callbackMethod)(std::string resolvedLink)) { + if (NULL == resolvedLinkCallbackMethod) { + resolvedLinkCallbackMethod = callbackMethod; + } } + +void setPurchaseVerificationResultCallbackMethod(void (*callbackMethod)(std::string verificationResult, int code, std::string message)) { + if (NULL == purchaseVerificationResultCallbackMethod) { + purchaseVerificationResultCallbackMethod = callbackMethod; + } +} + #endif diff --git a/dist/AdjustProxy2dx.h b/dist/AdjustProxy2dx.h index f9f10cc5..7d33d569 100755 --- a/dist/AdjustProxy2dx.h +++ b/dist/AdjustProxy2dx.h @@ -24,6 +24,8 @@ extern "C" { static void (*sessionTrackingSucceededCallbackMethod)(AdjustSessionSuccess2dx sessionSuccess); static bool (*deferredDeeplinkCallbackMethod)(std::string deeplink); static void (*adIdCallbackMethod)(std::string adId); + static void (*resolvedLinkCallbackMethod)(std::string resolvedLink); + static void (*purchaseVerificationResultCallbackMethod)(std::string verificationStatus, int code, std::string message); // Only for testing purposes. static void (*executeTestLibCommandCallbackMethod)(std::string className, std::string methodName, std::string jsonParameters); @@ -41,6 +43,10 @@ extern "C" { (JNIEnv *, jobject, jstring); JNIEXPORT void JNICALL Java_com_adjust_sdk_Adjust2dxAdIdCallback_adIdRead (JNIEnv *, jobject, jstring); + JNIEXPORT void JNICALL Java_com_adjust_sdk_Adjust2dxResolvedLinkCallback_resolvedLink + (JNIEnv *, jobject, jstring); + JNIEXPORT void JNICALL Java_com_adjust_sdk_Adjust2dxPurchaseVerificationResultCallback_verificationResult + (JNIEnv *, jobject, jstring, int, jstring); // Only for testing purposes. JNIEXPORT void JNICALL Java_com_adjust_test_Adjust2dxCommandJsonListenerCallback_executeCommand2dx (JNIEnv *, jobject, jstring, jstring, jstring); @@ -52,6 +58,8 @@ extern "C" { void setSessionTrackingSucceededCallbackMethod(void (*callbackMethod)(AdjustSessionSuccess2dx sessionSuccess)); void setDeferredDeeplinkCallbackMethod(bool (*callbackMethod)(std::string deeplink)); void setAdIdCallbackMethod(void (*callbackMethod)(std::string adId)); + void setResolvedLinkCallbackMethod(void (*callbackMethod)(std::string resolvedLink)); + void setPurchaseVerificationResultCallbackMethod(void (*callbackMethod)(std::string verificationStatus, int code, std::string message)); // Only for testing purposes. void setExecuteTestLibCommandCallbackMethod(void(*executeTestLibCommandCallbackMethod)(std::string className, std::string methodName, std::string jsonParameters)); } diff --git a/doc/migrate.md b/doc/migrate.md index 4bd1643e..267feea4 100644 --- a/doc/migrate.md +++ b/doc/migrate.md @@ -1,4 +1,4 @@ -## Migrate your Adjust SDK for Cocos2d-x to 4.32.0 from 4.0.x +## Migrate your Adjust SDK for Cocos2d-x to 4.37.0 from 4.0.x ### SDK initialization diff --git a/ext/android/proxy/adjust-android.jar b/ext/android/proxy/adjust-android.jar index c0b53add..d5ce84d1 100644 Binary files a/ext/android/proxy/adjust-android.jar and b/ext/android/proxy/adjust-android.jar differ diff --git a/ext/android/proxy/adjust-test-library.jar b/ext/android/proxy/adjust-test-library.jar index bce3a510..4273d941 100644 Binary files a/ext/android/proxy/adjust-test-library.jar and b/ext/android/proxy/adjust-test-library.jar differ diff --git a/ext/android/proxy/com/adjust/sdk/Adjust2dxPurchaseVerificationResultCallback.java b/ext/android/proxy/com/adjust/sdk/Adjust2dxPurchaseVerificationResultCallback.java new file mode 100644 index 00000000..2021f85e --- /dev/null +++ b/ext/android/proxy/com/adjust/sdk/Adjust2dxPurchaseVerificationResultCallback.java @@ -0,0 +1,12 @@ +package com.adjust.sdk; + +public class Adjust2dxPurchaseVerificationResultCallback implements OnPurchaseVerificationFinishedListener { + public native void verificationResult(String verificationResult, int code, String message); + + public Adjust2dxPurchaseVerificationResultCallback() {} + + @Override + public void onVerificationFinished(AdjustPurchaseVerificationResult result) { + verificationResult(result.getVerificationStatus(), result.getCode(), result.getMessage()); + } +} diff --git a/ext/android/proxy/com/adjust/sdk/Adjust2dxResolvedLinkCallback.java b/ext/android/proxy/com/adjust/sdk/Adjust2dxResolvedLinkCallback.java new file mode 100644 index 00000000..e2f1697d --- /dev/null +++ b/ext/android/proxy/com/adjust/sdk/Adjust2dxResolvedLinkCallback.java @@ -0,0 +1,12 @@ +package com.adjust.sdk; + +public class Adjust2dxResolvedLinkCallback implements OnDeeplinkResolvedListener { + public native void resolvedLink(String resolvedLink); + + public Adjust2dxResolvedLinkCallback() {} + + @Override + public void onDeeplinkResolved(String resolvedLink) { + resolvedLink(resolvedLink); + } +} diff --git a/ext/android/sdk b/ext/android/sdk index 00bac49f..6b58557f 160000 --- a/ext/android/sdk +++ b/ext/android/sdk @@ -1 +1 @@ -Subproject commit 00bac49f5e9dca43e74d7b6c6b1ef045a87daea9 +Subproject commit 6b58557f18d886a1392d0cc245a90d4bca880c6e diff --git a/ext/ios/sdk b/ext/ios/sdk index a7b50f18..f7a0ad4a 160000 --- a/ext/ios/sdk +++ b/ext/ios/sdk @@ -1 +1 @@ -Subproject commit a7b50f187855dfc0fb84114c22661216393387ae +Subproject commit f7a0ad4a9f99fcbfc4c73dcad557ea3c86c5aaf6 diff --git a/libs/android/adjust-android.jar b/libs/android/adjust-android.jar index c0b53add..d5ce84d1 100644 Binary files a/libs/android/adjust-android.jar and b/libs/android/adjust-android.jar differ diff --git a/libs/ios/AdjustSdk.framework/Modules/module.modulemap b/libs/ios/AdjustSdk.framework/Modules/module.modulemap index a2b63156..4483b1a6 100644 --- a/libs/ios/AdjustSdk.framework/Modules/module.modulemap +++ b/libs/ios/AdjustSdk.framework/Modules/module.modulemap @@ -1,5 +1,5 @@ framework module AdjustSdk { - umbrella header "AdjustSdk.h" + umbrella header "Adjust.h" export * module * { export * } diff --git a/libs/ios/AdjustSdk.framework/Versions/A/AdjustSdk b/libs/ios/AdjustSdk.framework/Versions/A/AdjustSdk index 36f78181..580babe8 100644 Binary files a/libs/ios/AdjustSdk.framework/Versions/A/AdjustSdk and b/libs/ios/AdjustSdk.framework/Versions/A/AdjustSdk differ diff --git a/libs/ios/AdjustSdk.framework/Versions/A/Headers/ADJConfig.h b/libs/ios/AdjustSdk.framework/Versions/A/Headers/ADJConfig.h index 7a04903d..e9b916e8 100644 --- a/libs/ios/AdjustSdk.framework/Versions/A/Headers/ADJConfig.h +++ b/libs/ios/AdjustSdk.framework/Versions/A/Headers/ADJConfig.h @@ -77,12 +77,25 @@ - (BOOL)adjustDeeplinkResponse:(nullable NSURL *)deeplink; /** - * @brief Optional delegate method that gets called when Adjust SDK sets conversion value for the user. + * @brief Optional SKAdNetwork pre 4.0 style delegate method that gets called when Adjust SDK sets conversion value for the user. * * @param conversionValue Conversion value used by Adjust SDK to invoke updateConversionValue: API. */ - (void)adjustConversionValueUpdated:(nullable NSNumber *)conversionValue; +/** + * @brief Optional SKAdNetwork 4.0 style delegate method that gets called when Adjust SDK sets conversion value for the user. + * You can use this callback even with using pre 4.0 SKAdNetwork. + * In that case you can expect coarseValue and lockWindow values to be nil. + * + * @param fineValue Conversion value set by Adjust SDK. + * @param coarseValue Coarse value set by Adjust SDK. + * @param lockWindow Lock window set by Adjust SDK. + */ +- (void)adjustConversionValueUpdated:(nullable NSNumber *)fineValue + coarseValue:(nullable NSString *)coarseValue + lockWindow:(nullable NSNumber *)lockWindow; + @end /** @@ -153,7 +166,7 @@ /** * @brief Enables/disables reading of iAd framework data needed for ASA tracking. */ -@property (nonatomic, assign) BOOL allowiAdInfoReading; +@property (nonatomic, assign) BOOL allowiAdInfoReading DEPRECATED_MSG_ATTRIBUTE("Apple Search Ads attribution with usage of iAd.framework has been sunset by Apple as of February 7th 2023"); /** * @brief Enables/disables reading of AdServices framework data needed for attribution. @@ -170,6 +183,11 @@ */ @property (nonatomic, assign) double delayStart; +/** + * @brief Define how many seconds to wait for ATT status before sending the first data. + */ +@property (nonatomic, assign) NSUInteger attConsentWaitingInterval; + /** * @brief User agent for the requests. */ @@ -273,4 +291,9 @@ */ @property (nonatomic, assign) BOOL coppaCompliantEnabled; +/** + * @brief Enables caching of device ids to read it only once + */ +@property (nonatomic, assign) BOOL readDeviceInfoOnceEnabled; + @end diff --git a/libs/ios/AdjustSdk.framework/Versions/A/Headers/ADJEvent.h b/libs/ios/AdjustSdk.framework/Versions/A/Headers/ADJEvent.h index a2363c22..a95e7d48 100644 --- a/libs/ios/AdjustSdk.framework/Versions/A/Headers/ADJEvent.h +++ b/libs/ios/AdjustSdk.framework/Versions/A/Headers/ADJEvent.h @@ -58,6 +58,11 @@ */ @property (nonatomic, assign, readonly) BOOL emptyReceipt; +/** + * @brief IAP product ID. + */ +@property (nonatomic, copy, readonly, nonnull) NSString *productId; + /** * @brief Create Event object with event token. * @@ -119,6 +124,20 @@ */ - (void)setCallbackId:(nonnull NSString *)callbackId; +/** + * @brief Set the product ID of a In-App Purchases to perform IAP verification. + * + * @param productId The product ID of the purchased item. + */ +- (void)setProductId:(NSString * _Nonnull)productId; + +/** + * @brief Set the receipt of a In-App Purchases to perform IAP verification. + * + * @param receipt The receipt obtained after successful IAP. + */ +- (void)setReceipt:(NSData * _Nonnull)receipt; + /** * @brief Check if created adjust event object is valid. * diff --git a/libs/ios/AdjustSdk.framework/Versions/A/Headers/ADJPurchase.h b/libs/ios/AdjustSdk.framework/Versions/A/Headers/ADJPurchase.h new file mode 100644 index 00000000..f1b54c95 --- /dev/null +++ b/libs/ios/AdjustSdk.framework/Versions/A/Headers/ADJPurchase.h @@ -0,0 +1,27 @@ +// +// ADJPurchase.h +// Adjust +// +// Created by Uglješa Erceg (@uerceg) on May 25th 2023. +// Copyright © 2023 Adjust. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface ADJPurchase : NSObject + +@property (nonatomic, copy, readonly, nonnull) NSString *transactionId; + +@property (nonatomic, copy, readonly, nonnull) NSData *receipt; + +@property (nonatomic, copy, readonly, nonnull) NSString *productId; + +- (nullable id)initWithTransactionId:(nonnull NSString *)transactionId + productId:(nonnull NSString *)productId + andReceipt:(nonnull NSData *)receipt; + +@end + +NS_ASSUME_NONNULL_END diff --git a/libs/ios/AdjustSdk.framework/Versions/A/Headers/ADJPurchaseVerificationResult.h b/libs/ios/AdjustSdk.framework/Versions/A/Headers/ADJPurchaseVerificationResult.h new file mode 100644 index 00000000..3e8f4040 --- /dev/null +++ b/libs/ios/AdjustSdk.framework/Versions/A/Headers/ADJPurchaseVerificationResult.h @@ -0,0 +1,38 @@ +// +// ADJPurchaseVerificationResult.h +// Adjust +// +// Created by Uglješa Erceg (@uerceg) on May 25th 2023. +// Copyright © 2023 Adjust. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface ADJPurchaseVerificationResult : NSObject + +/** + * @property message + * + * @brief Text message about current state of receipt verification. + */ +@property (nonatomic, copy) NSString *message; + +/** + * @property code + * + * @brief Response code returned from Adjust backend server. + */ +@property (nonatomic, assign) int code; + +/** + * @property verificationStatus + * + * @brief State of verification (success / failure / unknown / not verified) + */ +@property (nonatomic, copy) NSString *verificationStatus; + +@end + +NS_ASSUME_NONNULL_END diff --git a/libs/ios/AdjustSdk.framework/Versions/A/Headers/Adjust.h b/libs/ios/AdjustSdk.framework/Versions/A/Headers/Adjust.h index 64a5a12e..1bc08856 100644 --- a/libs/ios/AdjustSdk.framework/Versions/A/Headers/Adjust.h +++ b/libs/ios/AdjustSdk.framework/Versions/A/Headers/Adjust.h @@ -2,7 +2,7 @@ // Adjust.h // Adjust SDK // -// V4.32.1 +// V4.37.0 // Created by Christian Wellenbrock (@wellle) on 23rd July 2013. // Copyright (c) 2012-2021 Adjust GmbH. All rights reserved. // @@ -14,12 +14,17 @@ #import "ADJThirdPartySharing.h" #import "ADJAdRevenue.h" #import "ADJLinkResolution.h" +#import "ADJPurchase.h" +#import "ADJPurchaseVerificationResult.h" + +typedef void(^AdjustResolvedDeeplinkBlock)(NSString * _Nonnull resolvedLink); @interface AdjustTestOptions : NSObject @property (nonatomic, copy, nullable) NSString *baseUrl; @property (nonatomic, copy, nullable) NSString *gdprUrl; @property (nonatomic, copy, nullable) NSString *subscriptionUrl; +@property (nonatomic, copy, nullable) NSString *purchaseVerificationUrl; @property (nonatomic, copy, nullable) NSString *extraPath; @property (nonatomic, copy, nullable) NSNumber *timerIntervalInMilliseconds; @property (nonatomic, copy, nullable) NSNumber *timerStartInMilliseconds; @@ -28,7 +33,6 @@ @property (nonatomic, assign) BOOL teardown; @property (nonatomic, assign) BOOL deleteState; @property (nonatomic, assign) BOOL noBackoffWait; -@property (nonatomic, assign) BOOL iAdFrameworkEnabled; @property (nonatomic, assign) BOOL adServicesFrameworkEnabled; @property (nonatomic, assign) BOOL enableSigning; @property (nonatomic, assign) BOOL disableSigning; @@ -52,12 +56,16 @@ extern NSString * __nonnull const ADJAdRevenueSourceAdMost; extern NSString * __nonnull const ADJAdRevenueSourceUnity; extern NSString * __nonnull const ADJAdRevenueSourceHeliumChartboost; extern NSString * __nonnull const ADJAdRevenueSourcePublisher; +extern NSString * __nonnull const ADJAdRevenueSourceTopOn; +extern NSString * __nonnull const ADJAdRevenueSourceADX; /** * Constants for country app's URL strategies. */ extern NSString * __nonnull const ADJUrlStrategyIndia; extern NSString * __nonnull const ADJUrlStrategyChina; +extern NSString * __nonnull const ADJUrlStrategyCn; +extern NSString * __nonnull const ADJUrlStrategyCnOnly; extern NSString * __nonnull const ADJDataResidencyEU; extern NSString * __nonnull const ADJDataResidencyTR; extern NSString * __nonnull const ADJDataResidencyUS; @@ -131,6 +139,15 @@ extern NSString * __nonnull const ADJDataResidencyUS; */ + (void)appWillOpenUrl:(nonnull NSURL *)url; +/** + * @brief Process the deep link that has opened an app and potentially get a resolved link. + * + * @param deeplink URL object which contains info about adjust deep link. + * @param completionHandler Completion handler where either resolved or echoed deep link will be sent. + */ ++ (void)processDeeplink:(nonnull NSURL *)deeplink + completionHandler:(void (^_Nonnull)(NSString * _Nonnull resolvedLink))completionHandler; + /** * @brief Set the device token used by push notifications. * @@ -161,6 +178,14 @@ extern NSString * __nonnull const ADJDataResidencyUS; */ + (nullable NSString *)idfa; +/** + * @brief Retrieve iOS device IDFV value. + * + * @return Device IDFV value. + */ ++ (nullable NSString *)idfv; + + /** * @brief Get current adjust identifier for the user. * @@ -313,12 +338,45 @@ extern NSString * __nonnull const ADJDataResidencyUS; + (int)appTrackingAuthorizationStatus; /** - * @brief Adjust wrapper for updateConversionValue: method. + * @brief Adjust wrapper for SKAdNetwork's updateConversionValue: method. * * @param conversionValue Conversion value you would like SDK to set for given user. */ + (void)updateConversionValue:(NSInteger)conversionValue; +/** + * @brief Adjust wrapper for SKAdNetwork's updatePostbackConversionValue:completionHandler: method. + * + * @param conversionValue Conversion value you would like SDK to set for given user. + * @param completion Completion handler you can provide to catch and handle any errors. + */ ++ (void)updatePostbackConversionValue:(NSInteger)conversionValue + completionHandler:(void (^_Nullable)(NSError *_Nullable error))completion; + +/** + * @brief Adjust wrapper for SKAdNetwork's updatePostbackConversionValue:coarseValue:completionHandler: method. + * + * @param fineValue Conversion value you would like SDK to set for given user. + * @param coarseValue One of the possible SKAdNetworkCoarseConversionValue values. + * @param completion Completion handler you can provide to catch and handle any errors. + */ ++ (void)updatePostbackConversionValue:(NSInteger)fineValue + coarseValue:(nonnull NSString *)coarseValue + completionHandler:(void (^_Nullable)(NSError *_Nullable error))completion; + +/** + * @brief Adjust wrapper for SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method. + * + * @param fineValue Conversion value you would like SDK to set for given user. + * @param coarseValue One of the possible SKAdNetworkCoarseConversionValue values. + * @param lockWindow A Boolean value that indicates whether to send the postback before the conversion window ends. + * @param completion Completion handler you can provide to catch and handle any errors. + */ ++ (void)updatePostbackConversionValue:(NSInteger)fineValue + coarseValue:(nonnull NSString *)coarseValue + lockWindow:(BOOL)lockWindow + completionHandler:(void (^_Nullable)(NSError *_Nullable error))completion; + /** * @brief Instruct to Adjust SDK to check current state of att_status. */ @@ -331,6 +389,15 @@ extern NSString * __nonnull const ADJDataResidencyUS; */ + (nullable NSURL *)lastDeeplink; +/** + * @brief Verify in-app-purchase. + * + * @param purchase Purchase object. + * @param completionHandler Callback where verification result will be repoted. + */ ++ (void)verifyPurchase:(nonnull ADJPurchase *)purchase + completionHandler:(void (^_Nonnull)(ADJPurchaseVerificationResult * _Nonnull verificationResult))completionHandler; + /** * @brief Method used for internal testing only. Don't use it in production. */ @@ -351,6 +418,9 @@ extern NSString * __nonnull const ADJDataResidencyUS; - (void)appWillOpenUrl:(nonnull NSURL *)url; +- (void)processDeeplink:(nonnull NSURL *)deeplink + completionHandler:(void (^_Nonnull)(NSString * _Nonnull resolvedLink))completionHandler; + - (void)setOfflineMode:(BOOL)enabled; - (void)setDeviceToken:(nonnull NSData *)deviceToken; @@ -399,6 +469,18 @@ extern NSString * __nonnull const ADJDataResidencyUS; - (void)updateConversionValue:(NSInteger)conversionValue; +- (void)updatePostbackConversionValue:(NSInteger)conversionValue + completionHandler:(void (^_Nullable)(NSError *_Nullable error))completion; + +- (void)updatePostbackConversionValue:(NSInteger)fineValue + coarseValue:(nonnull NSString *)coarseValue + completionHandler:(void (^_Nullable)(NSError *_Nullable error))completion; + +- (void)updatePostbackConversionValue:(NSInteger)fineValue + coarseValue:(nonnull NSString *)coarseValue + lockWindow:(BOOL)lockWindow + completionHandler:(void (^_Nullable)(NSError *_Nullable error))completion; + - (void)trackThirdPartySharing:(nonnull ADJThirdPartySharing *)thirdPartySharing; - (void)trackMeasurementConsent:(BOOL)enabled; @@ -409,4 +491,7 @@ extern NSString * __nonnull const ADJDataResidencyUS; - (nullable NSURL *)lastDeeplink; +- (void)verifyPurchase:(nonnull ADJPurchase *)purchase + completionHandler:(void (^_Nonnull)(ADJPurchaseVerificationResult * _Nonnull verificationResult))completionHandler; + @end diff --git a/libs/ios/AdjustSdk.framework/Versions/A/Headers/AdjustSdk.h b/libs/ios/AdjustSdk.framework/Versions/A/Headers/AdjustSdk.h deleted file mode 100644 index c046f2c7..00000000 --- a/libs/ios/AdjustSdk.framework/Versions/A/Headers/AdjustSdk.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// AdjustSdkStatic.h -// AdjustSdkStatic -// -// Created by Genady Buchatsky on 12.03.22. -// Copyright © 2022 Adjust GmbH. All rights reserved. -// - -#import - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import diff --git a/src/ADJAdjust2dx.h b/src/ADJAdjust2dx.h index f61af0ad..dd5ed106 100755 --- a/src/ADJAdjust2dx.h +++ b/src/ADJAdjust2dx.h @@ -16,6 +16,7 @@ #include "ADJAppStoreSubscription2dx.h" #include "ADJThirdPartySharing2dx.h" #include "ADJAdRevenue2dx.h" +#include "ADJAppStorePurchase2dx.h" #include "AdjustAttribution2dx.h" extern const std::string ADJEnvironmentSandbox2dx; @@ -53,8 +54,14 @@ class ADJAdjust2dx { static void trackThirdPartySharing(ADJThirdPartySharing2dx thirdPartySharing); static void trackMeasurementConsent(bool measurementConsent); static void updateConversionValue(int conversionValue); + static void updatePostbackConversionValue(int conversionValue, void (*errorCallback)(std::string error)); + static void updatePostbackConversionValue(int conversionValue, std::string coarseValue, void (*errorCallback)(std::string error)); + static void updatePostbackConversionValue(int conversionValue, std::string coarseValue, bool lockWindow, void (*errorCallback)(std::string error)); static void checkForNewAttStatus(); static std::string getLastDeeplink(); + static void verifyAppStorePurchase(ADJAppStorePurchase2dx purchase, void (*verificationCallback)(std::string verificationStatus, int code, std::string message)); + static std::string getIdfv(); + static void processDeeplink(std::string url, void (*resolvedLinkCallback)(std::string resolvedLink)); // For testing purposes only. static void setTestOptions(std::map testOptionsMap); static void teardown(); diff --git a/src/ADJAdjust2dx.mm b/src/ADJAdjust2dx.mm index 85deb35b..accd0021 100755 --- a/src/ADJAdjust2dx.mm +++ b/src/ADJAdjust2dx.mm @@ -21,28 +21,33 @@ BOOL isSessionFailureCallbackImplemented = NULL != adjustConfig.getSessionFailureCallback() ? YES : NO; BOOL isDeferredDeeplinkCallbackImplemented = NULL != adjustConfig.getDeferredDeeplinkCallback() ? YES : NO; BOOL isConversionValueUpdatedListenerImplemented = NULL != adjustConfig.getConversionValueUpdatedCallback() ? YES : NO; - + BOOL isPostbackConversionValueUpdatedCallbackImplemented = NULL != adjustConfig.getPostbackConversionValueUpdatedCallback() ? YES : NO; + if (isAttributionCallbackImplemented || isEventSuccessCallbackImplemented || isEventFailureCallbackImplemented || isSessionSuccessCallbackImplemented || isSessionFailureCallbackImplemented || isDeferredDeeplinkCallbackImplemented - || isConversionValueUpdatedListenerImplemented) { - ((ADJConfig *)adjustConfig.getConfig()).delegate = [ADJDelegate2dx getInstanceWithSwizzleOfAttributionCallback:isAttributionCallbackImplemented - swizzleOfEventSuccessCallback:isEventSuccessCallbackImplemented - swizzleOfEventFailureCallback:isEventFailureCallbackImplemented - swizzleOfSessionSuccessCallback:isSessionSuccessCallbackImplemented - swizzleOfSessionFailureCallback:isSessionFailureCallbackImplemented - swizzleOfDeferredDeeplinkCallback:isDeferredDeeplinkCallbackImplemented - swizzleOfConversionValueUpdatedCallback:isConversionValueUpdatedListenerImplemented - andAttributionCallbackId:adjustConfig.getAttributionCallback() - eventSuccessCallbackId:adjustConfig.getEventSuccessCallback() - eventFailureCallbackId:adjustConfig.getEventFailureCallback() - sessionSuccessCallbackId:adjustConfig.getSessionSuccessCallback() - sessionFailureCallbackId:adjustConfig.getSessionFailureCallback() - deferredDeeplinkCallbackId:adjustConfig.getDeferredDeeplinkCallback() - conversionValueUpdatedCallbackId:adjustConfig.getConversionValueUpdatedCallback()]; + || isConversionValueUpdatedListenerImplemented + || isPostbackConversionValueUpdatedCallbackImplemented) { + ((ADJConfig *)adjustConfig.getConfig()).delegate = + [ADJDelegate2dx getInstanceWithSwizzleOfAttributionCallback:isAttributionCallbackImplemented + swizzleOfEventSuccessCallback:isEventSuccessCallbackImplemented + swizzleOfEventFailureCallback:isEventFailureCallbackImplemented + swizzleOfSessionSuccessCallback:isSessionSuccessCallbackImplemented + swizzleOfSessionFailureCallback:isSessionFailureCallbackImplemented + swizzleOfDeferredDeeplinkCallback:isDeferredDeeplinkCallbackImplemented + swizzleOfConversionValueUpdatedCallback:isConversionValueUpdatedListenerImplemented + swizzleOfPostbackConversionValueUpdatedCallback:isPostbackConversionValueUpdatedCallbackImplemented + andAttributionCallbackId:adjustConfig.getAttributionCallback() + eventSuccessCallbackId:adjustConfig.getEventSuccessCallback() + eventFailureCallbackId:adjustConfig.getEventFailureCallback() + sessionSuccessCallbackId:adjustConfig.getSessionSuccessCallback() + sessionFailureCallbackId:adjustConfig.getSessionFailureCallback() + deferredDeeplinkCallbackId:adjustConfig.getDeferredDeeplinkCallback() + conversionValueUpdatedCallbackId:adjustConfig.getConversionValueUpdatedCallback() + postbackConversionValueUpdatedCallbackId:adjustConfig.getPostbackConversionValueUpdatedCallback()]; } [Adjust appDidLaunch:(ADJConfig *)adjustConfig.getConfig()]; @@ -56,6 +61,16 @@ [Adjust trackSubscription:(ADJSubscription *)subscription.getSubscription()]; } +void ADJAdjust2dx::verifyAppStorePurchase(ADJAppStorePurchase2dx purchase, void (*verificationCallback)(std::string verificationStatus, int code, std::string message)) { + [Adjust verifyPurchase:(ADJPurchase *)purchase.getPurchase() completionHandler:^(ADJPurchaseVerificationResult * _Nonnull verificationResult) { + if (verificationCallback != NULL) { + verificationCallback(std::string([verificationResult.verificationStatus UTF8String]), + verificationResult.code, + std::string([verificationResult.message UTF8String])); + } + }]; +} + void ADJAdjust2dx::trackSubsessionStart() { [Adjust trackSubsessionStart]; } @@ -132,12 +147,13 @@ } std::string ADJAdjust2dx::getIdfa() { - if (nil == [Adjust idfa]) { + NSString *idfa = [Adjust idfa]; + if (nil == idfa) { return ""; } - std::string idfa = std::string([[Adjust idfa] UTF8String]); - return idfa; + std::string strIdfa = std::string([idfa UTF8String]); + return strIdfa; } std::string ADJAdjust2dx::getAdid() { @@ -227,7 +243,9 @@ void ADJAdjust2dx::requestTrackingAuthorizationWithCompletionHandler(void (*trackingStatusCallback)(int status)) { [Adjust requestTrackingAuthorizationWithCompletionHandler:^(NSUInteger status) { - trackingStatusCallback((int)status); + if (trackingStatusCallback != NULL) { + trackingStatusCallback((int)status); + } }]; } @@ -239,6 +257,35 @@ [Adjust updateConversionValue:conversionValue]; } +void ADJAdjust2dx::updatePostbackConversionValue(int conversionValue, void (*errorCallback)(std::string error)) { + [Adjust updatePostbackConversionValue:conversionValue completionHandler:^(NSError * _Nullable error) { + if (errorCallback != NULL) { + errorCallback(std::string([error.localizedDescription UTF8String])); + } + }]; +} + +void ADJAdjust2dx::updatePostbackConversionValue(int conversionValue, std::string coarseValue, void (*errorCallback)(std::string error)) { + [Adjust updatePostbackConversionValue:conversionValue + coarseValue:[NSString stringWithUTF8String:coarseValue.c_str()] + completionHandler:^(NSError * _Nullable error) { + if (errorCallback != NULL) { + errorCallback(std::string([error.localizedDescription UTF8String])); + } + }]; +} + +void ADJAdjust2dx::updatePostbackConversionValue(int conversionValue, std::string coarseValue, bool lockWindow, void (*errorCallback)(std::string error)) { + [Adjust updatePostbackConversionValue:conversionValue + coarseValue:[NSString stringWithUTF8String:coarseValue.c_str()] + lockWindow:lockWindow + completionHandler:^(NSError * _Nullable error) { + if (errorCallback != NULL) { + errorCallback(std::string([error.localizedDescription UTF8String])); + } + }]; +} + void ADJAdjust2dx::trackThirdPartySharing(ADJThirdPartySharing2dx thirdPartySharing) { [Adjust trackThirdPartySharing:(ADJThirdPartySharing *)thirdPartySharing.getThirdPartySharing()]; } @@ -265,11 +312,35 @@ return stdStrLastDeeplink; } +std::string ADJAdjust2dx::getIdfv() { + NSString *idfv = [Adjust idfv]; + if (nil == idfv) { + return ""; + } + + std::string strIdfv = std::string([idfv UTF8String]); + return strIdfv; +} + +void ADJAdjust2dx::processDeeplink(std::string url, void (*resolvedLinkCallback)(std::string resolvedLink)) { + NSURL *pUrl = [NSURL URLWithString:[NSString stringWithUTF8String:url.c_str()]]; + [Adjust processDeeplink:pUrl completionHandler:^(NSString * _Nonnull resolvedLink) { + if (resolvedLinkCallback != NULL) { + if (resolvedLink != nil) { + resolvedLinkCallback(std::string([resolvedLink UTF8String])); + } else { + resolvedLinkCallback(""); + } + } + }]; +} + void ADJAdjust2dx::setTestOptions(std::map testOptionsMap) { AdjustTestOptions *testOptions = [[AdjustTestOptions alloc] init]; testOptions.baseUrl = [NSString stringWithUTF8String:testOptionsMap["baseUrl"].c_str()]; testOptions.gdprUrl = [NSString stringWithUTF8String:testOptionsMap["gdprUrl"].c_str()]; testOptions.subscriptionUrl = [NSString stringWithUTF8String:testOptionsMap["subscriptionUrl"].c_str()]; + testOptions.purchaseVerificationUrl = [NSString stringWithUTF8String:testOptionsMap["purchaseVerificationUrl"].c_str()]; if (testOptionsMap.find("extraPath") != testOptionsMap.end()) { testOptions.extraPath = [NSString stringWithUTF8String:testOptionsMap["extraPath"].c_str()]; @@ -311,13 +382,6 @@ testOptions.noBackoffWait = YES; } } - testOptions.iAdFrameworkEnabled = NO; - if (testOptionsMap.find("iAdFrameworkEnabled") != testOptionsMap.end()) { - NSString *iAdFrameworkEnabled = [NSString stringWithUTF8String:testOptionsMap["iAdFrameworkEnabled"].c_str()]; - if ([iAdFrameworkEnabled isEqualToString:@"true"]) { - testOptions.iAdFrameworkEnabled = YES; - } - } testOptions.adServicesFrameworkEnabled = NO; if (testOptionsMap.find("adServicesFrameworkEnabled") != testOptionsMap.end()) { NSString *adServicesFrameworkEnabled = [NSString stringWithUTF8String:testOptionsMap["adServicesFrameworkEnabled"].c_str()]; diff --git a/src/ADJAppStorePurchase2dx.h b/src/ADJAppStorePurchase2dx.h new file mode 100755 index 00000000..9ac50edb --- /dev/null +++ b/src/ADJAppStorePurchase2dx.h @@ -0,0 +1,28 @@ +// +// ADJAppStorePurchase2dx.h +// Adjust SDK +// +// Created by Uglješa Erceg (@uerceg) on 17th January 2024. +// Copyright © 2015-Present Adjust GmbH. All rights reserved. +// + +#ifndef _ADJUST_ADJAPPSTOREPURCHASE2DX_H_ +#define _ADJUST_ADJAPPSTOREPURCHASE2DX_H_ + +#include + +class ADJAppStorePurchase2dx { +private: + void* purchase; + void initPurchase(std::string productId, std::string transactionId, std::string receipt); + +public: + ADJAppStorePurchase2dx() {} + ADJAppStorePurchase2dx(std::string productId, std::string transactionId, std::string receipt) { + initPurchase(productId, transactionId, receipt); + } + + void* getPurchase(); +}; + +#endif /* _ADJUST_ADJAPPSTOREPURCHASE2DX_H_ */ diff --git a/src/ADJAppStorePurchase2dx.mm b/src/ADJAppStorePurchase2dx.mm new file mode 100755 index 00000000..b5b66216 --- /dev/null +++ b/src/ADJAppStorePurchase2dx.mm @@ -0,0 +1,23 @@ +// +// ADJAppStorePurchase2dx.mm +// Adjust SDK +// +// Created by Uglješa Erceg (@uerceg) on 17th January 2024. +// Copyright © 2015-Present Adjust GmbH. All rights reserved. +// + +#include "ADJAppStorePurchase2dx.h" +#include + +void ADJAppStorePurchase2dx::initPurchase(std::string productId, std::string transactionId, std::string receipt) { + NSString *strProductId = [NSString stringWithUTF8String:productId.c_str()]; + NSString *strTransactionId = [NSString stringWithUTF8String:transactionId.c_str()]; + NSString *strReceipt = [NSString stringWithUTF8String:receipt.c_str()]; + purchase = [[ADJPurchase alloc] initWithTransactionId:strTransactionId + productId:strProductId + andReceipt:[strReceipt dataUsingEncoding:NSUTF8StringEncoding]]; +} + +void* ADJAppStorePurchase2dx::getPurchase() { + return purchase; +} diff --git a/src/ADJConfig2dx.h b/src/ADJConfig2dx.h index bec20897..676854fc 100755 --- a/src/ADJConfig2dx.h +++ b/src/ADJConfig2dx.h @@ -36,6 +36,7 @@ class ADJConfig2dx { void (*sessionFailureCallback)(AdjustSessionFailure2dx sessionFailure) = NULL; bool (*deferredDeeplinkCallback)(std::string deeplink) = NULL; void (*conversionValueUpdatedCallback)(int conversionValue) = NULL; + void (*postbackConversionValueUpdatedCallback)(int conversionValue, std::string coarseValue, bool lockWindow) = NULL; void initConfig(std::string appToken, std::string environment, bool allowSuppressLogLevel, std::string sdkPrefix); public: @@ -64,6 +65,7 @@ class ADJConfig2dx { void deactivateSkAdNetworkHandling(); void setCoppaCompliantEnabled(bool isEnabled); void setLinkMeEnabled(bool isEnabled); + void setAttConsentWaitingInterval(int numberOfSeconds); void setAttributionCallback(void(*callbackMethod)(AdjustAttribution2dx attribution)); void setEventSuccessCallback(void(*callbackMethod)(AdjustEventSuccess2dx eventSuccess)); void setEventFailureCallback(void(*callbackMethod)(AdjustEventFailure2dx eventFailure)); @@ -71,6 +73,8 @@ class ADJConfig2dx { void setSessionFailureCallback(void(*callbackMethod)(AdjustSessionFailure2dx sessionFailure)); void setDeferredDeeplinkCallback(bool(*callbackMethod)(std::string deeplink)); void setConversionValueUpdatedCallback(void(*callbackMethod)(int conversionValue)); + void setPostbackConversionValueUpdatedCallback(void(*callbackMethod)(int conversionValue, std::string coarseValue, bool lockWindow)); + void setReadDeviceInfoOnceEnabled(bool isEnabled); void* getConfig(); void(*getAttributionCallback())(AdjustAttribution2dx); void(*getEventSuccessCallback())(AdjustEventSuccess2dx); @@ -79,6 +83,7 @@ class ADJConfig2dx { void(*getSessionFailureCallback())(AdjustSessionFailure2dx); bool(*getDeferredDeeplinkCallback())(std::string); void(*getConversionValueUpdatedCallback())(int); + void(*getPostbackConversionValueUpdatedCallback())(int, std::string, bool); }; #endif /* _ADJUST_ADJCONFIG2DX_H_ */ diff --git a/src/ADJConfig2dx.mm b/src/ADJConfig2dx.mm index c0cc3845..318d9a95 100755 --- a/src/ADJConfig2dx.mm +++ b/src/ADJConfig2dx.mm @@ -38,7 +38,8 @@ } void ADJConfig2dx::setAllowiAdInfoReading(bool isAllowed) { - ((ADJConfig *)config).allowiAdInfoReading = isAllowed; + // deprecated + // ((ADJConfig *)config).allowiAdInfoReading = isAllowed; } void ADJConfig2dx::setAllowAdServicesInfoReading(bool isAllowed) { @@ -67,6 +68,10 @@ ((ADJConfig *)config).urlStrategy = ADJUrlStrategyChina; } else if ([strUrlStrategy isEqualToString:@"india"]) { ((ADJConfig *)config).urlStrategy = ADJUrlStrategyIndia; + } else if ([strUrlStrategy isEqualToString:@"cn"]) { + ((ADJConfig *)config).urlStrategy = ADJUrlStrategyCn; + } else if ([strUrlStrategy isEqualToString:@"cn-only"]) { + ((ADJConfig *)config).urlStrategy = ADJUrlStrategyCnOnly; } else if ([strUrlStrategy isEqualToString:@"data-residency-eu"]) { ((ADJConfig *)config).urlStrategy = ADJDataResidencyEU; } else if ([strUrlStrategy isEqualToString:@"data-residency-tr"]) { @@ -88,6 +93,10 @@ ((ADJConfig *)config).linkMeEnabled = isEnabled; } +void ADJConfig2dx::setAttConsentWaitingInterval(int numberOfSeconds) { + ((ADJConfig *)config).attConsentWaitingInterval = numberOfSeconds; +} + void ADJConfig2dx::setAttributionCallback(void (*callbackMethod)(AdjustAttribution2dx attribution)) { attributionCallback = callbackMethod; } @@ -116,6 +125,10 @@ conversionValueUpdatedCallback = callbackMethod; } +void ADJConfig2dx::setPostbackConversionValueUpdatedCallback(void(*callbackMethod)(int conversionValue, std::string coarseValue, bool lockWindow)) { + postbackConversionValueUpdatedCallback = callbackMethod; +} + void* ADJConfig2dx::getConfig() { return config; } @@ -128,6 +141,10 @@ [((ADJConfig *)config) setIsDeviceKnown:isDeviceKnown]; } +void ADJConfig2dx::setReadDeviceInfoOnceEnabled(bool isEnabled) { + ((ADJConfig *)config).readDeviceInfoOnceEnabled = isEnabled; +} + void(*ADJConfig2dx::getAttributionCallback())(AdjustAttribution2dx) { return attributionCallback; } @@ -155,3 +172,7 @@ void(*ADJConfig2dx::getConversionValueUpdatedCallback())(int) { return conversionValueUpdatedCallback; } + +void(*ADJConfig2dx::getPostbackConversionValueUpdatedCallback())(int, std::string, bool) { + return postbackConversionValueUpdatedCallback; +} diff --git a/src/ADJDelegate2dx.h b/src/ADJDelegate2dx.h index 3f931108..5f781a9b 100644 --- a/src/ADJDelegate2dx.h +++ b/src/ADJDelegate2dx.h @@ -17,6 +17,7 @@ @property (nonatomic) void (*sessionFailureCallbackMethod)(AdjustSessionFailure2dx sessionFailure); @property (nonatomic) bool (*deferredDeeplinkCallbackMethod)(std::string deeplink); @property (nonatomic) void (*conversionValueUpdatedCallbackMethod)(int conversionValue); +@property (nonatomic) void (*postbackConversionValueUpdatedCallbackMethod)(int conversionValue, std::string coarseValue, bool lockWindow); + (id)getInstanceWithSwizzleOfAttributionCallback:(BOOL)swizzleAttributionCallback swizzleOfEventSuccessCallback:(BOOL)swizzleEventSuccessCallback @@ -25,13 +26,15 @@ swizzleOfSessionFailureCallback:(BOOL)swizzleSessionFailureCallback swizzleOfDeferredDeeplinkCallback:(BOOL)swizzleDeferredDeeplinkCallback swizzleOfConversionValueUpdatedCallback:(BOOL)swizzleConversionValueUpdatedCallback - andAttributionCallbackId:(void (*)(AdjustAttribution2dx attribution))attributionCallbackId + swizzleOfPostbackConversionValueUpdatedCallback:(BOOL)swizzlePostbackConversionValueUpdatedCallback + andAttributionCallbackId:(void (*)(AdjustAttribution2dx attribution))attributionCallbackId eventSuccessCallbackId:(void (*)(AdjustEventSuccess2dx eventSuccess))eventSuccessCallbackId eventFailureCallbackId:(void (*)(AdjustEventFailure2dx eventFailure))eventFailureCallbackId sessionSuccessCallbackId:(void (*)(AdjustSessionSuccess2dx sessionSuccess))sessionSuccessCallbackId sessionFailureCallbackId:(void (*)(AdjustSessionFailure2dx sessionFailure))sessionFailureCallbackId - deferredDeeplinkCallbackId:(bool (*)(std::string deeplink))deferredDeeplinkCallbackId - conversionValueUpdatedCallbackId:(void (*)(int conversionValue))conversionValueUpdatedCallbackId; + deferredDeeplinkCallbackId:(bool (*)(std::string deeplink))deferredDeeplinkCallbackId + conversionValueUpdatedCallbackId:(void (*)(int conversionValue))conversionValueUpdatedCallbackId + postbackConversionValueUpdatedCallbackId:(void (*)(int conversionValue, std::string coarseValue, bool lockWindow))postbackConversionValueUpdatedCallbackId; + (void)teardown; @end diff --git a/src/ADJDelegate2dx.mm b/src/ADJDelegate2dx.mm index 4dbee598..85f80a23 100644 --- a/src/ADJDelegate2dx.mm +++ b/src/ADJDelegate2dx.mm @@ -22,13 +22,15 @@ + (id)getInstanceWithSwizzleOfAttributionCallback:(BOOL)swizzleAttributionCallba swizzleOfSessionFailureCallback:(BOOL)swizzleSessionFailureCallback swizzleOfDeferredDeeplinkCallback:(BOOL)swizzleDeferredDeeplinkCallback swizzleOfConversionValueUpdatedCallback:(BOOL)swizzleConversionValueUpdatedCallback + swizzleOfPostbackConversionValueUpdatedCallback:(BOOL)swizzlePostbackConversionValueUpdatedCallback andAttributionCallbackId:(void (*)(AdjustAttribution2dx attribution))attributionCallbackId eventSuccessCallbackId:(void (*)(AdjustEventSuccess2dx eventSuccess))eventSuccessCallbackId eventFailureCallbackId:(void (*)(AdjustEventFailure2dx eventFailure))eventFailureCallbackId sessionSuccessCallbackId:(void (*)(AdjustSessionSuccess2dx sessionSuccess))sessionSuccessCallbackId sessionFailureCallbackId:(void (*)(AdjustSessionFailure2dx sessionFailure))sessionFailureCallbackId deferredDeeplinkCallbackId:(bool (*)(std::string deeplink))deferredDeeplinkCallbackId - conversionValueUpdatedCallbackId:(void (*)(int conversionValue))conversionValueUpdatedCallbackId { + conversionValueUpdatedCallbackId:(void (*)(int conversionValue))conversionValueUpdatedCallbackId + postbackConversionValueUpdatedCallbackId:(void (*)(int conversionValue, std::string coarseValue, bool lockWindow))postbackConversionValueUpdatedCallbackId { dispatch_once(&onceToken, ^{ defaultInstance = [[ADJDelegate2dx alloc] init]; @@ -61,7 +63,11 @@ + (id)getInstanceWithSwizzleOfAttributionCallback:(BOOL)swizzleAttributionCallba [defaultInstance swizzleCallbackMethod:@selector(adjustConversionValueUpdated:) swizzledSelector:@selector(adjustConversionValueUpdatedWannabe:)]; } - + if (swizzlePostbackConversionValueUpdatedCallback) { + [defaultInstance swizzleCallbackMethod:@selector(adjustConversionValueUpdated:coarseValue:lockWindow:) + swizzledSelector:@selector(adjustConversionValueUpdatedWannabe:coarseValue:lockWindow:)]; + } + [defaultInstance setAttributionCallbackMethod:attributionCallbackId]; [defaultInstance setEventSuccessCallbackMethod:eventSuccessCallbackId]; [defaultInstance setEventFailureCallbackMethod:eventFailureCallbackId]; @@ -69,6 +75,7 @@ + (id)getInstanceWithSwizzleOfAttributionCallback:(BOOL)swizzleAttributionCallba [defaultInstance setSessionFailureCallbackMethod:sessionFailureCallbackId]; [defaultInstance setDeferredDeeplinkCallbackMethod:deferredDeeplinkCallbackId]; [defaultInstance setConversionValueUpdatedCallbackMethod:conversionValueUpdatedCallbackId]; + [defaultInstance setPostbackConversionValueUpdatedCallbackMethod:postbackConversionValueUpdatedCallbackId]; }); return defaultInstance; @@ -266,6 +273,17 @@ - (void)adjustConversionValueUpdatedWannabe:(NSNumber *)conversionValue { _conversionValueUpdatedCallbackMethod([conversionValue intValue]); } +- (void)adjustConversionValueUpdatedWannabe:(NSNumber *)fineValue + coarseValue:(NSString *)coarseValue + lockWindow:(NSNumber *)lockWindow { + if (fineValue == nil || coarseValue == nil || lockWindow == nil) { + return; + } + _postbackConversionValueUpdatedCallbackMethod([fineValue intValue], + std::string([coarseValue UTF8String]), + [lockWindow boolValue]); +} + - (void)swizzleCallbackMethod:(SEL)originalSelector swizzledSelector:(SEL)swizzledSelector { Class cls = [self class]; diff --git a/src/ADJEvent2dx.h b/src/ADJEvent2dx.h index 707124c6..dfef757b 100755 --- a/src/ADJEvent2dx.h +++ b/src/ADJEvent2dx.h @@ -28,6 +28,8 @@ class ADJEvent2dx { void setTransactionId(std::string transactionId); void setCallbackId(std::string callbackId); void setReceipt(std::string receipt, std::string transactionId); + void setProductId(std::string productId); + void setReceipt(std::string receipt); bool isValid(); void* getEvent(); }; diff --git a/src/ADJEvent2dx.mm b/src/ADJEvent2dx.mm index 818e83d4..cf666a58 100755 --- a/src/ADJEvent2dx.mm +++ b/src/ADJEvent2dx.mm @@ -43,6 +43,14 @@ transactionId:[NSString stringWithUTF8String:transactionId.c_str()]]; } +void ADJEvent2dx::setProductId(std::string productId) { + [((ADJEvent *)event) setProductId:[NSString stringWithUTF8String:productId.c_str()]]; +} + +void ADJEvent2dx::setReceipt(std::string receipt) { + [((ADJEvent *)event) setReceipt:[[NSString stringWithUTF8String:receipt.c_str()] dataUsingEncoding:NSUTF8StringEncoding]]; +} + bool ADJEvent2dx::isValid() { return [((ADJEvent *)event) isValid]; } diff --git a/src/Adjust2dx.cpp b/src/Adjust2dx.cpp index e8e44cbd..b26c1b90 100755 --- a/src/Adjust2dx.cpp +++ b/src/Adjust2dx.cpp @@ -55,6 +55,12 @@ void Adjust2dx::trackAppStoreSubscription(AdjustAppStoreSubscription2dx subscrip #endif } +void Adjust2dx::verifyAppStorePurchase(AdjustAppStorePurchase2dx purchase, void (*verificationCallback)(std::string verificationStatus, int code, std::string message)) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + ADJAdjust2dx::verifyAppStorePurchase(purchase.getPurchase(), verificationCallback); +#endif +} + void Adjust2dx::trackPlayStoreSubscription(AdjustPlayStoreSubscription2dx subscription) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) cocos2d::JniMethodInfo jmiTrackPlayStoreSubscription; @@ -65,6 +71,21 @@ void Adjust2dx::trackPlayStoreSubscription(AdjustPlayStoreSubscription2dx subscr #endif } +void Adjust2dx::verifyPlayStorePurchase(AdjustPlayStorePurchase2dx purchase, void (*verificationCallback)(std::string verificationStatus, int code, std::string message)) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + setPurchaseVerificationResultCallbackMethod(verificationCallback); + cocos2d::JniMethodInfo jmiVerifyPlayStorePurchase; + if (!cocos2d::JniHelper::getStaticMethodInfo(jmiVerifyPlayStorePurchase, "com/adjust/sdk/Adjust", "verifyPurchase", "(Lcom/adjust/sdk/AdjustPurchase;Lcom/adjust/sdk/OnPurchaseVerificationFinishedListener;)V")) { + return; + } + jclass clsAdjust2dxPurchaseVerificationResultCallback = jmiVerifyPlayStorePurchase.env->FindClass("com/adjust/sdk/Adjust2dxPurchaseVerificationResultCallback"); + jmethodID jmidInit = jmiVerifyPlayStorePurchase.env->GetMethodID(clsAdjust2dxPurchaseVerificationResultCallback, "", "()V"); + jobject jCallbackProxy = jmiVerifyPlayStorePurchase.env->NewObject(clsAdjust2dxPurchaseVerificationResultCallback, jmidInit); + jmiVerifyPlayStorePurchase.env->CallStaticVoidMethod(jmiVerifyPlayStorePurchase.classID, jmiVerifyPlayStorePurchase.methodID, purchase.getPurchase(), jCallbackProxy); + jmiVerifyPlayStorePurchase.env->DeleteLocalRef(jCallbackProxy); +#endif +} + void Adjust2dx::setEnabled(bool isEnabled) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) cocos2d::JniMethodInfo jmiSetEnabled; @@ -577,6 +598,36 @@ void Adjust2dx::trackAdRevenueNew(AdjustAdRevenue2dx adRevenue) { #endif } +void Adjust2dx::processDeeplink(std::string url, void (*resolvedLinkCallback)(std::string resolvedLink)) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + ADJAdjust2dx::processDeeplink(url, resolvedLinkCallback); +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + setResolvedLinkCallbackMethod(resolvedLinkCallback); + cocos2d::JniMethodInfo jmiProcessDeeplink; + if (!cocos2d::JniHelper::getStaticMethodInfo(jmiProcessDeeplink, "com/adjust/sdk/Adjust", "processDeeplink", "(Landroid/net/Uri;Landroid/content/Context;Lcom/adjust/sdk/OnDeeplinkResolvedListener;)V")) { + return; + } + cocos2d::JniMethodInfo jmiGetContext; + if (!cocos2d::JniHelper::getStaticMethodInfo(jmiGetContext, "org/cocos2dx/lib/Cocos2dxActivity", "getContext", "()Landroid/content/Context;")) { + return; + } + + jclass jcUri = jmiProcessDeeplink.env->FindClass("android/net/Uri"); + jmethodID midParse = jmiProcessDeeplink.env->GetStaticMethodID(jcUri, "parse", "(Ljava/lang/String;)Landroid/net/Uri;"); + jstring jUrl = jmiProcessDeeplink.env->NewStringUTF(url.c_str()); + jobject jUri = jmiProcessDeeplink.env->CallStaticObjectMethod(jcUri, midParse, jUrl); + jobject jContext = (jobject)jmiGetContext.env->CallStaticObjectMethod(jmiGetContext.classID, jmiGetContext.methodID); + jclass clsAdjust2dxResolvedLinkCallback = jmiProcessDeeplink.env->FindClass("com/adjust/sdk/Adjust2dxResolvedLinkCallback"); + jmethodID jmidInit = jmiProcessDeeplink.env->GetMethodID(clsAdjust2dxResolvedLinkCallback, "", "()V"); + jobject jCallbackProxy = jmiProcessDeeplink.env->NewObject(clsAdjust2dxResolvedLinkCallback, jmidInit); + jmiProcessDeeplink.env->CallStaticVoidMethod(jmiProcessDeeplink.classID, jmiProcessDeeplink.methodID, jUri, jContext, jCallbackProxy); + jmiProcessDeeplink.env->DeleteLocalRef(jUrl); + jmiProcessDeeplink.env->DeleteLocalRef(jUri); + jmiGetContext.env->DeleteLocalRef(jContext); + jmiProcessDeeplink.env->DeleteLocalRef(jCallbackProxy); +#endif +} + void Adjust2dx::setReferrer(std::string referrer) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) cocos2d::JniMethodInfo jmiSetReferrer; @@ -702,6 +753,24 @@ void Adjust2dx::updateConversionValue(int conversionValue) { #endif } +void Adjust2dx::updatePostbackConversionValue(int conversionValue, void (*errorCallback)(std::string error)) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + ADJAdjust2dx::updatePostbackConversionValue(conversionValue, errorCallback); +#endif +} + +void Adjust2dx::updatePostbackConversionValue(int conversionValue, std::string coarseValue, void (*errorCallback)(std::string error)) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + ADJAdjust2dx::updatePostbackConversionValue(conversionValue, coarseValue, errorCallback); +#endif +} + +void Adjust2dx::updatePostbackConversionValue(int conversionValue, std::string coarseValue, bool lockWindow, void (*errorCallback)(std::string error)) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + ADJAdjust2dx::updatePostbackConversionValue(conversionValue, coarseValue, lockWindow, errorCallback); +#endif +} + void Adjust2dx::checkForNewAttStatus() { #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) return ADJAdjust2dx::checkForNewAttStatus(); @@ -716,6 +785,14 @@ std::string Adjust2dx::getLastDeeplink() { #endif } +std::string Adjust2dx::getIdfv() { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + return ADJAdjust2dx::getIdfv(); +#else + return ""; +#endif +} + #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) jobject getTestOptions(std::map testOptions) { cocos2d::JniMethodInfo jmiInit; @@ -770,6 +847,11 @@ jobject getTestOptions(std::map testOptions) { jfieldID jfidSubscriptionUrl = jmiInit.env->GetFieldID(jclsTestOptions, "subscriptionUrl", "Ljava/lang/String;"); jmiInit.env->SetObjectField(jTestOptions, jfidSubscriptionUrl, jsSubscriptionUrl); + // Purchase verification URL. + jstring jsPurchaseVerificationUrl = jmiInit.env->NewStringUTF(testOptions["purchaseVerificationUrl"].c_str()); + jfieldID jfidPurchaseVerificationUrl = jmiInit.env->GetFieldID(jclsTestOptions, "purchaseVerificationUrl", "Ljava/lang/String;"); + jmiInit.env->SetObjectField(jTestOptions, jfidPurchaseVerificationUrl, jsPurchaseVerificationUrl); + // Base path. if (testOptions.find("basePath") != testOptions.end()) { jstring jsBasePath = jmiInit.env->NewStringUTF(testOptions["basePath"].c_str()); @@ -784,13 +866,20 @@ jobject getTestOptions(std::map testOptions) { jmiInit.env->SetObjectField(jTestOptions, jfidGdprPath, jsGdprPath); } - // GDPR path. + // Subscription path. if (testOptions.find("subscriptionPath") != testOptions.end()) { jstring jsSubscriptionPath = jmiInit.env->NewStringUTF(testOptions["subscriptionPath"].c_str()); jfieldID jfidSubscriptionPath = jmiInit.env->GetFieldID(jclsTestOptions, "subscriptionPath", "Ljava/lang/String;"); jmiInit.env->SetObjectField(jTestOptions, jfidSubscriptionPath, jsSubscriptionPath); } + // Purchase verification path. + if (testOptions.find("purchaseVerificationPath") != testOptions.end()) { + jstring jsPurchaseVerificationPath = jmiInit.env->NewStringUTF(testOptions["purchaseVerificationPath"].c_str()); + jfieldID jfidPurchaseVerificationPath = jmiInit.env->GetFieldID(jclsTestOptions, "purchaseVerificationPath", "Ljava/lang/String;"); + jmiInit.env->SetObjectField(jTestOptions, jfidPurchaseVerificationPath, jsPurchaseVerificationPath); + } + // Use test connection options. if (testOptions.find("useTestConnectionOptions") != testOptions.end()) { jboolean jUseTestConnectionOptions = testOptions["useTestConnectionOptions"] == "true" ? JNI_TRUE : JNI_FALSE; diff --git a/src/Adjust2dx.h b/src/Adjust2dx.h index 6307e65f..50d75453 100755 --- a/src/Adjust2dx.h +++ b/src/Adjust2dx.h @@ -18,6 +18,8 @@ #include "AdjustPlayStoreSubscription2dx.h" #include "AdjustThirdPartySharing2dx.h" #include "AdjustAdRevenue2dx.h" +#include "AdjustPlayStorePurchase2dx.h" +#include "AdjustAppStorePurchase2dx.h" extern const std::string AdjustEnvironmentSandbox2dx; extern const std::string AdjustEnvironmentProduction2dx; @@ -47,6 +49,7 @@ class Adjust2dx { static std::string getSdkVersion(); static AdjustAttribution2dx getAttribution(); static void trackAdRevenueNew(AdjustAdRevenue2dx adRevenue); + static void processDeeplink(std::string url, void (*resolvedLinkCallback)(std::string resolvedLink)); // Android specific methods. static void setReferrer(std::string referrer); static void getGoogleAdId(void (*adIdCallback)(std::string adId)); @@ -54,14 +57,20 @@ class Adjust2dx { static void onResume(); static void onPause(); static void trackPlayStoreSubscription(AdjustPlayStoreSubscription2dx subscription); + static void verifyPlayStorePurchase(AdjustPlayStorePurchase2dx purchase, void (*verificationCallback)(std::string verificationStatus, int code, std::string message)); // iOS specific methods. static std::string getIdfa(); static void trackAppStoreSubscription(AdjustAppStoreSubscription2dx subscription); static void requestTrackingAuthorizationWithCompletionHandler(void (*trackingStatusCallback)(int status)); static int getAppTrackingAuthorizationStatus(); static void updateConversionValue(int conversionValue); + static void updatePostbackConversionValue(int conversionValue, void (*errorCallback)(std::string error)); + static void updatePostbackConversionValue(int conversionValue, std::string coarseValue, void (*errorCallback)(std::string error)); + static void updatePostbackConversionValue(int conversionValue, std::string coarseValue, bool lockWindow, void (*errorCallback)(std::string error)); static void checkForNewAttStatus(); static std::string getLastDeeplink(); + static void verifyAppStorePurchase(AdjustAppStorePurchase2dx purchase, void (*verificationCallback)(std::string verificationStatus, int code, std::string message)); + static std::string getIdfv(); // For testing purposes only. static void setTestOptions(std::map testOptions); #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) diff --git a/src/AdjustAppStorePurchase2dx.cpp b/src/AdjustAppStorePurchase2dx.cpp new file mode 100755 index 00000000..ac20291c --- /dev/null +++ b/src/AdjustAppStorePurchase2dx.cpp @@ -0,0 +1,28 @@ +// +// AdjustAppStorePurchase2dx.cpp +// Adjust SDK +// +// Created by Uglješa Erceg (@uerceg) on 17th January 2024. +// Copyright © 2015-Present Adjust GmbH. All rights reserved. +// + +#include "AdjustAppStorePurchase2dx.h" + +void AdjustAppStorePurchase2dx::initPurchase( + std::string productId, + std::string transactionId, + std::string receipt +) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + purchase = ADJAppStorePurchase2dx(productId, transactionId, receipt); + isPurchaseSet = true; +#endif +} + +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) +ADJAppStorePurchase2dx AdjustAppStorePurchase2dx::getPurchase() { + return purchase; +} +#endif diff --git a/src/AdjustAppStorePurchase2dx.h b/src/AdjustAppStorePurchase2dx.h new file mode 100755 index 00000000..a8efefa6 --- /dev/null +++ b/src/AdjustAppStorePurchase2dx.h @@ -0,0 +1,44 @@ +// +// AdjustAppStorePurchase2dx.h +// Adjust SDK +// +// Created by Uglješa Erceg (@uerceg) on 17th January 2024. +// Copyright © 2015-Present Adjust GmbH. All rights reserved. +// + +#ifndef ADJUST_ADJUSTAPPSTOREPURCHASE2DX_H_ +#define ADJUST_ADJUSTAPPSTOREPURCHASE2DX_H_ + +#include "cocos2d.h" +#include + +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) +#include "ADJAppStorePurchase2dx.h" +#endif + +class AdjustAppStorePurchase2dx { +private: +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + bool isPurchaseSet; + ADJAppStorePurchase2dx purchase; +#endif + void initPurchase(std::string productId, std::string transactionId, std::string receipt); + +public: + AdjustAppStorePurchase2dx(std::string productId, std::string transactionId, std::string receipt) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + isPurchaseSet = false; + initPurchase(productId, transactionId, receipt); +#endif + } + +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + ADJAppStorePurchase2dx getPurchase(); +#endif +}; + +#endif /* ADJUST_ADJUSTAPPSTOREPURCHASE2DX_H_ */ diff --git a/src/AdjustConfig2dx.cpp b/src/AdjustConfig2dx.cpp index 39fa4fc7..6974a9e2 100755 --- a/src/AdjustConfig2dx.cpp +++ b/src/AdjustConfig2dx.cpp @@ -12,9 +12,11 @@ #include "AdjustProxy2dx.h" #endif -const std::string AdjustSdkPrefix2dx = "cocos2d-x4.32.0"; +const std::string AdjustSdkPrefix2dx = "cocos2d-x4.37.0"; const std::string AdjustUrlStrategyChina = "china"; const std::string AdjustUrlStrategyIndia = "india"; +const std::string AdjustUrlStrategyCn = "cn"; +const std::string AdjustUrlStrategyCnOnly = "cn-only"; const std::string AdjustDataResidencyEU = "data-residency-eu"; const std::string AdjustDataResidencyTR = "data-residency-tr"; const std::string AdjustDataResidencyUS = "data-residency-us"; @@ -26,6 +28,8 @@ const std::string AdjustAdRevenueSourceAdMostSource = "admost_sdk"; const std::string AdjustAdRevenueSourceUnity = "unity_sdk"; const std::string AdjustAdRevenueSourceHeliumChartboost = "helium_chartboost_sdk"; const std::string AdjustAdRevenueSourcePublisher = "publisher_sdk"; +const std::string AdjustAdRevenueSourceTopOn = "topon_sdk"; +const std::string AdjustAdRevenueSourceAdx = "adx_sdk"; void AdjustConfig2dx::initConfig(std::string appToken, std::string environment, bool allowSuppressLogLevel) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) @@ -303,6 +307,18 @@ void AdjustConfig2dx::setUrlStrategy(std::string urlStrategy) { jstring jUrlStrategyIndia = (jstring)jmiSetUrlStrategy.env->GetStaticObjectField(jclsAdjustConfig, jfidUrlStrategyIndia); jmiSetUrlStrategy.env->CallVoidMethod(config, jmiSetUrlStrategy.methodID, jUrlStrategyIndia); jmiSetUrlStrategy.env->DeleteLocalRef(jUrlStrategyIndia); + } else if (urlStrategy.compare(AdjustUrlStrategyCn) == 0) { + jclass jclsAdjustConfig = jmiSetUrlStrategy.env->FindClass("com/adjust/sdk/AdjustConfig"); + jfieldID jfidUrlStrategyCn = jmiSetUrlStrategy.env->GetStaticFieldID(jclsAdjustConfig, "URL_STRATEGY_CN", "Ljava/lang/String;"); + jstring jUrlStrategyCn = (jstring)jmiSetUrlStrategy.env->GetStaticObjectField(jclsAdjustConfig, jfidUrlStrategyCn); + jmiSetUrlStrategy.env->CallVoidMethod(config, jmiSetUrlStrategy.methodID, jUrlStrategyCn); + jmiSetUrlStrategy.env->DeleteLocalRef(jUrlStrategyCn); + } else if (urlStrategy.compare(AdjustUrlStrategyCnOnly) == 0) { + jclass jclsAdjustConfig = jmiSetUrlStrategy.env->FindClass("com/adjust/sdk/AdjustConfig"); + jfieldID jfidUrlStrategyCnOnly = jmiSetUrlStrategy.env->GetStaticFieldID(jclsAdjustConfig, "URL_STRATEGY_CN_ONLY", "Ljava/lang/String;"); + jstring jUrlStrategyCnOnly = (jstring)jmiSetUrlStrategy.env->GetStaticObjectField(jclsAdjustConfig, jfidUrlStrategyCnOnly); + jmiSetUrlStrategy.env->CallVoidMethod(config, jmiSetUrlStrategy.methodID, jUrlStrategyCnOnly); + jmiSetUrlStrategy.env->DeleteLocalRef(jUrlStrategyCnOnly); } else if (urlStrategy.compare(AdjustDataResidencyEU) == 0) { jclass jclsAdjustConfig = jmiSetUrlStrategy.env->FindClass("com/adjust/sdk/AdjustConfig"); jfieldID jfidDataResidencyEU = jmiSetUrlStrategy.env->GetStaticFieldID(jclsAdjustConfig, "DATA_RESIDENCY_EU", "Ljava/lang/String;"); @@ -615,6 +631,15 @@ void AdjustConfig2dx::setConversionValueUpdatedCallback(void(*conversionValueUpd #endif } +void AdjustConfig2dx::setPostbackConversionValueUpdatedCallback(void(*postbackConversionValueUpdatedCallback)(int conversionValue, std::string coarseValue, bool lockWindow)) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + if (isConfigSet) { + config.setPostbackConversionValueUpdatedCallback(postbackConversionValueUpdatedCallback); + } +#endif +} + void AdjustConfig2dx::setCoppaCompliantEnabled(bool isEnabled) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) if (config == NULL) { @@ -632,6 +657,23 @@ void AdjustConfig2dx::setCoppaCompliantEnabled(bool isEnabled) { #endif } +void AdjustConfig2dx::setReadDeviceInfoOnceEnabled(bool isEnabled) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + if (config == NULL) { + return; + } + cocos2d::JniMethodInfo jmiSetReadDeviceInfoOnceEnabled; + if (!cocos2d::JniHelper::getMethodInfo(jmiSetReadDeviceInfoOnceEnabled, "com/adjust/sdk/AdjustConfig", "setReadDeviceInfoOnceEnabled", "(Z)V")) { + return; + } + jmiSetReadDeviceInfoOnceEnabled.env->CallVoidMethod(config, jmiSetReadDeviceInfoOnceEnabled.methodID, isEnabled); +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + if (isConfigSet) { + config.setReadDeviceInfoOnceEnabled(isEnabled); + } +#endif +} + void AdjustConfig2dx::setPlayStoreKidsAppEnabled(bool isEnabled) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) if (config == NULL) { @@ -646,6 +688,37 @@ void AdjustConfig2dx::setPlayStoreKidsAppEnabled(bool isEnabled) { #endif } +void AdjustConfig2dx::setFinalAttributionEnabled(bool isEnabled) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + if (config == NULL) { + return; + } + cocos2d::JniMethodInfo jmiSetFinalAttributionEnabled; + if (!cocos2d::JniHelper::getMethodInfo(jmiSetFinalAttributionEnabled, "com/adjust/sdk/AdjustConfig", "setFinalAttributionEnabled", "(Z)V")) { + return; + } + jmiSetFinalAttributionEnabled.env->CallVoidMethod(config, jmiSetFinalAttributionEnabled.methodID, isEnabled); +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) +#endif +} + +void AdjustConfig2dx::setFbAppId(std::string fbAppId) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + if (config == NULL) { + return; + } + cocos2d::JniMethodInfo jmiSetFbAppId; + if (!cocos2d::JniHelper::getMethodInfo(jmiSetFbAppId, "com/adjust/sdk/AdjustConfig", "setFbAppId", "(Ljava/lang/String;)V")) { + return; + } + + jstring jFbAppId = jmiSetFbAppId.env->NewStringUTF(fbAppId.c_str()); + jmiSetFbAppId.env->CallVoidMethod(config, jmiSetFbAppId.methodID, jFbAppId); + jmiSetFbAppId.env->DeleteLocalRef(jFbAppId); +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) +#endif +} + void AdjustConfig2dx::setLinkMeEnabled(bool isEnabled) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) #elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) @@ -655,6 +728,15 @@ void AdjustConfig2dx::setLinkMeEnabled(bool isEnabled) { #endif } +void AdjustConfig2dx::setAttConsentWaitingInterval(int numberOfSeconds) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + if (isConfigSet) { + config.setAttConsentWaitingInterval(numberOfSeconds); + } +#endif +} + #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) jobject AdjustConfig2dx::getConfig() { return config; diff --git a/src/AdjustConfig2dx.h b/src/AdjustConfig2dx.h index f9c3ee5c..aafbbaff 100755 --- a/src/AdjustConfig2dx.h +++ b/src/AdjustConfig2dx.h @@ -26,6 +26,8 @@ extern const std::string AdjustSdkPrefix2dx; extern const std::string AdjustUrlStrategyChina; extern const std::string AdjustUrlStrategyIndia; +extern const std::string AdjustUrlStrategyCn; +extern const std::string AdjustUrlStrategyCnOnly; extern const std::string AdjustDataResidencyEU; extern const std::string AdjustDataResidencyTR; extern const std::string AdjustDataResidencyUS; @@ -37,6 +39,8 @@ extern const std::string AdjustAdRevenueSourceAdMostSource; extern const std::string AdjustAdRevenueSourceUnity; extern const std::string AdjustAdRevenueSourceHeliumChartboost; extern const std::string AdjustAdRevenueSourcePublisher; +extern const std::string AdjustAdRevenueSourceTopOn; +extern const std::string AdjustAdRevenueSourceAdx; enum AdjustLogLevel2dx { AdjustLogLevel2dxVerbose = 1, @@ -98,18 +102,23 @@ class AdjustConfig2dx { void setSessionFailureCallback(void(*sessionFailureCallback)(AdjustSessionFailure2dx sessionFailure)); void setDeferredDeeplinkCallback(bool(*deferredDeeplinkCallback)(std::string deeplink)); void setCoppaCompliantEnabled(bool isEnabled); + void setReadDeviceInfoOnceEnabled(bool isEnabled); // iOS only void deactivateSkAdNetworkHandling(); void setAllowIdfaReading(bool isAllowed); void setAllowiAdInfoReading(bool isAllowed); void setAllowAdServicesInfoReading(bool isAllowed); void setConversionValueUpdatedCallback(void(*conversionValueUpdatedCallback)(int conversionValue)); + void setPostbackConversionValueUpdatedCallback(void(*postbackConversionValueUpdatedCallback)(int conversionValue, std::string coarseValue, bool lockWindow)); void setLinkMeEnabled(bool isEnabled); + void setAttConsentWaitingInterval(int numberOfSeconds); // Android only void setReadMobileEquipmentIdentity(bool readMobileEquipmentIdentity); void setPreinstallTrackingEnabled(bool isEnabled); void setPreinstallFilePath(std::string filePath); void setPlayStoreKidsAppEnabled(bool isEnabled); + void setFinalAttributionEnabled(bool isEnabled); + void setFbAppId(std::string fbAppId); #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) jobject getConfig(); diff --git a/src/AdjustEvent2dx.cpp b/src/AdjustEvent2dx.cpp index 30cea812..c319e00f 100755 --- a/src/AdjustEvent2dx.cpp +++ b/src/AdjustEvent2dx.cpp @@ -135,14 +135,6 @@ void AdjustEvent2dx::setCallbackId(std::string callbackId) { #endif } -#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) -void AdjustEvent2dx::setReceipt(std::string receipt, std::string transactionId) { - if (isEventSet) { - event.setReceipt(receipt, transactionId); - } -} -#endif - bool AdjustEvent2dx::isValid() { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) if (event == NULL) { @@ -166,11 +158,57 @@ bool AdjustEvent2dx::isValid() { #endif } +void AdjustEvent2dx::setProductId(std::string productId) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + if (isEventSet) { + event.setProductId(productId); + } +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + if (event == NULL) { + return; + } + cocos2d::JniMethodInfo jmiSetProductId; + if (!cocos2d::JniHelper::getMethodInfo(jmiSetProductId, "com/adjust/sdk/AdjustEvent", "setProductId", "(Ljava/lang/String;)V")) { + return; + } + + jstring jProductId = jmiSetProductId.env->NewStringUTF(productId.c_str()); + jmiSetProductId.env->CallVoidMethod(event, jmiSetProductId.methodID, jProductId); + jmiSetProductId.env->DeleteLocalRef(jProductId); +#endif +} + #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) +void AdjustEvent2dx::setPurchaseToken(std::string purchaseToken) { + if (event == NULL) { + return; + } + cocos2d::JniMethodInfo jmiSetPurchaseToken; + if (!cocos2d::JniHelper::getMethodInfo(jmiSetPurchaseToken, "com/adjust/sdk/AdjustEvent", "setPurchaseToken", "(Ljava/lang/String;)V")) { + return; + } + + jstring jPurchaseToken = jmiSetPurchaseToken.env->NewStringUTF(purchaseToken.c_str()); + jmiSetPurchaseToken.env->CallVoidMethod(event, jmiSetPurchaseToken.methodID, jPurchaseToken); + jmiSetPurchaseToken.env->DeleteLocalRef(jPurchaseToken); +} + jobject AdjustEvent2dx::getEvent() { return event; } #elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) +void AdjustEvent2dx::setReceipt(std::string receipt, std::string transactionId) { + if (isEventSet) { + event.setReceipt(receipt, transactionId); + } +} + +void AdjustEvent2dx::setReceipt(std::string receipt) { + if (isEventSet) { + event.setReceipt(receipt); + } +} + ADJEvent2dx AdjustEvent2dx::getEvent() { return event; } diff --git a/src/AdjustEvent2dx.h b/src/AdjustEvent2dx.h index bbf0eca0..b1608281 100755 --- a/src/AdjustEvent2dx.h +++ b/src/AdjustEvent2dx.h @@ -44,11 +44,14 @@ class AdjustEvent2dx { void setCallbackId(std::string callbackId); void addCallbackParameter(std::string key, std::string value); void addPartnerParameter(std::string key, std::string value); + void setProductId(std::string productId); #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) jobject getEvent(); + void setPurchaseToken(std::string purchaseToken); #elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) ADJEvent2dx getEvent(); void setReceipt(std::string receipt, std::string transactionId); + void setReceipt(std::string receipt); #endif }; diff --git a/src/AdjustPlayStorePurchase2dx.cpp b/src/AdjustPlayStorePurchase2dx.cpp new file mode 100755 index 00000000..557b934e --- /dev/null +++ b/src/AdjustPlayStorePurchase2dx.cpp @@ -0,0 +1,37 @@ +// +// AdjustPlayStorePurchase2dx.cpp +// Adjust SDK +// +// Created by Uglješa Erceg (@uerceg) on 17th January 2024. +// Copyright © 2015-Present Adjust GmbH. All rights reserved. +// + +#include "AdjustPlayStorePurchase2dx.h" + +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) +#include +#include "platform/android/jni/JniHelper.h" +#endif + +void AdjustPlayStorePurchase2dx::initPurchase(std::string productId, std::string purchaseToken) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + cocos2d::JniMethodInfo jmiInit; + if (!cocos2d::JniHelper::getMethodInfo(jmiInit, "com/adjust/sdk/AdjustPurchase", "", "(Ljava/lang/String;Ljava/lang/String;)V")) { + return; + } + + jclass jclsAdjustPurchase = jmiInit.env->FindClass("com/adjust/sdk/AdjustPurchase"); + jmethodID jmidInit = jmiInit.env->GetMethodID(jclsAdjustPurchase, "", "(Ljava/lang/String;Ljava/lang/String;)V"); + jstring jProductId = jmiInit.env->NewStringUTF(productId.c_str()); + jstring jPurchaseToken = jmiInit.env->NewStringUTF(purchaseToken.c_str()); + purchase = jmiInit.env->NewObject(jclsAdjustPurchase, jmidInit, jProductId, jPurchaseToken); + jmiInit.env->DeleteLocalRef(jProductId); + jmiInit.env->DeleteLocalRef(jPurchaseToken); +#endif +} + +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) +jobject AdjustPlayStorePurchase2dx::getPurchase() { + return purchase; +} +#endif diff --git a/src/AdjustPlayStorePurchase2dx.h b/src/AdjustPlayStorePurchase2dx.h new file mode 100755 index 00000000..10ae10eb --- /dev/null +++ b/src/AdjustPlayStorePurchase2dx.h @@ -0,0 +1,38 @@ +// +// AdjustPlayStorePurchase2dx.h +// Adjust SDK +// +// Created by Uglješa Erceg (@uerceg) on 17th January 2024. +// Copyright © 2015-Present Adjust GmbH. All rights reserved. +// + +#ifndef ADJUST_ADJUSTPLAYSTOREPURCHASE2DX_H_ +#define ADJUST_ADJUSTPLAYSTOREPURCHASE2DX_H_ + +#include "cocos2d.h" +#include + +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) +#include +#endif + +class AdjustPlayStorePurchase2dx { +private: +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + jobject purchase; +#endif + void initPurchase(std::string productId, std::string purchaseToken); + +public: + AdjustPlayStorePurchase2dx(std::string productId, std::string purchaseToken) { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + initPurchase(productId, purchaseToken); +#endif + } + +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + jobject getPurchase(); +#endif +}; + +#endif /* ADJUST_ADJUSTPLAYSTOREPURCHASE2DX_H_ */ diff --git a/src/AdjustProxy2dx.cpp b/src/AdjustProxy2dx.cpp index 75497b29..ce4375c1 100755 --- a/src/AdjustProxy2dx.cpp +++ b/src/AdjustProxy2dx.cpp @@ -556,21 +556,6 @@ JNIEXPORT void JNICALL Java_com_adjust_sdk_Adjust2dxSessionTrackingSucceededCall sessionTrackingSucceededCallbackMethod(sessionSuccess); } -JNIEXPORT void JNICALL Java_com_adjust_sdk_Adjust2dxAdIdCallback_adIdRead -(JNIEnv *env, jobject obj, jstring jAdId) { - if (NULL == adIdCallbackMethod) { - return; - } - if (NULL == jAdId) { - return; - } - - const char *adIdCStr = env->GetStringUTFChars(jAdId, NULL); - std::string adId = std::string(adIdCStr); - adIdCallbackMethod(adId); - env->ReleaseStringUTFChars(jAdId, adIdCStr); -} - JNIEXPORT bool JNICALL Java_com_adjust_sdk_Adjust2dxDeferredDeeplinkCallback_deferredDeeplinkReceived (JNIEnv *env, jobject obj, jstring jDeeplink) { if (NULL == deferredDeeplinkCallbackMethod) { @@ -586,6 +571,51 @@ JNIEXPORT bool JNICALL Java_com_adjust_sdk_Adjust2dxDeferredDeeplinkCallback_def return deferredDeeplinkCallbackMethod(deeplink); } +JNIEXPORT void JNICALL Java_com_adjust_sdk_Adjust2dxAdIdCallback_adIdRead +(JNIEnv *env, jobject obj, jstring jAdId) { + if (NULL == adIdCallbackMethod) { + return; + } + if (NULL == jAdId) { + return; + } + + const char *adIdCStr = env->GetStringUTFChars(jAdId, NULL); + std::string adId = std::string(adIdCStr); + adIdCallbackMethod(adId); + env->ReleaseStringUTFChars(jAdId, adIdCStr); +} + +JNIEXPORT void JNICALL Java_com_adjust_sdk_Adjust2dxResolvedLinkCallback_resolvedLink +(JNIEnv *env, jobject obj, jstring jResolvedLink) { + if (NULL == resolvedLinkCallbackMethod) { + return; + } + if (NULL == jResolvedLink) { + return; + } + + const char *resolvedLinkCStr = env->GetStringUTFChars(jResolvedLink, NULL); + std::string resolvedLink = std::string(resolvedLinkCStr); + resolvedLinkCallbackMethod(resolvedLink); + env->ReleaseStringUTFChars(jResolvedLink, resolvedLinkCStr); +} + +JNIEXPORT void JNICALL Java_com_adjust_sdk_Adjust2dxPurchaseVerificationResultCallback_verificationResult +(JNIEnv *env, jobject obj, jstring jVerificationStatus, int jCode, jstring jMessage) { + if (NULL == purchaseVerificationResultCallbackMethod) { + return; + } + + const char *verificationStatusCStr = env->GetStringUTFChars(jVerificationStatus, NULL); + std::string verificationStatus = std::string(verificationStatusCStr); + const char *messageCStr = env->GetStringUTFChars(jMessage, NULL); + std::string message = std::string(messageCStr); + purchaseVerificationResultCallbackMethod(verificationStatus, jCode, message); + env->ReleaseStringUTFChars(jVerificationStatus, verificationStatusCStr); + env->ReleaseStringUTFChars(jMessage, messageCStr); +} + void setExecuteTestLibCommandCallbackMethod(void(*callbackMethod)(std::string className, std::string methodName, std::string jsonParameters)) { if (NULL == executeTestLibCommandCallbackMethod) { executeTestLibCommandCallbackMethod = callbackMethod; @@ -594,7 +624,7 @@ void setExecuteTestLibCommandCallbackMethod(void(*callbackMethod)(std::string cl void setAttributionCallbackMethod(void (*callbackMethod)(AdjustAttribution2dx attribution)) { if (NULL == attributionCallbackMethod) { - attributionCallbackMethod = callbackMethod; + attributionCallbackMethod = callbackMethod; } } @@ -629,8 +659,21 @@ void setDeferredDeeplinkCallbackMethod(bool (*callbackMethod)(std::string deepli } void setAdIdCallbackMethod(void (*callbackMethod)(std::string adId)) { - if (NULL == adIdCallbackMethod) { - adIdCallbackMethod = callbackMethod; - } + if (NULL == adIdCallbackMethod) { + adIdCallbackMethod = callbackMethod; + } +} + +void setResolvedLinkCallbackMethod(void (*callbackMethod)(std::string resolvedLink)) { + if (NULL == resolvedLinkCallbackMethod) { + resolvedLinkCallbackMethod = callbackMethod; + } } + +void setPurchaseVerificationResultCallbackMethod(void (*callbackMethod)(std::string verificationResult, int code, std::string message)) { + if (NULL == purchaseVerificationResultCallbackMethod) { + purchaseVerificationResultCallbackMethod = callbackMethod; + } +} + #endif diff --git a/src/AdjustProxy2dx.h b/src/AdjustProxy2dx.h index f9f10cc5..7d33d569 100755 --- a/src/AdjustProxy2dx.h +++ b/src/AdjustProxy2dx.h @@ -24,6 +24,8 @@ extern "C" { static void (*sessionTrackingSucceededCallbackMethod)(AdjustSessionSuccess2dx sessionSuccess); static bool (*deferredDeeplinkCallbackMethod)(std::string deeplink); static void (*adIdCallbackMethod)(std::string adId); + static void (*resolvedLinkCallbackMethod)(std::string resolvedLink); + static void (*purchaseVerificationResultCallbackMethod)(std::string verificationStatus, int code, std::string message); // Only for testing purposes. static void (*executeTestLibCommandCallbackMethod)(std::string className, std::string methodName, std::string jsonParameters); @@ -41,6 +43,10 @@ extern "C" { (JNIEnv *, jobject, jstring); JNIEXPORT void JNICALL Java_com_adjust_sdk_Adjust2dxAdIdCallback_adIdRead (JNIEnv *, jobject, jstring); + JNIEXPORT void JNICALL Java_com_adjust_sdk_Adjust2dxResolvedLinkCallback_resolvedLink + (JNIEnv *, jobject, jstring); + JNIEXPORT void JNICALL Java_com_adjust_sdk_Adjust2dxPurchaseVerificationResultCallback_verificationResult + (JNIEnv *, jobject, jstring, int, jstring); // Only for testing purposes. JNIEXPORT void JNICALL Java_com_adjust_test_Adjust2dxCommandJsonListenerCallback_executeCommand2dx (JNIEnv *, jobject, jstring, jstring, jstring); @@ -52,6 +58,8 @@ extern "C" { void setSessionTrackingSucceededCallbackMethod(void (*callbackMethod)(AdjustSessionSuccess2dx sessionSuccess)); void setDeferredDeeplinkCallbackMethod(bool (*callbackMethod)(std::string deeplink)); void setAdIdCallbackMethod(void (*callbackMethod)(std::string adId)); + void setResolvedLinkCallbackMethod(void (*callbackMethod)(std::string resolvedLink)); + void setPurchaseVerificationResultCallbackMethod(void (*callbackMethod)(std::string verificationStatus, int code, std::string message)); // Only for testing purposes. void setExecuteTestLibCommandCallbackMethod(void(*executeTestLibCommandCallbackMethod)(std::string className, std::string methodName, std::string jsonParameters)); } diff --git a/src/test/AdjustCommandDelegate2dx.h b/src/test/AdjustCommandDelegate2dx.h index 7491a90a..f53a9c09 100644 --- a/src/test/AdjustCommandDelegate2dx.h +++ b/src/test/AdjustCommandDelegate2dx.h @@ -15,4 +15,4 @@ + (id)getInstanceWithCommandExecutorCallbackId:(void (*)(std::string className, std::string methodName, std::string jsonParameters))commandExecutorCallbackId; -@end \ No newline at end of file +@end diff --git a/test/app/Classes/AdjustCommandExecutor.cpp b/test/app/Classes/AdjustCommandExecutor.cpp index e1ba6f70..d1d98bca 100644 --- a/test/app/Classes/AdjustCommandExecutor.cpp +++ b/test/app/Classes/AdjustCommandExecutor.cpp @@ -17,10 +17,14 @@ static std::string localBasePath; const std::string AdjustCommandExecutor::TAG = "AdjustCommandExecutor"; -AdjustCommandExecutor::AdjustCommandExecutor(std::string baseUrl, std::string gdprUrl, std::string subscriptionUrl) { +AdjustCommandExecutor::AdjustCommandExecutor(std::string baseUrl, + std::string gdprUrl, + std::string subscriptionUrl, + std::string purchaseVerificationUrl) { this->baseUrl = baseUrl; this->gdprUrl = gdprUrl; this->subscriptionUrl = subscriptionUrl; + this->purchaseVerificationUrl = purchaseVerificationUrl; } void AdjustCommandExecutor::executeCommand(Command *command) { @@ -81,6 +85,10 @@ void AdjustCommandExecutor::executeCommand(Command *command) { this->trackAdRevenueNew(); } else if (command->methodName == "getLastDeeplink") { this->getLastDeeplink(); + } else if (command->methodName == "verifyPurchase") { + this->verifyPurchase(); + } else if (command->methodName == "processDeeplink") { + this->processDeeplink(); } } @@ -89,10 +97,12 @@ void AdjustCommandExecutor::testOptions() { testOptions["baseUrl"] = this->baseUrl; testOptions["gdprUrl"] = this->gdprUrl; testOptions["subscriptionUrl"] = this->subscriptionUrl; + testOptions["purchaseVerificationUrl"] = this->purchaseVerificationUrl; if (this->command->containsParameter("basePath")) { this->basePath = command->getFirstParameterValue("basePath"); this->gdprPath = command->getFirstParameterValue("basePath"); this->subscriptionPath = command->getFirstParameterValue("basePath"); + this->purchaseVerificationPath = command->getFirstParameterValue("basePath"); this->extraPath = command->getFirstParameterValue("basePath"); } if (this->command->containsParameter("timerInterval")) { @@ -137,6 +147,7 @@ void AdjustCommandExecutor::testOptions() { testOptions["basePath"] = this->basePath; testOptions["gdprPath"] = this->gdprPath; testOptions["subscriptionPath"] = this->subscriptionPath; + testOptions["purchaseVerificationPath"] = this->purchaseVerificationPath; testOptions["extraPath"] = this->extraPath; // Android specific. #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) @@ -168,6 +179,7 @@ void AdjustCommandExecutor::testOptions() { testOptions["basePath"] = ""; testOptions["gdprPath"] = ""; testOptions["subscriptionPath"] = ""; + testOptions["purchaseVerificationPath"] = ""; testOptions["extraPath"] = ""; // Android specific. #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) @@ -349,6 +361,12 @@ void AdjustCommandExecutor::config() { adjustConfig->setPlayStoreKidsAppEnabled(playStoreKids); } + if (this->command->containsParameter("finalAttributionEnabled")) { + std::string finalAttributionEnabledString = command->getFirstParameterValue("finalAttributionEnabled"); + bool finalAttributionEnabled = (finalAttributionEnabledString == "true"); + adjustConfig->setFinalAttributionEnabled(finalAttributionEnabled); + } + if (this->command->containsParameter("attributionCallbackSendAll")) { localBasePath = this->basePath; adjustConfig->setAttributionCallback([](AdjustAttribution2dx attribution) { @@ -514,6 +532,28 @@ void AdjustCommandExecutor::event() { std::string callbackId = command->getFirstParameterValue("callbackId"); adjustEvent->setCallbackId(callbackId); } + + if (this->command->containsParameter("transactionId")) { + std::string transactionId = command->getFirstParameterValue("transactionId"); + adjustEvent->setTransactionId(transactionId); + } + + if (this->command->containsParameter("productId")) { + std::string productId = command->getFirstParameterValue("productId"); + adjustEvent->setProductId(productId); + } + +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + if (this->command->containsParameter("purchaseToken")) { + std::string purchaseToken = command->getFirstParameterValue("purchaseToken"); + adjustEvent->setPurchaseToken(purchaseToken); + } +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + if (this->command->containsParameter("receipt")) { + std::string receipt = command->getFirstParameterValue("receipt"); + adjustEvent->setReceipt(receipt); + } +#endif } void AdjustCommandExecutor::trackEvent() { @@ -814,11 +854,48 @@ void AdjustCommandExecutor::trackAdRevenueNew() { } void AdjustCommandExecutor::getLastDeeplink() { -#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) localBasePath = this->basePath; std::string lastDeeplink = Adjust2dx::getLastDeeplink(); TestLib2dx::addInfoToSend("last_deeplink", lastDeeplink); TestLib2dx::sendInfoToServer(localBasePath); +} + +void AdjustCommandExecutor::verifyPurchase() { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + std::string productId = command->getFirstParameterValue("productId"); + std::string transactionId = command->getFirstParameterValue("transactionId"); + std::string receipt = command->getFirstParameterValue("receipt"); + + AdjustAppStorePurchase2dx purchase = AdjustAppStorePurchase2dx(productId, transactionId, receipt); + + localBasePath = this->basePath; + Adjust2dx::verifyAppStorePurchase(purchase, [](std::string verificationStatus, int code, std::string message) { + TestLib2dx::addInfoToSend("verification_status", verificationStatus); + TestLib2dx::addInfoToSend("code", std::to_string(code)); + TestLib2dx::addInfoToSend("message", message); + TestLib2dx::sendInfoToServer(localBasePath); + }); #elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + std::string productId = command->getFirstParameterValue("productId"); + std::string purchaseToken = command->getFirstParameterValue("purchaseToken"); + + AdjustPlayStorePurchase2dx purchase = AdjustPlayStorePurchase2dx(productId, purchaseToken); + + localBasePath = this->basePath; + Adjust2dx::verifyPlayStorePurchase(purchase, [](std::string verificationStatus, int code, std::string message) { + TestLib2dx::addInfoToSend("verification_status", verificationStatus); + TestLib2dx::addInfoToSend("code", std::to_string(code)); + TestLib2dx::addInfoToSend("message", message); + TestLib2dx::sendInfoToServer(localBasePath); + }); #endif } + +void AdjustCommandExecutor::processDeeplink() { + std::string deeplink = command->getFirstParameterValue("deeplink"); + localBasePath = this->basePath; + Adjust2dx::processDeeplink(deeplink, [](std::string resolvedLink) { + TestLib2dx::addInfoToSend("resolved_link", resolvedLink); + TestLib2dx::sendInfoToServer(localBasePath); + }); +} diff --git a/test/app/Classes/AdjustCommandExecutor.h b/test/app/Classes/AdjustCommandExecutor.h index 0514aa16..565911ea 100644 --- a/test/app/Classes/AdjustCommandExecutor.h +++ b/test/app/Classes/AdjustCommandExecutor.h @@ -25,6 +25,8 @@ #include "Adjust/AdjustSessionFailure2dx.h" #include "Adjust/AdjustThirdPartySharing2dx.h" #include "Adjust/AdjustAdRevenue2dx.h" +#include "Adjust/AdjustAppStorePurchase2dx.h" +#include "Adjust/AdjustPlayStorePurchase2dx.h" #include "Adjust/test/TestLib2dx.h" #include "Adjust/test/TestConnectionOptions2dx.h" @@ -33,9 +35,11 @@ class AdjustCommandExecutor { std::string baseUrl; std::string gdprUrl; std::string subscriptionUrl; + std::string purchaseVerificationUrl; std::string basePath; std::string gdprPath; std::string subscriptionPath; + std::string purchaseVerificationPath; std::string extraPath; std::map savedEvents; std::map savedConfigs; @@ -69,10 +73,15 @@ class AdjustCommandExecutor { void trackMeasurementConsent(); void trackAdRevenueNew(); void getLastDeeplink(); + void verifyPurchase(); + void processDeeplink(); public: static const std::string TAG; - AdjustCommandExecutor(std::string baseUrl, std::string gdprUrl, std::string subscriptionUrl); + AdjustCommandExecutor(std::string baseUrl, + std::string gdprUrl, + std::string subscriptionUrl, + std::string purchaseVerificationUrl); void executeCommand(Command *command); }; -#endif // _ADJUST_COMMAND_EXECUTOR_H_ \ No newline at end of file +#endif // _ADJUST_COMMAND_EXECUTOR_H_ diff --git a/test/app/Classes/HelloWorldScene.cpp b/test/app/Classes/HelloWorldScene.cpp index f2cb0e3a..4d93802b 100644 --- a/test/app/Classes/HelloWorldScene.cpp +++ b/test/app/Classes/HelloWorldScene.cpp @@ -18,20 +18,25 @@ Scene *TestApp::createScene() { return TestApp::create(); } -static std::string serverIp = "192.168.86.44"; +static std::string serverIp = "192.168.86.21"; static std::string controlUrl = "ws://" + serverIp + ":1987"; #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) static std::string baseUrl = "http://" + serverIp + ":8080"; static std::string gdprUrl = "http://" + serverIp + ":8080"; static std::string subscriptionUrl = "http://" + serverIp + ":8080"; +static std::string purchaseVerificationUrl = "http://" + serverIp + ":8080"; #elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) static std::string baseUrl = "https://" + serverIp + ":8443"; static std::string gdprUrl = "https://" + serverIp + ":8443"; static std::string subscriptionUrl = "https://" + serverIp + ":8443"; +static std::string purchaseVerificationUrl = "https://" + serverIp + ":8443"; #endif -static AdjustCommandExecutor *commandExecutorInstance = new AdjustCommandExecutor(baseUrl, gdprUrl, subscriptionUrl); +static AdjustCommandExecutor *commandExecutorInstance = new AdjustCommandExecutor(baseUrl, + gdprUrl, + subscriptionUrl, + purchaseVerificationUrl); void TestApp::initTestLibrary() { auto func = [](std::string className, std::string methodName, std::string jsonParameters) { @@ -79,6 +84,7 @@ bool TestApp::init() { TestApp::initTestLibrary(); CCLOG("[AdjustTest]: Start test session called!"); + // this->testLibrary->addTestDirectory("purchase-verification"); this->testLibrary->startTestSession(Adjust2dx::getSdkVersion()); // Add main menu to screen diff --git a/test/libs/android/adjust-test-library.jar b/test/libs/android/adjust-test-library.jar index bce3a510..4273d941 100644 Binary files a/test/libs/android/adjust-test-library.jar and b/test/libs/android/adjust-test-library.jar differ diff --git a/test/libs/android/adjust-test-options.jar b/test/libs/android/adjust-test-options.jar index aa0c3a2f..e290b144 100644 Binary files a/test/libs/android/adjust-test-options.jar and b/test/libs/android/adjust-test-options.jar differ diff --git a/test/libs/ios/AdjustTestLibrary.framework/Versions/A/AdjustTestLibrary b/test/libs/ios/AdjustTestLibrary.framework/Versions/A/AdjustTestLibrary index 9e9457bb..70d931c4 100644 Binary files a/test/libs/ios/AdjustTestLibrary.framework/Versions/A/AdjustTestLibrary and b/test/libs/ios/AdjustTestLibrary.framework/Versions/A/AdjustTestLibrary differ