@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.
- package/CapgoCapacitorAppsflyer.podspec +27 -0
- package/LICENSE +21 -0
- package/Package.swift +30 -0
- package/README.md +1257 -0
- package/android/build.gradle +178 -0
- package/android/src/main/AndroidManifest.xml +7 -0
- package/android/src/main/java/capacitor/plugin/appsflyer/sdk/AFHelpers.kt +76 -0
- package/android/src/main/java/capacitor/plugin/appsflyer/sdk/AppsFlyerConstants.kt +76 -0
- package/android/src/main/java/capacitor/plugin/appsflyer/sdk/AppsFlyerPlugin.kt +812 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/dist/docs.json +2145 -0
- package/dist/esm/Appsflyer_constants.d.ts +29 -0
- package/dist/esm/Appsflyer_constants.js +33 -0
- package/dist/esm/Appsflyer_constants.js.map +1 -0
- package/dist/esm/appsflyer_interfaces.d.ts +200 -0
- package/dist/esm/appsflyer_interfaces.js +18 -0
- package/dist/esm/appsflyer_interfaces.js.map +1 -0
- package/dist/esm/definitions.d.ts +219 -0
- package/dist/esm/definitions.js +2 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +6 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/plugin.cjs.js +60 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +63 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Sources/AppsFlyerPlugin/AppsFlyerAttribution.swift +60 -0
- package/ios/Sources/AppsFlyerPlugin/AppsFlyerConstants.swift +86 -0
- package/ios/Sources/AppsFlyerPlugin/AppsFlyerPlugin.swift +1007 -0
- package/ios/Sources/AppsFlyerPlugin/Extensions.swift +78 -0
- package/ios/Tests/AppsFlyerPluginTests/AppsFlyerPluginTests.swift +8 -0
- 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
|
+
}
|