@amplitude/analytics-react-native 0.0.1-dev.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 (180) hide show
  1. package/README.md +0 -0
  2. package/amplitude-react-native.podspec +21 -0
  3. package/android/build.gradle +61 -0
  4. package/android/gradle.properties +3 -0
  5. package/android/src/main/AndroidManifest.xml +4 -0
  6. package/android/src/main/java/com/amplitude/reactnative/AmplitudeReactNativeModule.kt +36 -0
  7. package/android/src/main/java/com/amplitude/reactnative/AmplitudeReactNativePackage.java +28 -0
  8. package/android/src/main/java/com/amplitude/reactnative/AndroidContextProvider.kt +415 -0
  9. package/android/src/main/java/com/amplitude/reactnative/AndroidLogger.kt +56 -0
  10. package/android/src/main/java/com/amplitude/reactnative/Utils.kt +34 -0
  11. package/ios/AmplitudeReactNative-Bridging-Header.h +5 -0
  12. package/ios/AmplitudeReactNative.m +7 -0
  13. package/ios/AmplitudeReactNative.swift +29 -0
  14. package/ios/AmplitudeReactNative.xcodeproj/project.pbxproj +293 -0
  15. package/ios/AppleContextProvider.swift +219 -0
  16. package/lib/commonjs/attribution/campaign-parser.js +74 -0
  17. package/lib/commonjs/attribution/campaign-parser.js.map +1 -0
  18. package/lib/commonjs/attribution/campaign-tracker.js +133 -0
  19. package/lib/commonjs/attribution/campaign-tracker.js.map +1 -0
  20. package/lib/commonjs/attribution/constants.js +47 -0
  21. package/lib/commonjs/attribution/constants.js.map +1 -0
  22. package/lib/commonjs/config.js +257 -0
  23. package/lib/commonjs/config.js.map +1 -0
  24. package/lib/commonjs/constants.js +31 -0
  25. package/lib/commonjs/constants.js.map +1 -0
  26. package/lib/commonjs/cookie-migration/index.js +74 -0
  27. package/lib/commonjs/cookie-migration/index.js.map +1 -0
  28. package/lib/commonjs/index.js +141 -0
  29. package/lib/commonjs/index.js.map +1 -0
  30. package/lib/commonjs/plugins/context.js +136 -0
  31. package/lib/commonjs/plugins/context.js.map +1 -0
  32. package/lib/commonjs/react-native-client.js +362 -0
  33. package/lib/commonjs/react-native-client.js.map +1 -0
  34. package/lib/commonjs/session-manager.js +114 -0
  35. package/lib/commonjs/session-manager.js.map +1 -0
  36. package/lib/commonjs/storage/cookie.js +124 -0
  37. package/lib/commonjs/storage/cookie.js.map +1 -0
  38. package/lib/commonjs/storage/local-storage.js +79 -0
  39. package/lib/commonjs/storage/local-storage.js.map +1 -0
  40. package/lib/commonjs/storage/utm-cookie.js +42 -0
  41. package/lib/commonjs/storage/utm-cookie.js.map +1 -0
  42. package/lib/commonjs/transports/fetch.js +34 -0
  43. package/lib/commonjs/transports/fetch.js.map +1 -0
  44. package/lib/commonjs/transports/send-beacon.js +43 -0
  45. package/lib/commonjs/transports/send-beacon.js.map +1 -0
  46. package/lib/commonjs/transports/xhr.js +54 -0
  47. package/lib/commonjs/transports/xhr.js.map +1 -0
  48. package/lib/commonjs/typings/browser-snippet.d.js +6 -0
  49. package/lib/commonjs/typings/browser-snippet.d.js.map +1 -0
  50. package/lib/commonjs/typings/ua-parser.d.js +2 -0
  51. package/lib/commonjs/typings/ua-parser.d.js.map +1 -0
  52. package/lib/commonjs/utils/cookie-name.js +23 -0
  53. package/lib/commonjs/utils/cookie-name.js.map +1 -0
  54. package/lib/commonjs/utils/language.js +18 -0
  55. package/lib/commonjs/utils/language.js.map +1 -0
  56. package/lib/commonjs/utils/platform.js +21 -0
  57. package/lib/commonjs/utils/platform.js.map +1 -0
  58. package/lib/commonjs/utils/query-params.js +36 -0
  59. package/lib/commonjs/utils/query-params.js.map +1 -0
  60. package/lib/commonjs/utils/snippet-helper.js +56 -0
  61. package/lib/commonjs/utils/snippet-helper.js.map +1 -0
  62. package/lib/commonjs/version.js +9 -0
  63. package/lib/commonjs/version.js.map +1 -0
  64. package/lib/module/attribution/campaign-parser.js +62 -0
  65. package/lib/module/attribution/campaign-parser.js.map +1 -0
  66. package/lib/module/attribution/campaign-tracker.js +120 -0
  67. package/lib/module/attribution/campaign-tracker.js.map +1 -0
  68. package/lib/module/attribution/constants.js +26 -0
  69. package/lib/module/attribution/constants.js.map +1 -0
  70. package/lib/module/config.js +217 -0
  71. package/lib/module/config.js.map +1 -0
  72. package/lib/module/constants.js +13 -0
  73. package/lib/module/constants.js.map +1 -0
  74. package/lib/module/cookie-migration/index.js +56 -0
  75. package/lib/module/cookie-migration/index.js.map +1 -0
  76. package/lib/module/index.js +6 -0
  77. package/lib/module/index.js.map +1 -0
  78. package/lib/module/plugins/context.js +118 -0
  79. package/lib/module/plugins/context.js.map +1 -0
  80. package/lib/module/react-native-client.js +329 -0
  81. package/lib/module/react-native-client.js.map +1 -0
  82. package/lib/module/session-manager.js +104 -0
  83. package/lib/module/session-manager.js.map +1 -0
  84. package/lib/module/storage/cookie.js +114 -0
  85. package/lib/module/storage/cookie.js.map +1 -0
  86. package/lib/module/storage/local-storage.js +67 -0
  87. package/lib/module/storage/local-storage.js.map +1 -0
  88. package/lib/module/storage/utm-cookie.js +32 -0
  89. package/lib/module/storage/utm-cookie.js.map +1 -0
  90. package/lib/module/transports/fetch.js +24 -0
  91. package/lib/module/transports/fetch.js.map +1 -0
  92. package/lib/module/transports/send-beacon.js +33 -0
  93. package/lib/module/transports/send-beacon.js.map +1 -0
  94. package/lib/module/transports/xhr.js +44 -0
  95. package/lib/module/transports/xhr.js.map +1 -0
  96. package/lib/module/typings/browser-snippet.d.js +2 -0
  97. package/lib/module/typings/browser-snippet.d.js.map +1 -0
  98. package/lib/module/typings/ua-parser.d.js +2 -0
  99. package/lib/module/typings/ua-parser.d.js.map +1 -0
  100. package/lib/module/utils/cookie-name.js +10 -0
  101. package/lib/module/utils/cookie-name.js.map +1 -0
  102. package/lib/module/utils/language.js +9 -0
  103. package/lib/module/utils/language.js.map +1 -0
  104. package/lib/module/utils/platform.js +8 -0
  105. package/lib/module/utils/platform.js.map +1 -0
  106. package/lib/module/utils/query-params.js +26 -0
  107. package/lib/module/utils/query-params.js.map +1 -0
  108. package/lib/module/utils/snippet-helper.js +41 -0
  109. package/lib/module/utils/snippet-helper.js.map +1 -0
  110. package/lib/module/version.js +2 -0
  111. package/lib/module/version.js.map +1 -0
  112. package/lib/typescript/attribution/campaign-parser.d.ts +10 -0
  113. package/lib/typescript/attribution/campaign-parser.d.ts.map +1 -0
  114. package/lib/typescript/attribution/campaign-tracker.d.ts +72 -0
  115. package/lib/typescript/attribution/campaign-tracker.d.ts.map +1 -0
  116. package/lib/typescript/attribution/constants.d.ts +17 -0
  117. package/lib/typescript/attribution/constants.d.ts.map +1 -0
  118. package/lib/typescript/config.d.ts +90 -0
  119. package/lib/typescript/config.d.ts.map +1 -0
  120. package/lib/typescript/constants.d.ts +13 -0
  121. package/lib/typescript/constants.d.ts.map +1 -0
  122. package/lib/typescript/cookie-migration/index.d.ts +5 -0
  123. package/lib/typescript/cookie-migration/index.d.ts.map +1 -0
  124. package/lib/typescript/index.d.ts +6 -0
  125. package/lib/typescript/index.d.ts.map +1 -0
  126. package/lib/typescript/plugins/context.d.ts +31 -0
  127. package/lib/typescript/plugins/context.d.ts.map +1 -0
  128. package/lib/typescript/react-native-client.d.ts +209 -0
  129. package/lib/typescript/react-native-client.d.ts.map +1 -0
  130. package/lib/typescript/session-manager.d.ts +28 -0
  131. package/lib/typescript/session-manager.d.ts.map +1 -0
  132. package/lib/typescript/storage/cookie.d.ts +12 -0
  133. package/lib/typescript/storage/cookie.d.ts.map +1 -0
  134. package/lib/typescript/storage/local-storage.d.ts +10 -0
  135. package/lib/typescript/storage/local-storage.d.ts.map +1 -0
  136. package/lib/typescript/storage/utm-cookie.d.ts +6 -0
  137. package/lib/typescript/storage/utm-cookie.d.ts.map +1 -0
  138. package/lib/typescript/transports/fetch.d.ts +6 -0
  139. package/lib/typescript/transports/fetch.d.ts.map +1 -0
  140. package/lib/typescript/transports/send-beacon.d.ts +6 -0
  141. package/lib/typescript/transports/send-beacon.d.ts.map +1 -0
  142. package/lib/typescript/transports/xhr.d.ts +7 -0
  143. package/lib/typescript/transports/xhr.d.ts.map +1 -0
  144. package/lib/typescript/utils/cookie-name.d.ts +3 -0
  145. package/lib/typescript/utils/cookie-name.d.ts.map +1 -0
  146. package/lib/typescript/utils/language.d.ts +2 -0
  147. package/lib/typescript/utils/language.d.ts.map +1 -0
  148. package/lib/typescript/utils/platform.d.ts +3 -0
  149. package/lib/typescript/utils/platform.d.ts.map +1 -0
  150. package/lib/typescript/utils/query-params.d.ts +2 -0
  151. package/lib/typescript/utils/query-params.d.ts.map +1 -0
  152. package/lib/typescript/utils/snippet-helper.d.ts +16 -0
  153. package/lib/typescript/utils/snippet-helper.d.ts.map +1 -0
  154. package/lib/typescript/version.d.ts +2 -0
  155. package/lib/typescript/version.d.ts.map +1 -0
  156. package/package.json +93 -0
  157. package/src/attribution/campaign-parser.ts +78 -0
  158. package/src/attribution/campaign-tracker.ts +112 -0
  159. package/src/attribution/constants.ts +32 -0
  160. package/src/config.ts +210 -0
  161. package/src/constants.ts +14 -0
  162. package/src/cookie-migration/index.ts +54 -0
  163. package/src/index.ts +23 -0
  164. package/src/plugins/context.ts +106 -0
  165. package/src/react-native-client.ts +349 -0
  166. package/src/session-manager.ts +81 -0
  167. package/src/storage/cookie.ts +95 -0
  168. package/src/storage/local-storage.ts +67 -0
  169. package/src/storage/utm-cookie.ts +27 -0
  170. package/src/transports/fetch.ts +23 -0
  171. package/src/transports/send-beacon.ts +34 -0
  172. package/src/transports/xhr.ts +36 -0
  173. package/src/typings/browser-snippet.d.ts +7 -0
  174. package/src/typings/ua-parser.d.ts +4 -0
  175. package/src/utils/cookie-name.ts +9 -0
  176. package/src/utils/language.ts +7 -0
  177. package/src/utils/platform.ts +9 -0
  178. package/src/utils/query-params.ts +21 -0
  179. package/src/utils/snippet-helper.ts +35 -0
  180. package/src/version.ts +1 -0
