Skip to content

Commit

Permalink
Merge pull request #278 from AppsFlyerSDK/DELIVERY-23984/nullPointerE…
Browse files Browse the repository at this point in the history
…xceptionNewFix

Delivery 23984/null pointer exception new fix
  • Loading branch information
GM-appsflyer authored Jul 12, 2023
2 parents 0b0c9ae + a50e4e7 commit 2277c96
Show file tree
Hide file tree
Showing 18 changed files with 328 additions and 28 deletions.
12 changes: 12 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,18 @@ example/ios/Runner.xcodeproj/project.pbxproj

example/.flutter-plugins-dependencies

example/macos/*

example/linux/*

example/windows/*

example/web/*

example/\.metadata
example/analysis_options.yaml


node_modules/

covBadgeGen.js
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# Versions
## 6.11.3
- null pointer exception fix for android, push notification bug fix & ios sdk 6.11.2
## 6.11.2
- update to Android SDK to v6.11.2
## 6.11.1
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@
### <a id="plugin-build-for"> This plugin is built for

- Android AppsFlyer SDK **v6.11.2**
- iOS AppsFlyer SDK **v6.10.1**
- iOS AppsFlyer SDK **v6.11.2**

## <a id="breaking-changes"> ❗❗ Breaking changes when updating to v6.x.x❗❗

If you have used one of the removed/changed APIs, please check the integration guide for the updated instructions.

- From version `6.11.2`, the `setPushNotification` will not work in iOS. [Please use our new API `sendPushNotificationData` when receiving a notification on flutter side](/doc/API.md#sendPushNotificationData).

- From version `6.8.0`, the `enableLocationCollection` has been removed from the plugin.

- From version `6.4.0`, UDL (Unified deep link) now as a dedicated class with getters for handling the deeplink result.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
Expand Down Expand Up @@ -59,7 +60,7 @@ public class AppsflyerSdkPlugin implements MethodCallHandler, FlutterPlugin, Act
private static String cachedOnAttributionFailure;
private static String cachedOnConversionDataFail;
private static DeepLinkResult cachedDeepLinkResult;

final Handler uiThreadHandler = new Handler(Looper.getMainLooper());
private EventChannel mEventChannel;
/**
Expand Down Expand Up @@ -199,6 +200,10 @@ 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");
return;
}
final String method = call.method;
switch (method) {
case "initSdk":
Expand Down Expand Up @@ -289,6 +294,9 @@ public void onMethodCall(MethodCall call, Result result) {
setOneLinkCustomDomain(call, result);
break;
case "setPushNotification":
setPushNotification(call, result);
break;
case "sendPushNotificationData":
sendPushNotificationData(call, result);
break;
case "enableFacebookDeferredApplinks":
Expand Down Expand Up @@ -398,11 +406,58 @@ private void enableFacebookDeferredApplinks(MethodCall call, Result result) {
result.success(null);
}

private void sendPushNotificationData(MethodCall call, Result result) {
private void setPushNotification(MethodCall call, Result result) {
AppsFlyerLib.getInstance().sendPushNotificationData(activity);
result.success(null);
}

private void sendPushNotificationData(MethodCall call, Result result) {
final Map<String, Object> pushPayload = (Map<String, Object>) call.arguments;
String errorMsg = null;
Bundle bundle;

if(pushPayload == null){
Log.d("AppsFlyer", "Push payload is null");
return;
}

try {
bundle = this.jsonToBundle(new JSONObject(pushPayload));
} catch (JSONException e) {
Log.d("AppsFlyer", "Can't parse pushPayload to bundle");
return;
}

if (activity != null) {
Intent intent = activity.getIntent();
if (intent != null) {
intent.putExtras(bundle);
activity.setIntent(intent);
AppsFlyerLib.getInstance().sendPushNotificationData(activity);
} else {
errorMsg = "The intent is null. Push payload has not been sent!";
}
} else {
errorMsg = "The activity is null. Push payload has not been sent!";
}

if(errorMsg != null){
Log.d("AppsFlyer", errorMsg);
return;
}

result.success(null);
}
private static Bundle jsonToBundle(JSONObject jsonObject) throws JSONException {
Bundle bundle = new Bundle();
Iterator iter = jsonObject.keys();
while (iter.hasNext()) {
String key = (String) iter.next();
String value = jsonObject.getString(key);
bundle.putString(key, value);
}
return bundle;
}
private void setOneLinkCustomDomain(MethodCall call, Result result) {
ArrayList<String> brandDomains = (ArrayList<String>) call.arguments;
String[] brandDomainsArray = brandDomains.toArray(new String[brandDomains.size()]);
Expand Down
48 changes: 36 additions & 12 deletions doc/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
- [getHostPrefix](#getHostPrefix)
- [updateServerUninstallToken](#updateServerUninstallToken)
- [Validate Purchase](#validatePurchase)
- [setPushNotification](#setPushNotification)
- [setPushNotification](#setPushNotification)[DEPRECATED]
- [sendPushNotificationData](#sendPushNotificationData)
- [addPushNotificationDeepLinkPath](#addPushNotificationDeepLinkPath)
- [User Invite](#userInvite)
- [enableFacebookDeferredApplinks](#enableFacebookDeferredApplinks)
Expand All @@ -58,11 +59,18 @@

**`options`**

| name | type | default | description |
| ---------- | --------- | ------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `afDevKey` | `String` | | [Appsflyer Dev key](https://support.appsflyer.com/hc/en-us/articles/207032126-AppsFlyer-SDK-Integration-Android) |
| `afAppId` | `String` | | [Apple Application ID](https://support.appsflyer.com/hc/en-us/articles/207032066-AppsFlyer-SDK-Integration-iOS) (for iOS only) |
| `showDebug` | `bool` | `false` | debug mode (optional) |
|
| Setting | Type | Description |
| -------- | -------- | ------------- |
| devKey | String | Your application's [devKey](https://support.appsflyer.com/hc/en-us/articles/207032066-Basic-SDK-integration-guide#retrieving-the-dev-key) provided by AppsFlyer (required) |
| appId | String | Your application's [App ID](https://support.appsflyer.com/hc/en-us/articles/207377436-Adding-a-new-app#available-in-the-app-store-google-play-store-windows-phone-store) (required for iOS only) that you configured in your AppsFlyer dashboard |
| showDebug | bool | Debug mode - set to `true` for testing only, do not release to production with this parameter set to `true`! |
| timeToWaitForATTUserAuthorization | double | Delays the SDK start for x seconds until the user either accepts the consent dialog, declines it, or the timer runs out. |
| appInviteOneLink | String | The [OneLink template ID](https://support.appsflyer.com/hc/en-us/articles/115004480866-User-invite-attribution#parameters) that is used to generate a User Invite, this is not a required field in the `AppsFlyerOptions`, you may choose to set it later via the appropriate API. |
| disableAdvertisingIdentifier| bool | Opt-out of the collection of Advertising Identifiers, which include OAID, AAID, GAID and IDFA. |
| disableCollectASA | bool | Opt-out of the Apple Search Ads attributions. |



_Example:_

Expand Down Expand Up @@ -400,22 +408,38 @@ appsflyerSdk.onPurchaseValidation((res){
```

---
**<a id="setPushNotification"> `void setPushNotification(bool isEnabled)`**
**<a id="setPushNotification"> `void setPushNotification(bool isEnabled)`[DEPRECATED]**

_Example:_
```dart
appsFlyerSdk.setPushNotification(true);
```
---
**<a id="sendPushNotificationData"> `void sendPushNotificationData(Map? userInfo)`**

_NOTE:_
Push-notification campaigns are used to create fast re-engagements with existing users.

For Android: Make sure to call this API inside the page of every activity that is launched after clicking the notification.
[Learn more](https://support.appsflyer.com/hc/en-us/articles/207364076-Measuring-Push-Notification-Re-Engagement-Campaigns)

For iOS: This API can be called once at the initalization phase.
For Android: AppsFlyer SDK uses the activity in order to process the push payload. Make sure you call this api when the app's activity is available (NOT dead state).

Please check the following guide in order to understand the relevant payload needed for AppsFlyer to attribute the push notification:
_Example:_
```dart
final Map userInfo = {
"af":{
"c": "test_campaign",
"is_retargeting": true,
"pid": "push_provider_int",
},
"aps":{
"alert": "Get 5000 Coins",
"badge": "37",
"sound": "default"
}
};
https://support.appsflyer.com/hc/en-us/articles/207364076-Measuring-push-notification-re-engagement-campaigns
appsFlyerSdk.sendPushNotificationData(userInfo);
```

---
**<a id="addPushNotificationDeepLinkPath"> `void addPushNotificationDeepLinkPath(List<String> deeplinkPath)`**
Expand Down
45 changes: 41 additions & 4 deletions example/.metadata
Original file line number Diff line number Diff line change
@@ -1,8 +1,45 @@
# This file log properties of this Flutter project.
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
# This file should be version controlled.

version:
revision: f37c235c32fc15babe6dc7b7bc2ee4387e5ecf92
channel: beta
revision: 135454af32477f815a7525073027a3ff9eff1bfd
channel: stable

project_type: app

# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 135454af32477f815a7525073027a3ff9eff1bfd
base_revision: 135454af32477f815a7525073027a3ff9eff1bfd
- platform: android
create_revision: 135454af32477f815a7525073027a3ff9eff1bfd
base_revision: 135454af32477f815a7525073027a3ff9eff1bfd
- platform: ios
create_revision: 135454af32477f815a7525073027a3ff9eff1bfd
base_revision: 135454af32477f815a7525073027a3ff9eff1bfd
- platform: linux
create_revision: 135454af32477f815a7525073027a3ff9eff1bfd
base_revision: 135454af32477f815a7525073027a3ff9eff1bfd
- platform: macos
create_revision: 135454af32477f815a7525073027a3ff9eff1bfd
base_revision: 135454af32477f815a7525073027a3ff9eff1bfd
- platform: web
create_revision: 135454af32477f815a7525073027a3ff9eff1bfd
base_revision: 135454af32477f815a7525073027a3ff9eff1bfd
- platform: windows
create_revision: 135454af32477f815a7525073027a3ff9eff1bfd
base_revision: 135454af32477f815a7525073027a3ff9eff1bfd

# User provided section

# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />

<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
18 changes: 18 additions & 0 deletions example/android/app/src/main/res/values-night/styles.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
34 changes: 34 additions & 0 deletions example/ios/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
**/dgph
*.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/ephemeral/
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
2 changes: 1 addition & 1 deletion example/ios/Podfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '9.0'
# platform :ios, '11.0'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>
36 changes: 36 additions & 0 deletions example/ios/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import UIKit
import Flutter
import AppsFlyerLib
import AppTrackingTransparency

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
AppsFlyerLib.shared().waitForATTUserAuthorization(timeoutInterval: 60)

return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}

override func applicationDidBecomeActive(_ application: UIApplication) {
if #available(iOS 14, *) {
ATTrackingManager.requestTrackingAuthorization { (status) in
switch status {
case .denied:
print("AuthorizationSatus is denied")
case .notDetermined:
print("AuthorizationSatus is notDetermined")
case .restricted:
print("AuthorizationSatus is restricted")
case .authorized:
print("AuthorizationSatus is authorized")
@unknown default:
fatalError("Invalid authorization status")
}
}
}
}
}
Loading

0 comments on commit 2277c96

Please sign in to comment.