diff --git a/.gitignore b/.gitignore index 0e23047..6e6a1cc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,13 @@ -# Miscellaneous +# ============================================= +# ADJUST FLUTTER SDK - COMPREHENSIVE .GITIGNORE +# ============================================= +# This file handles all ignore patterns for the entire project. +# Organized by category for easy maintenance. + +# ===================== +# SYSTEM & EDITOR FILES +# ===================== +# miscellaneous system files *.class *.lock *.log @@ -6,70 +15,70 @@ *.swp .DS_Store .atom/ +.build/ .buildlog/ .history .svn/ +.swiftpm/ +migrate_working_dir/ -# IntelliJ related +# intellij related *.iml *.ipr *.iws .idea/ -# Visual Studio Code related +# visual studio code related .classpath .project .settings/ .vscode/ -# Flutter repo-specific -/bin/cache/ -/bin/internal/bootstrap.bat -/bin/internal/bootstrap.sh -/bin/mingit/ -/dev/benchmarks/mega_gallery/ -/dev/bots/.recipe_deps -/dev/bots/android_tools/ -/dev/devicelab/ABresults*.json -/dev/docs/doc/ -/dev/docs/flutter.docs.zip -/dev/docs/lib/ -/dev/docs/pubspec.yaml -/dev/integration_tests/**/xcuserdata -/dev/integration_tests/**/Pods -/packages/flutter/coverage/ -analysis_benchmark.json - -# packages file containing multi-root paths -.packages.generated - -# Flutter/Dart/Pub related +# ============== +# FLUTTER & DART +# ============== +# flutter/dart/pub related **/doc/api/ +**/ios/Flutter/.last_build_id .dart_tool/ .flutter-plugins .flutter-plugins-dependencies **/generated_plugin_registrant.dart .packages +.packages.generated .pub-cache/ .pub/ build/ +coverage/ flutter_*.png linked_*.ds unlinked.ds unlinked_spec.ds -# Android related -**/android/**/gradle-wrapper.jar +# ==================== +# ANDROID BUILD SYSTEM +# ==================== +# android build artifacts **/android/.gradle **/android/captures/ -**/android/gradlew -**/android/gradlew.bat **/android/local.properties **/android/**/GeneratedPluginRegistrant.java **/android/key.properties +**/android/app/debug +**/android/app/profile +**/android/app/release *.jks +*.keystore -# iOS/XCode related +# android studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release + +# ================= +# IOS BUILD SYSTEM +# ================= +# ios/xcode related **/ios/**/*.mode1v3 **/ios/**/*.mode2v3 **/ios/**/*.moved-aside @@ -83,10 +92,10 @@ unlinked_spec.ds **/ios/**/Icon? **/ios/**/Pods/ **/ios/**/.symlinks/ +**/ios/Podfile.lock **/ios/**/profile **/ios/**/xcuserdata **/ios/.generated/ -**/ios/Flutter/.last_build_id **/ios/Flutter/App.framework **/ios/Flutter/Flutter.framework **/ios/Flutter/Flutter.podspec @@ -98,20 +107,62 @@ unlinked_spec.ds **/ios/Flutter/flutter_export_environment.sh **/ios/ServiceDefinitions.json **/ios/Runner/GeneratedPluginRegistrant.* +**/ios/**/dgph -# macOS +# macos **/macos/Flutter/GeneratedPluginRegistrant.swift -# Coverage -coverage/ +# ==================== +# FLUTTER SDK SPECIFIC +# ==================== +# flutter repo-specific (for SDK development) +/bin/cache/ +/bin/internal/bootstrap.bat +/bin/internal/bootstrap.sh +/bin/mingit/ +/dev/benchmarks/mega_gallery/ +/dev/bots/.recipe_deps +/dev/bots/android_tools/ +/dev/devicelab/ABresults*.json +/dev/docs/doc/ +/dev/docs/flutter.docs.zip +/dev/docs/lib/ +/dev/docs/pubspec.yaml +/dev/integration_tests/**/xcuserdata +/dev/integration_tests/**/Pods +/packages/flutter/coverage/ +version +analysis_benchmark.json -# Symbols +# ========================= +# BUILD ARTIFACTS & SYMBOLS +# ========================= +# symbolication related app.*.symbols -# Exceptions to above rules. +# obfuscation related +app.*.map.json + +# ======================================= +# EXCEPTIONS - FILES THAT MUST BE TRACKED +# ======================================= +# these files are essential for building the apps after cloning + +# allow default ios files !**/ios/**/default.mode1v3 !**/ios/**/default.mode2v3 !**/ios/**/default.pbxuser !**/ios/**/default.perspectivev3 + +# allow essential flutter tools test data !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages -!/dev/ci/**/Gemfile.lock \ No newline at end of file +!/dev/ci/**/Gemfile.lock + +# allow gradle build system files for example and test apps +# these are essential for building without local gradle installation +!example/android/gradlew +!example/android/gradlew.bat +!example/android/gradle/wrapper/gradle-wrapper.jar +!test/app/android/gradlew +!test/app/android/gradlew.bat +!test/app/android/gradle/wrapper/gradle-wrapper.jar \ No newline at end of file diff --git a/.pubignore b/.pubignore new file mode 100644 index 0000000..e39e3d7 --- /dev/null +++ b/.pubignore @@ -0,0 +1,17 @@ +# Exclude test directory from published package +test/ + +# Exclude build artifacts and development files +**/build/ +**/.dart_tool/ +**/Pods/ +**/.pub-cache/ +**/example/build/ +**/example/ios/build/ +**/example/android/build/ +**/example/.dart_tool/ +**/example/ios/Pods/ +**/example/ios/Podfile.lock +**/example/android/local.properties +**/*.iml +**/.DS_Store \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 79a8f96..b67521f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,21 @@ +### Version 5.4.1 (1st July 2025) + +#### Added +- Added support for Google On-Device-Measurement. For more details about this feature, refer to the [official documentation](https://dev.adjust.com/en/sdk/flutter/plugins/google-odm). +- Optimized the logic behind the `processAndResolveDeeplink` method to immediately return links that have already been resolved. + +#### Changed +- Updated the Adjust Signature library version to 3.47.0. +- Updated look & feel of example and test apps. + +#### Native SDKs +- **iOS:** [v5.4.1](https://github.com/adjust/ios_sdk/tree/v5.4.1) +- **Android:** [v5.4.1](https://github.com/adjust/android_sdk/tree/v5.4.1) + +--- + ### Version 5.4.0 (13th June 2025) + #### Added - Added support for configuring store information via the `AdjustStoreInfo` object. You can now specify the store name and store app ID by assigning the `storeInfo` member of your `AdjustConfig` instance. This enables the SDK to record the intended app store source during initialization. For more details about this feature, refer to the [official documentation](https://dev.adjust.com/en/sdk/flutter/setup/store-type). - Added ability to initialize the SDK for the first session in delayed mode. You can start the SDK in the delayed mode by setting the `isFirstSessionDelayEnabled` member on your `AdjustConfig` instance to `true`. To end the delay, make sure to call `endFirstSessionDelay` method of `Adjust` instance. For more details about this feature, refer to the [official documentation](https://dev.adjust.com/en/sdk/flutter/features/first-session-delay). @@ -6,79 +23,87 @@ - Added ability to disable SDK's interaction with `AppTrackingTransparency.framework` API. You can disable it by setting the `isAppTrackingTransparencyUsageEnabled` member on your `AdjustConfig` instance to `false`. For more details about this feature, refer to the [official documentation](https://dev.adjust.com/en/sdk/flutter/features/att#disable-att-framework). #### Native SDKs -- [iOS@v5.4.0][ios_sdk_v5.4.0] -- [Android@v5.4.0][android_sdk_v5.4.0] +- **iOS:** [v5.4.0](https://github.com/adjust/ios_sdk/tree/v5.4.0) +- **Android:** [v5.4.0](https://github.com/adjust/android_sdk/tree/v5.4.0) --- ### Version 5.1.1 (March 5th 2025) + #### Fixed -- Fixed crashes happening in cases where native iOS `jsonResponse` is `nil` (https://github.com/adjust/flutter_sdk/pull/160). +- Fixed crashes happening in cases where native iOS `jsonResponse` is `nil` ([#160](https://github.com/adjust/flutter_sdk/pull/160)). #### Native SDKs -- [iOS@v5.1.1][ios_sdk_v5.1.1] -- [Android@v5.1.0][android_sdk_v5.1.0] +- **iOS:** [v5.1.1](https://github.com/adjust/ios_sdk/tree/v5.1.1) +- **Android:** [v5.1.0](https://github.com/adjust/android_sdk/tree/v5.1.0) --- ### Version 5.1.0 (25th February 2025) + #### Added - Added `jsonResponse` field (JSON string) to `AdjustAttribution` where every key-value pair sent by the backend as part of the attribution response can be found. #### Native SDKs -- [iOS@v5.1.1][ios_sdk_v5.1.1] -- [Android@v5.1.0][android_sdk_v5.1.0] +- **iOS:** [v5.1.1](https://github.com/adjust/ios_sdk/tree/v5.1.1) +- **Android:** [v5.1.0](https://github.com/adjust/android_sdk/tree/v5.1.0) --- ### Version 5.0.4 (6th February 2025) + #### Added - Added sending of the additional parameter to improve troubleshooting of `SKAdNetwork` related issues. #### Fixed - Fixed occasional occurrences in which ATT waiting interval timer was not being started. -- Fixed occasional NPE occurrences when app was entering background (https://github.com/adjust/android_sdk/issues/630). -- Fixed occasional NPE occurrences when `updateSkanConversionValue` returns `null` as error (https://github.com/adjust/flutter_sdk/issues/156). +- Fixed occasional NPE occurrences when app was entering background ([android_sdk#630](https://github.com/adjust/android_sdk/issues/630)). +- Fixed occasional NPE occurrences when `updateSkanConversionValue` returns `null` as error ([#156](https://github.com/adjust/flutter_sdk/issues/156)). #### Native SDKs -- [iOS@v5.1.0][ios_sdk_v5.1.0] -- [Android@v5.1.0][android_sdk_v5.1.0] +- **iOS:** [v5.1.0](https://github.com/adjust/ios_sdk/tree/v5.1.0) +- **Android:** [v5.1.0](https://github.com/adjust/android_sdk/tree/v5.1.0) --- ### Version 5.0.3 (6th December 2024) + #### Changed - Switched to native Android SDK version that depends on a specific version of the signature library. #### Native SDKs -- [iOS@v5.0.1][ios_sdk_v5.0.1] -- [Android@v5.0.2][android_sdk_v5.0.2] +- **iOS:** [v5.0.1](https://github.com/adjust/ios_sdk/tree/v5.0.1) +- **Android:** [v5.0.2](https://github.com/adjust/android_sdk/tree/v5.0.2) --- ### Version 5.0.2 (23rd September 2024) + #### Fixed - Fixed `Adjust.modulemap not found` error in certain CocoaPods integration cases. - Fixed occasional ANRs while reading install referrer from Shared Preferences during the SDK initialization. #### Native SDKs -- [iOS@v5.0.1][ios_sdk_v5.0.1] -- [Android@v5.0.1][android_sdk_v5.0.1] +- **iOS:** [v5.0.1](https://github.com/adjust/ios_sdk/tree/v5.0.1) +- **Android:** [v5.0.1](https://github.com/adjust/android_sdk/tree/v5.0.1) --- ### Version 5.0.1 (4th September 2024) + #### Fixed - Added missing `Adjust.getLastDeeplink` implementation on iOS platform. #### Native SDKs -- [iOS@v5.0.0][ios_sdk_v5.0.0] -- [Android@v5.0.0][android_sdk_v5.0.0] +- **iOS:** [v5.0.0](https://github.com/adjust/ios_sdk/tree/v5.0.0) +- **Android:** [v5.0.0](https://github.com/adjust/android_sdk/tree/v5.0.0) --- ### Version 5.0.0 (30th August 2024) +**Major Release** + We're excited to release our major new SDK version (v5). Among many internal improvements, our spoofing protection solution is now included out of the box, reinforcing our commitment to accurate, actionable, and fraud-free data. To try out SDK v5 in your app, you can follow our new v4 to v5 [migration guide](https://dev.adjust.com/en/sdk/flutter/migration/v4-to-v5). @@ -88,71 +113,77 @@ If you are a current Adjust client and have questions about SDK v5, please email In case you were using beta version of the SDK v5, please switch to the official v5 release. #### Native SDKs -- [iOS@v5.0.0][ios_sdk_v5.0.0] -- [Android@v5.0.0][android_sdk_v5.0.0] +- **iOS:** [v5.0.0](https://github.com/adjust/ios_sdk/tree/v5.0.0) +- **Android:** [v5.0.0](https://github.com/adjust/android_sdk/tree/v5.0.0) --- ### Version 4.38.2 (10th July 2024) + #### Fixed - Fixed occasional crashes when processing resolved deep links. #### Native SDKs -- [iOS@v4.38.4][ios_sdk_v4.38.4] -- [Android@v4.38.5][android_sdk_v4.38.5] +- **iOS:** [v4.38.4](https://github.com/adjust/ios_sdk/tree/v4.38.4) +- **Android:** [v4.38.5](https://github.com/adjust/android_sdk/tree/v4.38.5) --- ### Version 4.38.1 (30th April 2024) + #### Added - Added sending of the additional iOS SDK observability parameters for debugging purposes. #### Fixed -- Removed nullability type specifier warnings (https://github.com/adjust/ios_sdk/issues/703). +- Removed nullability type specifier warnings ([ios_sdk#703](https://github.com/adjust/ios_sdk/issues/703)). #### Native SDKs -- [iOS@v4.38.2][ios_sdk_v4.38.2] -- [Android@v4.38.3][android_sdk_v4.38.3] +- **iOS:** [v4.38.2](https://github.com/adjust/ios_sdk/tree/v4.38.2) +- **Android:** [v4.38.3](https://github.com/adjust/android_sdk/tree/v4.38.3) --- ### Version 4.38.0 (28th March 2024) + #### Added - Added iOS Privacy Manifest for the Adjust SDK. - Added new domains and corresponding payload restrictions for the Adjust SDK to direct the iOS traffic to: - - https://consent.adjust.com - for consented users - - https://analytics.adjust.com - for non-consented users + - `https://consent.adjust.com` - for consented users + - `https://analytics.adjust.com` - for non-consented users #### Native SDKs -- [iOS@v4.38.0][ios_sdk_v4.38.0] -- [Android@v4.38.3][android_sdk_v4.38.3] +- **iOS:** [v4.38.0](https://github.com/adjust/ios_sdk/tree/v4.38.0) +- **Android:** [v4.38.3](https://github.com/adjust/android_sdk/tree/v4.38.3) --- ### Version 4.37.1 (21st February 2024) + #### Added - Added support for `TradPlus` ad revenue tracking. #### Fixed -- Fixed return type mismatch between native Android and Dart implementation of iOS specific methods (https://github.com/adjust/flutter_sdk/issues/122). +- Fixed return type mismatch between native Android and Dart implementation of iOS specific methods ([#122](https://github.com/adjust/flutter_sdk/issues/122)). #### Native SDKs -- [iOS@v4.37.1][ios_sdk_v4.37.1] -- [Android@v4.38.1][android_sdk_v4.38.1] +- **iOS:** [v4.37.1](https://github.com/adjust/ios_sdk/tree/v4.37.1) +- **Android:** [v4.38.1](https://github.com/adjust/android_sdk/tree/v4.38.1) --- ### Version 4.37.0 (23rd January 2024) + #### Added - 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 `Adjust` instance. #### Native SDKs -- [iOS@v4.37.0][ios_sdk_v4.37.0] -- [Android@v4.38.0][android_sdk_v4.38.0] +- **iOS:** [v4.37.0](https://github.com/adjust/ios_sdk/tree/v4.37.0) +- **Android:** [v4.38.0](https://github.com/adjust/android_sdk/tree/v4.38.0) --- ### Version 4.36.0 (27th November 2023) + #### Added - Added getter for obtaining IDFV value of the iOS device. - Added support for Meta install referrer. @@ -162,76 +193,83 @@ In case you were using beta version of the SDK v5, please switch to the official - Added `readDeviceInfoOnceEnabled` member to `AdjustConfig` to indicate if Android device info should be read only once. #### Native SDKs -- [iOS@v4.36.0][ios_sdk_v4.36.0] -- [Android@v4.37.0][android_sdk_v4.37.0] +- **iOS:** [v4.36.0](https://github.com/adjust/ios_sdk/tree/v4.36.0) +- **Android:** [v4.37.0](https://github.com/adjust/android_sdk/tree/v4.37.0) --- ### Version 4.35.2 (9th October 2023) + #### Added - Added sending of `event_callback_id` parameter (if set) with the event payload. #### Native SDKs -- [iOS@v4.35.2][ios_sdk_v4.35.2] -- [Android@v4.35.1][android_sdk_v4.35.1] +- **iOS:** [v4.35.2](https://github.com/adjust/ios_sdk/tree/v4.35.2) +- **Android:** [v4.35.1](https://github.com/adjust/android_sdk/tree/v4.35.1) --- ### Version 4.35.1 (2nd October 2023) + #### Fixed - Fixed issue with signing iOS requests post ATT delay timer expiry. #### Native SDKs -- [iOS@v4.35.1][ios_sdk_v4.35.1] -- [Android@v4.35.0][android_sdk_v4.35.0] +- **iOS:** [v4.35.1](https://github.com/adjust/ios_sdk/tree/v4.35.1) +- **Android:** [v4.35.0](https://github.com/adjust/android_sdk/tree/v4.35.0) --- ### Version 4.35.0 (27th September 2023) + #### Added - 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) by setting the `androidFinalAttributionEnabled` member of the `AdjustConfig` instance. #### Native SDKs -- [iOS@v4.35.0][ios_sdk_v4.35.0] -- [Android@v4.35.0][android_sdk_v4.35.0] +- **iOS:** [v4.35.0](https://github.com/adjust/ios_sdk/tree/v4.35.0) +- **Android:** [v4.35.0](https://github.com/adjust/android_sdk/tree/v4.35.0) --- ### Version 4.34.0 (6th September 2023) + #### Added - Added support for Android apps using Gradle 8.0 or later. - 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 setting the `attConsentWaitingInterval` member of the `AdjustConfig` instance. - Added support for purchase verification. In case you are using this feature, you can now use it by calling `verifyAppStorePurchase` (for iOS) and `verifyPlayStorePurchase` (for Android) methods of the `Adjust` instance. #### Native SDKs -- [iOS@v4.34.2][ios_sdk_v4.34.2] -- [Android@v4.34.0][android_sdk_v4.34.0] +- **iOS:** [v4.34.2](https://github.com/adjust/ios_sdk/tree/v4.34.2) +- **Android:** [v4.34.0](https://github.com/adjust/android_sdk/tree/v4.34.0) --- ### Version 4.33.1 (16th February 2023) + #### Fixed - Skipped invocation of SKAN 4.0 style callback in case SKAN 4.0 API was not invoked (https://github.com/adjust/flutter_sdk/issues/104). #### Native SDKs -- [iOS@v4.33.4][ios_sdk_v4.33.4] -- [Android@v4.33.3][android_sdk_v4.33.3] +- **iOS:** [v4.33.4](https://github.com/adjust/ios_sdk/tree/v4.33.4) +- **Android:** [v4.33.3](https://github.com/adjust/android_sdk/tree/v4.33.3) --- ### Version 4.33.0 (9th December 2022) + #### Added - Added support for SKAN 4.0. - Added support for setting a new China URL Strategy. You can choose this setting by setting `urlStrategy` member of `AdjustConfig` instance to `AdjustConfig.UrlStrategyCn` value. #### Native SDKs -- [iOS@v4.33.2][ios_sdk_v4.33.2] -- [Android@v4.33.2][android_sdk_v4.33.2] +- **iOS:** [v4.33.2](https://github.com/adjust/ios_sdk/tree/v4.33.2) +- **Android:** [v4.33.2](https://github.com/adjust/android_sdk/tree/v4.33.2) --- ### Version 4.32.0 (7th October 2022) + #### Added - Added partner sharing settings to the third party sharing feature. - Added `getLastDeeplink` getter to `Adjust` API to be able to get last tracked deep link by the SDK for iOS platform. @@ -240,23 +278,25 @@ In case you were using beta version of the SDK v5, please switch to the official - Switched to adding permission `com.google.android.gms.permission.AD_ID` in the Android app's mainfest by default. #### Native SDKs -- [iOS@v4.32.1][ios_sdk_v4.32.1] -- [Android@v4.32.0][android_sdk_v4.32.0] +- **iOS:** [v4.32.1](https://github.com/adjust/ios_sdk/tree/v4.32.1) +- **Android:** [v4.32.0](https://github.com/adjust/android_sdk/tree/v4.32.0) --- ### Version 4.31.0 (3rd August 2022) + #### Added - Added support for `LinkMe` feature. - Added support to get Facebook install referrer information in attribution callback. #### Native SDKs -- [iOS@v4.31.0][ios_sdk_v4.31.0] -- [Android@v4.31.0][android_sdk_v4.31.0] +- **iOS:** [v4.31.0](https://github.com/adjust/ios_sdk/tree/v4.31.0) +- **Android:** [v4.31.0](https://github.com/adjust/android_sdk/tree/v4.31.0) --- ### Version 4.30.0 (9th June 2022) + #### Added - Added ability to mark your app as COPPA compliant. You can enable this setting by setting `coppaCompliantEnabled` member of `AdjustConfig` instance to `true`. - Added ability to mark your Android app as app for the kids in accordance to Google Play Families policies. You can enable this setting by setting `playStoreKidsAppEnabled` member of `AdjustConfig` instance to `true`. @@ -268,12 +308,13 @@ In case you were using beta version of the SDK v5, please switch to the official - Changed responses which is being returned when iOS specific API is being called on Android platform (https://github.com/adjust/flutter_sdk/issues/79 and https://github.com/adjust/flutter_sdk/issues/80). #### Native SDKs -- [iOS@v4.30.0][ios_sdk_v4.30.0] -- [Android@v4.30.1][android_sdk_v4.30.1] +- **iOS:** [v4.30.0](https://github.com/adjust/ios_sdk/tree/v4.30.0) +- **Android:** [v4.30.1](https://github.com/adjust/android_sdk/tree/v4.30.1) --- ### Version 4.29.2 (18th February 2022) + #### Added - Added support for `Unity` ad revenue tracking. - Added support for `Helium Chartboost` ad revenue tracking. @@ -283,12 +324,13 @@ In case you were using beta version of the SDK v5, please switch to the official - Migrated from `jcenter` to `mavenCentral` repository (https://github.com/adjust/flutter_sdk/pull/72). #### Native SDKs -- [iOS@v4.29.7][ios_sdk_v4.29.7] -- [Android@v4.29.1][android_sdk_v4.29.1] +- **iOS:** [v4.29.7](https://github.com/adjust/ios_sdk/tree/v4.29.7) +- **Android:** [v4.29.1](https://github.com/adjust/android_sdk/tree/v4.29.1) --- ### Version 4.29.1 (23rd September 2021) + #### Added - Added support for `Admost` ad revenue source. @@ -296,49 +338,50 @@ In case you were using beta version of the SDK v5, please switch to the official - Fixed compile time errors with Xcode 13. #### Native SDKs -- [iOS@v4.29.6][ios_sdk_v4.29.6] -- [Android@v4.28.5][android_sdk_v4.28.5] +- **iOS:** [v4.29.6](https://github.com/adjust/ios_sdk/tree/v4.29.6) +- **Android:** [v4.28.5](https://github.com/adjust/android_sdk/tree/v4.28.5) --- ### Version 4.29.0 (11th June 2021) + #### Added - Added support for null safety (thanks to @blaueeiner). - [beta] Added data residency feature. You can choose this setting by setting `urlStrategy` member of `AdjustConfig` instance to `AdjustConfig.DataResidencyEU` (for EU data residency region), `AdjustConfig.DataResidencyTR` (for TR data residency region) or `AdjustConfig.DataResidencyUS` value (for US data residency region). -- Added `trackAdRevenueNew` method to `Adjust` interface to allow tracking of ad revenue by passing `AdjustAdRevenue` object as parameter. +- Added support for `Topon` ad revenue tracking. +- Added support for `IronSource` ad revenue tracking. - Added support for `AppLovin MAX` ad revenue tracking. -- Added `conversionValueUpdatedCallback` member to `AdjustConfig` which can be used to set a callback which will get information when Adjust SDK updates conversion value for the user. - Added preinstall tracking with usage of system installer receiver on Android platform. #### Fixed - Fixed attribution value comparison logic which might cause same attribution value to be delivered into attribution callback on iOS platform. #### Native SDKs -- [iOS@v4.29.2][ios_sdk_v4.29.2] -- [Android@v4.28.1][android_sdk_v4.28.1] +- **iOS:** [v4.29.2](https://github.com/adjust/ios_sdk/tree/v4.29.2) +- **Android:** [v4.28.1](https://github.com/adjust/android_sdk/tree/v4.28.1) --- ### Version 4.28.0 (2nd April 2021) + #### Changed - Removed native iOS legacy code. #### Native SDKs -- [iOS@v4.28.0][ios_sdk_v4.28.0] -- [Android@v4.27.0][android_sdk_v4.27.0] +- **iOS:** [v4.28.0](https://github.com/adjust/ios_sdk/tree/v4.28.0) +- **Android:** [v4.27.0](https://github.com/adjust/android_sdk/tree/v4.27.0) --- ### Version 4.26.0 (23rd February 2021) + #### Added - Added possibility to get cost data information in attribution callback. - Added `needsCost` member to `AdjustConfig` to indicate if cost data is needed in attribution callback (by default cost data will not be part of attribution callback if not enabled with this setter method). -- Added `preinstallTrackingEnabled` member to `AdjustConfig` to allow enabling of preinstall tracking (this feature is OFF by default). -- Added support for Apple Search Ads attribution with usage of `AdServices.framework`. -- Added `allowAdServicesInfoReading` member to `AdjustConfig` to allow option for users to prevent SDK from performing any tasks related to Apple Search Ads attribution with usage of `AdServices.framework`. -- Added wrapper method `updateConversionValue` method to `Adjust` to allow updating SKAdNetwork conversion value via SDK API. -- Added `getAppTrackingAuthorizationStatus` getter to `Adjust` instance to be able to get current iOS app tracking status. -- Added improved measurement consent management and third party sharing mechanism. +- Added `AdjustPlayStoreSubscription` class to be used when tracking Play Store subscriptions. +- Added `AdjustAppStoreSubscription` class to be used when tracking App Store subscriptions. +- Added `trackAppStoreSubscription` method to `Adjust` interface to allow tracking of App Store subscriptions. +- Added `trackPlayStoreSubscription` method to `Adjust` interface to allow tracking of Play Store subscriptions. - Added public constants to be used as sources for ad revenue tracking with `trackAdRevenue` method. #### Changed @@ -348,43 +391,47 @@ In case you were using beta version of the SDK v5, please switch to the official - Fixed occasional NPEs in Android when firing callback methods. #### Native SDKs -- [iOS@v4.26.1][ios_sdk_v4.26.1] -- [Android@v4.26.2][android_sdk_v4.26.2] +- **iOS:** [v4.26.1](https://github.com/adjust/ios_sdk/tree/v4.26.1) +- **Android:** [v4.26.2](https://github.com/adjust/android_sdk/tree/v4.26.2) --- ### Version 4.23.3 (18th December 2020) + #### Added - Added URL strategy constants to `AdjustConfig` for more straight forward feature usage. #### Native SDKs -- [iOS@v4.23.2][ios_sdk_v4.23.2] -- [Android@v4.24.1][android_sdk_v4.24.1] +- **iOS:** [v4.23.2](https://github.com/adjust/ios_sdk/tree/v4.23.2) +- **Android:** [v4.24.1](https://github.com/adjust/android_sdk/tree/v4.24.1) --- ### Version 4.23.2 (11th November 2020) + #### Added - Added [Flutter 1.2 or later](https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects) support for Android projects. #### Native SDKs -- [iOS@v4.23.2][ios_sdk_v4.23.2] -- [Android@v4.24.1][android_sdk_v4.24.1] +- **iOS:** [v4.23.2](https://github.com/adjust/ios_sdk/tree/v4.23.2) +- **Android:** [v4.24.1](https://github.com/adjust/android_sdk/tree/v4.24.1) --- ### Version 4.23.1 (31st August 2020) + #### Fixed - Removed `iosPrefix` from `pubspec.yaml`. - Removed `ADJ` prefix from Flutter iOS class names. #### Native SDKs -- [iOS@v4.23.0][ios_sdk_v4.23.0] -- [Android@v4.24.0][android_sdk_v4.24.0] +- **iOS:** [v4.23.0](https://github.com/adjust/ios_sdk/tree/v4.23.0) +- **Android:** [v4.24.0](https://github.com/adjust/android_sdk/tree/v4.24.0) --- ### Version 4.23.0 (28th August 2020) + #### Added - Added communication with SKAdNetwork framework by default on iOS 14. - Added method `deactivateSKAdNetworkHandling` method to `AdjustConfig` to switch off default communication with SKAdNetwork framework in iOS 14. @@ -394,22 +441,24 @@ In case you were using beta version of the SDK v5, please switch to the official - Added `urlStrategy` member to `AdjustConfig` class to allow selection of URL strategy for specific market. #### Native SDKs -- [iOS@v4.23.0][ios_sdk_v4.23.0] -- [Android@v4.24.0][android_sdk_v4.24.0] +- **iOS:** [v4.23.0](https://github.com/adjust/ios_sdk/tree/v4.23.0) +- **Android:** [v4.24.0](https://github.com/adjust/android_sdk/tree/v4.24.0) --- ### Version 4.22.1 (3rd August 2020) + #### Changed - Changed referencing of native Android dependency from `implementation` to `api`. #### Native SDKs -- [iOS@v4.22.1][ios_sdk_v4.22.1] -- [Android@v4.22.0][android_sdk_v4.22.0] +- **iOS:** [v4.22.1](https://github.com/adjust/ios_sdk/tree/v4.22.1) +- **Android:** [v4.22.0](https://github.com/adjust/android_sdk/tree/v4.22.0) --- ### Version 4.22.0 (10th June 2020) + #### Added - Added subscription tracking feature. - Added support for Huawei App Gallery install referrer. @@ -418,12 +467,13 @@ In case you were using beta version of the SDK v5, please switch to the official - Updated communication flow with `iAd.framework`. #### Native SDKs -- [iOS@v4.22.1][ios_sdk_v4.22.1] -- [Android@v4.22.0][android_sdk_v4.22.0] +- **iOS:** [v4.22.1](https://github.com/adjust/ios_sdk/tree/v4.22.1) +- **Android:** [v4.22.0](https://github.com/adjust/android_sdk/tree/v4.22.0) --- ### Version 4.21.0 (25th March 2021) + #### Added - Added `disableThirdPartySharing` method to `Adjust` interface to allow disabling of data sharing with third parties outside of Adjust ecosystem. - Added support for signature library as a plugin. @@ -432,150 +482,96 @@ In case you were using beta version of the SDK v5, please switch to the official - Added external device ID support. #### Native SDKs -- [iOS@v4.21.0][ios_sdk_v4.21.0] -- [Android@4.21.0][android_sdk_v4.21.0] +- **iOS:** [v4.21.0](https://github.com/adjust/ios_sdk/tree/v4.21.0) +- **Android:** [v4.21.0](https://github.com/adjust/android_sdk/tree/v4.21.0) --- ### Version 4.18.1 (9th October 2019) + #### Fixed - Fixed lack of `getAdid` method implementation in native iOS bridge (thanks to @HenriBeck). #### Native SDKs -- [iOS@v4.18.3][ios_sdk_v4.18.3] -- [Android@v4.18.3][android_sdk_v4.18.3] +- **iOS:** [v4.18.3](https://github.com/adjust/ios_sdk/tree/v4.18.3) +- **Android:** [v4.18.3](https://github.com/adjust/android_sdk/tree/v4.18.3) --- ### Version 4.18.0 (4th July 2019) + #### Added - Added `trackAdRevenue` method to `Adjust` interface to allow tracking of ad revenue. With this release added support for `MoPub` ad revenue tracking. - Added reading of Facebook anonymous ID if available on iOS platform. #### Native SDKs -- [iOS@v4.18.0][ios_sdk_v4.18.0] -- [Android@v4.18.0][android_sdk_v4.18.0] +- **iOS:** [v4.18.0](https://github.com/adjust/ios_sdk/tree/v4.18.0) +- **Android:** [v4.18.0](https://github.com/adjust/android_sdk/tree/v4.18.0) --- ### Version 4.17.1 (5th June 2019) + #### Fixed - Fixed issue when trying to register Android plugin more than once (https://github.com/adjust/flutter_sdk/issues/7). #### Native SDKs -- [iOS@v4.17.3][ios_sdk_v4.17.3] -- [Android@v4.17.0][android_sdk_v4.17.0] +- **iOS:** [v4.17.3](https://github.com/adjust/ios_sdk/tree/v4.17.3) +- **Android:** [v4.17.0](https://github.com/adjust/android_sdk/tree/v4.17.0) --- ### Version 4.17.0 (4th December 2018) + #### Added - Official Flutter SDK release. #### Native SDKs -- [iOS@v4.17.0][ios_sdk_v4.17.0] -- [Android@v4.17.0][android_sdk_v4.17.0] +- **iOS:** [v4.17.0](https://github.com/adjust/ios_sdk/tree/v4.17.0) +- **Android:** [v4.17.0](https://github.com/adjust/android_sdk/tree/v4.17.0) --- ### Version 0.0.4 (4th December 2018) + #### Changed - Changed SDK API to be more Dart friendly. #### Native SDKs -- [iOS@v4.17.0][ios_sdk_v4.17.0] -- [Android@v4.17.0][android_sdk_v4.17.0] +- **iOS:** [v4.17.0](https://github.com/adjust/ios_sdk/tree/v4.17.0) +- **Android:** [v4.17.0](https://github.com/adjust/android_sdk/tree/v4.17.0) --- ### Version 0.0.3 (4th December 2018) + #### Changed - Changed SDK dependency in example app from local path to Flutter plugin repository. #### Native SDKs -- [iOS@v4.17.0][ios_sdk_v4.17.0] -- [Android@v4.17.0][android_sdk_v4.17.0] +- **iOS:** [v4.17.0](https://github.com/adjust/ios_sdk/tree/v4.17.0) +- **Android:** [v4.17.0](https://github.com/adjust/android_sdk/tree/v4.17.0) --- ### Version 0.0.2 (4th December 2018) + #### Added - Added example app to repo. - Added handling of process name for Android platform. #### Native SDKs -- [iOS@v4.17.0][ios_sdk_v4.17.0] -- [Android@v4.17.0][android_sdk_v4.17.0] +- **iOS:** [v4.17.0](https://github.com/adjust/ios_sdk/tree/v4.17.0) +- **Android:** [v4.17.0](https://github.com/adjust/android_sdk/tree/v4.17.0) --- ### Version 0.0.1 (4th December 2018) + #### Added - Test release of Flutter SDK. - Package available at: https://pub.dartlang.org/packages/adjust_sdk #### Native SDKs -- [iOS@v4.17.0][ios_sdk_v4.17.0] -- [Android@v4.17.0][android_sdk_v4.17.0] - -[ios_sdk_v4.17.0]: https://github.com/adjust/ios_sdk/tree/v4.17.0 -[ios_sdk_v4.17.3]: https://github.com/adjust/ios_sdk/tree/v4.17.3 -[ios_sdk_v4.18.0]: https://github.com/adjust/ios_sdk/tree/v4.18.0 -[ios_sdk_v4.18.3]: https://github.com/adjust/ios_sdk/tree/v4.18.3 -[ios_sdk_v4.21.0]: https://github.com/adjust/ios_sdk/tree/v4.21.0 -[ios_sdk_v4.22.1]: https://github.com/adjust/ios_sdk/tree/v4.22.1 -[ios_sdk_v4.23.0]: https://github.com/adjust/ios_sdk/tree/v4.23.0 -[ios_sdk_v4.23.2]: https://github.com/adjust/ios_sdk/tree/v4.23.2 -[ios_sdk_v4.26.1]: https://github.com/adjust/ios_sdk/tree/v4.26.1 -[ios_sdk_v4.28.0]: https://github.com/adjust/ios_sdk/tree/v4.28.0 -[ios_sdk_v4.29.2]: https://github.com/adjust/ios_sdk/tree/v4.29.2 -[ios_sdk_v4.29.6]: https://github.com/adjust/ios_sdk/tree/v4.29.6 -[ios_sdk_v4.29.7]: https://github.com/adjust/ios_sdk/tree/v4.29.7 -[ios_sdk_v4.30.0]: https://github.com/adjust/ios_sdk/tree/v4.30.0 -[ios_sdk_v4.31.0]: https://github.com/adjust/ios_sdk/tree/v4.31.0 -[ios_sdk_v4.32.1]: https://github.com/adjust/ios_sdk/tree/v4.32.1 -[ios_sdk_v4.33.2]: https://github.com/adjust/ios_sdk/tree/v4.33.2 -[ios_sdk_v4.33.4]: https://github.com/adjust/ios_sdk/tree/v4.33.4 -[ios_sdk_v4.34.2]: https://github.com/adjust/ios_sdk/tree/v4.34.2 -[ios_sdk_v4.35.0]: https://github.com/adjust/ios_sdk/tree/v4.35.0 -[ios_sdk_v4.35.1]: https://github.com/adjust/ios_sdk/tree/v4.35.1 -[ios_sdk_v4.35.2]: https://github.com/adjust/ios_sdk/tree/v4.35.2 -[ios_sdk_v4.36.0]: https://github.com/adjust/ios_sdk/tree/v4.36.0 -[ios_sdk_v4.37.0]: https://github.com/adjust/ios_sdk/tree/v4.37.0 -[ios_sdk_v4.37.1]: https://github.com/adjust/ios_sdk/tree/v4.37.1 -[ios_sdk_v4.38.0]: https://github.com/adjust/ios_sdk/tree/v4.38.0 -[ios_sdk_v4.38.2]: https://github.com/adjust/ios_sdk/tree/v4.38.2 -[ios_sdk_v4.38.4]: https://github.com/adjust/ios_sdk/tree/v4.38.4 -[ios_sdk_v5.0.0]: https://github.com/adjust/ios_sdk/tree/v5.0.0 -[ios_sdk_v5.0.1]: https://github.com/adjust/ios_sdk/tree/v5.0.1 -[ios_sdk_v5.1.1]: https://github.com/adjust/ios_sdk/tree/v5.1.1 -[ios_sdk_v5.4.0]: https://github.com/adjust/ios_sdk/tree/v5.4.0 - -[android_sdk_v4.17.0]: https://github.com/adjust/android_sdk/tree/v4.17.0 -[android_sdk_v4.18.0]: https://github.com/adjust/android_sdk/tree/v4.18.0 -[android_sdk_v4.21.0]: https://github.com/adjust/android_sdk/tree/v4.21.0 -[android_sdk_v4.22.0]: https://github.com/adjust/android_sdk/tree/v4.22.0 -[android_sdk_v4.24.0]: https://github.com/adjust/android_sdk/tree/v4.24.0 -[android_sdk_v4.24.1]: https://github.com/adjust/android_sdk/tree/v4.24.1 -[android_sdk_v4.26.2]: https://github.com/adjust/android_sdk/tree/v4.26.2 -[android_sdk_v4.27.0]: https://github.com/adjust/android_sdk/tree/v4.27.0 -[android_sdk_v4.28.1]: https://github.com/adjust/android_sdk/tree/v4.28.1 -[android_sdk_v4.28.5]: https://github.com/adjust/android_sdk/tree/v4.28.5 -[android_sdk_v4.30.1]: https://github.com/adjust/android_sdk/tree/v4.30.1 -[android_sdk_v4.31.0]: https://github.com/adjust/android_sdk/tree/v4.31.0 -[android_sdk_v4.32.0]: https://github.com/adjust/android_sdk/tree/v4.32.0 -[android_sdk_v4.33.2]: https://github.com/adjust/android_sdk/tree/v4.33.2 -[android_sdk_v4.33.3]: https://github.com/adjust/android_sdk/tree/v4.33.3 -[android_sdk_v4.34.0]: https://github.com/adjust/android_sdk/tree/v4.34.0 -[android_sdk_v4.35.0]: https://github.com/adjust/android_sdk/tree/v4.35.0 -[android_sdk_v4.35.1]: https://github.com/adjust/android_sdk/tree/v4.35.1 -[android_sdk_v4.37.0]: https://github.com/adjust/android_sdk/tree/v4.37.0 -[android_sdk_v4.38.0]: https://github.com/adjust/android_sdk/tree/v4.38.0 -[android_sdk_v4.38.1]: https://github.com/adjust/android_sdk/tree/v4.38.1 -[android_sdk_v4.38.3]: https://github.com/adjust/android_sdk/tree/v4.38.3 -[android_sdk_v4.38.5]: https://github.com/adjust/android_sdk/tree/v4.38.5 -[android_sdk_v5.0.0]: https://github.com/adjust/android_sdk/tree/v5.0.0 -[android_sdk_v5.0.1]: https://github.com/adjust/android_sdk/tree/v5.0.1 -[android_sdk_v5.0.2]: https://github.com/adjust/android_sdk/tree/v5.0.2 -[android_sdk_v5.1.0]: https://github.com/adjust/android_sdk/tree/v5.1.0 -[android_sdk_v5.4.0]: https://github.com/adjust/android_sdk/tree/v5.4.0 +- **iOS:** [v4.17.0](https://github.com/adjust/ios_sdk/tree/v4.17.0) +- **Android:** [v4.17.0](https://github.com/adjust/android_sdk/tree/v4.17.0) diff --git a/VERSION b/VERSION index 8a30e8f..ade6522 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -5.4.0 +5.4.1 diff --git a/android/.gitignore b/android/.gitignore deleted file mode 100644 index c6cbe56..0000000 --- a/android/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -*.iml -.gradle -/local.properties -/.idea/workspace.xml -/.idea/libraries -.DS_Store -/build -/captures diff --git a/android/build.gradle b/android/build.gradle index 7577056..fc6f042 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath('com.android.tools.build:gradle:8.1.4') + classpath('com.android.tools.build:gradle:8.2.1') } } rootProject.allprojects { @@ -37,5 +37,5 @@ android { } dependencies { - implementation 'com.adjust.sdk:adjust-android:5.4.0' + implementation 'com.adjust.sdk:adjust-android:5.4.1' } diff --git a/example/.gitignore b/example/.gitignore deleted file mode 100644 index 2bead7e..0000000 --- a/example/.gitignore +++ /dev/null @@ -1,118 +0,0 @@ -# Miscellaneous -*.class -*.lock -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# Visual Studio Code related -.classpath -.project -.settings/ -.vscode/ - -# Flutter repo-specific -/bin/cache/ -/bin/internal/bootstrap.bat -/bin/internal/bootstrap.sh -/bin/mingit/ -/dev/benchmarks/mega_gallery/ -/dev/bots/.recipe_deps -/dev/bots/android_tools/ -/dev/devicelab/ABresults*.json -/dev/docs/doc/ -/dev/docs/flutter.docs.zip -/dev/docs/lib/ -/dev/docs/pubspec.yaml -/dev/integration_tests/**/xcuserdata -/dev/integration_tests/**/Pods -/packages/flutter/coverage/ -version -analysis_benchmark.json - -# packages file containing multi-root paths -.packages.generated - -# Flutter/Dart/Pub related -**/doc/api/ -.dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies -**/generated_plugin_registrant.dart -.packages -.pub-cache/ -.pub/ -build/ -flutter_*.png -linked_*.ds -unlinked.ds -unlinked_spec.ds - -# Android related -**/android/**/gradle-wrapper.jar -**/android/.gradle -**/android/captures/ -**/android/gradlew -**/android/gradlew.bat -**/android/local.properties -**/android/**/GeneratedPluginRegistrant.java -**/android/key.properties -*.jks - -# iOS/XCode related -**/ios/**/*.mode1v3 -**/ios/**/*.mode2v3 -**/ios/**/*.moved-aside -**/ios/**/*.pbxuser -**/ios/**/*.perspectivev3 -**/ios/**/*sync/ -**/ios/**/.sconsign.dblite -**/ios/**/.tags* -**/ios/**/.vagrant/ -**/ios/**/DerivedData/ -**/ios/**/Icon? -**/ios/**/Pods/ -**/ios/**/.symlinks/ -**/ios/**/profile -**/ios/**/xcuserdata -**/ios/.generated/ -**/ios/Flutter/.last_build_id -**/ios/Flutter/App.framework -**/ios/Flutter/Flutter.framework -**/ios/Flutter/Flutter.podspec -**/ios/Flutter/Generated.xcconfig -**/ios/Flutter/ephemeral -**/ios/Flutter/app.flx -**/ios/Flutter/app.zip -**/ios/Flutter/flutter_assets/ -**/ios/Flutter/flutter_export_environment.sh -**/ios/ServiceDefinitions.json -**/ios/Runner/GeneratedPluginRegistrant.* - -# macOS -**/macos/Flutter/GeneratedPluginRegistrant.swift - -# Coverage -coverage/ - -# Symbols -app.*.symbols - -# Exceptions to above rules. -!**/ios/**/default.mode1v3 -!**/ios/**/default.mode2v3 -!**/ios/**/default.pbxuser -!**/ios/**/default.perspectivev3 -!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages -!/dev/ci/**/Gemfile.lock \ No newline at end of file diff --git a/example/.metadata b/example/.metadata index 6eb54a1..6bbd235 100644 --- a/example/.metadata +++ b/example/.metadata @@ -4,8 +4,8 @@ # This file should be version controlled and should not be manually edited. version: - revision: "761747bfc538b5af34aa0d3fac380f1bc331ec49" - channel: "stable" + revision: "961ce3ec82ab88237be012c24eee24f9b10591dd" + channel: "master" project_type: app @@ -13,26 +13,26 @@ project_type: app migration: platforms: - platform: root - create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49 - base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49 + create_revision: 961ce3ec82ab88237be012c24eee24f9b10591dd + base_revision: 961ce3ec82ab88237be012c24eee24f9b10591dd - platform: android - create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49 - base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49 + create_revision: 961ce3ec82ab88237be012c24eee24f9b10591dd + base_revision: 961ce3ec82ab88237be012c24eee24f9b10591dd - platform: ios - create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49 - base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49 + create_revision: 961ce3ec82ab88237be012c24eee24f9b10591dd + base_revision: 961ce3ec82ab88237be012c24eee24f9b10591dd - platform: linux - create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49 - base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49 + create_revision: 961ce3ec82ab88237be012c24eee24f9b10591dd + base_revision: 961ce3ec82ab88237be012c24eee24f9b10591dd - platform: macos - create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49 - base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49 + create_revision: 961ce3ec82ab88237be012c24eee24f9b10591dd + base_revision: 961ce3ec82ab88237be012c24eee24f9b10591dd - platform: web - create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49 - base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49 + create_revision: 961ce3ec82ab88237be012c24eee24f9b10591dd + base_revision: 961ce3ec82ab88237be012c24eee24f9b10591dd - platform: windows - create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49 - base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49 + create_revision: 961ce3ec82ab88237be012c24eee24f9b10591dd + base_revision: 961ce3ec82ab88237be012c24eee24f9b10591dd # User provided section diff --git a/example/README.md b/example/README.md index aeaccb6..cb44ee3 100644 --- a/example/README.md +++ b/example/README.md @@ -1,16 +1,80 @@ -# example +# Adjust Flutter Example App -Adjust Flutter Applicаtion +A comprehensive demonstration application showcasing the full functionality of the Adjust Flutter SDK. This app provides interactive examples of all major SDK features and serves as a reference implementation. + +## Features + +- **Event Tracking**: Demonstrate simple, revenue, callback, and partner events +- **Device Information**: Access Google AdID, Adjust identifier, IDFA, and attribution data +- **SDK Management**: Toggle SDK state and check enabled status +- **Real-time Callbacks**: Live demonstration of attribution, session, and event callbacks +- **Modern UI**: Beautiful, intuitive interface following Adjust design guidelines ## Getting Started -This project is a starting point for a Flutter application. +1. **Prerequisites**: Ensure Flutter is installed and configured +2. **Install Dependencies**: Run `flutter pub get` in this directory +3. **Run the App**: Use `flutter run` to start the example application +4. **Explore Features**: Tap buttons to test different SDK functionalities + +## App Structure + +- **Event Tracking Section**: Test different types of events with various parameters +- **Device Information Section**: Retrieve device-specific identifiers and attribution +- **SDK Control Section**: Manage SDK state and verify functionality + +## SDK Configuration + +The app is configured with: +- **App Token**: `2fm9gkqubvpc` (sandbox environment) +- **Environment**: Sandbox mode for safe testing +- **Log Level**: Verbose logging for detailed insights +- **Callbacks**: Comprehensive callback setup for all event types + +## Event Tokens + +The following test event tokens are configured: +- **Simple Event**: `g3mfiw` - Basic event tracking +- **Revenue Event**: `a4fd35` - Event with revenue data +- **Callback Event**: `34vgg9` - Event with callback parameters +- **Partner Event**: `w788qs` - Event with partner parameters + +## Usage Examples + +### Track a Simple Event +```dart +final event = AdjustEvent('g3mfiw'); +Adjust.trackEvent(event); +``` + +### Track Revenue Event +```dart +final event = AdjustEvent('a4fd35'); +event.setRevenue(100.0, 'EUR'); +event.transactionId = 'DummyTransactionId'; +Adjust.trackEvent(event); +``` + +### Get Attribution Data +```dart +Adjust.getAttribution().then((attribution) { + // Handle attribution data +}); +``` + +## Callbacks -A few resources to get you started if this is your first Flutter project: +The app demonstrates all available callback types: +- **Attribution Callback**: Triggered when attribution data changes +- **Session Success/Failure**: Monitor session tracking status +- **Event Success/Failure**: Track event delivery status +- **Deferred Deeplinks**: Handle deferred deeplink scenarios +- **SKAN Updates**: iOS StoreKit Ad Network updates -- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) +## Testing -For help getting started with Flutter, view our -[online documentation](https://flutter.dev/docs), which offers tutorials, -samples, guidance on mobile development, and a full API reference. +Use this app to: +- Verify SDK integration in your development environment +- Test different event tracking scenarios +- Understand callback behavior and data structure +- Validate attribution and device identifier retrieval diff --git a/example/android/.gitignore b/example/android/.gitignore deleted file mode 100644 index 0a741cb..0000000 --- a/example/android/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -gradle-wrapper.jar -/.gradle -/captures/ -/gradlew -/gradlew.bat -/local.properties -GeneratedPluginRegistrant.java - -# Remember to never publicly share your keystore. -# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app -key.properties diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle deleted file mode 100644 index 6822fae..0000000 --- a/example/android/app/build.gradle +++ /dev/null @@ -1,58 +0,0 @@ -plugins { - id "com.android.application" - id "kotlin-android" - // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. - id "dev.flutter.flutter-gradle-plugin" -} - -def localProperties = new Properties() -def localPropertiesFile = rootProject.file("local.properties") -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader("UTF-8") { reader -> - localProperties.load(reader) - } -} - -def flutterVersionCode = localProperties.getProperty("flutter.versionCode") -if (flutterVersionCode == null) { - flutterVersionCode = "1" -} - -def flutterVersionName = localProperties.getProperty("flutter.versionName") -if (flutterVersionName == null) { - flutterVersionName = "1.0" -} - -android { - namespace = "com.adjust.examples" - compileSdk = 34 - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - - defaultConfig { - applicationId "com.adjust.examples" - minSdkVersion flutter.minSdkVersion - targetSdkVersion 34 - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig = signingConfigs.debug - } - } -} - -flutter { - source = "../.." -} - -dependencies { - implementation 'com.adjust.sdk:adjust-android:5.4.0' -} \ No newline at end of file diff --git a/example/android/app/build.gradle.kts b/example/android/app/build.gradle.kts new file mode 100644 index 0000000..ab881a4 --- /dev/null +++ b/example/android/app/build.gradle.kts @@ -0,0 +1,40 @@ +plugins { + id("com.android.application") + id("kotlin-android") + // the Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins + id("dev.flutter.flutter-gradle-plugin") +} + +android { + namespace = "com.adjust.examples" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_11.toString() + } + + defaultConfig { + applicationId = "com.adjust.examples" + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode = flutter.versionCode + versionName = flutter.versionName + } + + buildTypes { + release { + // signing with debug keys for development convenience + signingConfig = signingConfigs.getByName("debug") + } + } +} + +flutter { + source = "../.." +} diff --git a/example/android/app/src/debug/AndroidManifest.xml b/example/android/app/src/debug/AndroidManifest.xml index f880684..399f698 100644 --- a/example/android/app/src/debug/AndroidManifest.xml +++ b/example/android/app/src/debug/AndroidManifest.xml @@ -1,5 +1,6 @@ - diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index 9802ea3..842f600 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -1,20 +1,17 @@ - + android:windowSoftInputMode="adjustResize"> - - - - - - - - @@ -50,4 +31,15 @@ android:name="flutterEmbedding" android:value="2" /> + + + + + + + diff --git a/example/android/app/src/main/kotlin/com/adjust/examples/MainActivity.kt b/example/android/app/src/main/kotlin/com/adjust/examples/MainActivity.kt index 17c8b39..582cb5a 100644 --- a/example/android/app/src/main/kotlin/com/adjust/examples/MainActivity.kt +++ b/example/android/app/src/main/kotlin/com/adjust/examples/MainActivity.kt @@ -1,24 +1,5 @@ package com.adjust.examples -import android.content.Intent -import android.os.Bundle -import com.adjust.sdk.Adjust -import com.adjust.sdk.AdjustDeeplink import io.flutter.embedding.android.FlutterActivity -class MainActivity: FlutterActivity(){ - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - val intent: Intent = intent - val data = intent.data - Adjust.processDeeplink(AdjustDeeplink(data), this) - } - - override fun onNewIntent(intent: Intent) { - super.onNewIntent(intent) - val data = intent?.data - Adjust.processDeeplink(AdjustDeeplink(data), this) - } - - -} +class MainActivity : FlutterActivity() \ No newline at end of file diff --git a/example/android/app/src/main/res/drawable-v21/launch_background.xml b/example/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..f74085f --- /dev/null +++ b/example/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/example/android/app/src/main/res/values-night/styles.xml b/example/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..06952be --- /dev/null +++ b/example/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/example/android/app/src/profile/AndroidManifest.xml b/example/android/app/src/profile/AndroidManifest.xml index f880684..399f698 100644 --- a/example/android/app/src/profile/AndroidManifest.xml +++ b/example/android/app/src/profile/AndroidManifest.xml @@ -1,5 +1,6 @@ - diff --git a/example/android/build.gradle b/example/android/build.gradle deleted file mode 100644 index bb91beb..0000000 --- a/example/android/build.gradle +++ /dev/null @@ -1,31 +0,0 @@ -buildscript { - ext.kotlin_version = '1.7.10' - repositories { - google() - mavenCentral() - } - - dependencies { - classpath 'com.android.tools.build:gradle:8.8.0' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} - -allprojects { - repositories { - google() - mavenCentral() - } -} - -rootProject.buildDir = "../build" -subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { - project.evaluationDependsOn(":app") -} - -tasks.register("clean", Delete) { - delete rootProject.buildDir -} diff --git a/example/android/build.gradle.kts b/example/android/build.gradle.kts new file mode 100644 index 0000000..dbee657 --- /dev/null +++ b/example/android/build.gradle.kts @@ -0,0 +1,24 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +val newBuildDir: Directory = + rootProject.layout.buildDirectory + .dir("../../build") + .get() +rootProject.layout.buildDirectory.value(newBuildDir) + +subprojects { + val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) + project.layout.buildDirectory.value(newSubprojectBuildDir) +} +subprojects { + project.evaluationDependsOn(":app") +} + +tasks.register("clean") { + delete(rootProject.layout.buildDirectory) +} diff --git a/example/android/gradle.properties b/example/android/gradle.properties index 5f5d39d..f018a61 100644 --- a/example/android/gradle.properties +++ b/example/android/gradle.properties @@ -1,6 +1,3 @@ -org.gradle.jvmargs=-Xmx4G -XX:+HeapDumpOnOutOfMemoryError +org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError android.useAndroidX=true android.enableJetifier=true -android.defaults.buildfeatures.buildconfig=true -android.nonTransitiveRClass=false -android.nonFinalResIds=false diff --git a/example/android/gradle/wrapper/gradle-wrapper.jar b/example/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..13372ae Binary files /dev/null and b/example/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index df97d72..ac3b479 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip -networkTimeout=10000 -validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip diff --git a/example/android/gradlew b/example/android/gradlew new file mode 100755 index 0000000..9d82f78 --- /dev/null +++ b/example/android/gradlew @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/example/android/gradlew.bat b/example/android/gradlew.bat new file mode 100644 index 0000000..aec9973 --- /dev/null +++ b/example/android/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/example/android/settings.gradle b/example/android/settings.gradle deleted file mode 100644 index de88743..0000000 --- a/example/android/settings.gradle +++ /dev/null @@ -1,25 +0,0 @@ -pluginManagement { - def flutterSdkPath = { - def properties = new Properties() - file("local.properties").withInputStream { properties.load(it) } - def flutterSdkPath = properties.getProperty("flutter.sdk") - assert flutterSdkPath != null, "flutter.sdk not set in local.properties" - return flutterSdkPath - }() - - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -plugins { - id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version '8.8.0' apply false - id "org.jetbrains.kotlin.android" version "1.7.10" apply false -} - -include ":app" diff --git a/example/android/settings.gradle.kts b/example/android/settings.gradle.kts new file mode 100644 index 0000000..fb605bc --- /dev/null +++ b/example/android/settings.gradle.kts @@ -0,0 +1,26 @@ +pluginManagement { + val flutterSdkPath = + run { + val properties = java.util.Properties() + file("local.properties").inputStream().use { properties.load(it) } + val flutterSdkPath = properties.getProperty("flutter.sdk") + require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } + flutterSdkPath + } + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id("dev.flutter.flutter-plugin-loader") version "1.0.0" + id("com.android.application") version "8.9.1" apply false + id("org.jetbrains.kotlin.android") version "2.1.0" apply false +} + +include(":app") diff --git a/example/ios/.gitignore b/example/ios/.gitignore deleted file mode 100644 index e96ef60..0000000 --- a/example/ios/.gitignore +++ /dev/null @@ -1,32 +0,0 @@ -*.mode1v3 -*.mode2v3 -*.moved-aside -*.pbxuser -*.perspectivev3 -**/*sync/ -.sconsign.dblite -.tags* -**/.vagrant/ -**/DerivedData/ -Icon? -**/Pods/ -**/.symlinks/ -profile -xcuserdata -**/.generated/ -Flutter/App.framework -Flutter/Flutter.framework -Flutter/Flutter.podspec -Flutter/Generated.xcconfig -Flutter/app.flx -Flutter/app.zip -Flutter/flutter_assets/ -Flutter/flutter_export_environment.sh -ServiceDefinitions.json -Runner/GeneratedPluginRegistrant.* - -# Exceptions to above rules. -!default.mode1v3 -!default.mode2v3 -!default.pbxuser -!default.perspectivev3 diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist index 8c6e561..1dc6cf7 100644 --- a/example/ios/Flutter/AppFrameworkInfo.plist +++ b/example/ios/Flutter/AppFrameworkInfo.plist @@ -3,7 +3,7 @@ CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) + en CFBundleExecutable App CFBundleIdentifier @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 12.0 + 13.0 diff --git a/example/ios/Flutter/Debug.xcconfig b/example/ios/Flutter/Debug.xcconfig index e8efba1..ec97fc6 100644 --- a/example/ios/Flutter/Debug.xcconfig +++ b/example/ios/Flutter/Debug.xcconfig @@ -1,2 +1,2 @@ -#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/example/ios/Flutter/Release.xcconfig b/example/ios/Flutter/Release.xcconfig index 399e934..c4855bf 100644 --- a/example/ios/Flutter/Release.xcconfig +++ b/example/ios/Flutter/Release.xcconfig @@ -1,2 +1,2 @@ -#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/example/ios/Podfile b/example/ios/Podfile index 2c068c4..620e46e 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -platform :ios, '12.0' +# platform :ios, '13.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' @@ -29,9 +29,11 @@ flutter_ios_podfile_setup target 'Runner' do use_frameworks! - use_modular_headers! flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end end post_install do |installer| diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index ca29ecb..f8be551 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -9,17 +9,28 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 3B5B8498EACC1EC5928B2C39 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF876297B32EC6E04F7E818F /* Pods_RunnerTests.framework */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 88F4A3FD2DC44C7129665E88 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC62EBC5D8990B3CF54CF3BD /* Pods_Runner.framework */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; - 9D934E032612994B00BDDA0B /* AdServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D934E022612994B00BDDA0B /* AdServices.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; - 9DF8055D24F9214A00A001CE /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9DF8055C24F9214900A001CE /* AdSupport.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; - 9DF8055F24F9215100A001CE /* AppTrackingTransparency.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9DF8055E24F9215100A001CE /* AppTrackingTransparency.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; - 9DF8056124F9215600A001CE /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9DF8056024F9215600A001CE /* StoreKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; - B6025B3595AA1F9CF9F139AC /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 356E070BF8DE437AF960ADE2 /* Pods_Runner.framework */; }; + 9DE448242E0E7D6C008D9604 /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9DE448232E0E7D6C008D9604 /* AdSupport.framework */; }; + 9DE448262E0E7D71008D9604 /* AdServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9DE448252E0E7D71008D9604 /* AdServices.framework */; }; + 9DE448282E0E7D76008D9604 /* AppTrackingTransparency.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9DE448272E0E7D76008D9604 /* AppTrackingTransparency.framework */; }; + 9DE4482A2E0E7D7A008D9604 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9DE448292E0E7D7A008D9604 /* StoreKit.framework */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXCopyFilesBuildPhase section */ 9705A1C41CF9048500538489 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; @@ -34,12 +45,13 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 08D505F93980F9E52B00EC1A /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 33F9C572C86811AA0C86097B /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - 356E070BF8DE437AF960ADE2 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 303AB0B2394CD08FECD86B96 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 5F31F7FF83E0ADA732B55E3B /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 5B88428D631C6DEE5FAD69F8 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + 5D79E5F82EB64B9CD0A679F8 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; @@ -50,40 +62,52 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 9D934E022612994B00BDDA0B /* AdServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdServices.framework; path = System/Library/Frameworks/AdServices.framework; sourceTree = SDKROOT; }; - 9DD8A2442DF887F700A682DE /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; - 9DF8055A24F9214500A001CE /* iAd.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = iAd.framework; path = System/Library/Frameworks/iAd.framework; sourceTree = SDKROOT; }; - 9DF8055C24F9214900A001CE /* AdSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdSupport.framework; path = System/Library/Frameworks/AdSupport.framework; sourceTree = SDKROOT; }; - 9DF8055E24F9215100A001CE /* AppTrackingTransparency.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppTrackingTransparency.framework; path = System/Library/Frameworks/AppTrackingTransparency.framework; sourceTree = SDKROOT; }; - 9DF8056024F9215600A001CE /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; }; - 9DF8056224F9215B00A001CE /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; }; - E1131B9CA4E134D6F01B8E27 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 9D70DCE02E13E63100BC089B /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 9DE448232E0E7D6C008D9604 /* AdSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdSupport.framework; path = System/Library/Frameworks/AdSupport.framework; sourceTree = SDKROOT; }; + 9DE448252E0E7D71008D9604 /* AdServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdServices.framework; path = System/Library/Frameworks/AdServices.framework; sourceTree = SDKROOT; }; + 9DE448272E0E7D76008D9604 /* AppTrackingTransparency.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppTrackingTransparency.framework; path = System/Library/Frameworks/AppTrackingTransparency.framework; sourceTree = SDKROOT; }; + 9DE448292E0E7D7A008D9604 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; }; + ACF65A8BFDE5CDDA65DDBFDC /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + BF876297B32EC6E04F7E818F /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + DC62EBC5D8990B3CF54CF3BD /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E65025A74749A988F3B85BFF /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 8F001A81A9C29896C07C7D24 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3B5B8498EACC1EC5928B2C39 /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EB1CF9000F007C117D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 9D934E032612994B00BDDA0B /* AdServices.framework in Frameworks */, - 9DF8055F24F9215100A001CE /* AppTrackingTransparency.framework in Frameworks */, - 9DF8055D24F9214A00A001CE /* AdSupport.framework in Frameworks */, - 9DF8056124F9215600A001CE /* StoreKit.framework in Frameworks */, - B6025B3595AA1F9CF9F139AC /* Pods_Runner.framework in Frameworks */, + 88F4A3FD2DC44C7129665E88 /* Pods_Runner.framework in Frameworks */, + 9DE448282E0E7D76008D9604 /* AppTrackingTransparency.framework in Frameworks */, + 9DE4482A2E0E7D7A008D9604 /* StoreKit.framework in Frameworks */, + 9DE448242E0E7D6C008D9604 /* AdSupport.framework in Frameworks */, + 9DE448262E0E7D71008D9604 /* AdServices.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 19C31DF7D5B6DFB9032481D8 /* Pods */ = { + 4ECF1B705801FDADAE8C879B /* Frameworks */ = { isa = PBXGroup; children = ( - E1131B9CA4E134D6F01B8E27 /* Pods-Runner.debug.xcconfig */, - 5F31F7FF83E0ADA732B55E3B /* Pods-Runner.release.xcconfig */, - 33F9C572C86811AA0C86097B /* Pods-Runner.profile.xcconfig */, + 9DE448292E0E7D7A008D9604 /* StoreKit.framework */, + 9DE448272E0E7D76008D9604 /* AppTrackingTransparency.framework */, + 9DE448252E0E7D71008D9604 /* AdServices.framework */, + 9DE448232E0E7D6C008D9604 /* AdSupport.framework */, + DC62EBC5D8990B3CF54CF3BD /* Pods_Runner.framework */, + BF876297B32EC6E04F7E818F /* Pods_RunnerTests.framework */, ); - path = Pods; + name = Frameworks; sourceTree = ""; }; 9740EEB11CF90186004384FC /* Flutter */ = { @@ -103,8 +127,8 @@ 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, - 9DF8055924F9214500A001CE /* Frameworks */, - 19C31DF7D5B6DFB9032481D8 /* Pods */, + EB003BCC806A08DFF19BEDB2 /* Pods */, + 4ECF1B705801FDADAE8C879B /* Frameworks */, ); sourceTree = ""; }; @@ -112,6 +136,7 @@ isa = PBXGroup; children = ( 97C146EE1CF9000F007C117D /* Runner.app */, + 9D70DCE02E13E63100BC089B /* RunnerTests.xctest */, ); name = Products; sourceTree = ""; @@ -119,7 +144,6 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( - 9DD8A2442DF887F700A682DE /* Runner.entitlements */, 97C146FA1CF9000F007C117D /* Main.storyboard */, 97C146FD1CF9000F007C117D /* Assets.xcassets */, 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, @@ -132,35 +156,53 @@ path = Runner; sourceTree = ""; }; - 9DF8055924F9214500A001CE /* Frameworks */ = { + EB003BCC806A08DFF19BEDB2 /* Pods */ = { isa = PBXGroup; children = ( - 9D934E022612994B00BDDA0B /* AdServices.framework */, - 9DF8056224F9215B00A001CE /* CoreTelephony.framework */, - 9DF8056024F9215600A001CE /* StoreKit.framework */, - 9DF8055E24F9215100A001CE /* AppTrackingTransparency.framework */, - 9DF8055C24F9214900A001CE /* AdSupport.framework */, - 9DF8055A24F9214500A001CE /* iAd.framework */, - 356E070BF8DE437AF960ADE2 /* Pods_Runner.framework */, + 303AB0B2394CD08FECD86B96 /* Pods-Runner.debug.xcconfig */, + 5D79E5F82EB64B9CD0A679F8 /* Pods-Runner.release.xcconfig */, + ACF65A8BFDE5CDDA65DDBFDC /* Pods-Runner.profile.xcconfig */, + 5B88428D631C6DEE5FAD69F8 /* Pods-RunnerTests.debug.xcconfig */, + E65025A74749A988F3B85BFF /* Pods-RunnerTests.release.xcconfig */, + 08D505F93980F9E52B00EC1A /* Pods-RunnerTests.profile.xcconfig */, ); - name = Frameworks; + path = Pods; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + A38622A5BE32A9FB39BD74ED /* [CP] Check Pods Manifest.lock */, + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + 8F001A81A9C29896C07C7D24 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 9D70DCE02E13E63100BC089B /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; 97C146ED1CF9000F007C117D /* Runner */ = { isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - 432950737933D1855DAFE804 /* [CP] Check Pods Manifest.lock */, + D6E8E1968FC2B8AB21EC215F /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - 8CC0374ACA4499C045686AA1 /* [CP] Embed Pods Frameworks */, + A0A004338F2FA5B43EBB0BB5 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -177,9 +219,14 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { + BuildIndependentTargetsInParallel = YES; LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; LastSwiftMigration = 1100; @@ -200,11 +247,19 @@ projectRoot = ""; targets = ( 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EC1CF9000F007C117D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -235,29 +290,22 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; - 432950737933D1855DAFE804 /* [CP] Check Pods Manifest.lock */ = { + 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( ); + name = "Run Script"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; - 8CC0374ACA4499C045686AA1 /* [CP] Embed Pods Frameworks */ = { + A0A004338F2FA5B43EBB0BB5 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -274,24 +322,60 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 9740EEB61CF901F6004384FC /* Run Script */ = { + A38622A5BE32A9FB39BD74ED /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "Run Script"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + D6E8E1968FC2B8AB21EC215F /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EA1CF9000F007C117D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -303,6 +387,14 @@ }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin PBXVariantGroup section */ 97C146FA1CF9000F007C117D /* Main.storyboard */ = { isa = PBXVariantGroup; @@ -327,6 +419,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -346,7 +439,6 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -357,6 +449,7 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -365,10 +458,10 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; + SUPPORTED_PLATFORMS = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -380,24 +473,14 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = QGUGW9AUMK; ENABLE_BITCODE = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); PRODUCT_BUNDLE_IDENTIFIER = com.adjust.examples; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -406,10 +489,61 @@ }; name = Profile; }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5B88428D631C6DEE5FAD69F8 /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.adjust.examples.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E65025A74749A988F3B85BFF /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.adjust.examples.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 08D505F93980F9E52B00EC1A /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.adjust.examples.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; 97C147031CF9000F007C117D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -429,7 +563,6 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -440,6 +573,7 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -454,7 +588,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -466,6 +600,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -485,7 +620,6 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -496,6 +630,7 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -504,10 +639,10 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; + SUPPORTED_PLATFORMS = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; TARGETED_DEVICE_FAMILY = "1,2"; @@ -521,24 +656,14 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = QGUGW9AUMK; ENABLE_BITCODE = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); PRODUCT_BUNDLE_IDENTIFIER = com.adjust.examples; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -554,24 +679,14 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = QGUGW9AUMK; ENABLE_BITCODE = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); PRODUCT_BUNDLE_IDENTIFIER = com.adjust.examples; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -583,6 +698,16 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 4590184..e3773d4 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -26,6 +26,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" shouldUseLaunchSchemeArgsEnv = "YES"> + + + + Bool { GeneratedPluginRegistrant.register(with: self) - if let url = launchOptions?[.url] as? URL { - Adjust.processDeeplink(ADJDeeplink(deeplink: url)!) - } return super.application(application, didFinishLaunchingWithOptions: launchOptions) } - -override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { - NSLog("Scheme based deep link opened an app: %@", url.absoluteString) - // add your code below to handle deep link - // (e.g., open deep link content) - // url object contains the deep link - - // Call the below method to send deep link to Adjust backend - Adjust.processDeeplink(ADJDeeplink(deeplink: url)!) - return true - } - -override func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { - if (userActivity.activityType == NSUserActivityTypeBrowsingWeb) { - NSLog("Universal link opened an app: %@", userActivity.webpageURL!.absoluteString) - // Pass deep link to Adjust in order to potentially reattribute user. - Adjust.processDeeplink(ADJDeeplink(deeplink: userActivity.webpageURL!)!) - } - return true - } } diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png index 28c6bf0..7353c41 100644 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png index 2ccbfd9..797d452 100644 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png index f091b6b..6ed2d93 100644 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png index 4cde121..4cd7b00 100644 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png index d0ef06e..fe73094 100644 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png index dcdc230..321773c 100644 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png index 2ccbfd9..797d452 100644 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png index c8f9ed8..502f463 100644 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png index a6d6b86..0ec3034 100644 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png index a6d6b86..0ec3034 100644 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png index 75b2d16..e9f5fea 100644 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png index c4df70d..84ac32a 100644 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png index 6a84f41..8953cba 100644 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png index d0e1f58..0467bf1 100644 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist index dd50c28..04edb1a 100644 --- a/example/ios/Runner/Info.plist +++ b/example/ios/Runner/Info.plist @@ -6,6 +6,8 @@ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + AdjustExample CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -13,31 +15,19 @@ CFBundleInfoDictionaryVersion 6.0 CFBundleName - example + AdjustExample CFBundlePackageType APPL CFBundleShortVersionString $(FLUTTER_BUILD_NAME) CFBundleSignature ???? - CFBundleURLTypes - - - CFBundleTypeRole - com.adjust.examples - CFBundleURLSchemes - - adjustexample - - - - CFBundleVersion $(FLUTTER_BUILD_NUMBER) LSRequiresIPhoneOS NSUserTrackingUsageDescription - This identifier will be used to deliver personalized ads and improve app analytics. + This is needed to access IDFA UIApplicationSupportsIndirectInputEvents UILaunchStoryboardName @@ -57,7 +47,5 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight - UIViewControllerBasedStatusBarAppearance - diff --git a/example/ios/Runner/Runner.entitlements b/example/ios/Runner/Runner.entitlements deleted file mode 100644 index 5df5cf7..0000000 --- a/example/ios/Runner/Runner.entitlements +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - diff --git a/example/lib/main.dart b/example/lib/main.dart index 73ceaa9..a52f264 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,435 +1,603 @@ import 'package:adjust_sdk/adjust.dart'; import 'package:adjust_sdk/adjust_attribution.dart'; import 'package:adjust_sdk/adjust_config.dart'; +import 'package:adjust_sdk/adjust_event.dart'; import 'package:adjust_sdk/adjust_event_failure.dart'; import 'package:adjust_sdk/adjust_event_success.dart'; import 'package:adjust_sdk/adjust_session_failure.dart'; import 'package:adjust_sdk/adjust_session_success.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'util.dart'; - void main() { - runApp(MyApp()); + runApp(const AdjustExampleApp()); } -class MyApp extends StatelessWidget { - // This widget is the root of your application. +/// main application widget for Adjust Flutter Example App +class AdjustExampleApp extends StatelessWidget { + const AdjustExampleApp({super.key}); + @override Widget build(BuildContext context) { return MaterialApp( - title: 'Flutter Demo', + title: 'Adjust Example', + debugShowCheckedModeBanner: false, theme: ThemeData( - // This is the theme of your application. - // - // Try running your application with "flutter run". You'll see the - // application has a blue toolbar. Then, without quitting the app, try - // changing the primarySwatch below to Colors.green and then invoke - // "hot reload" (press "r" in the console where you ran "flutter run", - // or simply save your changes to "hot reload" in a Flutter IDE). - // Notice that the counter didn't reset back to zero; the application - // is not restarted. primarySwatch: Colors.blue, - // This makes the visual density adapt to the platform that you run - // the app on. For desktop platforms, the controls will be smaller and - // closer together (more dense) than on mobile platforms. visualDensity: VisualDensity.adaptivePlatformDensity, + useMaterial3: true, + scaffoldBackgroundColor: const Color(0xFFF5F5F5), ), - home: MyHomePage(title: 'Flutter Demo Home Page'), + home: const HomePage(), ); } } -class MyHomePage extends StatefulWidget { - MyHomePage({Key? key, this.title}) : super(key: key); - - // This widget is the home page of your application. It is stateful, meaning - // that it has a State object (defined below) that contains fields that affect - // how it looks. - - // This class is the configuration for the state. It holds the values (in this - // case the title) provided by the parent (in this case the App widget) and - // used by the build method of the State. Fields in a Widget subclass are - // always marked "final". - - final String? title; +/// home page showcasing Adjust SDK functionality +class HomePage extends StatefulWidget { + const HomePage({super.key}); @override - _MyHomePageState createState() => _MyHomePageState(); + State createState() => _HomePageState(); } -class _MyHomePageState extends State with WidgetsBindingObserver { - bool _isSdkEnabled = true; +class _HomePageState extends State with WidgetsBindingObserver { + // event tokens for demonstration + static const String _eventTokenSimple = 'g3mfiw'; + static const String _eventTokenRevenue = 'a4fd35'; + static const String _eventTokenCallback = '34vgg9'; + static const String _eventTokenPartner = 'w788qs'; + + // adjust configuration constants + static const String _appToken = '2fm9gkqubvpc'; + static const AdjustEnvironment _environment = AdjustEnvironment.sandbox; + static const AdjustLogLevel _logLevel = AdjustLogLevel.verbose; + + // adjust brand colors + static const Color _adjustNavy = Color(0xFF1B2951); + static const Color _adjustNavyLight = Color(0xFF2A3A5C); + + // ui state + String _toggleButtonText = 'Toggle SDK'; + bool _isLoading = false; @override - initState() { + void initState() { super.initState(); - WidgetsBinding.instance!.addObserver(this); - initPlatformState(); + WidgetsBinding.instance.addObserver(this); + _initializeAdjustSdk(); + _updateToggleButtonText(); } @override void dispose() { - WidgetsBinding.instance!.removeObserver(this); + WidgetsBinding.instance.removeObserver(this); super.dispose(); } - @override - void didChangeAppLifecycleState(AppLifecycleState state) { - switch (state) { - case AppLifecycleState.inactive: - break; - case AppLifecycleState.resumed: - break; - case AppLifecycleState.paused: - break; - case AppLifecycleState.detached: - break; + /// initialize the Adjust SDK with configuration + Future _initializeAdjustSdk() async { + setState(() => _isLoading = true); + + try { + final config = AdjustConfig(_appToken, _environment); + config.logLevel = _logLevel; + + // configure attribution callback + config.attributionCallback = _handleAttributionCallback; + + // configure session callbacks + config.sessionSuccessCallback = _handleSessionSuccess; + config.sessionFailureCallback = _handleSessionFailure; + + // configure event callbacks + config.eventSuccessCallback = _handleEventSuccess; + config.eventFailureCallback = _handleEventFailure; + + // configure deeplink callback + config.deferredDeeplinkCallback = _handleDeferredDeeplink; + + // configure SKAN callback + config.skanUpdatedCallback = _handleSkanUpdate; + + // setup global parameters for demonstration + _setupGlobalParameters(); + + // initialize the SDK + Adjust.initSdk(config); + + print('[AdjustExample]: SDK initialized successfully'); + } catch (e) { + print('[AdjustExample]: Failed to initialize SDK: $e'); + } finally { + setState(() => _isLoading = false); } } - // Platform messages are asynchronous, so we initialize in an async method. - initPlatformState() async { - AdjustConfig config = - new AdjustConfig('2fm9gkqubvpc', AdjustEnvironment.sandbox); - config.logLevel = AdjustLogLevel.verbose; - - config.attributionCallback = (AdjustAttribution attributionChangedData) { - print('[Adjust]: Attribution changed!'); - - if (attributionChangedData.trackerToken != null) { - print( - '[Adjust]: Tracker token: ' + attributionChangedData.trackerToken!); - } - if (attributionChangedData.trackerName != null) { - print('[Adjust]: Tracker name: ' + attributionChangedData.trackerName!); - } - if (attributionChangedData.campaign != null) { - print('[Adjust]: Campaign: ' + attributionChangedData.campaign!); - } - if (attributionChangedData.network != null) { - print('[Adjust]: Network: ' + attributionChangedData.network!); - } - if (attributionChangedData.creative != null) { - print('[Adjust]: Creative: ' + attributionChangedData.creative!); - } - if (attributionChangedData.adgroup != null) { - print('[Adjust]: Adgroup: ' + attributionChangedData.adgroup!); - } - if (attributionChangedData.clickLabel != null) { - print('[Adjust]: Click label: ' + attributionChangedData.clickLabel!); - } - if (attributionChangedData.costType != null) { - print('[Adjust]: Cost type: ' + attributionChangedData.costType!); - } - if (attributionChangedData.costAmount != null) { - print('[Adjust]: Cost amount: ' + - attributionChangedData.costAmount!.toString()); - } - if (attributionChangedData.costCurrency != null) { - print( - '[Adjust]: Cost currency: ' + attributionChangedData.costCurrency!); - } - }; - - config.sessionSuccessCallback = (AdjustSessionSuccess sessionSuccessData) { - print('[Adjust]: Session tracking success!'); - - if (sessionSuccessData.message != null) { - print('[Adjust]: Message: ' + sessionSuccessData.message!); - } - if (sessionSuccessData.timestamp != null) { - print('[Adjust]: Timestamp: ' + sessionSuccessData.timestamp!); - } - if (sessionSuccessData.adid != null) { - print('[Adjust]: Adid: ' + sessionSuccessData.adid!); - } - if (sessionSuccessData.jsonResponse != null) { - print('[Adjust]: JSON response: ' + sessionSuccessData.jsonResponse!); - } - }; - - config.sessionFailureCallback = (AdjustSessionFailure sessionFailureData) { - print('[Adjust]: Session tracking failure!'); + /// setup global callback and partner parameters + void _setupGlobalParameters() { + // add global parameters + Adjust.addGlobalCallbackParameter('scp_foo_1', 'scp_bar'); + Adjust.addGlobalCallbackParameter('scp_foo_2', 'scp_value'); + Adjust.addGlobalPartnerParameter('spp_foo_1', 'spp_bar'); + Adjust.addGlobalPartnerParameter('spp_foo_2', 'spp_value'); + + // demonstrate parameter removal + Adjust.removeGlobalCallbackParameter('scp_foo_1'); + Adjust.removeGlobalPartnerParameter('spp_foo_1'); + + // clear all parameters (for demonstration) + Adjust.removeGlobalCallbackParameters(); + Adjust.removeGlobalPartnerParameters(); + } - if (sessionFailureData.message != null) { - print('[Adjust]: Message: ' + sessionFailureData.message!); - } - if (sessionFailureData.timestamp != null) { - print('[Adjust]: Timestamp: ' + sessionFailureData.timestamp!); - } - if (sessionFailureData.adid != null) { - print('[Adjust]: Adid: ' + sessionFailureData.adid!); - } - if (sessionFailureData.willRetry != null) { - print( - '[Adjust]: Will retry: ' + sessionFailureData.willRetry.toString()); - } - if (sessionFailureData.jsonResponse != null) { - print('[Adjust]: JSON response: ' + sessionFailureData.jsonResponse!); - } + /// handle attribution updates + void _handleAttributionCallback(AdjustAttribution attribution) { + print('[AdjustExample]: Attribution changed!'); + + final attributionData = { + 'Tracker token': attribution.trackerToken, + 'Tracker name': attribution.trackerName, + 'Campaign': attribution.campaign, + 'Network': attribution.network, + 'Creative': attribution.creative, + 'Adgroup': attribution.adgroup, + 'Click label': attribution.clickLabel, + 'Cost type': attribution.costType, + 'Cost amount': attribution.costAmount?.toString(), + 'Cost currency': attribution.costCurrency, + 'FB install referrer': attribution.fbInstallReferrer, }; - config.eventSuccessCallback = (AdjustEventSuccess eventSuccessData) { - print('[Adjust]: Event tracking success!'); - - if (eventSuccessData.eventToken != null) { - print('[Adjust]: Event token: ' + eventSuccessData.eventToken!); - } - if (eventSuccessData.message != null) { - print('[Adjust]: Message: ' + eventSuccessData.message!); - } - if (eventSuccessData.timestamp != null) { - print('[Adjust]: Timestamp: ' + eventSuccessData.timestamp!); - } - if (eventSuccessData.adid != null) { - print('[Adjust]: Adid: ' + eventSuccessData.adid!); - } - if (eventSuccessData.callbackId != null) { - print('[Adjust]: Callback ID: ' + eventSuccessData.callbackId!); + attributionData.forEach((key, value) { + if (value != null) { + print('[AdjustExample]: $key: $value'); } - if (eventSuccessData.jsonResponse != null) { - print('[Adjust]: JSON response: ' + eventSuccessData.jsonResponse!); - } - }; + }); - config.eventFailureCallback = (AdjustEventFailure eventFailureData) { - print('[Adjust]: Event tracking failure!'); + if (attribution.jsonResponse != null) { + print('[AdjustExample]: JSON response: ${attribution.jsonResponse}'); + } + } - if (eventFailureData.eventToken != null) { - print('[Adjust]: Event token: ' + eventFailureData.eventToken!); - } - if (eventFailureData.message != null) { - print('[Adjust]: Message: ' + eventFailureData.message!); - } - if (eventFailureData.timestamp != null) { - print('[Adjust]: Timestamp: ' + eventFailureData.timestamp!); - } - if (eventFailureData.adid != null) { - print('[Adjust]: Adid: ' + eventFailureData.adid!); - } - if (eventFailureData.callbackId != null) { - print('[Adjust]: Callback ID: ' + eventFailureData.callbackId!); - } - if (eventFailureData.willRetry != null) { - print('[Adjust]: Will retry: ' + eventFailureData.willRetry.toString()); - } - if (eventFailureData.jsonResponse != null) { - print('[Adjust]: JSON response: ' + eventFailureData.jsonResponse!); - } - }; + /// handle successful session tracking + void _handleSessionSuccess(AdjustSessionSuccess sessionSuccess) { + print('[AdjustExample]: Session tracking success!'); + _logSessionData('Success', sessionSuccess.message, sessionSuccess.timestamp, + sessionSuccess.adid, sessionSuccess.jsonResponse); + } - config.deferredDeeplinkCallback = (String? uri) { - print('[Adjust]: Received deferred deeplink: ' + uri!); - }; + /// handle failed session tracking + void _handleSessionFailure(AdjustSessionFailure sessionFailure) { + print('[AdjustExample]: Session tracking failure!'); + _logSessionData('Failure', sessionFailure.message, sessionFailure.timestamp, + sessionFailure.adid, sessionFailure.jsonResponse); + + if (sessionFailure.willRetry != null) { + print('[AdjustExample]: Will retry: ${sessionFailure.willRetry}'); + } + } - config.skanUpdatedCallback = (Map skanUpdateData) { - print('[Adjust]: Received SKAN update information!'); - if (skanUpdateData["conversion_value"] != null) { - print('[Adjust]: Conversion value: ' + skanUpdateData["conversion_value"]!); - } - if (skanUpdateData["coarse_value"] != null) { - print('[Adjust]: Coarse value: ' + skanUpdateData["coarse_value"]!); - } - if (skanUpdateData["lock_window"] != null) { - print('[Adjust]: Lock window: ' + skanUpdateData["lock_window"]!); - } - if (skanUpdateData["error"] != null) { - print('[Adjust]: Error: ' + skanUpdateData["error"]!); - } - }; + /// helper method to log session data + void _logSessionData(String type, String? message, String? timestamp, + String? adid, String? jsonResponse) { + if (message != null) print('[AdjustExample]: Message: $message'); + if (timestamp != null) print('[AdjustExample]: Timestamp: $timestamp'); + if (adid != null) print('[AdjustExample]: Adid: $adid'); + if (jsonResponse != null) print('[AdjustExample]: JSON response: $jsonResponse'); + } - // Add session callback parameters. - Adjust.addGlobalCallbackParameter('scp_foo_1', 'scp_bar'); - Adjust.addGlobalCallbackParameter('scp_foo_2', 'scp_value'); + /// handle successful event tracking + void _handleEventSuccess(AdjustEventSuccess eventSuccess) { + print('[AdjustExample]: Event tracking success!'); + _logEventData('Success', eventSuccess.eventToken, eventSuccess.message, + eventSuccess.timestamp, eventSuccess.adid, eventSuccess.callbackId, + eventSuccess.jsonResponse, null); + } - // Add session Partner parameters. - Adjust.addGlobalPartnerParameter('spp_foo_1', 'spp_bar'); - Adjust.addGlobalPartnerParameter('spp_foo_2', 'spp_value'); + /// handle failed event tracking + void _handleEventFailure(AdjustEventFailure eventFailure) { + print('[AdjustExample]: Event tracking failure!'); + _logEventData('Failure', eventFailure.eventToken, eventFailure.message, + eventFailure.timestamp, eventFailure.adid, eventFailure.callbackId, + eventFailure.jsonResponse, eventFailure.willRetry); + } - // Remove session callback parameters. - Adjust.removeGlobalCallbackParameter('scp_foo_1'); - Adjust.removeGlobalPartnerParameter('spp_foo_1'); + /// helper method to log event data + void _logEventData(String type, String? eventToken, String? message, + String? timestamp, String? adid, String? callbackId, + String? jsonResponse, bool? willRetry) { + if (eventToken != null) print('[AdjustExample]: Event token: $eventToken'); + if (message != null) print('[AdjustExample]: Message: $message'); + if (timestamp != null) print('[AdjustExample]: Timestamp: $timestamp'); + if (adid != null) print('[AdjustExample]: Adid: $adid'); + if (callbackId != null) print('[AdjustExample]: Callback ID: $callbackId'); + if (willRetry != null) print('[AdjustExample]: Will retry: $willRetry'); + if (jsonResponse != null) print('[AdjustExample]: JSON response: $jsonResponse'); + } - // Clear all session callback parameters. - Adjust.removeGlobalCallbackParameters(); + /// handle deferred deeplinks + void _handleDeferredDeeplink(String? uri) { + print('[AdjustExample]: Received deferred deeplink: $uri'); + } - // Clear all session partner parameters. - Adjust.removeGlobalPartnerParameters(); + /// handle SKAN updates + void _handleSkanUpdate(Map skanData) { + print('[AdjustExample]: Received SKAN update information!'); + + final skanFields = { + 'conversion_value': 'Conversion value', + 'coarse_value': 'Coarse value', + 'lock_window': 'Lock window', + 'error': 'Error', + }; - // Ask for tracking consent. - Adjust.requestAppTrackingAuthorization().then((status) { - print('[Adjust]: Authorization status update!'); - final int statusInt = status.toInt(); - switch (statusInt) { - case 0: - print( - '[Adjust]: Authorization status update: ATTrackingManagerAuthorizationStatusNotDetermined'); - break; - case 1: - print( - '[Adjust]: Authorization status update: ATTrackingManagerAuthorizationStatusRestricted'); - break; - case 2: - print( - '[Adjust]: Authorization status update: ATTrackingManagerAuthorizationStatusDenied'); - break; - case 3: - print( - '[Adjust]: Authorization status update: ATTrackingManagerAuthorizationStatusAuthorized'); - break; + skanFields.forEach((key, description) { + if (skanData[key] != null) { + print('[AdjustExample]: $description: ${skanData[key]}'); } }); - - // start SDK - Adjust.initSdk(config); } @override Widget build(BuildContext context) { - return new CustomScrollView( - shrinkWrap: true, - slivers: [ - new SliverPadding( - padding: const EdgeInsets.all(20.0), - sliver: new SliverList( - delegate: new SliverChildListDelegate( - [ - const Padding(padding: const EdgeInsets.all(7.0)), - - Util.buildCupertinoButton( - 'Is Enabled ?', () => _showIsSdkEnabled()), - const Padding(padding: const EdgeInsets.all(7.0)), - - // Track simple event button. - Util.buildCupertinoButton('Track Simple Event', - () => Adjust.trackEvent(Util.buildSimpleEvent())), - const Padding(padding: const EdgeInsets.all(7.0)), - - // Track revenue event button. - Util.buildCupertinoButton('Track Revenue Event', - () => Adjust.trackEvent(Util.buildRevenueEvent())), - const Padding(padding: const EdgeInsets.all(7.0)), - - // Track callback event button. - Util.buildCupertinoButton('Track Callback Event', - () => Adjust.trackEvent(Util.buildCallbackEvent())), - const Padding(padding: const EdgeInsets.all(7.0)), - - // Track partner event button. - Util.buildCupertinoButton('Track Partner Event', - () => Adjust.trackEvent(Util.buildPartnerEvent())), - const Padding(padding: const EdgeInsets.all(7.0)), - - // Get Google Advertising Id. - Util.buildCupertinoButton( - 'Get Google AdId', - () => Adjust.getGoogleAdId().then((googleAdid) { - _showDialogMessage('Get Google Advertising Id', - 'Received Google Advertising Id: $googleAdid'); - })), - const Padding(padding: const EdgeInsets.all(7.0)), - - // Get Adjust identifier. - Util.buildCupertinoButton( - 'Get Adjust identifier', - () => Adjust.getAdid().then((adid) { - _showDialogMessage('Adjust identifier', - 'Received Adjust identifier: $adid'); - })), - const Padding(padding: const EdgeInsets.all(7.0)), - - // Get IDFA. - Util.buildCupertinoButton( - 'Get IDFA', - () => Adjust.getIdfa().then((idfa) { - _showDialogMessage('IDFA', 'Received IDFA: $idfa'); - })), - const Padding(padding: const EdgeInsets.all(7.0)), - - // Get attribution. - Util.buildCupertinoButton( - 'Get attribution', - () => Adjust.getAttribution().then((attribution) { - _showDialogMessage('Attribution', - 'Received attribution: ${attribution.toString()}'); - })), - const Padding(padding: const EdgeInsets.all(7.0)), - - // Enable / disable SDK. - new Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - // Is SDK enabled switch. - new Text( - _isSdkEnabled ? 'Enabled' : 'Disabled', - style: _isSdkEnabled - ? new TextStyle(fontSize: 32.0, color: Colors.green) - : new TextStyle(fontSize: 32.0, color: Colors.red), - ), - new CupertinoSwitch( - value: _isSdkEnabled, - onChanged: (bool value) { - setState(() { - if(value == true){ - Adjust.enable(); - }else { - Adjust.disable(); - } - _isSdkEnabled = value; - print('Switch state = $_isSdkEnabled'); - }); - }, - ), - ], - ), - const Padding(padding: const EdgeInsets.all(7.0)), - - // end + return Scaffold( + appBar: AppBar( + title: const Text( + 'Adjust Example', + style: TextStyle( + fontWeight: FontWeight.w600, + color: Colors.white, + ), + ), + centerTitle: true, + backgroundColor: _adjustNavy, + elevation: 0, + ), + body: Container( + width: double.infinity, + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [_adjustNavy, _adjustNavyLight], + ), + ), + child: SafeArea( + child: SingleChildScrollView( + padding: const EdgeInsets.all(20.0), + child: Column( + children: [ + // app header section + _buildHeaderSection(), + const SizedBox(height: 32), + + // loading indicator or action buttons + if (_isLoading) + _buildLoadingSection() + else + _buildActionButtons(), ], ), ), ), + ), + ); + } + + /// build the header section with app icon and description + Widget _buildHeaderSection() { + return Column( + children: [ + // app icon + Container( + width: 80, + height: 80, + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.1), + borderRadius: BorderRadius.circular(16), + ), + child: const Icon( + Icons.analytics_outlined, + size: 40, + color: Colors.white, + ), + ), + const SizedBox(height: 16), + + // app title and description + const Text( + 'Adjust SDK Demo', + style: TextStyle( + fontSize: 28, + fontWeight: FontWeight.bold, + color: Colors.white, + ), + ), + const SizedBox(height: 8), + Text( + 'Explore the full functionality of the Adjust SDK\nwith this example application', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + color: Colors.white.withOpacity(0.8), + height: 1.4, + ), + ), ], ); } - _showIsSdkEnabled() { + /// build loading section + Widget _buildLoadingSection() { + return Column( + children: [ + const CircularProgressIndicator( + color: Colors.white, + ), + const SizedBox(height: 16), + Text( + 'Initializing Adjust SDK...', + style: TextStyle( + color: Colors.white.withOpacity(0.8), + fontSize: 16, + ), + ), + ], + ); + } + + /// build all action buttons in organized sections + Widget _buildActionButtons() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // event tracking section + _buildSectionHeader('Event Tracking'), + const SizedBox(height: 16), + _buildActionButton('Track Simple Event', Icons.touch_app, _trackSimpleEvent), + const SizedBox(height: 12), + _buildActionButton('Track Revenue Event', Icons.monetization_on, _trackRevenueEvent), + const SizedBox(height: 12), + _buildActionButton('Track Callback Event', Icons.call_made, _trackCallbackEvent), + const SizedBox(height: 12), + _buildActionButton('Track Partner Event', Icons.handshake, _trackPartnerEvent), + + const SizedBox(height: 32), + + // device information section + _buildSectionHeader('Device Information'), + const SizedBox(height: 16), + _buildActionButton('Get Google AdId', Icons.android, _getGoogleAdId), + const SizedBox(height: 12), + _buildActionButton('Get Adjust Identifier', Icons.alternate_email, _getAdjustIdentifier), + const SizedBox(height: 12), + _buildActionButton('Get IDFA', Icons.phone_iphone, _getIdfa), + const SizedBox(height: 12), + _buildActionButton('Get Attribution', Icons.analytics, _getAttribution), + + const SizedBox(height: 32), + + // SDK control section + _buildSectionHeader('SDK Control'), + const SizedBox(height: 16), + _buildActionButton(_toggleButtonText, Icons.power_settings_new, _toggleSdkState), + const SizedBox(height: 12), + _buildActionButton('Is Enabled?', Icons.help_outline, _checkIfSdkEnabled), + ], + ); + } + + /// build section header + Widget _buildSectionHeader(String title) { + return Text( + title, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w600, + color: Colors.white, + ), + ); + } + + /// build enhanced action button with icon + Widget _buildActionButton(String text, IconData icon, VoidCallback onPressed) { + return SizedBox( + width: double.infinity, + height: 56, + child: ElevatedButton.icon( + onPressed: onPressed, + icon: Icon(icon, size: 20), + label: Text( + text, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + ), + ), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.white, + foregroundColor: _adjustNavy, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(28), + ), + elevation: 8, + shadowColor: Colors.black.withOpacity(0.3), + ), + ), + ); + } + + /// update toggle button text based on SDK state + void _updateToggleButtonText() { try { Adjust.isEnabled().then((isEnabled) { - _isSdkEnabled = isEnabled; - _showDialogMessage('SDK Enabled?', 'Adjust is enabled = $isEnabled'); + if (mounted) { + setState(() { + _toggleButtonText = isEnabled ? 'Disable SDK' : 'Enable SDK'; + }); + } }); } on PlatformException { - _showDialogMessage( - 'SDK Enabled?', 'No such method found in plugin: isEnabled'); + // keep default text if method not found } } - void _showDialogMessage(String title, String text, - [bool printToConsoleAlso = true]) { - if (printToConsoleAlso) { - print(text); + /// toggle SDK enabled/disabled state + void _toggleSdkState() { + try { + Adjust.isEnabled().then((isEnabled) { + if (isEnabled) { + Adjust.disable(); + print('[AdjustExample]: SDK disabled'); + _showDialog('SDK State', 'Adjust SDK has been disabled'); + } else { + Adjust.enable(); + print('[AdjustExample]: SDK enabled'); + _showDialog('SDK State', 'Adjust SDK has been enabled'); + } + // update button text after toggle + _updateToggleButtonText(); + }); + } on PlatformException { + _showDialog('Toggle SDK', 'No such method found in plugin: isEnabled'); } + } + /// check if SDK is currently enabled + void _checkIfSdkEnabled() { + try { + Adjust.isEnabled().then((isEnabled) { + _showDialog('SDK Enabled?', 'Adjust is enabled = $isEnabled'); + }); + } on PlatformException { + _showDialog('SDK Enabled?', 'No such method found in plugin: isEnabled'); + } + } + + /// track a simple event without additional parameters + void _trackSimpleEvent() { + final event = AdjustEvent(_eventTokenSimple); + Adjust.trackEvent(event); + print('[AdjustExample]: Simple event tracked'); + } + + /// track a revenue event with transaction details + void _trackRevenueEvent() { + final event = AdjustEvent(_eventTokenRevenue); + event.setRevenue(100.0, 'EUR'); + event.transactionId = 'DummyTransactionId'; + Adjust.trackEvent(event); + print('[AdjustExample]: Revenue event tracked (€100.00)'); + } + + /// track an event with callback parameters + void _trackCallbackEvent() { + final event = AdjustEvent(_eventTokenCallback); + event.addCallbackParameter('key1', 'value1'); + event.addCallbackParameter('key2', 'value2'); + Adjust.trackEvent(event); + print('[AdjustExample]: Callback event tracked with parameters'); + } + + /// track an event with partner parameters + void _trackPartnerEvent() { + final event = AdjustEvent(_eventTokenPartner); + event.addPartnerParameter('foo1', 'bar1'); + event.addPartnerParameter('foo2', 'bar2'); + Adjust.trackEvent(event); + print('[AdjustExample]: Partner event tracked with parameters'); + } + + /// get Google Advertising ID + void _getGoogleAdId() { + Adjust.getGoogleAdId().then((googleAdId) { + _showDialog('Google Advertising ID', 'Received Google Advertising Id:\n$googleAdId'); + }); + } + + /// get Adjust identifier + void _getAdjustIdentifier() { + Adjust.getAdid().then((adid) { + _showDialog('Adjust Identifier', 'Received Adjust identifier:\n$adid'); + }); + } + + /// get IDFA (iOS) + void _getIdfa() { + Adjust.getIdfa().then((idfa) { + _showDialog('IDFA', 'Received IDFA:\n$idfa'); + }); + } + + /// get current attribution information + void _getAttribution() { + Adjust.getAttribution().then((attribution) { + final attributionFields = { + 'Tracker token': attribution.trackerToken, + 'Tracker name': attribution.trackerName, + 'Campaign': attribution.campaign, + 'Network': attribution.network, + 'Creative': attribution.creative, + 'Adgroup': attribution.adgroup, + 'Click label': attribution.clickLabel, + 'Cost type': attribution.costType, + 'Cost amount': attribution.costAmount?.toString(), + 'Cost currency': attribution.costCurrency, + 'FB install referrer': attribution.fbInstallReferrer, + }; + + String attributionInfo = 'Attribution data:\n\n'; + attributionFields.forEach((key, value) { + if (value != null) { + attributionInfo += '$key: $value\n'; + } + }); + + if (attribution.jsonResponse != null) { + attributionInfo += '\nJSON response: ${attribution.jsonResponse}'; + } + + _showDialog('Attribution', attributionInfo); + }); + } + + /// show information dialog with enhanced styling + void _showDialog(String title, String message) { + print('[AdjustExample]: $title - $message'); + showDialog( context: context, builder: (BuildContext context) { - return new CupertinoAlertDialog( - title: Text(title), - content: Text(text), + return AlertDialog( + title: Text( + title, + style: const TextStyle( + fontWeight: FontWeight.w600, + color: _adjustNavy, + ), + ), + content: SingleChildScrollView( + child: Text( + message, + style: const TextStyle(fontSize: 14), + ), + ), actions: [ - new CupertinoDialogAction( - child: const Text('OK'), - onPressed: () { - Navigator.pop(context, 'OK'); - }, - ) + TextButton( + onPressed: () => Navigator.of(context).pop(), + style: TextButton.styleFrom( + foregroundColor: _adjustNavy, + ), + child: const Text( + 'OK', + style: TextStyle(fontWeight: FontWeight.w600), + ), + ), ], + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), ); }, ); diff --git a/example/lib/util.dart b/example/lib/util.dart deleted file mode 100644 index bdedf9a..0000000 --- a/example/lib/util.dart +++ /dev/null @@ -1,119 +0,0 @@ -import 'package:adjust_sdk/adjust_event.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; - -class Util { - static const String EVENT_TOKEN_SIMPLE = 'g3mfiw'; - static const String EVENT_TOKEN_REVENUE = 'a4fd35'; - static const String EVENT_TOKEN_CALLBACK = '34vgg9'; - static const String EVENT_TOKEN_PARTNER = 'w788qs'; - - static Widget buildRaisedButton(String text, Function action) { - return new Align( - alignment: const Alignment(0.0, -0.2), - child: new Column( - mainAxisSize: MainAxisSize.min, - children: [ - new ButtonBar( - mainAxisSize: MainAxisSize.min, - children: [ - new ElevatedButton( - child: Text(text), - onPressed: () { - action(); - }, - ), - ], - ), - ], - ), - ); - } - - static Widget buildCupertinoButton(String text, Function action) { - return new CupertinoButton( - child: Text(text), - color: CupertinoColors.activeBlue, - padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 30.0), - onPressed: action as void Function()?, - ); - } - - static Widget buildRaisedButtonRow(String text, Function action) { - return new Align( - alignment: const Alignment(0.0, -0.2), - child: new Container( - child: new Row( - mainAxisSize: MainAxisSize.min, - children: [ - new ElevatedButton( - child: Text(text), - onPressed: () { - action(); - }, - ), - ], - ), - margin: new EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0), - padding: new EdgeInsets.all(1.0), - decoration: - new BoxDecoration(border: new Border.all(color: Colors.black)), - ), - ); - } - - static AdjustEvent buildSimpleEvent() { - return new AdjustEvent(EVENT_TOKEN_SIMPLE); - } - - static AdjustEvent buildRevenueEvent() { - AdjustEvent event = new AdjustEvent(EVENT_TOKEN_REVENUE); - event.setRevenue(100.0, 'EUR'); - event.transactionId = 'DummyTransactionId'; - return event; - } - - static AdjustEvent buildCallbackEvent() { - AdjustEvent event = new AdjustEvent(EVENT_TOKEN_CALLBACK); - event.addCallbackParameter('key1', 'value1'); - event.addCallbackParameter('key2', 'value2'); - return event; - } - - static AdjustEvent buildPartnerEvent() { - AdjustEvent event = new AdjustEvent(EVENT_TOKEN_PARTNER); - event.addPartnerParameter('foo1', 'bar1'); - event.addPartnerParameter('foo2', 'bar2'); - return event; - } - - static void showMessage( - BuildContext context, String dialogText, String message) { - showDialog( - context: context, - builder: (_) => new AlertDialog( - title: new Text(dialogText), - content: new Text(message), - )); - } - - static void showDemoDialog( - {GlobalKey? scaffoldKey, - required BuildContext context, - Widget? child}) { - showDialog( - context: context, - barrierDismissible: false, - builder: (BuildContext context) => child!, - ).then((T? value) { - // The value passed to Navigator.pop() or null. - if (scaffoldKey != null && value != null) { - ScaffoldMessenger.of(context).showSnackBar( - new SnackBar( - content: new Text('You selected: $value'), - ), - ); - } - }); - } -} diff --git a/example/pubspec.yaml b/example/pubspec.yaml index e73f09c..55796b0 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -1,24 +1,10 @@ -name: example -description: Adjust Flutter Appliaction - -# The following line prevents the package from being accidentally published to -# pub.dev using `pub publish`. This is preferred for private packages. -publish_to: 'none' # Remove this line if you wish to publish to pub.dev - -# The following defines the version and build number for your application. -# A version number is three numbers separated by dots, like 1.2.43 -# followed by an optional build number separated by a +. -# Both the version and the builder number may be overridden in flutter -# build by specifying --build-name and --build-number, respectively. -# In Android, build-name is used as versionName while build-number used as versionCode. -# Read more about Android versioning at https://developer.android.com/studio/publish/versioning -# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. -# Read more about iOS versioning at -# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.0.0+1 +name: AdjustExample +description: "Adjust Flutter Example App" +publish_to: 'none' +version: 0.0.1 environment: - sdk: '>=2.12.0 <3.0.0' + sdk: ^3.9.0-277.0.dev dependencies: flutter: @@ -26,22 +12,15 @@ dependencies: adjust_sdk: path: ../ - - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^1.0.0 +dependency_overrides: + characters: ^1.4.1 + material_color_utilities: ^0.13.0 + meta: ^1.17.0 dev_dependencies: flutter_test: sdk: flutter + flutter_lints: ^6.0.0 -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter. flutter: - - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. uses-material-design: true diff --git a/example/test/widget_test.dart b/example/test/widget_test.dart deleted file mode 100644 index 747db1d..0000000 --- a/example/test/widget_test.dart +++ /dev/null @@ -1,30 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility that Flutter provides. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'package:example/main.dart'; - -void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(MyApp()); - - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); - }); -} diff --git a/ios/.gitignore b/ios/.gitignore deleted file mode 100644 index 956c87f..0000000 --- a/ios/.gitignore +++ /dev/null @@ -1,31 +0,0 @@ -.idea/ -.vagrant/ -.sconsign.dblite -.svn/ - -.DS_Store -*.swp -profile - -DerivedData/ -build/ - -*.pbxuser -*.mode1v3 -*.mode2v3 -*.perspectivev3 - -!default.pbxuser -!default.mode1v3 -!default.mode2v3 -!default.perspectivev3 - -xcuserdata - -*.moved-aside - -*.pyc -*sync/ -Icon? -.tags* - diff --git a/ios/adjust_sdk.podspec b/ios/adjust_sdk.podspec index ecba12c..9847be2 100644 --- a/ios/adjust_sdk.podspec +++ b/ios/adjust_sdk.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'adjust_sdk' - s.version = '5.4.0' + s.version = '5.4.1' s.summary = 'Adjust Flutter SDK for iOS platform' s.description = <<-DESC Adjust Flutter SDK for iOS platform. @@ -14,5 +14,5 @@ Pod::Spec.new do |s| s.ios.deployment_target = '12.0' s.dependency 'Flutter' - s.dependency 'Adjust', '5.4.0' + s.dependency 'Adjust', '5.4.1' end diff --git a/lib/adjust.dart b/lib/adjust.dart index 52f37e0..44980d2 100644 --- a/lib/adjust.dart +++ b/lib/adjust.dart @@ -24,7 +24,7 @@ import 'package:flutter/services.dart'; import 'package:meta/meta.dart'; class Adjust { - static const String _sdkPrefix = 'flutter5.4.0'; + static const String _sdkPrefix = 'flutter5.4.1'; static const MethodChannel _channel = const MethodChannel('com.adjust.sdk/api'); diff --git a/lib/adjust_app_store_purchase.dart b/lib/adjust_app_store_purchase.dart index 14b0c8b..afde1c0 100644 --- a/lib/adjust_app_store_purchase.dart +++ b/lib/adjust_app_store_purchase.dart @@ -15,12 +15,8 @@ class AdjustAppStorePurchase { Map get toMap { Map purchaseMap = new Map(); - if (_productId != null) { - purchaseMap['productId'] = _productId; - } - if (_transactionId != null) { - purchaseMap['transactionId'] = _transactionId; - } + purchaseMap['productId'] = _productId; + purchaseMap['transactionId'] = _transactionId; return purchaseMap; } diff --git a/lib/adjust_app_store_subscription.dart b/lib/adjust_app_store_subscription.dart index 0500617..66b0e20 100644 --- a/lib/adjust_app_store_subscription.dart +++ b/lib/adjust_app_store_subscription.dart @@ -35,15 +35,9 @@ class AdjustAppStoreSubscription { Map get toMap { Map subscriptionMap = new Map(); - if (_price != null) { - subscriptionMap['price'] = _price; - } - if (_currency != null) { - subscriptionMap['currency'] = _currency; - } - if (_transactionId != null) { - subscriptionMap['transactionId'] = _transactionId; - } + subscriptionMap['price'] = _price; + subscriptionMap['currency'] = _currency; + subscriptionMap['transactionId'] = _transactionId; if (transactionDate != null) { subscriptionMap['transactionDate'] = transactionDate; } diff --git a/lib/adjust_deeplink.dart b/lib/adjust_deeplink.dart index 8c4db04..f0da652 100644 --- a/lib/adjust_deeplink.dart +++ b/lib/adjust_deeplink.dart @@ -6,8 +6,6 @@ // Copyright (c) 2024-Present Adjust GmbH. All rights reserved. // -import 'dart:convert'; - class AdjustDeeplink { String deeplink; String? referrer; @@ -17,9 +15,7 @@ class AdjustDeeplink { Map get toMap { Map deeplinkMap = new Map(); - if (deeplink != null) { - deeplinkMap['deeplink'] = deeplink; - } + deeplinkMap['deeplink'] = deeplink; if (referrer != null) { deeplinkMap['referrer'] = referrer; } diff --git a/lib/adjust_play_store_purchase.dart b/lib/adjust_play_store_purchase.dart index 9a59def..052da78 100644 --- a/lib/adjust_play_store_purchase.dart +++ b/lib/adjust_play_store_purchase.dart @@ -15,12 +15,8 @@ class AdjustPlayStorePurchase { Map get toMap { Map purchaseMap = new Map(); - if (_productId != null) { - purchaseMap['productId'] = _productId; - } - if (_purchaseToken != null) { - purchaseMap['purchaseToken'] = _purchaseToken; - } + purchaseMap['productId'] = _productId; + purchaseMap['purchaseToken'] = _purchaseToken; return purchaseMap; } diff --git a/lib/adjust_play_store_subscription.dart b/lib/adjust_play_store_subscription.dart index 4924039..ad905ff 100644 --- a/lib/adjust_play_store_subscription.dart +++ b/lib/adjust_play_store_subscription.dart @@ -41,26 +41,14 @@ class AdjustPlayStoreSubscription { } Map get toMap { - Map subscriptionMap = new Map(); + Map subscriptionMap = new Map(); - if (_price != null) { - subscriptionMap['price'] = _price; - } - if (_currency != null) { - subscriptionMap['currency'] = _currency; - } - if (_sku != null) { - subscriptionMap['sku'] = _sku; - } - if (_orderId != null) { - subscriptionMap['orderId'] = _orderId; - } - if (_signature != null) { - subscriptionMap['signature'] = _signature; - } - if (_purchaseToken != null) { - subscriptionMap['purchaseToken'] = _purchaseToken; - } + subscriptionMap['price'] = _price; + subscriptionMap['currency'] = _currency; + subscriptionMap['sku'] = _sku; + subscriptionMap['orderId'] = _orderId; + subscriptionMap['signature'] = _signature; + subscriptionMap['purchaseToken'] = _purchaseToken; if (_billingStore != null) { subscriptionMap['billingStore'] = _billingStore; } diff --git a/lib/adjust_purchase_verification_result.dart b/lib/adjust_purchase_verification_result.dart index 41f9b21..265681d 100644 --- a/lib/adjust_purchase_verification_result.dart +++ b/lib/adjust_purchase_verification_result.dart @@ -6,8 +6,6 @@ // Copyright (c) 2020-Present Adjust GmbH. All rights reserved. // -import 'dart:convert'; - class AdjustPurchaseVerificationResult { final num code; final String message; @@ -35,15 +33,9 @@ class AdjustPurchaseVerificationResult { Map get toMap { Map verificationInfoMap = new Map(); - if (code != null) { - verificationInfoMap['code'] = code.toString(); - } - if (message != null) { - verificationInfoMap['message'] = message; - } - if (verificationStatus != null) { - verificationInfoMap['verificationStatus'] = verificationStatus; - } + verificationInfoMap['code'] = code.toString(); + verificationInfoMap['message'] = message; + verificationInfoMap['verificationStatus'] = verificationStatus; return verificationInfoMap; } diff --git a/lib/adjust_store_info.dart b/lib/adjust_store_info.dart index fbcbff2..cdfd680 100644 --- a/lib/adjust_store_info.dart +++ b/lib/adjust_store_info.dart @@ -6,8 +6,6 @@ // Copyright (c) 2025-Present Adjust GmbH. All rights reserved. // -import 'dart:convert'; - class AdjustStoreInfo { String? storeName; String? storeAppId; diff --git a/pubspec.yaml b/pubspec.yaml index 5e1780f..b50fca8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,10 +1,10 @@ name: adjust_sdk description: This is the Flutter SDK of Adjust™. You can read more about Adjust™ at adjust.com. homepage: https://github.com/adjust/flutter_sdk -version: 5.4.0 +version: 5.4.1 environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ">=2.12.0 <4.0.0" flutter: ">=1.10.0" dependencies: diff --git a/test/.gitignore b/test/.gitignore deleted file mode 100644 index 2bead7e..0000000 --- a/test/.gitignore +++ /dev/null @@ -1,118 +0,0 @@ -# Miscellaneous -*.class -*.lock -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# Visual Studio Code related -.classpath -.project -.settings/ -.vscode/ - -# Flutter repo-specific -/bin/cache/ -/bin/internal/bootstrap.bat -/bin/internal/bootstrap.sh -/bin/mingit/ -/dev/benchmarks/mega_gallery/ -/dev/bots/.recipe_deps -/dev/bots/android_tools/ -/dev/devicelab/ABresults*.json -/dev/docs/doc/ -/dev/docs/flutter.docs.zip -/dev/docs/lib/ -/dev/docs/pubspec.yaml -/dev/integration_tests/**/xcuserdata -/dev/integration_tests/**/Pods -/packages/flutter/coverage/ -version -analysis_benchmark.json - -# packages file containing multi-root paths -.packages.generated - -# Flutter/Dart/Pub related -**/doc/api/ -.dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies -**/generated_plugin_registrant.dart -.packages -.pub-cache/ -.pub/ -build/ -flutter_*.png -linked_*.ds -unlinked.ds -unlinked_spec.ds - -# Android related -**/android/**/gradle-wrapper.jar -**/android/.gradle -**/android/captures/ -**/android/gradlew -**/android/gradlew.bat -**/android/local.properties -**/android/**/GeneratedPluginRegistrant.java -**/android/key.properties -*.jks - -# iOS/XCode related -**/ios/**/*.mode1v3 -**/ios/**/*.mode2v3 -**/ios/**/*.moved-aside -**/ios/**/*.pbxuser -**/ios/**/*.perspectivev3 -**/ios/**/*sync/ -**/ios/**/.sconsign.dblite -**/ios/**/.tags* -**/ios/**/.vagrant/ -**/ios/**/DerivedData/ -**/ios/**/Icon? -**/ios/**/Pods/ -**/ios/**/.symlinks/ -**/ios/**/profile -**/ios/**/xcuserdata -**/ios/.generated/ -**/ios/Flutter/.last_build_id -**/ios/Flutter/App.framework -**/ios/Flutter/Flutter.framework -**/ios/Flutter/Flutter.podspec -**/ios/Flutter/Generated.xcconfig -**/ios/Flutter/ephemeral -**/ios/Flutter/app.flx -**/ios/Flutter/app.zip -**/ios/Flutter/flutter_assets/ -**/ios/Flutter/flutter_export_environment.sh -**/ios/ServiceDefinitions.json -**/ios/Runner/GeneratedPluginRegistrant.* - -# macOS -**/macos/Flutter/GeneratedPluginRegistrant.swift - -# Coverage -coverage/ - -# Symbols -app.*.symbols - -# Exceptions to above rules. -!**/ios/**/default.mode1v3 -!**/ios/**/default.mode2v3 -!**/ios/**/default.pbxuser -!**/ios/**/default.perspectivev3 -!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages -!/dev/ci/**/Gemfile.lock \ No newline at end of file diff --git a/test/android/.gitignore b/test/android/.gitignore deleted file mode 100644 index c6cbe56..0000000 --- a/test/android/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -*.iml -.gradle -/local.properties -/.idea/workspace.xml -/.idea/libraries -.DS_Store -/build -/captures diff --git a/test/android/build.gradle b/test/android/build.gradle index 92e44ee..98c5344 100644 --- a/test/android/build.gradle +++ b/test/android/build.gradle @@ -3,7 +3,7 @@ version '1.0-SNAPSHOT' buildscript { ext { - agp_version = '8.1.2' + agp_version = '8.2.1' } repositories { google() diff --git a/test/android/libs/adjust-test-options.jar b/test/android/libs/adjust-test-options.jar index e290b14..2e84644 100644 Binary files a/test/android/libs/adjust-test-options.jar and b/test/android/libs/adjust-test-options.jar differ diff --git a/test/android/src/main/java/com/adjust/test/lib/TestLibPlugin.java b/test/android/src/main/java/com/adjust/test/lib/TestLibPlugin.java index 2659c9f..26bf193 100644 --- a/test/android/src/main/java/com/adjust/test/lib/TestLibPlugin.java +++ b/test/android/src/main/java/com/adjust/test/lib/TestLibPlugin.java @@ -3,7 +3,7 @@ // Adjust SDK // // Created by Srdjan Tubin (@2beens) on 1st October 2018. -// Copyright (c) 2018-2021 Adjust GmbH. All rights reserved. +// Copyright (c) 2018-Present Adjust GmbH. All rights reserved. // package com.adjust.test.lib; diff --git a/test/app/.gitignore b/test/app/.gitignore deleted file mode 100644 index 2bead7e..0000000 --- a/test/app/.gitignore +++ /dev/null @@ -1,118 +0,0 @@ -# Miscellaneous -*.class -*.lock -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# Visual Studio Code related -.classpath -.project -.settings/ -.vscode/ - -# Flutter repo-specific -/bin/cache/ -/bin/internal/bootstrap.bat -/bin/internal/bootstrap.sh -/bin/mingit/ -/dev/benchmarks/mega_gallery/ -/dev/bots/.recipe_deps -/dev/bots/android_tools/ -/dev/devicelab/ABresults*.json -/dev/docs/doc/ -/dev/docs/flutter.docs.zip -/dev/docs/lib/ -/dev/docs/pubspec.yaml -/dev/integration_tests/**/xcuserdata -/dev/integration_tests/**/Pods -/packages/flutter/coverage/ -version -analysis_benchmark.json - -# packages file containing multi-root paths -.packages.generated - -# Flutter/Dart/Pub related -**/doc/api/ -.dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies -**/generated_plugin_registrant.dart -.packages -.pub-cache/ -.pub/ -build/ -flutter_*.png -linked_*.ds -unlinked.ds -unlinked_spec.ds - -# Android related -**/android/**/gradle-wrapper.jar -**/android/.gradle -**/android/captures/ -**/android/gradlew -**/android/gradlew.bat -**/android/local.properties -**/android/**/GeneratedPluginRegistrant.java -**/android/key.properties -*.jks - -# iOS/XCode related -**/ios/**/*.mode1v3 -**/ios/**/*.mode2v3 -**/ios/**/*.moved-aside -**/ios/**/*.pbxuser -**/ios/**/*.perspectivev3 -**/ios/**/*sync/ -**/ios/**/.sconsign.dblite -**/ios/**/.tags* -**/ios/**/.vagrant/ -**/ios/**/DerivedData/ -**/ios/**/Icon? -**/ios/**/Pods/ -**/ios/**/.symlinks/ -**/ios/**/profile -**/ios/**/xcuserdata -**/ios/.generated/ -**/ios/Flutter/.last_build_id -**/ios/Flutter/App.framework -**/ios/Flutter/Flutter.framework -**/ios/Flutter/Flutter.podspec -**/ios/Flutter/Generated.xcconfig -**/ios/Flutter/ephemeral -**/ios/Flutter/app.flx -**/ios/Flutter/app.zip -**/ios/Flutter/flutter_assets/ -**/ios/Flutter/flutter_export_environment.sh -**/ios/ServiceDefinitions.json -**/ios/Runner/GeneratedPluginRegistrant.* - -# macOS -**/macos/Flutter/GeneratedPluginRegistrant.swift - -# Coverage -coverage/ - -# Symbols -app.*.symbols - -# Exceptions to above rules. -!**/ios/**/default.mode1v3 -!**/ios/**/default.mode2v3 -!**/ios/**/default.pbxuser -!**/ios/**/default.perspectivev3 -!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages -!/dev/ci/**/Gemfile.lock \ No newline at end of file diff --git a/test/app/README.md b/test/app/README.md index 77323b2..81fd42e 100644 --- a/test/app/README.md +++ b/test/app/README.md @@ -1,16 +1,38 @@ -# app +# Adjust Flutter Test App -Adjust Flutter Test Application +A comprehensive test application for the Adjust Flutter SDK, designed to validate SDK functionality through automated testing. + +## Features + +- **Automated Test Execution**: Connects to test framework for automated SDK testing +- **Modern UI**: Clean, modern interface following Adjust design guidelines +- **Cross-Platform**: Supports both Android and iOS testing scenarios +- **Real-time Command Processing**: Executes test commands in real-time from test server ## Getting Started -This project is a starting point for a Flutter application. +1. **Prerequisites**: Make sure Flutter is installed and configured +2. **Install Dependencies**: Run `flutter pub get` in this directory +3. **Configure Test Server**: Update IP addresses in `main.dart` if needed +4. **Run the App**: Use `flutter run` to start the test application + +## Test Configuration + +The app connects to a test server for automated command execution: +- **Android**: Uses HTTPS connection on port 8443 +- **iOS**: Uses HTTP connection on port 8080 +- **WebSocket**: Control connection on port 1987 + +## Architecture -A few resources to get you started if this is your first Flutter project: +- `main.dart`: Main app entry point with modern UI +- `command.dart`: Command parsing and representation +- `command_executor.dart`: SDK method execution engine +- Test framework integration via `test_lib` package -- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) +## Usage -For help getting started with Flutter, view our -[online documentation](https://flutter.dev/docs), which offers tutorials, -samples, guidance on mobile development, and a full API reference. +1. Launch the app +2. Tap "Start Test Session" to begin automated testing +3. The app will connect to the test server and execute commands automatically +4. Monitor console output for test execution details diff --git a/test/app/android/.gitignore b/test/app/android/.gitignore deleted file mode 100644 index 0a741cb..0000000 --- a/test/app/android/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -gradle-wrapper.jar -/.gradle -/captures/ -/gradlew -/gradlew.bat -/local.properties -GeneratedPluginRegistrant.java - -# Remember to never publicly share your keystore. -# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app -key.properties diff --git a/test/app/android/app/build.gradle b/test/app/android/app/build.gradle deleted file mode 100644 index 517a139..0000000 --- a/test/app/android/app/build.gradle +++ /dev/null @@ -1,72 +0,0 @@ -plugins { - id "com.android.application" - id "kotlin-android" - id "dev.flutter.flutter-gradle-plugin" -} - -def localProperties = new Properties() -def localPropertiesFile = rootProject.file('local.properties') -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) - } -} - -// def flutterRoot = localProperties.getProperty('flutter.sdk') -// if (flutterRoot == null) { -// throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -// } - -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' -} - -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - flutterVersionName = '1.0' -} - -// apply plugin: 'com.android.application' -// apply plugin: 'kotlin-android' -// apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" - -android { - namespace 'com.adjust.app' - compileSdkVersion 35 - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - } - - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.adjust.app" - minSdkVersion flutter.minSdkVersion - targetSdkVersion 35 - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug - } - } - lint { - disable 'InvalidPackage' - } -} - -flutter { - source '../..' -} - -dependencies { - implementation 'com.google.android.gms:play-services-analytics:18.0.1' - implementation 'com.android.installreferrer:installreferrer:2.2' - implementation group: 'org.slf4j', name: 'slf4j-simple', version: '1.6.2' -} diff --git a/test/app/android/app/build.gradle.kts b/test/app/android/app/build.gradle.kts new file mode 100644 index 0000000..c0201c5 --- /dev/null +++ b/test/app/android/app/build.gradle.kts @@ -0,0 +1,54 @@ +plugins { + id("com.android.application") + id("kotlin-android") + // the Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins + id("dev.flutter.flutter-gradle-plugin") +} + +android { + namespace = "com.adjust.examples" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_11.toString() + } + + defaultConfig { + applicationId = "com.adjust.examples" + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode = flutter.versionCode + versionName = flutter.versionName + } + + buildTypes { + release { + signingConfig = signingConfigs.getByName("debug") + } + } + + lint { + disable.add("InvalidPackage") + } +} + +flutter { + source = "../.." +} + +dependencies { + // google Play Services for analytics + implementation("com.google.android.gms:play-services-analytics:18.0.1") + + // install referrer for attribution + implementation("com.android.installreferrer:installreferrer:2.2") + + // modern logging framework + implementation("org.slf4j:slf4j-simple:2.0.9") +} \ No newline at end of file diff --git a/test/app/android/app/src/main/kotlin/com/adjust/app/MainActivity.kt b/test/app/android/app/src/main/kotlin/com/adjust/examples/MainActivity.kt similarity index 75% rename from test/app/android/app/src/main/kotlin/com/adjust/app/MainActivity.kt rename to test/app/android/app/src/main/kotlin/com/adjust/examples/MainActivity.kt index ab65b3c..615b428 100644 --- a/test/app/android/app/src/main/kotlin/com/adjust/app/MainActivity.kt +++ b/test/app/android/app/src/main/kotlin/com/adjust/examples/MainActivity.kt @@ -1,6 +1,6 @@ -package com.adjust.app +package com.adjust.examples import io.flutter.embedding.android.FlutterActivity class MainActivity: FlutterActivity() { -} +} \ No newline at end of file diff --git a/test/app/android/build.gradle b/test/app/android/build.gradle deleted file mode 100644 index aed4dbe..0000000 --- a/test/app/android/build.gradle +++ /dev/null @@ -1,31 +0,0 @@ -// buildscript { -// ext.kotlin_version = '1.6.10' -// repositories { -// google() -// mavenCentral() -// } - -// dependencies { -// classpath 'com.android.tools.build:gradle:7.1.1' -// classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" -// } -// } - -allprojects { - repositories { - google() - mavenCentral() - } -} - -rootProject.buildDir = '../build' -subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { - project.evaluationDependsOn(':app') -} - -tasks.register("clean", Delete) { - delete rootProject.buildDir -} diff --git a/test/app/android/build.gradle.kts b/test/app/android/build.gradle.kts new file mode 100644 index 0000000..ad4aba9 --- /dev/null +++ b/test/app/android/build.gradle.kts @@ -0,0 +1,24 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +val newBuildDir: Directory = + rootProject.layout.buildDirectory + .dir("../../build") + .get() +rootProject.layout.buildDirectory.value(newBuildDir) + +subprojects { + val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) + project.layout.buildDirectory.value(newSubprojectBuildDir) +} +subprojects { + project.evaluationDependsOn(":app") +} + +tasks.register("clean") { + delete(rootProject.layout.buildDirectory) +} \ No newline at end of file diff --git a/test/app/android/gradle.properties b/test/app/android/gradle.properties index 94adc3a..f018a61 100644 --- a/test/app/android/gradle.properties +++ b/test/app/android/gradle.properties @@ -1,3 +1,3 @@ -org.gradle.jvmargs=-Xmx1536M +org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError android.useAndroidX=true android.enableJetifier=true diff --git a/test/app/android/gradle/wrapper/gradle-wrapper.jar b/test/app/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..13372ae Binary files /dev/null and b/test/app/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/test/app/android/gradle/wrapper/gradle-wrapper.properties b/test/app/android/gradle/wrapper/gradle-wrapper.properties index df97d72..ac3b479 100644 --- a/test/app/android/gradle/wrapper/gradle-wrapper.properties +++ b/test/app/android/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip -networkTimeout=10000 -validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip diff --git a/test/app/android/gradlew b/test/app/android/gradlew new file mode 100755 index 0000000..9d82f78 --- /dev/null +++ b/test/app/android/gradlew @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/test/app/android/gradlew.bat b/test/app/android/gradlew.bat new file mode 100644 index 0000000..aec9973 --- /dev/null +++ b/test/app/android/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/test/app/android/settings.gradle b/test/app/android/settings.gradle deleted file mode 100644 index 904a85a..0000000 --- a/test/app/android/settings.gradle +++ /dev/null @@ -1,35 +0,0 @@ -pluginManagement { - def flutterSdkPath = { - def properties = new Properties() - file("local.properties").withInputStream { properties.load(it) } - def flutterSdkPath = properties.getProperty("flutter.sdk") - assert flutterSdkPath != null, "flutter.sdk not set in local.properties" - return flutterSdkPath - }() - - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -plugins { - id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.1.4" apply false - id "org.jetbrains.kotlin.android" version "1.7.10" apply false -} - -include ':app' - -// def localPropertiesFile = new File(rootProject.projectDir, "local.properties") -// def properties = new Properties() - -// assert localPropertiesFile.exists() -// localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } - -// def flutterSdkPath = properties.getProperty("flutter.sdk") -// assert flutterSdkPath != null, "flutter.sdk not set in local.properties" -// apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/test/app/android/settings.gradle.kts b/test/app/android/settings.gradle.kts new file mode 100644 index 0000000..16f2310 --- /dev/null +++ b/test/app/android/settings.gradle.kts @@ -0,0 +1,26 @@ +pluginManagement { + val flutterSdkPath = + run { + val properties = java.util.Properties() + file("local.properties").inputStream().use { properties.load(it) } + val flutterSdkPath = properties.getProperty("flutter.sdk") + require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } + flutterSdkPath + } + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id("dev.flutter.flutter-plugin-loader") version "1.0.0" + id("com.android.application") version "8.9.1" apply false + id("org.jetbrains.kotlin.android") version "2.1.0" apply false +} + +include(":app") \ No newline at end of file diff --git a/test/app/ios/.gitignore b/test/app/ios/.gitignore deleted file mode 100644 index e96ef60..0000000 --- a/test/app/ios/.gitignore +++ /dev/null @@ -1,32 +0,0 @@ -*.mode1v3 -*.mode2v3 -*.moved-aside -*.pbxuser -*.perspectivev3 -**/*sync/ -.sconsign.dblite -.tags* -**/.vagrant/ -**/DerivedData/ -Icon? -**/Pods/ -**/.symlinks/ -profile -xcuserdata -**/.generated/ -Flutter/App.framework -Flutter/Flutter.framework -Flutter/Flutter.podspec -Flutter/Generated.xcconfig -Flutter/app.flx -Flutter/app.zip -Flutter/flutter_assets/ -Flutter/flutter_export_environment.sh -ServiceDefinitions.json -Runner/GeneratedPluginRegistrant.* - -# Exceptions to above rules. -!default.mode1v3 -!default.mode2v3 -!default.pbxuser -!default.perspectivev3 diff --git a/test/app/ios/Flutter/AppFrameworkInfo.plist b/test/app/ios/Flutter/AppFrameworkInfo.plist index 8c6e561..d57061d 100644 --- a/test/app/ios/Flutter/AppFrameworkInfo.plist +++ b/test/app/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 12.0 + 13.0 diff --git a/test/app/ios/Podfile b/test/app/ios/Podfile index 1535fd8..17adeb1 100644 --- a/test/app/ios/Podfile +++ b/test/app/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -platform :ios, '12.0' +# platform :ios, '13.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' @@ -29,20 +29,12 @@ flutter_ios_podfile_setup target 'Runner' do use_frameworks! - use_modular_headers! flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) -# target 'RunnerTests' do -# inherit! :search_paths -# end end post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) - target.build_configurations.each do |config| - config.build_settings.delete 'IPHONEOS_DEPLOYMENT_TARGET' - config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'i386 arm64' - end end end diff --git a/test/app/ios/Runner.xcodeproj/project.pbxproj b/test/app/ios/Runner.xcodeproj/project.pbxproj index ab4fddb..264206e 100644 --- a/test/app/ios/Runner.xcodeproj/project.pbxproj +++ b/test/app/ios/Runner.xcodeproj/project.pbxproj @@ -363,7 +363,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -467,7 +467,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -517,7 +517,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/test/app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/test/app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index c53e2b3..9c12df5 100644 --- a/test/app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/test/app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -26,6 +26,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" shouldUseLaunchSchemeArgsEnv = "YES"> ? _parameters; + /// creates a Command from a dynamic map received from the test framework Command(dynamic map) { try { _className = map['className']; _methodName = map['methodName']; if (Platform.isAndroid) { + // android sends parameters as JSON string _jsonParameters = map['jsonParameters']; _parameters = json.decode(_jsonParameters!); } else { + // iOS sends parameters as map directly _parameters = map['jsonParameters']; _jsonParameters = json.encode(_parameters); } } catch (e) { - print( - '[Command]: Error! Failed to map Command from incoming data. Details: ' + - e.toString()); + print('[Command]: Failed to parse command from incoming data. Error: $e'); } } + /// the class name to execute the method on String? get className => _className; + + /// the method name to execute String? get methodName => _methodName; + /// gets the first value for a given parameter key + /// returns null if parameter doesn't exist or has no values String? getFirstParameterValue(String parameterKey) { - List? parameterValues = _parameters![parameterKey]; - if (parameterValues == null || parameterValues.length == 0) { + final List? parameterValues = _parameters![parameterKey]; + if (parameterValues == null || parameterValues.isEmpty) { return null; } return parameterValues.first; } - List? getParamteters(String parameterKey) { + /// gets all parameter values for a given key + /// fixed typo: was "getParamteters", now "getParameters" + List? getParameters(String parameterKey) { return _parameters![parameterKey]; } + /// checks if the command contains a specific parameter bool containsParameter(String parameterKey) { - return _parameters![parameterKey] != null; + return _parameters?[parameterKey] != null; } + /// returns a string representation of the command for debugging @override String toString() { return 'Command[className: $_className, methodName: $_methodName, jsonParameters: $_jsonParameters]'; diff --git a/test/app/lib/command_executor.dart b/test/app/lib/command_executor.dart index b710e5a..9062718 100644 --- a/test/app/lib/command_executor.dart +++ b/test/app/lib/command_executor.dart @@ -29,6 +29,8 @@ import 'package:adjust_sdk/adjust_store_info.dart'; import 'package:test_app/command.dart'; import 'package:test_lib/test_lib.dart'; +/// executes test commands received from the test framework +/// handles all Adjust SDK method calls and configurations class CommandExecutor { String? _baseUrl; String? _basePath; @@ -41,9 +43,10 @@ class CommandExecutor { String? _overwriteUrl; String? _extraPath; late Command _command; - Map _savedEvents = new Map(); - Map _savedConfigs = new Map(); + final Map _savedEvents = {}; + final Map _savedConfigs = {}; + /// creates a new CommandExecutor with the specified base URL CommandExecutor(String? overwriteUrl) { _baseUrl = overwriteUrl; _gdprUrl = overwriteUrl; @@ -52,6 +55,7 @@ class CommandExecutor { _overwriteUrl = overwriteUrl; } + /// executes the given command by dispatching to the appropriate method void executeCommand(Command command) { _command = command; switch (command.methodName) { @@ -151,6 +155,7 @@ class CommandExecutor { } } + /// configure test options for the SDK void _testOptions() { final dynamic testOptions = {}; testOptions['baseUrl'] = _overwriteUrl; @@ -158,6 +163,7 @@ class CommandExecutor { testOptions['subscriptionUrl'] = _overwriteUrl; testOptions['purchaseVerificationUrl'] = _overwriteUrl; testOptions['urlOverwrite'] = _overwriteUrl; + if (_command.containsParameter('basePath')) { _basePath = _command.getFirstParameterValue('basePath'); _gdprPath = _command.getFirstParameterValue('basePath'); @@ -165,54 +171,66 @@ class CommandExecutor { _purchaseVerificationPath = _command.getFirstParameterValue('basePath'); _extraPath = _command.getFirstParameterValue('basePath'); } + if (_command.containsParameter('timerInterval')) { testOptions['timerIntervalInMilliseconds'] = _command.getFirstParameterValue('timerInterval'); } + if (_command.containsParameter('timerStart')) { testOptions['timerStartInMilliseconds'] = _command.getFirstParameterValue('timerStart'); } + if (_command.containsParameter('sessionInterval')) { testOptions['sessionIntervalInMilliseconds'] = _command.getFirstParameterValue('sessionInterval'); } + if (_command.containsParameter('subsessionInterval')) { testOptions['subsessionIntervalInMilliseconds'] = _command.getFirstParameterValue('subsessionInterval'); } + if (_command.containsParameter('tryInstallReferrer')) { testOptions['tryInstallReferrer'] = _command.getFirstParameterValue('tryInstallReferrer'); } + if (_command.containsParameter('noBackoffWait')) { testOptions['noBackoffWait'] = _command.getFirstParameterValue('noBackoffWait'); } + if (_command.containsParameter("doNotIgnoreSystemLifecycleBootstrap")) { - String? doNotIgnoreSystemLifecycleBootstrapString = - _command.getFirstParameterValue("doNotIgnoreSystemLifecycleBootstrap"); - bool doNotIgnoreSystemLifecycleBootstrap = (doNotIgnoreSystemLifecycleBootstrapString == 'true'); + final String? doNotIgnoreSystemLifecycleBootstrapString = + _command.getFirstParameterValue("doNotIgnoreSystemLifecycleBootstrap"); + final bool doNotIgnoreSystemLifecycleBootstrap = + (doNotIgnoreSystemLifecycleBootstrapString == 'true'); if (doNotIgnoreSystemLifecycleBootstrap) { testOptions['ignoreSystemLifecycleBootstrap'] = false; } } + if (_command.containsParameter('adServicesFrameworkEnabled')) { testOptions['adServicesFrameworkEnabled'] = _command.getFirstParameterValue('adServicesFrameworkEnabled'); } + if (_command.containsParameter('attStatus')) { testOptions['attStatus'] = _command.getFirstParameterValue('attStatus'); } + if (_command.containsParameter('idfa')) { testOptions['idfa'] = _command.getFirstParameterValue('idfa'); } + bool useTestConnectionOptions = false; if (_command.containsParameter('teardown')) { - List teardownOptions = _command.getParamteters('teardown')!; - for (String teardownOption in teardownOptions) { + final List teardownOptions = _command.getParameters('teardown')!; + for (final String teardownOption in teardownOptions) { if (teardownOption == 'resetSdk') { testOptions['teardown'] = 'true'; testOptions['basePath'] = _extraPath; @@ -220,7 +238,7 @@ class CommandExecutor { testOptions['subscriptionPath'] = _extraPath; testOptions['purchaseVerificationPath'] = _extraPath; testOptions['extraPath'] = _extraPath; - // Android specific + // android specific testOptions['useTestConnectionOptions'] = 'true'; testOptions['tryInstallReferrer'] = 'false'; useTestConnectionOptions = true; @@ -242,7 +260,7 @@ class CommandExecutor { testOptions['gdprPath'] = null; testOptions['subscriptionPath'] = null; testOptions['extraPath'] = null; - // Android specific. + // android specific testOptions['useTestConnectionOptions'] = 'false'; useTestConnectionOptions = false; } @@ -578,14 +596,14 @@ class CommandExecutor { } if (_command.containsParameter('revenue')) { - List revenueParams = _command.getParamteters('revenue')!; + List revenueParams = _command.getParameters('revenue')!; // TODO: find better way to filter null values for Flutter platform if (revenueParams[0] != null && revenueParams[1] != null) { adjustEvent!.setRevenue(num.parse(revenueParams[1]), revenueParams[0]); } } if (_command.containsParameter('callbackParams')) { - List callbackParams = _command.getParamteters('callbackParams')!; + List callbackParams = _command.getParameters('callbackParams')!; for (int i = 0; i < callbackParams.length; i = i + 2) { if (callbackParams[i] != null && callbackParams[i + 1] != null) { String key = callbackParams[i]; @@ -595,7 +613,7 @@ class CommandExecutor { } } if (_command.containsParameter('partnerParams')) { - List partnerParams = _command.getParamteters('partnerParams')!; + List partnerParams = _command.getParameters('partnerParams')!; for (int i = 0; i < partnerParams.length; i = i + 2) { if (partnerParams[i] != null && partnerParams[i + 1] != null) { String key = partnerParams[i]; @@ -686,7 +704,7 @@ class CommandExecutor { return; } - List keyValuePairs = _command.getParamteters('KeyValue')!; + List keyValuePairs = _command.getParameters('KeyValue')!; for (int i = 0; i < keyValuePairs.length; i = i + 2) { String key = keyValuePairs[i]; String value = keyValuePairs[i + 1]; @@ -699,7 +717,7 @@ class CommandExecutor { return; } - List keyValuePairs = _command.getParamteters('KeyValue')!; + List keyValuePairs = _command.getParameters('KeyValue')!; for (int i = 0; i < keyValuePairs.length; i = i + 2) { String key = keyValuePairs[i]; String value = keyValuePairs[i + 1]; @@ -712,7 +730,7 @@ class CommandExecutor { return; } - List keys = _command.getParamteters('key')!; + List keys = _command.getParameters('key')!; for (int i = 0; i < keys.length; i = i + 1) { String key = keys[i]; Adjust.removeGlobalCallbackParameter(key); @@ -724,7 +742,7 @@ class CommandExecutor { return; } - List keys = _command.getParamteters('key')!; + List keys = _command.getParameters('key')!; for (int i = 0; i < keys.length; i = i + 1) { String key = keys[i]; Adjust.removeGlobalPartnerParameter(key); @@ -756,7 +774,7 @@ class CommandExecutor { if (_command.containsParameter('callbackParams')) { List callbackParams = - _command.getParamteters('callbackParams')!; + _command.getParameters('callbackParams')!; for (int i = 0; i < callbackParams.length; i = i + 2) { if (callbackParams[i] != null && callbackParams[i + 1] != null) { String key = callbackParams[i]; @@ -766,7 +784,7 @@ class CommandExecutor { } } if (_command.containsParameter('partnerParams')) { - List partnerParams = _command.getParamteters('partnerParams')!; + List partnerParams = _command.getParameters('partnerParams')!; for (int i = 0; i < partnerParams.length; i = i + 2) { if (partnerParams[i] != null && partnerParams[i + 1] != null) { String key = partnerParams[i]; @@ -793,7 +811,7 @@ class CommandExecutor { if (_command.containsParameter('callbackParams')) { List callbackParams = - _command.getParamteters('callbackParams')!; + _command.getParameters('callbackParams')!; for (int i = 0; i < callbackParams.length; i = i + 2) { if (callbackParams[i] != null && callbackParams[i + 1] != null) { String key = callbackParams[i]; @@ -803,7 +821,7 @@ class CommandExecutor { } } if (_command.containsParameter('partnerParams')) { - List partnerParams = _command.getParamteters('partnerParams')!; + List partnerParams = _command.getParameters('partnerParams')!; for (int i = 0; i < partnerParams.length; i = i + 2) { if (partnerParams[i] != null && partnerParams[i + 1] != null) { String key = partnerParams[i]; @@ -827,7 +845,7 @@ class CommandExecutor { if (_command.containsParameter('granularOptions')) { List granularOptions = - _command.getParamteters('granularOptions')!; + _command.getParameters('granularOptions')!; for (var i = 0; i < granularOptions.length; i += 3) { if (granularOptions[i] != null && granularOptions[i + 1] != null && granularOptions[i + 2] != null) { String partnerName = granularOptions[i]; @@ -840,7 +858,7 @@ class CommandExecutor { if (_command.containsParameter('partnerSharingSettings')) { List partnerSharingSettings = - _command.getParamteters('partnerSharingSettings')!; + _command.getParameters('partnerSharingSettings')!; for (var i = 0; i < partnerSharingSettings.length; i += 3) { if (partnerSharingSettings[i] != null && partnerSharingSettings[i + 1] != null && partnerSharingSettings[i + 2] != null) { String partnerName = partnerSharingSettings[i]; @@ -864,11 +882,11 @@ class CommandExecutor { AdjustAdRevenue adjustAdRevenue = new AdjustAdRevenue(source); if (_command.containsParameter('revenue')) { - List revenueParams = _command.getParamteters('revenue')!; + List revenueParams = _command.getParameters('revenue')!; adjustAdRevenue.setRevenue(num.parse(revenueParams[1]), revenueParams[0]); } if (_command.containsParameter('callbackParams')) { - List callbackParams = _command.getParamteters('callbackParams')!; + List callbackParams = _command.getParameters('callbackParams')!; for (int i = 0; i < callbackParams.length; i = i + 2) { if (callbackParams[i] != null && callbackParams[i + 1] != null) { String key = callbackParams[i]; @@ -878,7 +896,7 @@ class CommandExecutor { } } if (_command.containsParameter('partnerParams')) { - List partnerParams = _command.getParamteters('partnerParams')!; + List partnerParams = _command.getParameters('partnerParams')!; for (int i = 0; i < partnerParams.length; i = i + 2) { if (partnerParams[i] != null && partnerParams[i + 1] != null) { String key = partnerParams[i]; @@ -1022,7 +1040,7 @@ class CommandExecutor { void _attributionGetter() { Adjust.getAttribution().then((attribution){ if(attribution != null) { - Map fields = new Map(); + Map fields = {}; fields["tracker_token"] = attribution.trackerToken; fields["tracker_name"] = attribution.trackerName; fields["network"] = attribution.network; diff --git a/test/app/lib/main.dart b/test/app/lib/main.dart index e020d0d..ff103bf 100644 --- a/test/app/lib/main.dart +++ b/test/app/lib/main.dart @@ -1,22 +1,55 @@ import 'dart:io'; import 'package:adjust_sdk/adjust.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:test_app/command.dart'; import 'package:test_app/command_executor.dart'; import 'package:test_lib/test_lib.dart'; void main() { - runApp(MyApp()); + runApp(const AdjustTestApp()); } -class MyApp extends StatefulWidget { +/// main application widget for Adjust Flutter Test App +class AdjustTestApp extends StatelessWidget { + const AdjustTestApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Adjust Test App', + debugShowCheckedModeBanner: false, + theme: ThemeData( + primarySwatch: Colors.blue, + visualDensity: VisualDensity.adaptivePlatformDensity, + useMaterial3: true, + ), + home: const TestHomePage(), + ); + } +} + +/// home page containing the test session controls +class TestHomePage extends StatefulWidget { + const TestHomePage({super.key}); + @override - _MyAppState createState() => new _MyAppState(); + State createState() => _TestHomePageState(); } -class _MyAppState extends State { +class _TestHomePageState extends State { + // configuration constants + static const String _defaultAddress = '192.168.86.237'; + static const String _androidProtocol = 'https'; + static const String _androidPort = '8443'; + static const String _iosProtocol = 'http'; + static const String _iosPort = '8080'; + static const String _wsPort = '1987'; + + // adjust brand colors + static const Color _adjustNavy = Color(0xFF1B2951); + static const Color _adjustNavyLight = Color(0xFF2A3A5C); + String? _overwriteUrl; late String _controlUrl; late CommandExecutor _commandExecutor; @@ -24,68 +57,230 @@ class _MyAppState extends State { @override void initState() { super.initState(); + _initializeTestEnvironment(); + } + /// initialize the test environment with platform-specific URLs + void _initializeTestEnvironment() { if (Platform.isAndroid) { - String _address = '192.168.86.227'; - String _protocol = 'https'; - String _port = '8443'; - _overwriteUrl = _protocol + '://' + _address + ':' + _port; - _controlUrl = 'ws://' + _address + ':1987'; + _overwriteUrl = '$_androidProtocol://$_defaultAddress:$_androidPort'; } else { - String _address = '192.168.86.227'; - String _protocol = 'http'; - String _port = '8080'; - _overwriteUrl = _protocol + '://' + _address + ':' + _port; - _controlUrl = 'ws://' + _address + ':1987'; + _overwriteUrl = '$_iosProtocol://$_defaultAddress:$_iosPort'; } + _controlUrl = 'ws://$_defaultAddress:$_wsPort'; - // Initialise command executor. - _commandExecutor = - new CommandExecutor(_overwriteUrl); - - // Initialise test library. - TestLib.setExecuteCommandHalder((final dynamic callArgs) { - print('[AdjustTestApp]: executeCommandHandler pinged in test app!'); - Command command = new Command(callArgs); - print( - '[AdjustTestApp]: Executing command ${command.className}.${command.methodName}'); - _commandExecutor.executeCommand(command); - }); + // initialize command executor + _commandExecutor = CommandExecutor(_overwriteUrl); + + // initialize test library with command handler + TestLib.setExecuteCommandHalder(_handleTestCommand); TestLib.init(_overwriteUrl!, _controlUrl); } + /// handle incoming test commands + void _handleTestCommand(dynamic callArgs) { + print('[AdjustTestApp]: Command handler triggered'); + final command = Command(callArgs); + print('[AdjustTestApp]: Executing ${command.className}.${command.methodName}'); + _commandExecutor.executeCommand(command); + } + + /// start a new test session + void _startTestSession() { + Adjust.getSdkVersion().then((sdkVersion) { + print('[AdjustTestApp]: Starting test session with SDK version: $sdkVersion'); + TestLib.startTestSession(sdkVersion); + }); + } + @override Widget build(BuildContext context) { - return new MaterialApp( - home: new Scaffold( - appBar: new AppBar( - title: const Text('Adjust Flutter SDK Test App'), + return Scaffold( + appBar: AppBar( + title: const Text( + 'Adjust Test App', + style: TextStyle( + fontWeight: FontWeight.w600, + color: Colors.white, + ), + ), + centerTitle: true, + backgroundColor: _adjustNavy, + elevation: 0, + ), + body: Container( + width: double.infinity, + height: double.infinity, + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [_adjustNavy, _adjustNavyLight], + ), + ), + child: SafeArea( + child: Padding( + padding: const EdgeInsets.all(24.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // app icon or logo space + Container( + width: 80, + height: 80, + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.1), + borderRadius: BorderRadius.circular(16), + ), + child: const Icon( + Icons.science_outlined, + size: 40, + color: Colors.white, + ), + ), + const SizedBox(height: 32), + + // title and description + const Text( + 'Test Session', + style: TextStyle( + fontSize: 28, + fontWeight: FontWeight.bold, + color: Colors.white, + ), + ), + const SizedBox(height: 8), + Text( + 'Tap the button below to start testing\nthe Adjust SDK functionality', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + color: Colors.white.withOpacity(0.8), + height: 1.4, + ), + ), + const SizedBox(height: 48), + + // main action button + _buildStartButton(), + + const SizedBox(height: 24), + + // connection info + _buildConnectionInfo(), + ], + ), + ), ), - body: new CustomScrollView(shrinkWrap: true, slivers: [ - new SliverPadding( - padding: const EdgeInsets.all(20.0), - sliver: new SliverList( - delegate: new SliverChildListDelegate([ - new Text('Running'), - buildCupertinoButton( - 'Start Test Session', - () => Adjust.getSdkVersion().then((sdkVersion) { - // TestLib.addTestDirectory('event-callbacks'); - // TestLib.addTest('Test_Parameters_FeatureFlags_present'); - TestLib.startTestSession(sdkVersion); - })) - ]))) - ]), ), ); } - static Widget buildCupertinoButton(String text, Function action) { - return new CupertinoButton( - child: Text(text), - color: CupertinoColors.activeBlue, - padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 30.0), - onPressed: action as void Function()?, + /// build the main start test session button + Widget _buildStartButton() { + return SizedBox( + width: double.infinity, + height: 56, + child: ElevatedButton( + onPressed: _startTestSession, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.white, + foregroundColor: _adjustNavy, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(28), + ), + elevation: 8, + shadowColor: Colors.black.withOpacity(0.3), + ), + child: const Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.play_arrow_rounded, size: 24), + SizedBox(width: 8), + Text( + 'Start Test Session', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ), + ); + } + + /// build connection information display + Widget _buildConnectionInfo() { + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.1), + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: Colors.white.withOpacity(0.2), + width: 1, + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Icon( + Icons.info_outline, + size: 16, + color: Colors.white.withOpacity(0.7), + ), + const SizedBox(width: 8), + Text( + 'Connection Info', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w600, + color: Colors.white.withOpacity(0.9), + ), + ), + ], + ), + const SizedBox(height: 8), + _buildInfoRow('Platform', Platform.isAndroid ? 'Android' : 'iOS'), + _buildInfoRow('Test URL', _overwriteUrl ?? 'Not set'), + _buildInfoRow('Control URL', _controlUrl), + ], + ), + ); + } + + /// build an information row + Widget _buildInfoRow(String label, String value) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 2), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: 80, + child: Text( + '$label:', + style: TextStyle( + fontSize: 12, + color: Colors.white.withOpacity(0.6), + ), + ), + ), + Expanded( + child: Text( + value, + style: TextStyle( + fontSize: 12, + color: Colors.white.withOpacity(0.8), + fontFamily: 'monospace', + ), + ), + ), + ], + ), ); } } diff --git a/test/app/pubspec.yaml b/test/app/pubspec.yaml index ba8adce..17e003c 100644 --- a/test/app/pubspec.yaml +++ b/test/app/pubspec.yaml @@ -1,24 +1,10 @@ name: test_app -description: Adjust Flutter Test Application - -# The following line prevents the package from being accidentally published to -# pub.dev using `pub publish`. This is preferred for private packages. -publish_to: 'none' # Remove this line if you wish to publish to pub.dev - -# The following defines the version and build number for your application. -# A version number is three numbers separated by dots, like 1.2.43 -# followed by an optional build number separated by a +. -# Both the version and the builder number may be overridden in flutter -# build by specifying --build-name and --build-number, respectively. -# In Android, build-name is used as versionName while build-number used as versionCode. -# Read more about Android versioning at https://developer.android.com/studio/publish/versioning -# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. -# Read more about iOS versioning at -# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +description: "Adjust Flutter Test App" +publish_to: 'none' version: 1.0.0+1 environment: - sdk: '>=2.12.0 <3.0.0' + sdk: ^3.9.0-277.0.dev dependencies: flutter: @@ -28,53 +14,15 @@ dependencies: test_lib: path: ../ - - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^1.0.0 +dependency_overrides: + characters: ^1.4.1 + material_color_utilities: ^0.13.0 + meta: ^1.17.0 dev_dependencies: flutter_test: sdk: flutter + flutter_lints: ^6.0.0 -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter. flutter: - - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. uses-material-design: true - - # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/assets-and-images/#resolution-aware. - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/assets-and-images/#from-packages - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/custom-fonts/#from-packages diff --git a/test/app/test/widget_test.dart b/test/app/test/widget_test.dart deleted file mode 100644 index 1a53d78..0000000 --- a/test/app/test/widget_test.dart +++ /dev/null @@ -1,29 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility that Flutter provides. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:test_app/main.dart'; - -void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(MyApp()); - - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); - }); -} diff --git a/test/ios/.gitignore b/test/ios/.gitignore deleted file mode 100644 index 710ec6c..0000000 --- a/test/ios/.gitignore +++ /dev/null @@ -1,36 +0,0 @@ -.idea/ -.vagrant/ -.sconsign.dblite -.svn/ - -.DS_Store -*.swp -profile - -DerivedData/ -build/ -GeneratedPluginRegistrant.h -GeneratedPluginRegistrant.m - -.generated/ - -*.pbxuser -*.mode1v3 -*.mode2v3 -*.perspectivev3 - -!default.pbxuser -!default.mode1v3 -!default.mode2v3 -!default.perspectivev3 - -xcuserdata - -*.moved-aside - -*.pyc -*sync/ -Icon? -.tags* - -/Flutter/Generated.xcconfig diff --git a/test/ios/Classes/AdjustCommandExecutor.h b/test/ios/Classes/AdjustCommandExecutor.h index bda06e4..de35fab 100644 --- a/test/ios/Classes/AdjustCommandExecutor.h +++ b/test/ios/Classes/AdjustCommandExecutor.h @@ -3,7 +3,7 @@ // Adjust SDK // // Created by Srdjan Tubin (@2beens) on 1st October 2018. -// Copyright (c) 2018-2021 Adjust GmbH. All rights reserved. +// Copyright (c) 2018-Present Adjust GmbH. All rights reserved. // #import diff --git a/test/ios/Classes/AdjustCommandExecutor.m b/test/ios/Classes/AdjustCommandExecutor.m index 57d5476..e7904b0 100644 --- a/test/ios/Classes/AdjustCommandExecutor.m +++ b/test/ios/Classes/AdjustCommandExecutor.m @@ -3,7 +3,7 @@ // Adjust SDK // // Created by Srdjan Tubin (@2beens) on 1st October 2018. -// Copyright (c) 2018-2021 Adjust GmbH. All rights reserved. +// Copyright (c) 2018-Present Adjust GmbH. All rights reserved. // #import diff --git a/test/ios/Classes/TestLibPlugin.h b/test/ios/Classes/TestLibPlugin.h index b58429d..5ef6f8d 100644 --- a/test/ios/Classes/TestLibPlugin.h +++ b/test/ios/Classes/TestLibPlugin.h @@ -3,7 +3,7 @@ // Adjust SDK // // Created by Srdjan Tubin (@2beens) on 1st October 2018. -// Copyright (c) 2018-2021 Adjust GmbH. All rights reserved. +// Copyright (c) 2018-Present Adjust GmbH. All rights reserved. // #import diff --git a/test/ios/Classes/TestLibPlugin.m b/test/ios/Classes/TestLibPlugin.m index 3767197..1027a3e 100644 --- a/test/ios/Classes/TestLibPlugin.m +++ b/test/ios/Classes/TestLibPlugin.m @@ -3,7 +3,7 @@ // Adjust SDK // // Created by Srdjan Tubin (@2beens) on 1st October 2018. -// Copyright (c) 2018-2021 Adjust GmbH. All rights reserved. +// Copyright (c) 2018-Present Adjust GmbH. All rights reserved. // #import "TestLibPlugin.h" diff --git a/test/ios/test_lib.podspec b/test/ios/test_lib.podspec index d5b9efc..ec1c972 100644 --- a/test/ios/test_lib.podspec +++ b/test/ios/test_lib.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'test_lib' - s.version = '5.4.0' + s.version = '5.4.1' s.summary = 'Adjust test library for iOS platform' s.description = <<-DESC Adjust test library for iOS platform. diff --git a/test/lib/test_lib.dart b/test/lib/test_lib.dart index c76057b..beca10e 100644 --- a/test/lib/test_lib.dart +++ b/test/lib/test_lib.dart @@ -3,7 +3,7 @@ // Adjust SDK // // Created by Srdjan Tubin (@2beens) on 25th April 2018. -// Copyright (c) 2018-2021 Adjust GmbH. All rights reserved. +// Copyright (c) 2018-Present Adjust GmbH. All rights reserved. // import 'package:flutter/services.dart'; diff --git a/test/pubspec.yaml b/test/pubspec.yaml index 521c9b4..7174598 100644 --- a/test/pubspec.yaml +++ b/test/pubspec.yaml @@ -1,6 +1,6 @@ name: test_lib description: Flutter plugin for Adjust Testing Library. Intended exclusively for internal use. -version: 5.4.0 +version: 5.4.1 author: Adjust (sdk@adjust.com) environment: