@capgo/capacitor-appsflyer 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/CapgoCapacitorAppsflyer.podspec +27 -0
  2. package/LICENSE +21 -0
  3. package/Package.swift +30 -0
  4. package/README.md +1257 -0
  5. package/android/build.gradle +178 -0
  6. package/android/src/main/AndroidManifest.xml +7 -0
  7. package/android/src/main/java/capacitor/plugin/appsflyer/sdk/AFHelpers.kt +76 -0
  8. package/android/src/main/java/capacitor/plugin/appsflyer/sdk/AppsFlyerConstants.kt +76 -0
  9. package/android/src/main/java/capacitor/plugin/appsflyer/sdk/AppsFlyerPlugin.kt +812 -0
  10. package/android/src/main/res/.gitkeep +0 -0
  11. package/dist/docs.json +2145 -0
  12. package/dist/esm/Appsflyer_constants.d.ts +29 -0
  13. package/dist/esm/Appsflyer_constants.js +33 -0
  14. package/dist/esm/Appsflyer_constants.js.map +1 -0
  15. package/dist/esm/appsflyer_interfaces.d.ts +200 -0
  16. package/dist/esm/appsflyer_interfaces.js +18 -0
  17. package/dist/esm/appsflyer_interfaces.js.map +1 -0
  18. package/dist/esm/definitions.d.ts +219 -0
  19. package/dist/esm/definitions.js +2 -0
  20. package/dist/esm/definitions.js.map +1 -0
  21. package/dist/esm/index.d.ts +6 -0
  22. package/dist/esm/index.js +7 -0
  23. package/dist/esm/index.js.map +1 -0
  24. package/dist/plugin.cjs.js +60 -0
  25. package/dist/plugin.cjs.js.map +1 -0
  26. package/dist/plugin.js +63 -0
  27. package/dist/plugin.js.map +1 -0
  28. package/ios/Sources/AppsFlyerPlugin/AppsFlyerAttribution.swift +60 -0
  29. package/ios/Sources/AppsFlyerPlugin/AppsFlyerConstants.swift +86 -0
  30. package/ios/Sources/AppsFlyerPlugin/AppsFlyerPlugin.swift +1007 -0
  31. package/ios/Sources/AppsFlyerPlugin/Extensions.swift +78 -0
  32. package/ios/Tests/AppsFlyerPluginTests/AppsFlyerPluginTests.swift +8 -0
  33. package/package.json +93 -0
