appsprint-react-native 0.2.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/LICENSE +21 -0
- package/README.md +173 -0
- package/android/build.gradle +39 -0
- package/android/libs/appsprint-sdk.aar +0 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/kotlin/com/appsprint/AppSprintBridgeModule.kt +182 -0
- package/android/src/main/kotlin/com/appsprint/AppSprintPackage.kt +16 -0
- package/app.plugin.js +3 -0
- package/appsprint-react-native.podspec +23 -0
- package/ios/AppSprintBridge.m +59 -0
- package/ios/AppSprintBridge.swift +210 -0
- package/ios/AppSprintSDK.xcframework/Info.plist +44 -0
- package/ios/AppSprintSDK.xcframework/ios-arm64/AppSprintSDK.framework/AppSprintSDK +0 -0
- package/ios/AppSprintSDK.xcframework/ios-arm64/AppSprintSDK.framework/Headers/AppSprintSDK-Swift.h +3 -0
- package/ios/AppSprintSDK.xcframework/ios-arm64/AppSprintSDK.framework/Info.plist +0 -0
- package/ios/AppSprintSDK.xcframework/ios-arm64/AppSprintSDK.framework/Modules/AppSprintSDK.swiftmodule/arm64-apple-ios.abi.json +4952 -0
- package/ios/AppSprintSDK.xcframework/ios-arm64/AppSprintSDK.framework/Modules/AppSprintSDK.swiftmodule/arm64-apple-ios.package.swiftinterface +165 -0
- package/ios/AppSprintSDK.xcframework/ios-arm64/AppSprintSDK.framework/Modules/AppSprintSDK.swiftmodule/arm64-apple-ios.private.swiftinterface +165 -0
- package/ios/AppSprintSDK.xcframework/ios-arm64/AppSprintSDK.framework/Modules/AppSprintSDK.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
- package/ios/AppSprintSDK.xcframework/ios-arm64/AppSprintSDK.framework/Modules/AppSprintSDK.swiftmodule/arm64-apple-ios.swiftinterface +165 -0
- package/ios/AppSprintSDK.xcframework/ios-arm64/AppSprintSDK.framework/Modules/module.modulemap +4 -0
- package/ios/AppSprintSDK.xcframework/ios-arm64_x86_64-simulator/AppSprintSDK.framework/AppSprintSDK +0 -0
- package/ios/AppSprintSDK.xcframework/ios-arm64_x86_64-simulator/AppSprintSDK.framework/Headers/AppSprintSDK-Swift.h +3 -0
- package/ios/AppSprintSDK.xcframework/ios-arm64_x86_64-simulator/AppSprintSDK.framework/Info.plist +0 -0
- package/ios/AppSprintSDK.xcframework/ios-arm64_x86_64-simulator/AppSprintSDK.framework/Modules/AppSprintSDK.swiftmodule/arm64-apple-ios-simulator.abi.json +4952 -0
- package/ios/AppSprintSDK.xcframework/ios-arm64_x86_64-simulator/AppSprintSDK.framework/Modules/AppSprintSDK.swiftmodule/arm64-apple-ios-simulator.package.swiftinterface +165 -0
- package/ios/AppSprintSDK.xcframework/ios-arm64_x86_64-simulator/AppSprintSDK.framework/Modules/AppSprintSDK.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +165 -0
- package/ios/AppSprintSDK.xcframework/ios-arm64_x86_64-simulator/AppSprintSDK.framework/Modules/AppSprintSDK.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
- package/ios/AppSprintSDK.xcframework/ios-arm64_x86_64-simulator/AppSprintSDK.framework/Modules/AppSprintSDK.swiftmodule/arm64-apple-ios-simulator.swiftinterface +165 -0
- package/ios/AppSprintSDK.xcframework/ios-arm64_x86_64-simulator/AppSprintSDK.framework/Modules/AppSprintSDK.swiftmodule/x86_64-apple-ios-simulator.abi.json +4952 -0
- package/ios/AppSprintSDK.xcframework/ios-arm64_x86_64-simulator/AppSprintSDK.framework/Modules/AppSprintSDK.swiftmodule/x86_64-apple-ios-simulator.package.swiftinterface +165 -0
- package/ios/AppSprintSDK.xcframework/ios-arm64_x86_64-simulator/AppSprintSDK.framework/Modules/AppSprintSDK.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +165 -0
- package/ios/AppSprintSDK.xcframework/ios-arm64_x86_64-simulator/AppSprintSDK.framework/Modules/AppSprintSDK.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
- package/ios/AppSprintSDK.xcframework/ios-arm64_x86_64-simulator/AppSprintSDK.framework/Modules/AppSprintSDK.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +165 -0
- package/ios/AppSprintSDK.xcframework/ios-arm64_x86_64-simulator/AppSprintSDK.framework/Modules/module.modulemap +4 -0
- package/ios/AppSprintSDK.xcframework/ios-arm64_x86_64-simulator/AppSprintSDK.framework/_CodeSignature/CodeResources +101 -0
- package/lib/commonjs/AppSprint.js +50 -0
- package/lib/commonjs/NativeAppSprint.js +50 -0
- package/lib/commonjs/index.js +20 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/types.js +2 -0
- package/lib/module/AppSprint.js +46 -0
- package/lib/module/NativeAppSprint.js +47 -0
- package/lib/module/index.js +5 -0
- package/lib/module/package.json +1 -0
- package/lib/module/types.js +2 -0
- package/lib/typescript/AppSprint.d.ts +18 -0
- package/lib/typescript/NativeAppSprint.d.ts +4 -0
- package/lib/typescript/index.d.ts +4 -0
- package/lib/typescript/types.d.ts +60 -0
- package/package.json +56 -0
- package/plugin/build/index.d.ts +10 -0
- package/plugin/build/index.js +22 -0
- package/plugin/src/index.ts +27 -0
- package/src/AppSprint.ts +74 -0
- package/src/NativeAppSprint.ts +52 -0
- package/src/index.ts +13 -0
- package/src/types.ts +93 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 AppSprint
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# appsprint-react-native
|
|
2
|
+
|
|
3
|
+
AppSprint mobile attribution SDK for React Native. It tracks installs, attribution, lifecycle events, custom events, and revenue events, with local event queueing for transient failures.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install appsprint-react-native
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### iOS
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
cd ios && pod install
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Expo config plugin
|
|
18
|
+
|
|
19
|
+
If you use Expo prebuild, add the plugin to your app config:
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"plugins": [
|
|
24
|
+
[
|
|
25
|
+
"appsprint-react-native",
|
|
26
|
+
{
|
|
27
|
+
"trackingDescription": "This identifier will be used to deliver personalized ads to you."
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Plugin options:
|
|
35
|
+
|
|
36
|
+
| Option | Type | Description | Default |
|
|
37
|
+
|---|---|---|---|
|
|
38
|
+
| `trackingDescription` | `string` | ATT permission dialog text for `NSUserTrackingUsageDescription` | `"This identifier will be used to deliver personalized ads to you."` |
|
|
39
|
+
| `advertisingAttributionEndpoint` | `string` | Sets `NSAdvertisingAttributionReportEndpoint` | — |
|
|
40
|
+
|
|
41
|
+
## Quick start
|
|
42
|
+
|
|
43
|
+
Initialize the SDK as early as possible in app startup:
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
import { AppSprint } from "appsprint-react-native";
|
|
47
|
+
|
|
48
|
+
await AppSprint.configure({
|
|
49
|
+
apiKey: "YOUR_API_KEY",
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Configuration
|
|
54
|
+
|
|
55
|
+
| Option | Type | Required | Default |
|
|
56
|
+
|---|---|---|---|
|
|
57
|
+
| `apiKey` | `string` | Yes | — |
|
|
58
|
+
| `apiUrl` | `string` | No | `https://api.appsprint.app` |
|
|
59
|
+
| `enableAppleAdsAttribution` | `boolean` | No | `true` |
|
|
60
|
+
| `isDebug` | `boolean` | No | `false` |
|
|
61
|
+
| `logLevel` | `0 \| 1 \| 2 \| 3` | No | `2` |
|
|
62
|
+
| `customerUserId` | `string \| null` | No | `null` |
|
|
63
|
+
|
|
64
|
+
Log levels:
|
|
65
|
+
|
|
66
|
+
`0 = debug`, `1 = info`, `2 = warn`, `3 = error`
|
|
67
|
+
|
|
68
|
+
## Sending events
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
import { AppSprint } from "appsprint-react-native";
|
|
72
|
+
|
|
73
|
+
await AppSprint.sendEvent("login");
|
|
74
|
+
await AppSprint.sendEvent("sign_up");
|
|
75
|
+
await AppSprint.sendEvent("purchase", null, {
|
|
76
|
+
revenue: 9.99,
|
|
77
|
+
currency: "USD",
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
await AppSprint.sendEvent("custom", "onboarding_step", {
|
|
81
|
+
screen: "welcome",
|
|
82
|
+
step: 1,
|
|
83
|
+
});
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Supported `eventType` values:
|
|
87
|
+
|
|
88
|
+
`login` | `sign_up` | `register` | `purchase` | `subscribe` | `start_trial` | `add_to_cart` | `add_to_wishlist` | `initiate_checkout` | `view_content` | `view_item` | `search` | `share` | `tutorial_complete` | `level_start` | `level_complete` | `custom`
|
|
89
|
+
|
|
90
|
+
Notes:
|
|
91
|
+
|
|
92
|
+
- Use `eventType: "custom"` together with the optional `name` argument for custom event names.
|
|
93
|
+
- Revenue fields are accepted through `params.revenue` and `params.currency`.
|
|
94
|
+
- If an event cannot be delivered, it is queued locally and retried on the next initialization or explicit flush.
|
|
95
|
+
|
|
96
|
+
## Public API
|
|
97
|
+
|
|
98
|
+
### `AppSprint`
|
|
99
|
+
|
|
100
|
+
```tsx
|
|
101
|
+
import { AppSprint } from "appsprint-react-native";
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Available methods:
|
|
105
|
+
|
|
106
|
+
- `configure(config)` initializes the SDK and performs install tracking when needed.
|
|
107
|
+
- `sendEvent(eventType, name?, params?)` sends or queues an event.
|
|
108
|
+
- `sendTestEvent()` sends a diagnostic event and returns `{ success, message }`.
|
|
109
|
+
- `flush()` retries queued events immediately.
|
|
110
|
+
- `clearData()` clears cached SDK state and the local event queue.
|
|
111
|
+
- `isSdkDisabled()` returns whether the SDK has been disabled because the API key was rejected.
|
|
112
|
+
- `setCustomerUserId(userId)` updates the customer user id locally and remotely when possible.
|
|
113
|
+
- `getAppSprintId()` returns the cached AppSprint install identifier, if available.
|
|
114
|
+
- `getAttribution()` returns the last cached attribution result, if available.
|
|
115
|
+
- `enableAppleAdsAttribution()` re-enables Apple Ads attribution in the current runtime config.
|
|
116
|
+
- `isInitialized()` reports whether `configure()` completed.
|
|
117
|
+
- `destroy()` removes SDK listeners.
|
|
118
|
+
|
|
119
|
+
### `NativeAppSprint`
|
|
120
|
+
|
|
121
|
+
```tsx
|
|
122
|
+
import { NativeAppSprint } from "appsprint-react-native";
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Available methods:
|
|
126
|
+
|
|
127
|
+
- `getDeviceInfo()`
|
|
128
|
+
- `getAdServicesToken()`
|
|
129
|
+
- `requestTrackingAuthorization()`
|
|
130
|
+
|
|
131
|
+
Example ATT request on iOS:
|
|
132
|
+
|
|
133
|
+
```tsx
|
|
134
|
+
import { NativeAppSprint } from "appsprint-react-native";
|
|
135
|
+
|
|
136
|
+
const authorized = await NativeAppSprint.requestTrackingAuthorization();
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Attribution
|
|
140
|
+
|
|
141
|
+
The SDK tracks install attribution once an install is registered. You can read the cached values at any time:
|
|
142
|
+
|
|
143
|
+
```tsx
|
|
144
|
+
const attribution = await AppSprint.getAttribution();
|
|
145
|
+
const appsprintId = await AppSprint.getAppSprintId();
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
`AttributionResult.source` can be:
|
|
149
|
+
|
|
150
|
+
`apple_ads` | `fingerprint` | `organic`
|
|
151
|
+
|
|
152
|
+
## Offline and retry behavior
|
|
153
|
+
|
|
154
|
+
- The SDK keeps up to `100` queued events in local storage.
|
|
155
|
+
- Queued events are flushed after `configure()` and when the app moves to the background.
|
|
156
|
+
- Failed flushes keep the unsent events queued for a later retry.
|
|
157
|
+
- A rejected API key (`401` or `403`) disables the SDK and drops future events until cached data is cleared.
|
|
158
|
+
|
|
159
|
+
## Local development
|
|
160
|
+
|
|
161
|
+
Point the SDK at a non-production backend during development:
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
await AppSprint.configure({
|
|
165
|
+
apiKey: "YOUR_API_KEY",
|
|
166
|
+
apiUrl: "http://localhost:3000",
|
|
167
|
+
isDebug: true,
|
|
168
|
+
});
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## License
|
|
172
|
+
|
|
173
|
+
MIT
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
buildscript {
|
|
2
|
+
ext.safeExtGet = {prop, fallback ->
|
|
3
|
+
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
apply plugin: 'com.android.library'
|
|
8
|
+
apply plugin: 'kotlin-android'
|
|
9
|
+
|
|
10
|
+
android {
|
|
11
|
+
namespace "com.appsprint"
|
|
12
|
+
compileSdkVersion safeExtGet('compileSdkVersion', 35)
|
|
13
|
+
|
|
14
|
+
defaultConfig {
|
|
15
|
+
minSdkVersion safeExtGet('minSdkVersion', 24)
|
|
16
|
+
targetSdkVersion safeExtGet('targetSdkVersion', 35)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
compileOptions {
|
|
20
|
+
sourceCompatibility JavaVersion.VERSION_17
|
|
21
|
+
targetCompatibility JavaVersion.VERSION_17
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
kotlinOptions {
|
|
25
|
+
jvmTarget = '17'
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
sourceSets {
|
|
29
|
+
main {
|
|
30
|
+
java.srcDirs += 'src/main/kotlin'
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
dependencies {
|
|
36
|
+
implementation "com.facebook.react:react-android:+"
|
|
37
|
+
implementation files('libs/appsprint-sdk.aar')
|
|
38
|
+
implementation "androidx.lifecycle:lifecycle-process:2.8.7"
|
|
39
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
package com.appsprint
|
|
2
|
+
|
|
3
|
+
import com.appsprint.sdk.AppSprint
|
|
4
|
+
import com.appsprint.sdk.AppSprintConfig
|
|
5
|
+
import com.appsprint.sdk.AppSprintEventType
|
|
6
|
+
import com.facebook.react.bridge.*
|
|
7
|
+
import kotlin.concurrent.thread
|
|
8
|
+
|
|
9
|
+
class AppSprintBridgeModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
|
|
10
|
+
|
|
11
|
+
override fun getName(): String = "AppSprintModule"
|
|
12
|
+
|
|
13
|
+
private fun sdk(): AppSprint {
|
|
14
|
+
val sdkClass = AppSprint::class.java
|
|
15
|
+
|
|
16
|
+
runCatching {
|
|
17
|
+
val shared = sdkClass.getMethod("shared", android.content.Context::class.java)
|
|
18
|
+
return shared.invoke(null, reactApplicationContext) as AppSprint
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
val companion = sdkClass.getField("Companion").get(null)
|
|
22
|
+
val shared = companion.javaClass.getMethod("shared", android.content.Context::class.java)
|
|
23
|
+
return shared.invoke(companion, reactApplicationContext) as AppSprint
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private fun runAsync(code: String, promise: Promise, block: () -> Unit) {
|
|
27
|
+
thread(start = true) {
|
|
28
|
+
try {
|
|
29
|
+
block()
|
|
30
|
+
} catch (e: Exception) {
|
|
31
|
+
promise.reject(code, e.message, e)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Core SDK
|
|
37
|
+
|
|
38
|
+
@ReactMethod
|
|
39
|
+
fun configure(config: ReadableMap, promise: Promise) {
|
|
40
|
+
val apiKey = config.getString("apiKey")?.trim().orEmpty()
|
|
41
|
+
if (apiKey.isEmpty()) {
|
|
42
|
+
promise.reject("CONFIGURE_ERROR", "AppSprint.configure requires a non-empty apiKey.")
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
runAsync("CONFIGURE_ERROR", promise) {
|
|
47
|
+
val sdkConfig = AppSprintConfig(
|
|
48
|
+
apiKey = apiKey,
|
|
49
|
+
apiUrl = if (config.hasKey("apiUrl")) config.getString("apiUrl") ?: "https://api.appsprint.app" else "https://api.appsprint.app",
|
|
50
|
+
enableAppleAdsAttribution = if (config.hasKey("enableAppleAdsAttribution")) config.getBoolean("enableAppleAdsAttribution") else true,
|
|
51
|
+
isDebug = if (config.hasKey("isDebug")) config.getBoolean("isDebug") else false,
|
|
52
|
+
logLevel = if (config.hasKey("logLevel")) config.getInt("logLevel") else if (config.hasKey("isDebug") && config.getBoolean("isDebug")) 0 else 2,
|
|
53
|
+
customerUserId = if (config.hasKey("customerUserId")) config.getString("customerUserId") else null,
|
|
54
|
+
)
|
|
55
|
+
sdk().configure(sdkConfig)
|
|
56
|
+
promise.resolve(null)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@ReactMethod
|
|
61
|
+
fun sendEvent(eventType: String, name: String?, revenue: Double?, currency: String?, parameters: ReadableMap?, promise: Promise) {
|
|
62
|
+
runAsync("SEND_EVENT_ERROR", promise) {
|
|
63
|
+
val type = AppSprintEventType.entries.find { it.wireValue == eventType } ?: AppSprintEventType.CUSTOM
|
|
64
|
+
val params = mutableMapOf<String, Any?>()
|
|
65
|
+
parameters?.toHashMap()?.forEach { (key, value) -> params[key] = value }
|
|
66
|
+
if (revenue != null && revenue != 0.0) params["revenue"] = revenue
|
|
67
|
+
if (currency != null) params["currency"] = currency
|
|
68
|
+
sdk().sendEvent(type, name, if (params.isNotEmpty()) params else null)
|
|
69
|
+
promise.resolve(null)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@ReactMethod
|
|
74
|
+
fun sendTestEvent(promise: Promise) {
|
|
75
|
+
runAsync("TEST_EVENT_ERROR", promise) {
|
|
76
|
+
val result = sdk().sendTestEvent()
|
|
77
|
+
val map = Arguments.createMap()
|
|
78
|
+
map.putBoolean("success", result.success)
|
|
79
|
+
map.putString("message", result.message)
|
|
80
|
+
promise.resolve(map)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
@ReactMethod
|
|
85
|
+
fun flush(promise: Promise) {
|
|
86
|
+
runAsync("FLUSH_ERROR", promise) {
|
|
87
|
+
sdk().flush()
|
|
88
|
+
promise.resolve(null)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
@ReactMethod
|
|
93
|
+
fun clearData(promise: Promise) {
|
|
94
|
+
runAsync("CLEAR_DATA_ERROR", promise) {
|
|
95
|
+
sdk().clearData()
|
|
96
|
+
promise.resolve(null)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
@ReactMethod
|
|
101
|
+
fun setCustomerUserId(userId: String, promise: Promise) {
|
|
102
|
+
runAsync("SET_USER_ID_ERROR", promise) {
|
|
103
|
+
sdk().setCustomerUserId(userId)
|
|
104
|
+
promise.resolve(null)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@ReactMethod
|
|
109
|
+
fun enableAppleAdsAttribution(promise: Promise) {
|
|
110
|
+
sdk().enableAppleAdsAttribution()
|
|
111
|
+
promise.resolve(null)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
@ReactMethod
|
|
115
|
+
fun getAppSprintId(promise: Promise) {
|
|
116
|
+
promise.resolve(sdk().getAppSprintId())
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@ReactMethod
|
|
120
|
+
fun getAttribution(promise: Promise) {
|
|
121
|
+
val attr = sdk().getAttribution()
|
|
122
|
+
if (attr == null) {
|
|
123
|
+
promise.resolve(null)
|
|
124
|
+
return
|
|
125
|
+
}
|
|
126
|
+
val map = Arguments.createMap()
|
|
127
|
+
map.putString("source", attr.source)
|
|
128
|
+
map.putDouble("confidence", attr.confidence)
|
|
129
|
+
attr.campaignName?.let { map.putString("campaignName", it) }
|
|
130
|
+
attr.utmSource?.let { map.putString("utmSource", it) }
|
|
131
|
+
attr.utmMedium?.let { map.putString("utmMedium", it) }
|
|
132
|
+
attr.utmCampaign?.let { map.putString("utmCampaign", it) }
|
|
133
|
+
promise.resolve(map)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
@ReactMethod
|
|
137
|
+
fun isInitialized(promise: Promise) {
|
|
138
|
+
promise.resolve(sdk().isInitialized())
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
@ReactMethod
|
|
142
|
+
fun isSdkDisabled(promise: Promise) {
|
|
143
|
+
promise.resolve(sdk().isSdkDisabled())
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
@ReactMethod
|
|
147
|
+
fun destroy(promise: Promise) {
|
|
148
|
+
runAsync("DESTROY_ERROR", promise) {
|
|
149
|
+
sdk().destroy()
|
|
150
|
+
promise.resolve(null)
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Utility
|
|
155
|
+
|
|
156
|
+
@ReactMethod
|
|
157
|
+
fun getDeviceInfo(promise: Promise) {
|
|
158
|
+
try {
|
|
159
|
+
val info = Arguments.createMap()
|
|
160
|
+
info.putString("deviceModel", android.os.Build.MODEL)
|
|
161
|
+
val metrics = reactApplicationContext.resources.displayMetrics
|
|
162
|
+
info.putInt("screenWidth", metrics.widthPixels)
|
|
163
|
+
info.putInt("screenHeight", metrics.heightPixels)
|
|
164
|
+
info.putString("locale", java.util.Locale.getDefault().toLanguageTag())
|
|
165
|
+
info.putString("timezone", java.util.TimeZone.getDefault().id)
|
|
166
|
+
info.putString("osVersion", android.os.Build.VERSION.RELEASE)
|
|
167
|
+
promise.resolve(info)
|
|
168
|
+
} catch (e: Exception) {
|
|
169
|
+
promise.reject("DEVICE_INFO_ERROR", e.message, e)
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
@ReactMethod
|
|
174
|
+
fun getAdServicesToken(promise: Promise) {
|
|
175
|
+
promise.resolve(null) // iOS only
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
@ReactMethod
|
|
179
|
+
fun requestTrackingAuthorization(promise: Promise) {
|
|
180
|
+
promise.resolve(false) // iOS only
|
|
181
|
+
}
|
|
182
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
package com.appsprint
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.ReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.uimanager.ViewManager
|
|
7
|
+
|
|
8
|
+
class AppSprintPackage : ReactPackage {
|
|
9
|
+
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
|
|
10
|
+
return listOf(AppSprintBridgeModule(reactContext))
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
|
14
|
+
return emptyList()
|
|
15
|
+
}
|
|
16
|
+
}
|
package/app.plugin.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = "appsprint-react-native"
|
|
7
|
+
s.version = package["version"]
|
|
8
|
+
s.summary = package["description"]
|
|
9
|
+
s.homepage = package["homepage"]
|
|
10
|
+
s.license = package["license"]
|
|
11
|
+
s.authors = package["author"]
|
|
12
|
+
|
|
13
|
+
s.platforms = { :ios => "14.0" }
|
|
14
|
+
s.source = { :git => package["repository"], :tag => "#{s.version}" }
|
|
15
|
+
|
|
16
|
+
s.source_files = "ios/AppSprintBridge.{swift,m}"
|
|
17
|
+
s.swift_version = "5.0"
|
|
18
|
+
|
|
19
|
+
s.dependency "React-Core"
|
|
20
|
+
|
|
21
|
+
s.ios.vendored_frameworks = "ios/AppSprintSDK.xcframework"
|
|
22
|
+
s.frameworks = "AdServices", "AppTrackingTransparency", "AdSupport"
|
|
23
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#import <React/RCTBridgeModule.h>
|
|
2
|
+
|
|
3
|
+
@interface RCT_EXTERN_MODULE(AppSprintModule, NSObject)
|
|
4
|
+
|
|
5
|
+
// Core SDK
|
|
6
|
+
RCT_EXTERN_METHOD(configure:(NSDictionary *)config
|
|
7
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
8
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
9
|
+
|
|
10
|
+
RCT_EXTERN_METHOD(sendEvent:(NSString *)eventType
|
|
11
|
+
name:(NSString * _Nullable)name
|
|
12
|
+
revenue:(NSNumber * _Nullable)revenue
|
|
13
|
+
currency:(NSString * _Nullable)currency
|
|
14
|
+
parameters:(NSDictionary * _Nullable)parameters
|
|
15
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
16
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
17
|
+
|
|
18
|
+
RCT_EXTERN_METHOD(sendTestEvent:(RCTPromiseResolveBlock)resolve
|
|
19
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
20
|
+
|
|
21
|
+
RCT_EXTERN_METHOD(flush:(RCTPromiseResolveBlock)resolve
|
|
22
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
23
|
+
|
|
24
|
+
RCT_EXTERN_METHOD(clearData:(RCTPromiseResolveBlock)resolve
|
|
25
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
26
|
+
|
|
27
|
+
RCT_EXTERN_METHOD(setCustomerUserId:(NSString *)userId
|
|
28
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
29
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
30
|
+
|
|
31
|
+
RCT_EXTERN_METHOD(enableAppleAdsAttribution:(RCTPromiseResolveBlock)resolve
|
|
32
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
33
|
+
|
|
34
|
+
RCT_EXTERN_METHOD(getAppSprintId:(RCTPromiseResolveBlock)resolve
|
|
35
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
36
|
+
|
|
37
|
+
RCT_EXTERN_METHOD(getAttribution:(RCTPromiseResolveBlock)resolve
|
|
38
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
39
|
+
|
|
40
|
+
RCT_EXTERN_METHOD(isInitialized:(RCTPromiseResolveBlock)resolve
|
|
41
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
42
|
+
|
|
43
|
+
RCT_EXTERN_METHOD(isSdkDisabled:(RCTPromiseResolveBlock)resolve
|
|
44
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
45
|
+
|
|
46
|
+
RCT_EXTERN_METHOD(destroy:(RCTPromiseResolveBlock)resolve
|
|
47
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
48
|
+
|
|
49
|
+
// Utility
|
|
50
|
+
RCT_EXTERN_METHOD(getDeviceInfo:(RCTPromiseResolveBlock)resolve
|
|
51
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
52
|
+
|
|
53
|
+
RCT_EXTERN_METHOD(getAdServicesToken:(RCTPromiseResolveBlock)resolve
|
|
54
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
55
|
+
|
|
56
|
+
RCT_EXTERN_METHOD(requestTrackingAuthorization:(RCTPromiseResolveBlock)resolve
|
|
57
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
58
|
+
|
|
59
|
+
@end
|