package/README.md ADDED
File without changes
@@ -0,0 +1,21 @@
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 = "amplitude-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.swift_version = "5.0"
14
+
15
+ s.platforms = { :ios => "10.0", :tvos => "10.0" }
16
+ s.source = { :git => "https://github.com/amplitude/Amplitude-TypeScript.git", :tag => "#{s.version}" }
17
+
18
+ s.source_files = "ios/**/*.{h,m,mm,swift}"
19
+
20
+ s.dependency "React-Core"
21
+ end
@@ -0,0 +1,61 @@
1
+ buildscript {
2
+ ext.kotlinVersion = "1.5.30"
3
+ if (project == rootProject) {
4
+ repositories {
5
+ google()
6
+ jcenter()
7
+ }
8
+
9
+ dependencies {
10
+ classpath 'com.android.tools.build:gradle:3.5.3'
11
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
12
+ }
13
+ }
14
+ }
15
+
16
+ apply plugin: 'com.android.library'
17
+ apply plugin: 'kotlin-android'
18
+
19
+ def safeExtGet(prop, fallback) {
20
+ rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
21
+ }
22
+
23
+ android {
24
+ compileSdkVersion safeExtGet('compileSdkVersion', 29)
25
+ buildToolsVersion safeExtGet('buildToolsVersion', '29.0.2')
26
+ defaultConfig {
27
+ minSdkVersion safeExtGet('minSdkVersion', 16)
28
+ targetSdkVersion safeExtGet('targetSdkVersion', 29)
29
+ versionCode 1
30
+ versionName "1.0"
31
+
32
+ }
33
+
34
+ buildTypes {
35
+ release {
36
+ minifyEnabled false
37
+ }
38
+ }
39
+ lintOptions {
40
+ disable 'GradleCompatible'
41
+ }
42
+ compileOptions {
43
+ sourceCompatibility JavaVersion.VERSION_1_8
44
+ targetCompatibility JavaVersion.VERSION_1_8
45
+ }
46
+ }
47
+
48
+ repositories {
49
+ mavenLocal()
50
+ maven {
51
+ // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
52
+ url("$rootDir/../node_modules/react-native/android")
53
+ }
54
+ google()
55
+ jcenter()
56
+ }
57
+
58
+ dependencies {
59
+ //noinspection GradleDynamicVersion
60
+ implementation "com.facebook.react:react-native:+" // From node_modules
61
+ }
@@ -0,0 +1,3 @@
1
+ android.useAndroidX=true
2
+ android.enableJetifier=true
3
+ kotlin.code.style=official
@@ -0,0 +1,4 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
+ package="com.amplitude.reactnative">
3
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
4
+ </manifest>
@@ -0,0 +1,36 @@
1
+ package com.amplitude.reactnative
2
+
3
+ import com.facebook.react.bridge.Promise
4
+ import com.facebook.react.module.annotations.ReactModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.bridge.ReactContextBaseJavaModule
7
+ import com.facebook.react.bridge.ReactMethod
8
+ import com.facebook.react.bridge.ReadableMap
9
+ import com.facebook.react.bridge.WritableNativeMap
10
+
11
+ const val MODULE_NAME = "AmplitudeReactNative"
12
+
13
+ @ReactModule(name = MODULE_NAME)
14
+ class AmplitudeReactNativeModule(private val reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
15
+
16
+ private val androidContextProvider = AndroidContextProvider(reactContext.applicationContext, false)
17
+
18
+ override fun getName(): String {
19
+ return MODULE_NAME
20
+ }
21
+
22
+ @ReactMethod
23
+ private fun getApplicationContext(promise: Promise) {
24
+ promise.resolve(WritableNativeMap().apply {
25
+ putString("version", androidContextProvider.versionName)
26
+ putString("platform", androidContextProvider.osName)
27
+ putString("language", androidContextProvider.language)
28
+ putString("os_name", androidContextProvider.osName)
29
+ putString("os_version", androidContextProvider.osVersion)
30
+ putString("device_brand", androidContextProvider.brand)
31
+ putString("device_manufacturer", androidContextProvider.manufacturer)
32
+ putString("device_model", androidContextProvider.model)
33
+ putString("carrier", androidContextProvider.carrier)
34
+ })
35
+ }
36
+ }
@@ -0,0 +1,28 @@
1
+ package com.amplitude.reactnative;
2
+
3
+ import androidx.annotation.NonNull;
4
+
5
+ import com.facebook.react.ReactPackage;
6
+ import com.facebook.react.bridge.NativeModule;
7
+ import com.facebook.react.bridge.ReactApplicationContext;
8
+ import com.facebook.react.uimanager.ViewManager;
9
+
10
+ import java.util.ArrayList;
11
+ import java.util.Collections;
12
+ import java.util.List;
13
+
14
+ public class AmplitudeReactNativePackage implements ReactPackage {
15
+ @NonNull
16
+ @Override
17
+ public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) {
18
+ List<NativeModule> modules = new ArrayList<>();
19
+ modules.add(new AmplitudeReactNativeModule(reactContext));
20
+ return modules;
21
+ }
22
+
23
+ @NonNull
24
+ @Override
25
+ public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
26
+ return Collections.emptyList();
27
+ }
28
+ }
@@ -0,0 +1,415 @@
1
+ package com.amplitude.reactnative
2
+
3
+ import android.content.Context
4
+ import android.content.pm.PackageInfo
5
+ import android.content.pm.PackageManager
6
+ import android.content.res.Resources
7
+ import android.location.Geocoder
8
+ import android.location.Location
9
+ import android.location.LocationManager
10
+ import android.os.Build
11
+ import android.provider.Settings.Secure
12
+ import android.telephony.TelephonyManager
13
+ import java.io.IOException
14
+ import java.lang.Exception
15
+ import java.lang.IllegalArgumentException
16
+ import java.lang.IllegalStateException
17
+ import java.lang.NullPointerException
18
+ import java.lang.reflect.InvocationTargetException
19
+ import java.util.Locale
20
+ import java.util.UUID
21
+ import kotlin.collections.ArrayList
22
+
23
+ class AndroidContextProvider(private val context: Context, locationListening: Boolean) {
24
+ var isLocationListening = true
25
+ private var cachedInfo: CachedInfo? = null
26
+ private get() {
27
+ if (field == null) {
28
+ field = CachedInfo()
29
+ }
30
+ return field
31
+ }
32
+
33
+ /**
34
+ * Internal class serves as a cache
35
+ */
36
+ inner class CachedInfo {
37
+ var advertisingId: String
38
+ val country: String?
39
+ val versionName: String?
40
+ val osName: String
41
+ val osVersion: String
42
+ val brand: String
43
+ val manufacturer: String
44
+ val model: String
45
+ val carrier: String?
46
+ val language: String
47
+ var limitAdTrackingEnabled: Boolean = true
48
+ val gpsEnabled: Boolean
49
+ var appSetId: String
50
+
51
+ init {
52
+ advertisingId = fetchAdvertisingId()
53
+ versionName = fetchVersionName()
54
+ osName = OS_NAME
55
+ osVersion = fetchOsVersion()
56
+ brand = fetchBrand()
57
+ manufacturer = fetchManufacturer()
58
+ model = fetchModel()
59
+ carrier = fetchCarrier()
60
+ country = fetchCountry()
61
+ language = fetchLanguage()
62
+ gpsEnabled = checkGPSEnabled()
63
+ appSetId = fetchAppSetId()
64
+ }
65
+
66
+ /**
67
+ * Internal methods for getting raw information
68
+ */
69
+ private fun fetchVersionName(): String? {
70
+ val packageInfo: PackageInfo
71
+ try {
72
+ packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)
73
+ return packageInfo.versionName
74
+ } catch (e: PackageManager.NameNotFoundException) {
75
+ } catch (e: Exception) {
76
+ }
77
+ return null
78
+ }
79
+
80
+ private fun fetchOsVersion(): String {
81
+ return Build.VERSION.RELEASE
82
+ }
83
+
84
+ private fun fetchBrand(): String {
85
+ return Build.BRAND
86
+ }
87
+
88
+ private fun fetchManufacturer(): String {
89
+ return Build.MANUFACTURER
90
+ }
91
+
92
+ private fun fetchModel(): String {
93
+ return Build.MODEL
94
+ }
95
+
96
+ private fun fetchCarrier(): String? {
97
+ try {
98
+ val manager = context
99
+ .getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
100
+ return manager.networkOperatorName
101
+ } catch (e: Exception) {
102
+ // Failed to get network operator name from network
103
+ }
104
+ return null
105
+ }
106
+
107
+ private fun fetchCountry(): String? {
108
+ // This should not be called on the main thread.
109
+
110
+ // Prioritize reverse geocode, but until we have a result from that,
111
+ // we try to grab the country from the network, and finally the locale
112
+ var country = countryFromLocation
113
+ if (!country.isNullOrEmpty()) {
114
+ return country
115
+ }
116
+ country = countryFromNetwork
117
+ return if (!country.isNullOrEmpty()) {
118
+ country
119
+ } else countryFromLocale
120
+ } // Customized Android System without Google Play Service Installed// sometimes the location manager is unavailable// Bad lat / lon values can cause Geocoder to throw IllegalArgumentExceptions// failed to fetch geocoder// Failed to reverse geocode location
121
+
122
+ // Failed to reverse geocode location
123
+ private val countryFromLocation: String?
124
+ private get() {
125
+ if (!isLocationListening) {
126
+ return null
127
+ }
128
+ val recent = mostRecentLocation
129
+ if (recent != null) {
130
+ try {
131
+ if (Geocoder.isPresent()) {
132
+ val geocoder = geocoder
133
+ val addresses = geocoder.getFromLocation(
134
+ recent.latitude,
135
+ recent.longitude, 1
136
+ )
137
+ if (addresses != null) {
138
+ for (address in addresses) {
139
+ if (address != null) {
140
+ return address.countryCode
141
+ }
142
+ }
143
+ }
144
+ }
145
+ } catch (e: IOException) {
146
+ // Failed to reverse geocode location
147
+ } catch (e: NullPointerException) {
148
+ // Failed to reverse geocode location
149
+ } catch (e: NoSuchMethodError) {
150
+ // failed to fetch geocoder
151
+ } catch (e: IllegalArgumentException) {
152
+ // Bad lat / lon values can cause Geocoder to throw IllegalArgumentExceptions
153
+ } catch (e: IllegalStateException) {
154
+ // sometimes the location manager is unavailable
155
+ } catch (e: SecurityException) {
156
+ // Customized Android System without Google Play Service Installed
157
+ }
158
+ }
159
+ return null
160
+ }
161
+
162
+ // Failed to get country from network
163
+ private val countryFromNetwork: String?
164
+ private get() {
165
+ try {
166
+ val manager = context
167
+ .getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
168
+ if (manager.phoneType != TelephonyManager.PHONE_TYPE_CDMA) {
169
+ val country = manager.networkCountryIso
170
+ if (country != null) {
171
+ return country.toUpperCase(Locale.US)
172
+ }
173
+ }
174
+ } catch (e: Exception) {
175
+ // Failed to get country from network
176
+ }
177
+ return null
178
+ }
179
+
180
+ private val locale: Locale
181
+ private get() {
182
+ val configuration = Resources.getSystem().configuration
183
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
184
+ val localeList = configuration.locales
185
+ if (localeList.isEmpty) {
186
+ return Locale.getDefault()
187
+ } else {
188
+ return localeList.get(0)
189
+ }
190
+ } else {
191
+ return configuration.locale
192
+ }
193
+ }
194
+
195
+ private val countryFromLocale: String
196
+ private get() = locale.country
197
+
198
+ private fun fetchLanguage(): String {
199
+ return locale.language
200
+ }
201
+
202
+ private fun fetchAdvertisingId(): String {
203
+ // This should not be called on the main thread.
204
+ return if ("Amazon" == fetchManufacturer()) {
205
+ fetchAndCacheAmazonAdvertisingId
206
+ } else {
207
+ fetchAndCacheGoogleAdvertisingId
208
+ }
209
+ }
210
+
211
+ private fun fetchAppSetId(): String {
212
+ try {
213
+ val AppSet = Class
214
+ .forName("com.google.android.gms.appset.AppSet")
215
+ val getClient = AppSet.getMethod("getClient", Context::class.java)
216
+ val appSetIdClient = getClient.invoke(null, context)
217
+ val getAppSetIdInfo = appSetIdClient.javaClass.getMethod("getAppSetIdInfo")
218
+ val taskWithAppSetInfo = getAppSetIdInfo.invoke(appSetIdClient)
219
+ val Tasks = Class.forName("com.google.android.gms.tasks.Tasks")
220
+ val await =
221
+ Tasks.getMethod("await", Class.forName("com.google.android.gms.tasks.Task"))
222
+ val appSetInfo = await.invoke(null, taskWithAppSetInfo)
223
+ val getId = appSetInfo.javaClass.getMethod("getId")
224
+ appSetId = getId.invoke(appSetInfo) as String
225
+ } catch (e: ClassNotFoundException) {
226
+ LogcatLogger.logger
227
+ .warn("Google Play Services SDK not found for app set id!")
228
+ } catch (e: InvocationTargetException) {
229
+ LogcatLogger.logger.warn("Google Play Services not available for app set id")
230
+ } catch (e: Exception) {
231
+ LogcatLogger.logger.error(
232
+ "Encountered an error connecting to Google Play Services for app set id"
233
+ )
234
+ }
235
+ return appSetId
236
+ }
237
+
238
+ private val fetchAndCacheAmazonAdvertisingId: String
239
+ private get() {
240
+ val cr = context.contentResolver
241
+ limitAdTrackingEnabled = Secure.getInt(cr, SETTING_LIMIT_AD_TRACKING, 0) == 1
242
+ advertisingId = Secure.getString(cr, SETTING_ADVERTISING_ID)
243
+ return advertisingId
244
+ }
245
+ private val fetchAndCacheGoogleAdvertisingId: String
246
+ private get() {
247
+ try {
248
+ val AdvertisingIdClient = Class
249
+ .forName("com.google.android.gms.ads.identifier.AdvertisingIdClient")
250
+ val getAdvertisingInfo = AdvertisingIdClient.getMethod(
251
+ "getAdvertisingIdInfo",
252
+ Context::class.java
253
+ )
254
+ val advertisingInfo = getAdvertisingInfo.invoke(null, context)
255
+ val isLimitAdTrackingEnabled = advertisingInfo.javaClass.getMethod(
256
+ "isLimitAdTrackingEnabled"
257
+ )
258
+ val limitAdTrackingEnabled = isLimitAdTrackingEnabled
259
+ .invoke(advertisingInfo) as Boolean
260
+ this.limitAdTrackingEnabled =
261
+ limitAdTrackingEnabled != null && limitAdTrackingEnabled
262
+ val getId = advertisingInfo.javaClass.getMethod("getId")
263
+ advertisingId = getId.invoke(advertisingInfo) as String
264
+ } catch (e: ClassNotFoundException) {
265
+ LogcatLogger.logger
266
+ .warn("Google Play Services SDK not found for advertising id!")
267
+ } catch (e: InvocationTargetException) {
268
+ LogcatLogger.logger
269
+ .warn("Google Play Services not available for advertising id")
270
+ } catch (e: Exception) {
271
+ LogcatLogger.logger.error(
272
+ "Encountered an error connecting to Google Play Services for advertising id"
273
+ )
274
+ }
275
+ return advertisingId
276
+ }
277
+
278
+ private fun checkGPSEnabled(): Boolean {
279
+ // This should not be called on the main thread.
280
+ try {
281
+ val GPSUtil = Class
282
+ .forName("com.google.android.gms.common.GooglePlayServicesUtil")
283
+ val getGPSAvailable = GPSUtil.getMethod(
284
+ "isGooglePlayServicesAvailable",
285
+ Context::class.java
286
+ )
287
+ val status = getGPSAvailable.invoke(null, context) as Int
288
+ // status 0 corresponds to com.google.android.gms.common.ConnectionResult.SUCCESS;
289
+ return status != null && status == 0
290
+ } catch (e: NoClassDefFoundError) {
291
+ LogcatLogger.logger.warn("Google Play Services Util not found!")
292
+ } catch (e: ClassNotFoundException) {
293
+ LogcatLogger.logger.warn("Google Play Services Util not found!")
294
+ } catch (e: NoSuchMethodException) {
295
+ LogcatLogger.logger.warn("Google Play Services not available")
296
+ } catch (e: InvocationTargetException) {
297
+ LogcatLogger.logger.warn("Google Play Services not available")
298
+ } catch (e: IllegalAccessException) {
299
+ LogcatLogger.logger.warn("Google Play Services not available")
300
+ } catch (e: Exception) {
301
+ LogcatLogger.logger.warn(
302
+ "Error when checking for Google Play Services: $e"
303
+ )
304
+ }
305
+ return false
306
+ }
307
+ }
308
+
309
+ fun prefetch() {
310
+ cachedInfo
311
+ }
312
+
313
+ fun isGooglePlayServicesEnabled(): Boolean {
314
+ return cachedInfo!!.gpsEnabled
315
+ }
316
+
317
+ fun isLimitAdTrackingEnabled(): Boolean {
318
+ return cachedInfo!!.limitAdTrackingEnabled
319
+ }
320
+
321
+ val versionName: String?
322
+ get() = cachedInfo!!.versionName
323
+ val osName: String
324
+ get() = cachedInfo!!.osName
325
+ val osVersion: String
326
+ get() = cachedInfo!!.osVersion
327
+ val brand: String
328
+ get() = cachedInfo!!.brand
329
+ val manufacturer: String
330
+ get() = cachedInfo!!.manufacturer
331
+ val model: String
332
+ get() = cachedInfo!!.model
333
+ val carrier: String?
334
+ get() = cachedInfo!!.carrier
335
+ val country: String?
336
+ get() = cachedInfo!!.country
337
+ val language: String
338
+ get() = cachedInfo!!.language
339
+ val advertisingId: String
340
+ get() = cachedInfo!!.advertisingId
341
+ val appSetId: String
342
+ get() = cachedInfo!!.appSetId // other causes// failed to get providers list
343
+ // Don't crash if the device does not have location services.
344
+
345
+ // It's possible that the location service is running out of process
346
+ // and the remote getProviders call fails. Handle null provider lists.
347
+ val mostRecentLocation: Location?
348
+ get() {
349
+ if (!isLocationListening) {
350
+ return null
351
+ }
352
+ if (!Utils.checkLocationPermissionAllowed(context)) {
353
+ return null
354
+ }
355
+ val locationManager = context
356
+ .getSystemService(Context.LOCATION_SERVICE) as LocationManager
357
+ ?: return null
358
+
359
+ // Don't crash if the device does not have location services.
360
+
361
+ // It's possible that the location service is running out of process
362
+ // and the remote getProviders call fails. Handle null provider lists.
363
+ var providers: List<String?>? = null
364
+ try {
365
+ providers = locationManager.getProviders(true)
366
+ } catch (e: SecurityException) {
367
+ // failed to get providers list
368
+ } catch (e: Exception) {
369
+ // other causes
370
+ }
371
+ if (providers == null) {
372
+ return null
373
+ }
374
+ val locations: MutableList<Location> = ArrayList()
375
+ for (provider in providers) {
376
+ var location: Location? = null
377
+ try {
378
+ location = locationManager.getLastKnownLocation(provider!!)
379
+ } catch (e: SecurityException) {
380
+ LogcatLogger.logger.warn("Failed to get most recent location")
381
+ } catch (e: Exception) {
382
+ LogcatLogger.logger.warn("Failed to get most recent location")
383
+ }
384
+ if (location != null) {
385
+ locations.add(location)
386
+ }
387
+ }
388
+ var maximumTimestamp: Long = -1
389
+ var bestLocation: Location? = null
390
+ for (location in locations) {
391
+ if (location.time > maximumTimestamp) {
392
+ maximumTimestamp = location.time
393
+ bestLocation = location
394
+ }
395
+ }
396
+ return bestLocation
397
+ }
398
+
399
+ // @VisibleForTesting
400
+ protected val geocoder: Geocoder
401
+ protected get() = Geocoder(context, Locale.ENGLISH)
402
+
403
+ companion object {
404
+ const val OS_NAME = "android"
405
+ const val SETTING_LIMIT_AD_TRACKING = "limit_ad_tracking"
406
+ const val SETTING_ADVERTISING_ID = "advertising_id"
407
+ fun generateUUID(): String {
408
+ return UUID.randomUUID().toString()
409
+ }
410
+ }
411
+
412
+ init {
413
+ isLocationListening = locationListening
414
+ }
415
+ }
@@ -0,0 +1,56 @@
1
+ package com.amplitude.reactnative
2
+
3
+ import android.util.Log
4
+
5
+ interface Logger {
6
+ enum class LogMode(i: Int) {
7
+ DEBUG(1),
8
+ INFO(2),
9
+ WARN(3),
10
+ ERROR(4),
11
+ OFF(5)
12
+ }
13
+
14
+ var logMode: LogMode
15
+
16
+ fun debug(message: String)
17
+
18
+ fun error(message: String)
19
+
20
+ fun info(message: String)
21
+
22
+ fun warn(message: String)
23
+ }
24
+
25
+ class LogcatLogger() : Logger {
26
+ override var logMode: Logger.LogMode = Logger.LogMode.INFO
27
+ private val tag = "Amplitude"
28
+
29
+ override fun debug(message: String) {
30
+ if (logMode <= Logger.LogMode.DEBUG) {
31
+ Log.d(tag, message)
32
+ }
33
+ }
34
+
35
+ override fun error(message: String) {
36
+ if (logMode <= Logger.LogMode.ERROR) {
37
+ Log.e(tag, message)
38
+ }
39
+ }
40
+
41
+ override fun info(message: String) {
42
+ if (logMode <= Logger.LogMode.INFO) {
43
+ Log.i(tag, message)
44
+ }
45
+ }
46
+
47
+ override fun warn(message: String) {
48
+ if (logMode <= Logger.LogMode.WARN) {
49
+ Log.w(tag, message)
50
+ }
51
+ }
52
+
53
+ companion object {
54
+ val logger = LogcatLogger()
55
+ }
56
+ }
@@ -0,0 +1,34 @@
1
+ package com.amplitude.reactnative
2
+
3
+ import android.Manifest
4
+ import android.app.Activity
5
+ import android.content.Context
6
+ import android.content.pm.PackageManager
7
+ import android.os.Build
8
+
9
+ object Utils {
10
+
11
+ fun checkLocationPermissionAllowed(context: Context?): Boolean {
12
+ return checkPermissionAllowed(context, Manifest.permission.ACCESS_COARSE_LOCATION) ||
13
+ checkPermissionAllowed(context, Manifest.permission.ACCESS_FINE_LOCATION)
14
+ }
15
+
16
+ fun checkPermissionAllowed(context: Context?, permission: String?): Boolean {
17
+ // ANDROID 6.0 AND UP!
18
+ return if (Build.VERSION.SDK_INT >= 23) {
19
+ var hasPermission = false
20
+ try {
21
+ // Invoke checkSelfPermission method from Android 6 (API 23 and UP)
22
+ val methodCheckPermission =
23
+ Activity::class.java.getMethod("checkSelfPermission", String::class.java)
24
+ val resultObj = methodCheckPermission.invoke(context, permission)
25
+ val result = resultObj.toString().toInt()
26
+ hasPermission = result == PackageManager.PERMISSION_GRANTED
27
+ } catch (ex: Exception) {
28
+ }
29
+ hasPermission
30
+ } else {
31
+ true
32
+ }
33
+ }
34
+ }
@@ -0,0 +1,5 @@
1
+ #if __has_include("RCTBridgeModule.h")
2
+ #import "RCTBridgeModule.h"
3
+ #else
4
+ #import <React/RCTBridgeModule.h>
5
+ #endif
@@ -0,0 +1,7 @@
1
+ #import <React/RCTBridgeModule.h>
2
+
3
+ @interface RCT_EXTERN_MODULE(AmplitudeReactNative, NSObject)
4
+
5
+ RCT_EXTERN_METHOD(getApplicationContext: (RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
6
+
7
+ @end