@@ -0,0 +1,812 @@
1
+ package capacitor.plugin.appsflyer.sdk
2
+
3
+ import android.Manifest
4
+ import android.content.Intent
5
+ import android.util.Log
6
+
7
+ import com.appsflyer.*
8
+ import com.appsflyer.attribution.AppsFlyerRequestListener
9
+ import com.appsflyer.deeplink.DeepLinkListener
10
+ import com.appsflyer.deeplink.DeepLinkResult
11
+ import com.appsflyer.internal.platform_extension.PluginInfo
12
+ import com.appsflyer.share.CrossPromotionHelper
13
+ import com.appsflyer.share.LinkGenerator
14
+ import com.appsflyer.share.ShareInviteHelper
15
+ import com.getcapacitor.JSObject
16
+ import com.getcapacitor.Plugin
17
+ import com.getcapacitor.PluginCall
18
+ import com.getcapacitor.PluginMethod
19
+ import com.getcapacitor.annotation.CapacitorPlugin
20
+ import com.getcapacitor.annotation.Permission
21
+ import org.json.JSONObject
22
+
23
+
24
+ @CapacitorPlugin(
25
+ name = "AppsFlyerPlugin",
26
+ permissions = [Permission(
27
+ strings = arrayOf(
28
+ Manifest.permission.INTERNET,
29
+ Manifest.permission.ACCESS_NETWORK_STATE,
30
+ "com.google.android.gms.permission.AD_ID"
31
+ )
32
+ )]
33
+ )
34
+ class AppsFlyerPlugin : Plugin() {
35
+ private var conversion: Boolean? = null
36
+ private var oaoa: Boolean? = null
37
+ private var udl: Boolean? = null
38
+ @Volatile private var hasSDKStarted: Boolean = false
39
+ @Volatile private var isStarting: Boolean = false
40
+
41
+
42
+ override fun handleOnNewIntent(intent: Intent?) {
43
+ super.handleOnNewIntent(intent)
44
+ if (intent != null) {
45
+ activity.intent = intent
46
+ }
47
+ }
48
+
49
+
50
+ @PluginMethod
51
+ fun initSDK(call: PluginCall) {
52
+ val devKey = call.getString(AF_DEV_KEY)
53
+ val debug = call.getBoolean(AF_DEBUG, false)
54
+ val minTime = call.getInt(AF_MIN_TIME)
55
+ val manualStart = call.getBoolean(AF_MANUAL_START, false)
56
+ conversion = call.getBoolean(AF_CONVERSION_LISTENER, true)
57
+ oaoa = call.getBoolean(AF_OAOA, true)
58
+ udl = call.getBoolean(AF_UDL, false)
59
+ val timeout = call.getInt(AF_DEEP_LINK_TIME_OUT)?.toLong()
60
+
61
+ AppsFlyerLib.getInstance().apply {
62
+ setPluginInfo(
63
+ PluginInfo(
64
+ com.appsflyer.internal.platform_extension.Plugin.CAPACITOR,
65
+ BuildConfig.VERSION_NAME
66
+ //, mapOf("build_number" to BuildConfig.VERSION_CODE.toString())
67
+ )
68
+ )
69
+ if (debug == true) {
70
+ setDebugLog(true)
71
+ }
72
+ minTime?.let {
73
+ setMinTimeBetweenSessions(it)
74
+ }
75
+
76
+ devKey?.let {
77
+ init(
78
+ devKey,
79
+ if (conversion == true) getConversionListener() else null,
80
+ context.applicationContext
81
+ )
82
+ } ?: run {
83
+ call.reject(AF_NULL_DEV_KEY)
84
+
85
+ }
86
+ if (udl == true) {
87
+ if (timeout != null) {
88
+ subscribeForDeepLink(getDeepLinkListener(), timeout)
89
+ } else {
90
+ subscribeForDeepLink(getDeepLinkListener())
91
+ }
92
+ }
93
+
94
+ if (manualStart == false) {
95
+ startSDK(call)
96
+ } else {
97
+ val result = JSObject().apply {
98
+ put("res", "SDK initiated successfully. SDK has NOT been started yet")
99
+ }
100
+ call.resolve(result)
101
+ }
102
+ }
103
+
104
+ }
105
+
106
+ @PluginMethod
107
+ fun logEvent(call: PluginCall) {
108
+ val eventName = call.getString(AF_EVENT_NAME)
109
+ val eventValue = AFHelpers.jsonToMap(call.getObject(AF_EVENT_VALUE))
110
+ AppsFlyerLib.getInstance()
111
+ .logEvent(
112
+ activity ?: context.applicationContext,
113
+ eventName,
114
+ eventValue,
115
+ object : AppsFlyerRequestListener {
116
+ override fun onSuccess() {
117
+ val ret = JSObject()
118
+ ret.put("res", "ok")
119
+ call.resolve(ret)
120
+ }
121
+
122
+ override fun onError(i: Int, s: String) {
123
+ call.reject(s, i.toString())
124
+ }
125
+ })
126
+ }
127
+
128
+ @PluginMethod(returnType = PluginMethod.RETURN_NONE)
129
+ fun setCustomerUserId(call: PluginCall) {
130
+ val cuid = call.getString(AF_CUID)
131
+ if (!cuid.isNullOrEmpty()) {
132
+ AppsFlyerLib.getInstance().setCustomerUserId(cuid)
133
+ } else {
134
+ call.reject("Invalid Customer User ID")
135
+ }
136
+
137
+ }
138
+
139
+ @PluginMethod(returnType = PluginMethod.RETURN_NONE)
140
+ fun setCurrencyCode(call: PluginCall) {
141
+ val code = call.getString(AF_CURRENCY_CODE)
142
+ if (!code.isNullOrEmpty()) {
143
+ AppsFlyerLib.getInstance().setCurrencyCode(code)
144
+ } else {
145
+ call.reject("Invalid Currency Code")
146
+ }
147
+ }
148
+
149
+ @PluginMethod(returnType = PluginMethod.RETURN_NONE)
150
+ fun updateServerUninstallToken(call: PluginCall) {
151
+ val token = call.getString(AF_TOKEN)
152
+ if (!token.isNullOrEmpty()) {
153
+ AppsFlyerLib.getInstance().updateServerUninstallToken(context, token)
154
+ } else {
155
+ call.reject("Invalid device token")
156
+ }
157
+ }
158
+
159
+ @PluginMethod(returnType = PluginMethod.RETURN_NONE)
160
+ fun setAppInviteOneLink(call: PluginCall) {
161
+ val id = call.getString(AF_ONELINK_ID)
162
+ if (!id.isNullOrEmpty()) {
163
+ AppsFlyerLib.getInstance().setAppInviteOneLink(id)
164
+ } else {
165
+ call.reject("Onelink id is missing")
166
+ }
167
+ }
168
+
169
+
170
+ @PluginMethod(returnType = PluginMethod.RETURN_NONE)
171
+ fun setOneLinkCustomDomain(call: PluginCall) {
172
+ val arr = call.getArray(AF_ONELINK_DOMAIN)
173
+ if (arr != null && arr.length() > 0) {
174
+ val dom = arr.toList<String>().toTypedArray()
175
+ AppsFlyerLib.getInstance().setOneLinkCustomDomain(*dom)
176
+ } else {
177
+ call.reject("Domains are missing")
178
+ }
179
+ }
180
+
181
+ @PluginMethod(returnType = PluginMethod.RETURN_NONE)
182
+ fun appendParametersToDeepLinkingURL(call: PluginCall) {
183
+ val contains = call.getString(AF_CONTAINS)
184
+ val parameters = AFHelpers.jsonToStringMap(call.getObject(AF_PARAMETERS))
185
+ if (!contains.isNullOrEmpty() && !parameters.isNullOrEmpty()) {
186
+ AppsFlyerLib.getInstance().appendParametersToDeepLinkingURL(contains, parameters)
187
+ }
188
+ }
189
+
190
+
191
+ @PluginMethod(returnType = PluginMethod.RETURN_NONE)
192
+ fun setResolveDeepLinkURLs(call: PluginCall) {
193
+ val arr = call.getArray(AF_DEEPLINK_URLS)
194
+ if (arr != null && arr.length() > 0) {
195
+ val urls = arr.toList<String>().toTypedArray()
196
+ AppsFlyerLib.getInstance().setResolveDeepLinkURLs(*urls)
197
+ } else {
198
+ call.reject("URLs are missing")
199
+ }
200
+ }
201
+
202
+ @PluginMethod(returnType = PluginMethod.RETURN_NONE)
203
+ fun addPushNotificationDeepLinkPath(call: PluginCall) {
204
+ val arr = call.getArray(AF_PATH)
205
+ if (arr != null && arr.length() > 0) {
206
+ val path = arr.toList<String>().toTypedArray()
207
+ AppsFlyerLib.getInstance().addPushNotificationDeepLinkPath(*path)
208
+ } else {
209
+ call.reject("Path is missing")
210
+ }
211
+ }
212
+
213
+ @Deprecated("Use setSharingFilterForPartners")
214
+ @PluginMethod(returnType = PluginMethod.RETURN_NONE)
215
+ fun setSharingFilter(call: PluginCall) {
216
+ val arr = call.getArray(AF_FILTERS)
217
+ if (arr != null && arr.length() > 0) {
218
+ val filters = arr.toList<String>().toTypedArray()
219
+ AppsFlyerLib.getInstance().setSharingFilter(*filters)
220
+ } else {
221
+ AppsFlyerLib.getInstance().setSharingFilter("")
222
+ }
223
+ }
224
+
225
+ @Deprecated("Use setSharingFilterForPartners")
226
+ @PluginMethod(returnType = PluginMethod.RETURN_NONE)
227
+ fun setSharingFilterForAllPartners(call: PluginCall) {
228
+ AppsFlyerLib.getInstance().setSharingFilterForAllPartners()
229
+ }
230
+
231
+ @PluginMethod(returnType = PluginMethod.RETURN_NONE)
232
+ fun setSharingFilterForPartners(call: PluginCall) {
233
+ val filters = call.getArray(AF_FILTERS)?.run {
234
+ toList<String>().toTypedArray()
235
+ } ?: return call.reject("cannot extract the filters value")
236
+ AppsFlyerLib.getInstance().setSharingFilterForPartners(*filters)
237
+
238
+ }
239
+
240
+ @PluginMethod(returnType = PluginMethod.RETURN_NONE)
241
+ fun setAdditionalData(call: PluginCall) {
242
+ val data = call.getObject(AF_ADDITIONAL_DATA)
243
+ if (data != null) {
244
+ AppsFlyerLib.getInstance().setAdditionalData(AFHelpers.jsonToMap(data))
245
+ } else {
246
+ call.reject("Data is missing")
247
+ }
248
+ }
249
+
250
+ @PluginMethod
251
+ fun getAppsFlyerUID(call: PluginCall) {
252
+ val id = AppsFlyerLib.getInstance().getAppsFlyerUID(context)
253
+ val obj = JSObject().apply {
254
+ put(AF_UID, id)
255
+ }
256
+ call.resolve(obj)
257
+ }
258
+
259
+ @PluginMethod(returnType = PluginMethod.RETURN_NONE)
260
+ fun anonymizeUser(call: PluginCall) {
261
+ call.getBoolean(AF_ANONYMIZE_USER)?.let {
262
+ AppsFlyerLib.getInstance().anonymizeUser(it)
263
+ } ?: run { call.reject("Missing boolean value anonymizeUser") }
264
+ }
265
+
266
+ @PluginMethod(returnType = PluginMethod.RETURN_NONE)
267
+ fun setDisableNetworkData(call: PluginCall) {
268
+ call.getBoolean(AF_DISABLE)?.let {
269
+ AppsFlyerLib.getInstance().setDisableNetworkData(it)
270
+ } ?: run { call.reject("Missing boolean value disable") }
271
+ }
272
+
273
+ @PluginMethod
274
+ fun stop(call: PluginCall) {
275
+ val shouldStop = call.getBoolean(AF_STOP)
276
+ AppsFlyerLib.getInstance().apply {
277
+ if (shouldStop != null) {
278
+ stop(shouldStop, context)
279
+ }
280
+ val obj = JSObject().apply {
281
+ put(AF_IS_STOP, isStopped)
282
+ }
283
+ call.resolve(obj)
284
+ }
285
+ }
286
+
287
+ @Synchronized
288
+ @PluginMethod
289
+ fun startSDK(call: PluginCall) {
290
+ when {
291
+ hasSDKStarted -> {
292
+ call.resolve(JSObject().apply {
293
+ put("res", "AppsFlyer SDK already started")
294
+ })
295
+ return
296
+ }
297
+ isStarting -> {
298
+ call.reject("SDK start already in progress. Please wait for the callback.")
299
+ return
300
+ }
301
+ else -> {
302
+ isStarting = true
303
+ }
304
+ }
305
+
306
+ AppsFlyerLib.getInstance().start(
307
+ activity ?: context.applicationContext,
308
+ null,
309
+ object : AppsFlyerRequestListener {
310
+ override fun onSuccess() {
311
+ hasSDKStarted = true
312
+ isStarting = false
313
+ call.resolve(JSObject().apply {
314
+ put("res", "success")
315
+ })
316
+ }
317
+
318
+ override fun onError(errCode: Int, msg: String) {
319
+ isStarting = false
320
+ call.reject("Error Code: $errCode, Message: $msg")
321
+ }
322
+ }
323
+ )
324
+ }
325
+
326
+ @PluginMethod
327
+ fun disableSKAdNetwork(call: PluginCall) {
328
+ call.unavailable()
329
+ }
330
+
331
+ @PluginMethod
332
+ fun isSDKStarted(call: PluginCall) {
333
+ val result = JSObject().apply {
334
+ put("isStarted", hasSDKStarted)
335
+ }
336
+ call.resolve(result)
337
+ }
338
+
339
+ @PluginMethod
340
+ fun isSDKStopped(call: PluginCall) {
341
+ val result = JSObject().apply {
342
+ put("isStopped", AppsFlyerLib.getInstance().isStopped)
343
+ }
344
+ call.resolve(result)
345
+ }
346
+
347
+ @PluginMethod(returnType = PluginMethod.RETURN_NONE)
348
+ fun disableAdvertisingIdentifier(call: PluginCall) {
349
+ call.getBoolean(AF_DISABLE_SKAD)?.let {
350
+ AppsFlyerLib.getInstance().setDisableAdvertisingIdentifiers(it)
351
+ } ?: run { call.reject("Missing boolean value shouldDisable") }
352
+ }
353
+
354
+ @PluginMethod
355
+ fun disableCollectASA(call: PluginCall) {
356
+ call.unavailable()
357
+ }
358
+
359
+
360
+ @PluginMethod(returnType = PluginMethod.RETURN_NONE)
361
+ fun setHost(call: PluginCall) {
362
+ val pre = call.getString(AF_HOST_PREFIX)
363
+ val post = call.getString(AF_HOST_NAME)
364
+ if (pre != null && post != null) {
365
+ AppsFlyerLib.getInstance().setHost(pre, post)
366
+ } else {
367
+ call.reject("Missing host prefix and/or host name")
368
+ }
369
+ }
370
+
371
+ @PluginMethod
372
+ fun generateInviteLink(call: PluginCall) {
373
+
374
+ val linkGenerator = ShareInviteHelper.generateInviteUrl(context).apply {
375
+ brandDomain = call.getString(AF_BRAND_DOMAIN)
376
+ campaign = call.getString(AF_CAMPAIGN)
377
+ channel = call.getString(AF_CHANNEL)
378
+ setReferrerName(call.getString(AF_REFERRER_NAME))
379
+ setReferrerImageURL(call.getString(AF_REFERRER_IMAGE_URL))
380
+ setReferrerCustomerId(call.getString(AF_REFERRER_CUSTOMER_ID))
381
+ setBaseDeeplink(call.getString(AF_BASE_DEEPLINK))
382
+ addParameters(AFHelpers.jsonToStringMap(call.getObject(AF_ADD_PARAMETERS)))
383
+
384
+ }
385
+
386
+ val listener = object : LinkGenerator.ResponseListener {
387
+ override fun onResponse(s: String?) {
388
+ val obj = JSObject().apply {
389
+ put(AF_LINK_READY, s)
390
+ }
391
+ call.resolve(obj)
392
+ }
393
+
394
+ override fun onResponseError(s: String?) {
395
+ call.reject(s)
396
+ }
397
+ }
398
+
399
+ linkGenerator.generateLink(context, listener)
400
+ }
401
+
402
+ @Deprecated("Use validateAndLogInAppPurchaseV2 instead")
403
+ @PluginMethod
404
+ fun validateAndLogInAppPurchaseAndroid(call: PluginCall) {
405
+ val currency = call.getString(AF_CURRENCY)
406
+ val publicKey = call.getString(AF_PUBLIC_KEY)
407
+ val signature = call.getString(AF_SIGNATURE)
408
+ val purchaseData = call.getString(AF_PURCHASE_DATA)
409
+ val price = call.getString(AF_PRICE)
410
+ val additionalParameters =
411
+ AFHelpers.jsonToStringMap(call.getObject(AF_ADDITIONAL_PARAMETERS))
412
+ if (currency != null && publicKey != null && signature != null && purchaseData != null) {
413
+ AppsFlyerLib.getInstance().apply {
414
+ registerValidatorListener(
415
+ context,
416
+ object : AppsFlyerInAppPurchaseValidatorListener {
417
+ override fun onValidateInApp() {
418
+ val ret = JSObject()
419
+ ret.put("res", "ok")
420
+ call.resolve(ret)
421
+ }
422
+
423
+ override fun onValidateInAppFailure(p0: String?) {
424
+ call.reject(p0)
425
+ }
426
+ })
427
+
428
+ validateAndLogInAppPurchase(
429
+ context,
430
+ publicKey,
431
+ signature,
432
+ purchaseData,
433
+ price,
434
+ currency,
435
+ additionalParameters
436
+ )
437
+ }
438
+ } else {
439
+ call.reject("Missing some fields")
440
+ }
441
+ }
442
+
443
+ @Deprecated("Use validateAndLogInAppPurchaseV2 instead")
444
+ @PluginMethod
445
+ fun validateAndLogInAppPurchaseIos(call: PluginCall) {
446
+ call.unavailable()
447
+ }
448
+
449
+ @PluginMethod
450
+ fun validateAndLogInAppPurchaseV2(call: PluginCall) {
451
+ try {
452
+ val purchaseDetailsMap = call.getObject(AF_PURCHASE_DETAILS)
453
+ ?: return call.reject("Purchase details are required")
454
+ val additionalParameters = call.getObject(AF_ADDITIONAL_PARAMETERS)
455
+
456
+ // Extract purchase details
457
+ val purchaseTypeString = purchaseDetailsMap.getString(AF_PURCHASE_TYPE)
458
+ ?: return call.reject("Purchase type is required")
459
+ val purchaseToken = purchaseDetailsMap.getString(AF_PURCHASE_TOKEN)
460
+ ?: return call.reject("Purchase token is required")
461
+ val productId = purchaseDetailsMap.getString(AF_PRODUCT_ID)
462
+ ?: return call.reject("Product ID is required")
463
+
464
+ // Map purchase type
465
+ val purchaseType = mapPurchaseType(purchaseTypeString)
466
+ ?: return call.reject("Invalid purchase type: $purchaseTypeString")
467
+
468
+ // Create AFPurchaseDetails object
469
+ val purchaseDetails = AFPurchaseDetails(
470
+ purchaseType,
471
+ purchaseToken,
472
+ productId
473
+ )
474
+
475
+ // Convert additional parameters
476
+ val additionalParamsMap = additionalParameters?.let {
477
+ AFHelpers.jsonToStringMap(it)
478
+ }
479
+
480
+ // Call AppsFlyer SDK
481
+ AppsFlyerLib.getInstance().validateAndLogInAppPurchase(
482
+ purchaseDetails,
483
+ additionalParamsMap,
484
+ object : AppsFlyerInAppPurchaseValidationCallback {
485
+ override fun onInAppPurchaseValidationFinished(validationResult: Map<String, Any?>) {
486
+ try {
487
+ val jsonResult = JSObject()
488
+ for ((key, value) in validationResult) {
489
+ jsonResult.put(key, value)
490
+ }
491
+ call.resolve(jsonResult)
492
+ } catch (e: Exception) {
493
+ call.reject("Error parsing validation result: ${e.message}")
494
+ }
495
+ }
496
+
497
+ override fun onInAppPurchaseValidationError(validationError: Map<String, Any>) {
498
+ try {
499
+ var errorMessage = "Validation failed"
500
+ if (validationError.containsKey("error")) {
501
+ errorMessage = validationError["error"].toString()
502
+ }
503
+
504
+ val jsonError = JSObject()
505
+ for ((key, value) in validationError) {
506
+ jsonError.put(key, value)
507
+ }
508
+ call.reject(errorMessage, jsonError.toString())
509
+ } catch (e: Exception) {
510
+ call.reject("Error parsing validation error: ${e.message}")
511
+ }
512
+ }
513
+ }
514
+ )
515
+ } catch (e: Exception) {
516
+ call.reject("Error in validateAndLogInAppPurchaseV2: ${e.message}")
517
+ }
518
+ }
519
+
520
+ private fun mapPurchaseType(purchaseTypeString: String): AFPurchaseType? {
521
+ return when (purchaseTypeString) {
522
+ "subscription" -> AFPurchaseType.SUBSCRIPTION
523
+ "one_time_purchase" -> AFPurchaseType.ONE_TIME_PURCHASE
524
+ else -> null
525
+ }
526
+ }
527
+
528
+ @PluginMethod
529
+ fun getSdkVersion(call: PluginCall) {
530
+ val v = AppsFlyerLib.getInstance().sdkVersion
531
+ val obj = JSObject().apply {
532
+ put("res", v)
533
+ }
534
+ call.resolve(obj)
535
+ }
536
+
537
+ @PluginMethod
538
+ fun enableFacebookDeferredApplinks(call: PluginCall) {
539
+ val b = call.getBoolean(AF_FB)
540
+ if (b != null) {
541
+ AppsFlyerLib.getInstance().enableFacebookDeferredApplinks(b)
542
+ val obj = JSObject().apply {
543
+ val m = (if (b) "enabled" else "disabled")
544
+ put("res", m)
545
+ }
546
+ call.resolve(obj)
547
+ } else {
548
+ call.reject("missing boolean value $AF_FB")
549
+ }
550
+ }
551
+
552
+ @PluginMethod
553
+ fun sendPushNotificationData(call: PluginCall) {
554
+ val json = call.getObject(AF_PUSH_PAYLOAD)
555
+ val i = activity.intent
556
+ AFHelpers.jsonToBundle(json)?.run {
557
+ i.putExtras(this)
558
+ }
559
+ activity.intent = i
560
+ AppsFlyerLib.getInstance().sendPushNotificationData(activity)
561
+
562
+ }
563
+
564
+ @PluginMethod
565
+ fun logCrossPromoteImpression(call: PluginCall) {
566
+ val appID =
567
+ call.getString(AF_APP_ID) ?: return call.reject("cannot extract the appID value")
568
+ val campaign =
569
+ call.getString(AF_CAMPAIGN) ?: return call.reject("cannot extract the campaign value")
570
+ val parameters = AFHelpers.jsonToStringMap(call.getObject(AF_PARAMETERS))
571
+ ?: return call.reject("cannot extract the parameters value")
572
+
573
+ CrossPromotionHelper.logCrossPromoteImpression(
574
+ context.applicationContext,
575
+ appID,
576
+ campaign,
577
+ parameters
578
+ )
579
+ val ret = JSObject()
580
+ ret.put("res", "ok")
581
+ call.resolve(ret)
582
+
583
+ }
584
+
585
+ @PluginMethod
586
+ fun setUserEmails(call: PluginCall) {
587
+ val emails = call.getArray(AF_EMAILS)?.run {
588
+ toList<String>().toTypedArray()
589
+ } ?: return call.reject("cannot extract the emails value")
590
+
591
+ val enc = call.getBoolean(AF_ENCODE)
592
+
593
+ if (enc != true) {
594
+ AppsFlyerLib.getInstance().setUserEmails(*emails)
595
+ } else {
596
+ AppsFlyerLib.getInstance()
597
+ .setUserEmails(AppsFlyerProperties.EmailsCryptType.SHA256, *emails)
598
+ }
599
+
600
+ val ret = JSObject()
601
+ ret.put("res", "ok")
602
+ call.resolve(ret)
603
+
604
+ }
605
+
606
+ @PluginMethod
607
+ fun logLocation(call: PluginCall) {
608
+ val longitude =
609
+ call.getDouble(AF_LONGITUDE) ?: return call.reject("cannot extract the longitude value")
610
+ val latitude =
611
+ call.getDouble(AF_LATITUDE) ?: return call.reject("cannot extract the latitude value")
612
+ AppsFlyerLib.getInstance().logLocation(context.applicationContext, latitude, longitude)
613
+ val ret = JSObject()
614
+ ret.put("res", "ok")
615
+ call.resolve(ret)
616
+
617
+ }
618
+
619
+ @PluginMethod
620
+ fun setPhoneNumber(call: PluginCall) {
621
+ val phone = call.getString(AF_PHONE) ?: return call.reject("cannot extract the phone value")
622
+ AppsFlyerLib.getInstance().setPhoneNumber(phone)
623
+ val ret = JSObject()
624
+ ret.put("res", "ok")
625
+ call.resolve(ret)
626
+
627
+ }
628
+
629
+ @PluginMethod
630
+ fun setPartnerData(call: PluginCall) {
631
+ val data = AFHelpers.jsonToMap(call.getObject(AF_DATA))
632
+ ?: return call.reject("cannot extract the data value")
633
+ val pid = call.getString(AF_PARTNER_ID)
634
+ ?: return call.reject("cannot extract the partnerId value")
635
+
636
+ AppsFlyerLib.getInstance().setPartnerData(pid, data)
637
+ val ret = JSObject()
638
+ ret.put("res", "ok")
639
+ call.resolve(ret)
640
+
641
+ }
642
+
643
+ @PluginMethod
644
+ fun logInvite(call: PluginCall) {
645
+ val data = AFHelpers.jsonToStringMap(call.getObject(AF_EVENT_PARAMETERS))
646
+ ?: return call.reject("cannot extract the eventParameters value")
647
+ val channel =
648
+ call.getString(AF_CHANNEL) ?: return call.reject("cannot extract the channel value")
649
+ ShareInviteHelper.logInvite(activity.application, channel, data)
650
+ val ret = JSObject()
651
+ ret.put("res", "ok")
652
+ call.resolve(ret)
653
+
654
+ }
655
+
656
+ @PluginMethod(returnType = PluginMethod.RETURN_NONE)
657
+ fun enableTCFDataCollection(call: PluginCall) {
658
+ val shouldEnable = call.getBoolean(AF_ENABLE_TCF_DATA_COLLECTION)
659
+ if (shouldEnable != null) {
660
+ AppsFlyerLib.getInstance().enableTCFDataCollection(shouldEnable)
661
+ } else {
662
+ call.reject("Missing boolean value $AF_ENABLE_TCF_DATA_COLLECTION")
663
+ }
664
+ }
665
+
666
+ @Deprecated("Please use setConsentDataV2 instead, which includes improved handling for GDPR and data privacy.")
667
+ @PluginMethod(returnType = PluginMethod.RETURN_NONE)
668
+ fun setConsentData(call: PluginCall) {
669
+ val consentData = call.getObject("data") ?: return call.reject("Missing consent data")
670
+
671
+ val isUserSubjectToGDPR = consentData.optBoolean(AF_IS_SUBJECTED_TO_GDPR)
672
+ val hasConsentForDataUsage = consentData.optBoolean(AF_CONSENT_FOR_DATA_USAGE)
673
+ val hasConsentForAdsPersonalization =
674
+ consentData.optBoolean(AF_CONSENT_FOR_ADS_PERSONALIZATION)
675
+
676
+ val consentObject = if (isUserSubjectToGDPR) {
677
+ AppsFlyerConsent.forGDPRUser(hasConsentForDataUsage, hasConsentForAdsPersonalization)
678
+ } else {
679
+ AppsFlyerConsent.forNonGDPRUser()
680
+ }
681
+
682
+ AppsFlyerLib.getInstance().setConsentData(consentObject)
683
+
684
+ call.resolve()
685
+ }
686
+
687
+ @PluginMethod(returnType = PluginMethod.RETURN_NONE)
688
+ fun setConsentDataV2(call: PluginCall) {
689
+ AppsFlyerLib.getInstance().setConsentData(
690
+ AppsFlyerConsent(
691
+ isUserSubjectToGDPR = call.getBoolean(AF_IS_SUBJECTED_TO_GDPR),
692
+ hasConsentForDataUsage = call.getBoolean(AF_CONSENT_FOR_DATA_USAGE),
693
+ hasConsentForAdsPersonalization = call.getBoolean(AF_CONSENT_FOR_ADS_PERSONALIZATION),
694
+ hasConsentForAdStorage = call.getBoolean(AF_CONSENT_FOR_ADS_STORAGE)
695
+ )
696
+ )
697
+ }
698
+
699
+ @PluginMethod(returnType = PluginMethod.RETURN_NONE)
700
+ fun logAdRevenue(call: PluginCall) {
701
+ val adRevenueDataJson = call.data
702
+ ?: return call.reject("adRevenueData is missing, the data mandatory to use this API.")
703
+
704
+ // Parse the fields from the adRevenueDataJson object
705
+ val monetizationNetwork = adRevenueDataJson.getString(AF_MONETIZATION_NETWORK)
706
+ ?: return call.reject("monetizationNetwork is missing")
707
+ val currencyIso4217Code = adRevenueDataJson.getString(AF_CURRENCY_ISO4217_CODE)
708
+ ?: return call.reject("currencyIso4217Code is missing")
709
+ val revenue = adRevenueDataJson.getDouble(AF_REVENUE)
710
+ if (revenue.isNaN()) {
711
+ return call.reject("revenue is missing or not a number")
712
+ }
713
+ val additionalParams =
714
+ AFHelpers.jsonToMap(adRevenueDataJson.getJSObject(AF_ADDITIONAL_PARAMETERS)) // can be nullable
715
+
716
+ // Convert the mediationNetwork string to the MediationNetwork enum
717
+ val mediationNetworkValue = adRevenueDataJson.getString(AF_MEDIATION_NETWORK)
718
+ ?: return call.reject("mediationNetwork is missing")
719
+ val mediationNetwork: MediationNetwork
720
+ try {
721
+ mediationNetwork = MediationNetwork.valueOf(mediationNetworkValue.uppercase())
722
+ } catch (e: IllegalArgumentException) {
723
+ return call.reject("Invalid mediation network")
724
+ }
725
+
726
+ // Create the AFAdRevenueData object
727
+ val adRevenueData = AFAdRevenueData(
728
+ monetizationNetwork = monetizationNetwork,
729
+ mediationNetwork = mediationNetwork,
730
+ currencyIso4217Code = currencyIso4217Code,
731
+ revenue = revenue
732
+ )
733
+
734
+ AppsFlyerLib.getInstance().logAdRevenue(adRevenueData, additionalParams)
735
+
736
+ call.resolve()
737
+ }
738
+
739
+ @PluginMethod(returnType = PluginMethod.RETURN_NONE)
740
+ fun disableAppSetId(call: PluginCall) {
741
+ AppsFlyerLib.getInstance().disableAppSetId()
742
+ call.resolve()
743
+ }
744
+
745
+ private fun getDeepLinkListener(): DeepLinkListener {
746
+ return DeepLinkListener {
747
+ if (udl == true) {
748
+
749
+ val res = JSObject().apply {
750
+ put("status", it.status)
751
+ put("error", it.error)
752
+ if (it.status == DeepLinkResult.Status.FOUND && it.deepLink != null)
753
+ put(
754
+ "deepLink",
755
+ JSObject.fromJSONObject(JSONObject(it.deepLink.toString()))
756
+ )
757
+ }
758
+
759
+ notifyListeners(UDL_CALLBACK, res)
760
+ }
761
+ }
762
+ }
763
+
764
+ private fun getConversionListener(): AppsFlyerConversionListener {
765
+ return object : AppsFlyerConversionListener {
766
+ override fun onConversionDataSuccess(map: MutableMap<String, Any>?) {
767
+ if (conversion != true)
768
+ return
769
+
770
+ val res = JSObject().apply {
771
+ put("callbackName", "onConversionDataSuccess")
772
+ put("data", AFHelpers.mapToJson(map))
773
+ }
774
+ notifyListeners(CONVERSION_CALLBACK, res)
775
+ }
776
+
777
+ override fun onConversionDataFail(s: String?) {
778
+ if (conversion != true)
779
+ return
780
+
781
+ val res = JSObject().apply {
782
+ put("callbackName", "onConversionDataFail")
783
+ put("error", s)
784
+
785
+ }
786
+ notifyListeners(CONVERSION_CALLBACK, res)
787
+ }
788
+
789
+ override fun onAppOpenAttribution(map: MutableMap<String, String>?) {
790
+ if (oaoa != true)
791
+ return
792
+
793
+ val res = JSObject().apply {
794
+ put("callbackName", "onAppOpenAttribution")
795
+ put("data", AFHelpers.mapToJson(map))
796
+ }
797
+ notifyListeners(OAOA_CALLBACK, res)
798
+ }
799
+
800
+ override fun onAttributionFailure(s: String?) {
801
+ if (oaoa != true)
802
+ return
803
+ val res = JSObject().apply {
804
+ put("callbackName", "onAttributionFailure")
805
+ put("error", s)
806
+
807
+ }
808
+ notifyListeners(OAOA_CALLBACK, res)
809
+ }
810
+ }
811
+ }
812
+ }