diff --git a/CHANGELOG.md b/CHANGELOG.md index cb93dfd..f41636b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,9 @@ # Versions +## 6.15.2 +- Fixed NullPointerException issue on Android that some clients had. +- Fixed Android MediationNetwork enum issue. +- Update iOS version to 6.15.3 +- Update Android version to 6.15.2 ## 6.15.1 - Implementation of the new logAdRevenue API for iOS and Android - Documentation update for the new logAdRevenue API diff --git a/README.md b/README.md index 5a68ad6..9640498 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,8 @@ ### This plugin is built for -- Android AppsFlyer SDK **v6.15.1** -- iOS AppsFlyer SDK **v6.15.1** +- Android AppsFlyer SDK **v6.15.2** +- iOS AppsFlyer SDK **v6.15.3** ## ❗❗ Breaking changes when updating to v6.x.x❗❗ diff --git a/android/build.gradle b/android/build.gradle index 9669568..0969e87 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -31,6 +31,6 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.appcompat:appcompat:1.0.0' - implementation 'com.appsflyer:af-android-sdk:6.15.1' + implementation 'com.appsflyer:af-android-sdk:6.15.2' implementation 'com.android.installreferrer:installreferrer:2.1' } \ No newline at end of file diff --git a/android/src/main/java/com/appsflyer/appsflyersdk/AppsFlyerConstants.java b/android/src/main/java/com/appsflyer/appsflyersdk/AppsFlyerConstants.java index b6f419c..c8a7847 100644 --- a/android/src/main/java/com/appsflyer/appsflyersdk/AppsFlyerConstants.java +++ b/android/src/main/java/com/appsflyer/appsflyersdk/AppsFlyerConstants.java @@ -1,30 +1,32 @@ package com.appsflyer.appsflyersdk; -public class AppsFlyerConstants { - final static String PLUGIN_VERSION = "6.15.1"; - final static String AF_APP_INVITE_ONE_LINK = "appInviteOneLink"; - final static String AF_HOST_PREFIX = "hostPrefix"; - final static String AF_HOST_NAME = "hostName"; - final static String AF_IS_DEBUG = "isDebug"; - final static String AF_MANUAL_START = "manualStart"; - final static String AF_DEV_KEY = "afDevKey"; - final static String AF_EVENT_NAME = "eventName"; - final static String AF_EVENT_VALUES = "eventValues"; - final static String AF_ON_INSTALL_CONVERSION_DATA_LOADED = "onInstallConversionDataLoaded"; - final static String AF_ON_APP_OPEN_ATTRIBUTION = "onAppOpenAttribution"; - final static String AF_SUCCESS = "success"; - final static String AF_FAILURE = "failure"; - final static String AF_GCD = "GCD"; - final static String AF_UDL = "UDL"; - final static String AF_VALIDATE_PURCHASE = "validatePurchase"; - final static String AF_GCD_CALLBACK = "onInstallConversionData"; - final static String AF_OAOA_CALLBACK = "onAppOpenAttribution"; - final static String AF_UDL_CALLBACK = "onDeepLinking"; - final static String DISABLE_ADVERTISING_IDENTIFIER = "disableAdvertisingIdentifier"; +public final class AppsFlyerConstants { + final static String PLUGIN_VERSION = "6.15.1"; + final static String AF_APP_INVITE_ONE_LINK = "appInviteOneLink"; + final static String AF_HOST_PREFIX = "hostPrefix"; + final static String AF_HOST_NAME = "hostName"; + final static String AF_IS_DEBUG = "isDebug"; + final static String AF_MANUAL_START = "manualStart"; + final static String AF_DEV_KEY = "afDevKey"; + final static String AF_EVENT_NAME = "eventName"; + final static String AF_EVENT_VALUES = "eventValues"; + final static String AF_ON_INSTALL_CONVERSION_DATA_LOADED = "onInstallConversionDataLoaded"; + final static String AF_ON_APP_OPEN_ATTRIBUTION = "onAppOpenAttribution"; + final static String AF_SUCCESS = "success"; + final static String AF_FAILURE = "failure"; + final static String AF_GCD = "GCD"; + final static String AF_UDL = "UDL"; + final static String AF_VALIDATE_PURCHASE = "validatePurchase"; + final static String AF_GCD_CALLBACK = "onInstallConversionData"; + final static String AF_OAOA_CALLBACK = "onAppOpenAttribution"; + final static String AF_UDL_CALLBACK = "onDeepLinking"; + final static String DISABLE_ADVERTISING_IDENTIFIER = "disableAdvertisingIdentifier"; - final static String AF_EVENTS_CHANNEL = "af-events"; - final static String AF_METHOD_CHANNEL = "af-api"; - final static String AF_CALLBACK_CHANNEL = "callbacks"; + final static String AF_EVENTS_CHANNEL = "af-events"; + final static String AF_METHOD_CHANNEL = "af-api"; + final static String AF_CALLBACK_CHANNEL = "callbacks"; - final static String AF_BROADCAST_ACTION_NAME = "com.appsflyer.appsflyersdk"; + final static String AF_BROADCAST_ACTION_NAME = "com.appsflyer.appsflyersdk"; + + final static String AF_PLUGIN_TAG = "AppsFlyer_FlutterPlugin"; } diff --git a/android/src/main/java/com/appsflyer/appsflyersdk/AppsflyerSdkPlugin.java b/android/src/main/java/com/appsflyer/appsflyersdk/AppsflyerSdkPlugin.java index bc66b4a..be1d7e6 100644 --- a/android/src/main/java/com/appsflyer/appsflyersdk/AppsflyerSdkPlugin.java +++ b/android/src/main/java/com/appsflyer/appsflyersdk/AppsflyerSdkPlugin.java @@ -49,6 +49,7 @@ import static com.appsflyer.appsflyersdk.AppsFlyerConstants.AF_EVENTS_CHANNEL; import static com.appsflyer.appsflyersdk.AppsFlyerConstants.AF_FAILURE; +import static com.appsflyer.appsflyersdk.AppsFlyerConstants.AF_PLUGIN_TAG; import static com.appsflyer.appsflyersdk.AppsFlyerConstants.AF_SUCCESS; /** @@ -203,7 +204,7 @@ private void startListening(Object arguments, Result rawResult) { @Override public void onMethodCall(MethodCall call, Result result) { if (activity == null) { - Log.d("AppsFlyer", "Activity isn't attached to the flutter engine"); + Log.d(AF_PLUGIN_TAG, LogMessages.ACTIVITY_NOT_ATTACHED_TO_ENGINE); return; } final String method = call.method; @@ -362,11 +363,11 @@ private void performOnDeepLinking(MethodCall call, Result result) { AppsFlyerLib.getInstance().performOnDeepLinking(intent, mApplication); result.success(null); } else { - Log.d("AppsFlyer", "performOnDeepLinking: intent is null!"); + Log.d(AF_PLUGIN_TAG, "performOnDeepLinking: intent is null!"); result.error("NO_INTENT", "The intent is null", null); } } else { - Log.d("AppsFlyer", "performOnDeepLinking: activity is null!"); + Log.d(AF_PLUGIN_TAG, "performOnDeepLinking: activity is null!"); result.error("NO_ACTIVITY", "The current activity is null", null); } } @@ -379,34 +380,37 @@ private void anonymizeUser(MethodCall call, Result result) { private void startSDKwithHandler(MethodCall call, final Result result) { try { - final AppsFlyerLib instance = AppsFlyerLib.getInstance(); - instance.start(activity, null, new AppsFlyerRequestListener() { + final AppsFlyerLib appsFlyerLib = AppsFlyerLib.getInstance(); + + appsFlyerLib.start(activity, null, new AppsFlyerRequestListener() { @Override public void onSuccess() { - uiThreadHandler.post(new Runnable() { - @Override - public void run() { - mMethodChannel.invokeMethod("onSuccess", null); - } - }); + if (mMethodChannel != null) { + uiThreadHandler.post(() -> mMethodChannel.invokeMethod("onSuccess", null)); + } else { + Log.e(AF_PLUGIN_TAG, LogMessages.METHOD_CHANNEL_IS_NULL); + result.error("NULL_OBJECT", LogMessages.METHOD_CHANNEL_IS_NULL, null); + } } @Override public void onError(final int errorCode, final String errorMessage) { - uiThreadHandler.post(new Runnable() { - @Override - public void run() { + if (mMethodChannel != null) { + uiThreadHandler.post(() -> { HashMap errorDetails = new HashMap<>(); errorDetails.put("errorCode", errorCode); errorDetails.put("errorMessage", errorMessage); mMethodChannel.invokeMethod("onError", errorDetails); - } - }); + }); + } else { + Log.e(AF_PLUGIN_TAG, LogMessages.METHOD_CHANNEL_IS_NULL); + result.error("NULL_OBJECT", LogMessages.METHOD_CHANNEL_IS_NULL, null); + } } }); result.success(null); - } catch (Exception e) { - result.error("UNEXPECTED_ERROR", e.getMessage(), null); + } catch (Throwable t) { + result.error("UNEXPECTED_ERROR", t.getMessage(), null); } } @@ -532,14 +536,14 @@ private void sendPushNotificationData(MethodCall call, Result result) { Bundle bundle; if (pushPayload == null) { - Log.d("AppsFlyer", "Push payload is null"); + Log.d(AF_PLUGIN_TAG, "Push payload is null"); return; } try { bundle = this.jsonToBundle(new JSONObject(pushPayload)); } catch (JSONException e) { - Log.d("AppsFlyer", "Can't parse pushPayload to bundle"); + Log.d(AF_PLUGIN_TAG, "Can't parse pushPayload to bundle"); return; } @@ -557,7 +561,7 @@ private void sendPushNotificationData(MethodCall call, Result result) { } if (errorMsg != null) { - Log.d("AppsFlyer", errorMsg); + Log.d(AF_PLUGIN_TAG, errorMsg); return; } @@ -963,8 +967,8 @@ private void logAdRevenue(MethodCall call, Result result) { try { String monetizationNetwork = requireNonNullArgument(call, "monetizationNetwork"); String currencyIso4217Code = requireNonNullArgument(call, "currencyIso4217Code"); - double revenue = requireNonNullArgument(call,"revenue"); - String mediationNetworkString = requireNonNullArgument(call,"mediationNetwork"); + double revenue = requireNonNullArgument(call, "revenue"); + String mediationNetworkString = requireNonNullArgument(call, "mediationNetwork"); MediationNetwork mediationNetwork = MediationNetwork.valueOf(mediationNetworkString.toUpperCase()); @@ -984,10 +988,9 @@ private void logAdRevenue(MethodCall call, Result result) { } catch (IllegalArgumentException e) { // The IllegalArgumentException could come from either requireNonNullArgument or valueOf methods. result.error("INVALID_ARGUMENT_PROVIDED", e.getMessage(), null); - } - catch (Throwable t) { + } catch (Throwable t) { result.error("UNEXPECTED_ERROR", "[logAdRevenue]: An unexpected error occurred: " + t.getMessage(), null); - Log.e("AppsFlyer", "Unexpected exception occurred: [logAdRevenue]", t); + Log.e(AF_PLUGIN_TAG, "Unexpected exception occurred: [logAdRevenue]", t); } } @@ -1004,7 +1007,7 @@ private void logAdRevenue(MethodCall call, Result result) { private T requireNonNullArgument(MethodCall call, String argumentName) throws IllegalArgumentException { T argument = call.argument(argumentName); if (argument == null) { - Log.e("AppsFlyer", "Exception occurred when trying to: " + call.method + "->" + argumentName + " must not be null"); + Log.e(AF_PLUGIN_TAG, "Exception occurred when trying to: " + call.method + "->" + argumentName + " must not be null"); throw new IllegalArgumentException("[" + call.method + "]: " + argumentName + " must not be null"); } return argument; diff --git a/android/src/main/java/com/appsflyer/appsflyersdk/LogMessages.java b/android/src/main/java/com/appsflyer/appsflyersdk/LogMessages.java new file mode 100644 index 0000000..cc363ef --- /dev/null +++ b/android/src/main/java/com/appsflyer/appsflyersdk/LogMessages.java @@ -0,0 +1,12 @@ +package com.appsflyer.appsflyersdk; + +public final class LogMessages { + + // Prevent the instantiation of this utilities class. + private LogMessages() { + throw new IllegalStateException("LogMessages class should not be instantiated"); + } + + public static final String METHOD_CHANNEL_IS_NULL = "mMethodChannel is null, cannot invoke the callback"; + public static final String ACTIVITY_NOT_ATTACHED_TO_ENGINE = "Activity isn't attached to the flutter engine"; +} diff --git a/example/lib/home_container.dart b/example/lib/home_container.dart index 43d8d82..a474830 100644 --- a/example/lib/home_container.dart +++ b/example/lib/home_container.dart @@ -7,12 +7,14 @@ import 'utils.dart'; class HomeContainer extends StatefulWidget { final Map onData; final Future Function(String, Map) logEvent; + final void Function() logAdRevenueEvent; Object deepLinkData; HomeContainer({ required this.onData, required this.deepLinkData, required this.logEvent, + required this.logAdRevenueEvent, }); @override @@ -136,6 +138,20 @@ class _HomeContainerState extends State { ), ), ), + ElevatedButton( + onPressed: () { + widget.logAdRevenueEvent(); + }, + child: Text("Trigger AdRevenue Event"), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.white, + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10), + textStyle: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 16, + ), + ), + ), ], ), ) diff --git a/example/lib/main_page.dart b/example/lib/main_page.dart index e0da017..70ce33b 100644 --- a/example/lib/main_page.dart +++ b/example/lib/main_page.dart @@ -124,6 +124,7 @@ class MainPageState extends State { onData: _gcd, deepLinkData: _deepLinkData, logEvent: logEvent, + logAdRevenueEvent: logAdRevenueEvent, ), ), ElevatedButton( @@ -133,7 +134,8 @@ class MainPageState extends State { showMessage("AppsFlyer SDK initialized successfully."); }, onError: (int errorCode, String errorMessage) { - showMessage("Error initializing AppsFlyer SDK: Code $errorCode - $errorMessage"); + showMessage( + "Error initializing AppsFlyer SDK: Code $errorCode - $errorMessage"); }, ); }, @@ -158,13 +160,29 @@ class MainPageState extends State { return logResult; } + void logAdRevenueEvent() { + try { + Map customParams = { + 'ad_platform': 'Admob', + 'ad_currency': 'USD', + }; + + AdRevenueData adRevenueData = AdRevenueData( + monetizationNetwork: 'SpongeBob', + mediationNetwork: AFMediationNetwork.googleAdMob.value, + currencyIso4217Code: 'USD', + revenue: 100.3, + additionalParameters: customParams); + _appsflyerSdk.logAdRevenue(adRevenueData); + print("Ad Revenue event logged with no errors"); + } catch (e) { + print("Failed to log event: $e"); + } + } + void showMessage(String message) { - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar( - content: - Text(message), + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(message), )); } } - - diff --git a/ios/Classes/AppsflyerSdkPlugin.m b/ios/Classes/AppsflyerSdkPlugin.m index 4295044..f497c68 100644 --- a/ios/Classes/AppsflyerSdkPlugin.m +++ b/ios/Classes/AppsflyerSdkPlugin.m @@ -255,20 +255,20 @@ - (void)logAdRevenue:(FlutterMethodCall*)call result:(FlutterResult)result { - (AppsFlyerAdRevenueMediationNetworkType)getEnumValueFromString:(NSString *)mediationNetworkString { NSDictionary *stringToEnumMap = @{ - @"googleadmob": @(AppsFlyerAdRevenueMediationNetworkTypeGoogleAdMob), + @"google_admob": @(AppsFlyerAdRevenueMediationNetworkTypeGoogleAdMob), @"ironsource": @(AppsFlyerAdRevenueMediationNetworkTypeIronSource), - @"applovinmax": @(AppsFlyerAdRevenueMediationNetworkTypeApplovinMax), + @"applovin_max": @(AppsFlyerAdRevenueMediationNetworkTypeApplovinMax), @"fyber": @(AppsFlyerAdRevenueMediationNetworkTypeFyber), @"appodeal": @(AppsFlyerAdRevenueMediationNetworkTypeAppodeal), - @"Admost": @(AppsFlyerAdRevenueMediationNetworkTypeAdmost), - @"Topon": @(AppsFlyerAdRevenueMediationNetworkTypeTopon), - @"Tradplus": @(AppsFlyerAdRevenueMediationNetworkTypeTradplus), - @"Yandex": @(AppsFlyerAdRevenueMediationNetworkTypeYandex), + @"admost": @(AppsFlyerAdRevenueMediationNetworkTypeAdmost), + @"topon": @(AppsFlyerAdRevenueMediationNetworkTypeTopon), + @"tradplus": @(AppsFlyerAdRevenueMediationNetworkTypeTradplus), + @"yandex": @(AppsFlyerAdRevenueMediationNetworkTypeYandex), @"chartboost": @(AppsFlyerAdRevenueMediationNetworkTypeChartBoost), - @"Unity": @(AppsFlyerAdRevenueMediationNetworkTypeUnity), - @"toponpte": @(AppsFlyerAdRevenueMediationNetworkTypeToponPte), - @"customMediation": @(AppsFlyerAdRevenueMediationNetworkTypeCustom), - @"directMonetizationNetwork": @(AppsFlyerAdRevenueMediationNetworkTypeDirectMonetization) + @"unity": @(AppsFlyerAdRevenueMediationNetworkTypeUnity), + @"topon_pte": @(AppsFlyerAdRevenueMediationNetworkTypeToponPte), + @"custom_mediation": @(AppsFlyerAdRevenueMediationNetworkTypeCustom), + @"direct_monetization_network": @(AppsFlyerAdRevenueMediationNetworkTypeDirectMonetization) }; NSNumber *enumValueNumber = stringToEnumMap[mediationNetworkString]; diff --git a/ios/appsflyer_sdk.podspec b/ios/appsflyer_sdk.podspec index 56145b3..c030545 100644 --- a/ios/appsflyer_sdk.podspec +++ b/ios/appsflyer_sdk.podspec @@ -3,7 +3,7 @@ # Pod::Spec.new do |s| s.name = 'appsflyer_sdk' - s.version = '6.15.1' + s.version = '6.15.3' s.summary = 'AppsFlyer Integration for Flutter' s.description = <<-DESC AppsFlyer is the market leader in mobile advertising attribution & analytics, helping marketers to pinpoint their targeting, optimize their ad spend and boost their ROI. @@ -21,5 +21,5 @@ AppsFlyer is the market leader in mobile advertising attribution & analytics, he s.source_files = 'Classes/**/*' s.public_header_files = 'Classes/**/*.h' s.dependency 'Flutter' - s.ios.dependency 'AppsFlyerFramework','6.15.1' + s.ios.dependency 'AppsFlyerFramework','6.15.3' end diff --git a/lib/src/appsflyer_constants.dart b/lib/src/appsflyer_constants.dart index 6f86f56..641db02 100644 --- a/lib/src/appsflyer_constants.dart +++ b/lib/src/appsflyer_constants.dart @@ -49,31 +49,31 @@ enum AFMediationNetwork { case AFMediationNetwork.ironSource: return "ironsource"; case AFMediationNetwork.applovinMax: - return "applovinmax"; + return "applovin_max"; case AFMediationNetwork.googleAdMob: - return "googleadmob"; + return "google_admob"; case AFMediationNetwork.fyber: return "fyber"; case AFMediationNetwork.appodeal: return "appodeal"; case AFMediationNetwork.admost: - return "Admost"; + return "admost"; case AFMediationNetwork.topon: - return "Topon"; + return "topon"; case AFMediationNetwork.tradplus: - return "Tradplus"; + return "tradplus"; case AFMediationNetwork.yandex: - return "Yandex"; + return "yandex"; case AFMediationNetwork.chartboost: return "chartboost"; case AFMediationNetwork.unity: - return "Unity"; + return "unity"; case AFMediationNetwork.toponPte: - return "toponpte"; + return "topon_pte"; case AFMediationNetwork.customMediation: - return "customMediation"; + return "custom_mediation"; case AFMediationNetwork.directMonetizationNetwork: - return "directMonetizationNetwork"; + return "direct_monetization_network"; } } } diff --git a/pubspec.yaml b/pubspec.yaml index 90a5a68..cb6c369 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: appsflyer_sdk description: A Flutter plugin for AppsFlyer SDK. Supports iOS and Android. -version: 6.15.1 +version: 6.15.2 homepage: https://github.com/AppsFlyerSDK/flutter_appsflyer_sdk