@sentry/react-native 5.0.0-alpha.1 → 5.0.0-alpha.11

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 (168) hide show
  1. package/CHANGELOG.md +403 -4
  2. package/README.md +6 -0
  3. package/RNSentry.podspec +22 -5
  4. package/android/build.gradle +20 -2
  5. package/android/src/main/java/io/sentry/react/{RNSentryModule.java → RNSentryModuleImpl.java} +174 -114
  6. package/android/src/main/java/io/sentry/react/RNSentryPackage.java +35 -19
  7. package/android/src/newarch/java/io/sentry/react/RNSentryModule.java +119 -0
  8. package/android/src/oldarch/java/io/sentry/react/RNSentryModule.java +119 -0
  9. package/dist/js/NativeRNSentry.d.ts +52 -0
  10. package/dist/js/NativeRNSentry.d.ts.map +1 -0
  11. package/dist/js/NativeRNSentry.js +4 -0
  12. package/dist/js/NativeRNSentry.js.map +1 -0
  13. package/dist/js/client.d.ts +18 -6
  14. package/dist/js/client.d.ts.map +1 -1
  15. package/dist/js/client.js +96 -37
  16. package/dist/js/client.js.map +1 -1
  17. package/dist/js/index.d.ts +4 -3
  18. package/dist/js/index.d.ts.map +1 -1
  19. package/dist/js/index.js +3 -2
  20. package/dist/js/index.js.map +1 -1
  21. package/dist/js/integrations/debugsymbolicator.d.ts +9 -0
  22. package/dist/js/integrations/debugsymbolicator.d.ts.map +1 -1
  23. package/dist/js/integrations/debugsymbolicator.js +0 -2
  24. package/dist/js/integrations/debugsymbolicator.js.map +1 -1
  25. package/dist/js/integrations/index.d.ts +2 -0
  26. package/dist/js/integrations/index.d.ts.map +1 -1
  27. package/dist/js/integrations/index.js +2 -0
  28. package/dist/js/integrations/index.js.map +1 -1
  29. package/dist/js/integrations/modulesloader.d.ts +17 -0
  30. package/dist/js/integrations/modulesloader.d.ts.map +1 -0
  31. package/dist/js/integrations/modulesloader.js +39 -0
  32. package/dist/js/integrations/modulesloader.js.map +1 -0
  33. package/dist/js/integrations/reactnativeerrorhandlers.d.ts.map +1 -1
  34. package/dist/js/integrations/reactnativeerrorhandlers.js +10 -7
  35. package/dist/js/integrations/reactnativeerrorhandlers.js.map +1 -1
  36. package/dist/js/integrations/reactnativeinfo.d.ts +23 -0
  37. package/dist/js/integrations/reactnativeinfo.d.ts.map +1 -0
  38. package/dist/js/integrations/reactnativeinfo.js +43 -0
  39. package/dist/js/integrations/reactnativeinfo.js.map +1 -0
  40. package/dist/js/integrations/screenshot.d.ts +23 -0
  41. package/dist/js/integrations/screenshot.d.ts.map +1 -0
  42. package/dist/js/integrations/screenshot.js +39 -0
  43. package/dist/js/integrations/screenshot.js.map +1 -0
  44. package/dist/js/integrations/sdkinfo.d.ts +4 -1
  45. package/dist/js/integrations/sdkinfo.d.ts.map +1 -1
  46. package/dist/js/integrations/sdkinfo.js +13 -7
  47. package/dist/js/integrations/sdkinfo.js.map +1 -1
  48. package/dist/js/measurements.d.ts +4 -0
  49. package/dist/js/measurements.d.ts.map +1 -1
  50. package/dist/js/measurements.js +12 -1
  51. package/dist/js/measurements.js.map +1 -1
  52. package/dist/js/misc.d.ts +9 -0
  53. package/dist/js/misc.d.ts.map +1 -0
  54. package/dist/js/misc.js +17 -0
  55. package/dist/js/misc.js.map +1 -0
  56. package/dist/js/options.d.ts +45 -9
  57. package/dist/js/options.d.ts.map +1 -1
  58. package/dist/js/options.js.map +1 -1
  59. package/dist/js/scope.d.ts +10 -2
  60. package/dist/js/scope.d.ts.map +1 -1
  61. package/dist/js/scope.js +13 -1
  62. package/dist/js/scope.js.map +1 -1
  63. package/dist/js/sdk.d.ts +25 -0
  64. package/dist/js/sdk.d.ts.map +1 -1
  65. package/dist/js/sdk.js +86 -27
  66. package/dist/js/sdk.js.map +1 -1
  67. package/dist/js/tools/ModulesCollector.d.ts +17 -0
  68. package/dist/js/tools/ModulesCollector.d.ts.map +1 -0
  69. package/dist/js/tools/ModulesCollector.js +109 -0
  70. package/dist/js/tools/ModulesCollector.js.map +1 -0
  71. package/dist/js/tools/collectModules.d.ts +2 -0
  72. package/dist/js/tools/collectModules.d.ts.map +1 -0
  73. package/dist/js/tools/collectModules.js +11 -0
  74. package/dist/js/tools/collectModules.js.map +1 -0
  75. package/dist/js/touchevents.d.ts +8 -0
  76. package/dist/js/touchevents.d.ts.map +1 -1
  77. package/dist/js/touchevents.js +10 -5
  78. package/dist/js/touchevents.js.map +1 -1
  79. package/dist/js/tracing/nativeframes.js.map +1 -1
  80. package/dist/js/tracing/reactnativenavigation.d.ts +9 -0
  81. package/dist/js/tracing/reactnativenavigation.d.ts.map +1 -1
  82. package/dist/js/tracing/reactnativenavigation.js +20 -12
  83. package/dist/js/tracing/reactnativenavigation.js.map +1 -1
  84. package/dist/js/tracing/reactnativetracing.d.ts +15 -6
  85. package/dist/js/tracing/reactnativetracing.d.ts.map +1 -1
  86. package/dist/js/tracing/reactnativetracing.js +16 -9
  87. package/dist/js/tracing/reactnativetracing.js.map +1 -1
  88. package/dist/js/tracing/reactnavigation.d.ts +7 -1
  89. package/dist/js/tracing/reactnavigation.d.ts.map +1 -1
  90. package/dist/js/tracing/reactnavigation.js +31 -23
  91. package/dist/js/tracing/reactnavigation.js.map +1 -1
  92. package/dist/js/tracing/reactnavigationv4.d.ts +9 -9
  93. package/dist/js/tracing/reactnavigationv4.d.ts.map +1 -1
  94. package/dist/js/tracing/reactnavigationv4.js +27 -15
  95. package/dist/js/tracing/reactnavigationv4.js.map +1 -1
  96. package/dist/js/tracing/routingInstrumentation.d.ts +1 -1
  97. package/dist/js/tracing/routingInstrumentation.d.ts.map +1 -1
  98. package/dist/js/tracing/routingInstrumentation.js.map +1 -1
  99. package/dist/js/tracing/utils.d.ts +4 -3
  100. package/dist/js/tracing/utils.d.ts.map +1 -1
  101. package/dist/js/tracing/utils.js +7 -10
  102. package/dist/js/tracing/utils.js.map +1 -1
  103. package/dist/js/transports/TextEncoder.d.ts +3 -0
  104. package/dist/js/transports/TextEncoder.d.ts.map +1 -0
  105. package/dist/js/transports/TextEncoder.js +12 -0
  106. package/dist/js/transports/TextEncoder.js.map +1 -0
  107. package/dist/js/transports/native.d.ts +10 -1
  108. package/dist/js/transports/native.d.ts.map +1 -1
  109. package/dist/js/transports/native.js +15 -4
  110. package/dist/js/transports/native.js.map +1 -1
  111. package/dist/js/user.d.ts +6 -0
  112. package/dist/js/user.d.ts.map +1 -0
  113. package/dist/js/user.js +1 -0
  114. package/dist/js/user.js.map +1 -0
  115. package/dist/js/utils/envelope.d.ts +12 -0
  116. package/dist/js/utils/envelope.d.ts.map +1 -0
  117. package/dist/js/utils/envelope.js +21 -0
  118. package/dist/js/utils/envelope.js.map +1 -0
  119. package/dist/js/utils/environment.d.ts +7 -0
  120. package/dist/js/utils/environment.d.ts.map +1 -0
  121. package/dist/js/utils/environment.js +14 -0
  122. package/dist/js/utils/environment.js.map +1 -0
  123. package/dist/js/utils/ignorerequirecyclelogs.d.ts +6 -0
  124. package/dist/js/utils/ignorerequirecyclelogs.d.ts.map +1 -0
  125. package/dist/js/utils/ignorerequirecyclelogs.js +15 -0
  126. package/dist/js/utils/ignorerequirecyclelogs.js.map +1 -0
  127. package/dist/js/utils/outcome.d.ts +6 -0
  128. package/dist/js/utils/outcome.d.ts.map +1 -0
  129. package/dist/js/utils/outcome.js +19 -0
  130. package/dist/js/utils/outcome.js.map +1 -0
  131. package/dist/js/utils/safe.d.ts +18 -0
  132. package/dist/js/utils/safe.d.ts.map +1 -0
  133. package/dist/js/utils/safe.js +46 -0
  134. package/dist/js/utils/safe.js.map +1 -0
  135. package/dist/js/utils/worldwide.d.ts +13 -0
  136. package/dist/js/utils/worldwide.d.ts.map +1 -0
  137. package/dist/js/utils/worldwide.js +4 -0
  138. package/dist/js/utils/worldwide.js.map +1 -0
  139. package/dist/js/vendor/buffer/index.d.ts +2 -0
  140. package/dist/js/vendor/buffer/index.d.ts.map +1 -0
  141. package/dist/js/vendor/buffer/index.js +2 -0
  142. package/dist/js/vendor/buffer/index.js.map +1 -0
  143. package/dist/js/vendor/buffer/utf8ToBytes.d.ts +10 -0
  144. package/dist/js/vendor/buffer/utf8ToBytes.d.ts.map +1 -0
  145. package/dist/js/vendor/buffer/utf8ToBytes.js +82 -0
  146. package/dist/js/vendor/buffer/utf8ToBytes.js.map +1 -0
  147. package/dist/js/vendor/index.d.ts +2 -0
  148. package/dist/js/vendor/index.d.ts.map +1 -0
  149. package/dist/js/vendor/index.js +2 -0
  150. package/dist/js/vendor/index.js.map +1 -0
  151. package/dist/js/version.d.ts +2 -1
  152. package/dist/js/version.d.ts.map +1 -1
  153. package/dist/js/version.js +2 -1
  154. package/dist/js/version.js.map +1 -1
  155. package/dist/js/wrapper.d.ts +13 -4
  156. package/dist/js/wrapper.d.ts.map +1 -1
  157. package/dist/js/wrapper.js +129 -71
  158. package/dist/js/wrapper.js.map +1 -1
  159. package/ios/{RNSentry.m → RNSentry.mm} +98 -57
  160. package/package.json +32 -26
  161. package/sample-new-architecture/react-native.config.js +10 -0
  162. package/scripts/collect-modules.sh +43 -0
  163. package/sentry.gradle +57 -6
  164. package/src/js/NativeRNSentry.ts +66 -0
  165. package/dist/js/definitions.d.ts +0 -52
  166. package/dist/js/definitions.d.ts.map +0 -1
  167. package/dist/js/definitions.js +0 -1
  168. package/dist/js/definitions.js.map +0 -1
@@ -1,62 +1,76 @@
1
1
  package io.sentry.react;
2
2
 
3
+ import static io.sentry.android.core.internal.util.ScreenshotUtils.takeScreenshot;
4
+
3
5
  import android.app.Activity;
4
6
  import android.content.Context;
5
7
  import android.content.pm.PackageInfo;
6
8
  import android.content.pm.PackageManager;
9
+ import android.content.res.AssetManager;
7
10
  import android.util.SparseIntArray;
8
11
 
12
+ import androidx.annotation.Nullable;
9
13
  import androidx.core.app.FrameMetricsAggregator;
10
14
 
11
15
  import com.facebook.react.bridge.Arguments;
12
- import com.facebook.react.bridge.LifecycleEventListener;
13
16
  import com.facebook.react.bridge.Promise;
14
17
  import com.facebook.react.bridge.ReactApplicationContext;
15
- import com.facebook.react.bridge.ReactContextBaseJavaModule;
16
- import com.facebook.react.bridge.ReactMethod;
18
+ import com.facebook.react.bridge.ReadableArray;
17
19
  import com.facebook.react.bridge.ReadableMap;
18
20
  import com.facebook.react.bridge.ReadableMapKeySetIterator;
21
+ import com.facebook.react.bridge.WritableArray;
19
22
  import com.facebook.react.bridge.WritableMap;
23
+ import com.facebook.react.bridge.WritableNativeArray;
24
+ import com.facebook.react.bridge.WritableNativeMap;
20
25
  import com.facebook.react.module.annotations.ReactModule;
21
26
 
27
+ import java.io.BufferedInputStream;
22
28
  import java.io.File;
29
+ import java.io.FileNotFoundException;
23
30
  import java.io.FileOutputStream;
24
- import java.io.UnsupportedEncodingException;
31
+ import java.io.InputStream;
25
32
  import java.nio.charset.Charset;
26
33
  import java.util.Date;
27
34
  import java.util.HashMap;
28
35
  import java.util.List;
29
36
  import java.util.Map;
30
37
  import java.util.UUID;
31
- import java.util.logging.Level;
32
- import java.util.logging.Logger;
33
38
 
34
- import io.sentry.SentryEvent;
35
- import io.sentry.android.core.AnrIntegration;
36
- import io.sentry.android.core.AppStartState;
37
- import io.sentry.android.core.NdkIntegration;
38
- import io.sentry.android.core.SentryAndroid;
39
39
  import io.sentry.Breadcrumb;
40
40
  import io.sentry.HubAdapter;
41
+ import io.sentry.ILogger;
41
42
  import io.sentry.Integration;
42
43
  import io.sentry.Sentry;
44
+ import io.sentry.SentryEvent;
43
45
  import io.sentry.SentryLevel;
44
46
  import io.sentry.UncaughtExceptionHandlerIntegration;
47
+ import io.sentry.android.core.AnrIntegration;
48
+ import io.sentry.android.core.AppStartState;
49
+ import io.sentry.android.core.BuildInfoProvider;
50
+ import io.sentry.android.core.CurrentActivityHolder;
51
+ import io.sentry.android.core.NdkIntegration;
52
+ import io.sentry.android.core.ScreenshotEventProcessor;
53
+ import io.sentry.android.core.SentryAndroid;
54
+ import io.sentry.android.core.AndroidLogger;
45
55
  import io.sentry.protocol.SdkVersion;
46
56
  import io.sentry.protocol.SentryException;
47
57
  import io.sentry.protocol.SentryPackage;
48
58
  import io.sentry.protocol.User;
49
59
 
50
- @ReactModule(name = RNSentryModule.NAME)
51
- public class RNSentryModule extends ReactContextBaseJavaModule {
60
+ public class RNSentryModuleImpl {
52
61
 
53
62
  public static final String NAME = "RNSentry";
54
63
 
55
- private static final Logger logger = Logger.getLogger("react-native-sentry");
64
+ private static final ILogger logger = new AndroidLogger(NAME);
65
+ private static final BuildInfoProvider buildInfo = new BuildInfoProvider(logger);
66
+ private static final String modulesPath = "modules.json";
67
+ private static final Charset UTF_8 = Charset.forName("UTF-8");
56
68
 
57
- private PackageInfo packageInfo = null;
69
+ private final ReactApplicationContext reactApplicationContext;
70
+ private final PackageInfo packageInfo;
58
71
  private FrameMetricsAggregator frameMetricsAggregator = null;
59
- private boolean androidXAvailable = true;
72
+ private boolean androidXAvailable;
73
+ private ScreenshotEventProcessor screenshotEventProcessor;
60
74
 
61
75
  private static boolean didFetchAppStart;
62
76
 
@@ -65,39 +79,36 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
65
79
  // 16ms (slower than 60fps) to constitute slow frames.
66
80
  private static final int SLOW_FRAME_THRESHOLD = 16;
67
81
 
68
- public RNSentryModule(ReactApplicationContext reactContext) {
69
- super(reactContext);
70
- packageInfo = getPackageInfo(reactContext);
82
+ public RNSentryModuleImpl(ReactApplicationContext reactApplicationContext) {
83
+ packageInfo = getPackageInfo(reactApplicationContext);
84
+ this.reactApplicationContext = reactApplicationContext;
71
85
  }
72
86
 
73
- @Override
74
- public String getName() {
75
- return NAME;
87
+ private ReactApplicationContext getReactApplicationContext() {
88
+ return this.reactApplicationContext;
76
89
  }
77
90
 
78
- @Override
79
- public Map<String, Object> getConstants() {
80
- final Map<String, Object> constants = new HashMap<>();
81
- constants.put("nativeClientAvailable", true);
82
- constants.put("nativeTransport", true);
83
- return constants;
91
+ private @Nullable
92
+ Activity getCurrentActivity() {
93
+ return this.reactApplicationContext.getCurrentActivity();
84
94
  }
85
95
 
86
- @ReactMethod
87
96
  public void initNativeSdk(final ReadableMap rnOptions, Promise promise) {
88
97
  SentryAndroid.init(this.getReactApplicationContext(), options -> {
89
98
  if (rnOptions.hasKey("debug") && rnOptions.getBoolean("debug")) {
90
99
  options.setDebug(true);
91
- logger.setLevel(Level.INFO);
92
100
  }
93
101
  if (rnOptions.hasKey("dsn") && rnOptions.getString("dsn") != null) {
94
102
  String dsn = rnOptions.getString("dsn");
95
- logger.info(String.format("Starting with DSN: '%s'", dsn));
103
+ logger.log(SentryLevel.INFO, String.format("Starting with DSN: '%s'", dsn));
96
104
  options.setDsn(dsn);
97
105
  } else {
98
106
  // SentryAndroid needs an empty string fallback for the dsn.
99
107
  options.setDsn("");
100
108
  }
109
+ if (rnOptions.hasKey("sendClientReports")) {
110
+ options.setSendClientReports(rnOptions.getBoolean("sendClientReports"));
111
+ }
101
112
  if (rnOptions.hasKey("maxBreadcrumbs")) {
102
113
  options.setMaxBreadcrumbs(rnOptions.getInt("maxBreadcrumbs"));
103
114
  }
@@ -129,35 +140,18 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
129
140
  options.setAttachStacktrace(rnOptions.getBoolean("attachStacktrace"));
130
141
  }
131
142
  if (rnOptions.hasKey("attachThreads")) {
132
- // JS use top level stacktraces and android attaches Threads which hides them so
143
+ // JS use top level stacktrace and android attaches Threads which hides them so
133
144
  // by default we hide.
134
145
  options.setAttachThreads(rnOptions.getBoolean("attachThreads"));
135
146
  }
147
+ if (rnOptions.hasKey("attachScreenshot")) {
148
+ options.setAttachScreenshot(rnOptions.getBoolean("attachScreenshot"));
149
+ }
136
150
  if (rnOptions.hasKey("sendDefaultPii")) {
137
151
  options.setSendDefaultPii(rnOptions.getBoolean("sendDefaultPii"));
138
152
  }
139
- if (rnOptions.hasKey("enableAutoPerformanceTracking")
140
- && rnOptions.getBoolean("enableAutoPerformanceTracking")) {
141
- androidXAvailable = checkAndroidXAvailability();
142
-
143
- if (androidXAvailable) {
144
- frameMetricsAggregator = new FrameMetricsAggregator();
145
- final Activity currentActivity = getCurrentActivity();
146
-
147
- if (frameMetricsAggregator != null && currentActivity != null) {
148
- try {
149
- frameMetricsAggregator.add(currentActivity);
150
- } catch (Throwable ignored) {
151
- // throws ConcurrentModification when calling addOnFrameMetricsAvailableListener
152
- // this is a best effort since we can't reproduce it
153
- logger.warning("Error adding Activity to frameMetricsAggregator.");
154
- }
155
- }
156
- } else {
157
- logger.warning("androidx.core' isn't available as a dependency.");
158
- }
159
- } else {
160
- this.disableNativeFramesTracking();
153
+ if (rnOptions.hasKey("maxQueueSize")) {
154
+ options.setMaxQueueSize(rnOptions.getInt("maxQueueSize"));
161
155
  }
162
156
 
163
157
  options.setBeforeSend((event, hint) -> {
@@ -188,19 +182,40 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
188
182
  }
189
183
  }
190
184
  }
185
+ logger.log(SentryLevel.INFO, String.format("Native Integrations '%s'", options.getIntegrations()));
191
186
 
192
- logger.info(String.format("Native Integrations '%s'", options.getIntegrations().toString()));
187
+ final CurrentActivityHolder currentActivityHolder = CurrentActivityHolder.getInstance();
188
+ final Activity currentActivity = getCurrentActivity();
189
+ if (currentActivity != null) {
190
+ currentActivityHolder.setActivity(currentActivity);
191
+ }
193
192
  });
194
193
 
195
194
  promise.resolve(true);
196
195
  }
197
196
 
198
- @ReactMethod
199
197
  public void crash() {
200
198
  throw new RuntimeException("TEST - Sentry Client Crash (only works in release mode)");
201
199
  }
202
200
 
203
- @ReactMethod
201
+ public void fetchModules(Promise promise) {
202
+ final AssetManager assets = this.getReactApplicationContext().getResources().getAssets();
203
+ try (final InputStream stream =
204
+ new BufferedInputStream(assets.open(RNSentryModuleImpl.modulesPath))) {
205
+ int size = stream.available();
206
+ byte[] buffer = new byte[size];
207
+ stream.read(buffer);
208
+ stream.close();
209
+ String modulesJson = new String(buffer, RNSentryModuleImpl.UTF_8);
210
+ promise.resolve(modulesJson);
211
+ } catch (FileNotFoundException e) {
212
+ promise.resolve(null);
213
+ } catch (Throwable e) {
214
+ logger.log(SentryLevel.WARNING, "Fetching JS Modules failed.");
215
+ promise.resolve(null);
216
+ }
217
+ }
218
+
204
219
  public void fetchNativeRelease(Promise promise) {
205
220
  WritableMap release = Arguments.createMap();
206
221
  release.putString("id", packageInfo.packageName);
@@ -209,17 +224,16 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
209
224
  promise.resolve(release);
210
225
  }
211
226
 
212
- @ReactMethod
213
227
  public void fetchNativeAppStart(Promise promise) {
214
228
  final AppStartState appStartInstance = AppStartState.getInstance();
215
229
  final Date appStartTime = appStartInstance.getAppStartTime();
216
230
  final Boolean isColdStart = appStartInstance.isColdStart();
217
231
 
218
232
  if (appStartTime == null) {
219
- logger.warning("App start won't be sent due to missing appStartTime.");
233
+ logger.log(SentryLevel.WARNING, "App start won't be sent due to missing appStartTime.");
220
234
  promise.resolve(null);
221
235
  } else if (isColdStart == null) {
222
- logger.warning("App start won't be sent due to missing isColdStart.");
236
+ logger.log(SentryLevel.WARNING, "App start won't be sent due to missing isColdStart.");
223
237
  promise.resolve(null);
224
238
  } else {
225
239
  final double appStartTimestamp = (double) appStartTime.getTime();
@@ -241,7 +255,6 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
241
255
  /**
242
256
  * Returns frames metrics at the current point in time.
243
257
  */
244
- @ReactMethod
245
258
  public void fetchNativeFrames(Promise promise) {
246
259
  if (!isFrameMetricsAggregatorAvailable()) {
247
260
  promise.resolve(null);
@@ -285,87 +298,118 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
285
298
 
286
299
  promise.resolve(map);
287
300
  } catch (Throwable ignored) {
288
- logger.warning("Error fetching native frames.");
301
+ logger.log(SentryLevel.WARNING, "Error fetching native frames.");
289
302
  promise.resolve(null);
290
303
  }
291
304
  }
292
305
  }
293
306
 
294
- @ReactMethod
295
- public void captureEnvelope(String envelope, Promise promise) {
307
+ public void captureEnvelope(ReadableArray rawBytes, ReadableMap options, Promise promise) {
308
+ byte[] bytes = new byte[rawBytes.size()];
309
+ for (int i = 0; i < rawBytes.size(); i++) {
310
+ bytes[i] = (byte) rawBytes.getInt(i);
311
+ }
312
+
296
313
  try {
297
314
  final String outboxPath = HubAdapter.getInstance().getOptions().getOutboxPath();
298
315
 
299
316
  if (outboxPath == null) {
300
- logger.severe(
317
+ logger.log(SentryLevel.ERROR,
301
318
  "Error retrieving outboxPath. Envelope will not be sent. Is the Android SDK initialized?");
302
319
  } else {
303
320
  File installation = new File(outboxPath, UUID.randomUUID().toString());
304
321
  try (FileOutputStream out = new FileOutputStream(installation)) {
305
- out.write(envelope.getBytes(Charset.forName("UTF-8")));
322
+ out.write(bytes);
306
323
  }
307
324
  }
308
325
  } catch (Throwable ignored) {
309
- logger.severe("Error reading envelope");
326
+ logger.log(SentryLevel.ERROR, "Error while writing envelope to outbox.");
310
327
  }
311
328
  promise.resolve(true);
312
329
  }
313
330
 
314
- @ReactMethod
315
- public void getStringBytesLength(String payload, Promise promise) {
316
- try {
317
- promise.resolve(payload.getBytes("UTF-8").length);
318
- } catch (UnsupportedEncodingException e) {
319
- promise.reject(e);
331
+ public void captureScreenshot(Promise promise) {
332
+
333
+ final Activity activity = getCurrentActivity();
334
+ if (activity == null) {
335
+ logger.log(SentryLevel.WARNING, "CurrentActivity is null, can't capture screenshot.");
336
+ promise.resolve(null);
337
+ return;
320
338
  }
339
+
340
+ final byte[] raw = takeScreenshot(activity, logger, buildInfo);
341
+ if (raw == null) {
342
+ logger.log(SentryLevel.WARNING, "Screenshot is null, screen was not captured.");
343
+ promise.resolve(null);
344
+ return;
345
+ }
346
+
347
+ final WritableNativeArray data = new WritableNativeArray();
348
+ for (final byte b : raw) {
349
+ data.pushInt(b);
350
+ }
351
+ final WritableMap screenshot = new WritableNativeMap();
352
+ screenshot.putString("contentType", "image/png");
353
+ screenshot.putArray("data", data);
354
+ screenshot.putString("filename", "screenshot.png");
355
+
356
+ final WritableArray screenshotsArray = new WritableNativeArray();
357
+ screenshotsArray.pushMap(screenshot);
358
+ promise.resolve(screenshotsArray);
321
359
  }
322
360
 
323
361
  private static PackageInfo getPackageInfo(Context ctx) {
324
362
  try {
325
363
  return ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), 0);
326
364
  } catch (PackageManager.NameNotFoundException e) {
327
- logger.warning("Error getting package info.");
365
+ logger.log(SentryLevel.WARNING, "Error getting package info.");
328
366
  return null;
329
367
  }
330
368
  }
331
369
 
332
- @ReactMethod
333
- public void setUser(final ReadableMap user, final ReadableMap otherUserKeys) {
370
+ public void setUser(final ReadableMap userKeys, final ReadableMap userDataKeys) {
334
371
  Sentry.configureScope(scope -> {
335
- if (user == null && otherUserKeys == null) {
372
+ if (userKeys == null && userDataKeys == null) {
336
373
  scope.setUser(null);
337
374
  } else {
338
375
  User userInstance = new User();
339
376
 
340
- if (user != null) {
341
- if (user.hasKey("email")) {
342
- userInstance.setEmail(user.getString("email"));
377
+ if (userKeys != null) {
378
+ if (userKeys.hasKey("email")) {
379
+ userInstance.setEmail(userKeys.getString("email"));
380
+ }
381
+
382
+ if (userKeys.hasKey("id")) {
383
+ userInstance.setId(userKeys.getString("id"));
343
384
  }
344
385
 
345
- if (user.hasKey("id")) {
346
- userInstance.setId(user.getString("id"));
386
+ if (userKeys.hasKey("username")) {
387
+ userInstance.setUsername(userKeys.getString("username"));
347
388
  }
348
389
 
349
- if (user.hasKey("username")) {
350
- userInstance.setUsername(user.getString("username"));
390
+ if (userKeys.hasKey("ip_address")) {
391
+ userInstance.setIpAddress(userKeys.getString("ip_address"));
351
392
  }
352
393
 
353
- if (user.hasKey("ip_address")) {
354
- userInstance.setIpAddress(user.getString("ip_address"));
394
+ if (userKeys.hasKey("segment")) {
395
+ userInstance.setSegment(userKeys.getString("segment"));
355
396
  }
356
397
  }
357
398
 
358
- if (otherUserKeys != null) {
359
- HashMap<String, String> otherUserKeysMap = new HashMap<String, String>();
360
- ReadableMapKeySetIterator it = otherUserKeys.keySetIterator();
399
+ if (userDataKeys != null) {
400
+ HashMap<String, String> userDataMap = new HashMap<>();
401
+ ReadableMapKeySetIterator it = userDataKeys.keySetIterator();
361
402
  while (it.hasNextKey()) {
362
403
  String key = it.nextKey();
363
- String value = otherUserKeys.getString(key);
404
+ String value = userDataKeys.getString(key);
364
405
 
365
- otherUserKeysMap.put(key, value);
406
+ // other is ConcurrentHashMap and can't have null values
407
+ if (value != null) {
408
+ userDataMap.put(key, value);
409
+ }
366
410
  }
367
411
 
368
- userInstance.setOthers(otherUserKeysMap);
412
+ userInstance.setData(userDataMap);
369
413
  }
370
414
 
371
415
  scope.setUser(userInstance);
@@ -373,7 +417,6 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
373
417
  });
374
418
  }
375
419
 
376
- @ReactMethod
377
420
  public void addBreadcrumb(final ReadableMap breadcrumb) {
378
421
  Sentry.configureScope(scope -> {
379
422
  Breadcrumb breadcrumbInstance = new Breadcrumb();
@@ -398,29 +441,27 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
398
441
  case "warning":
399
442
  breadcrumbInstance.setLevel(SentryLevel.WARNING);
400
443
  break;
401
- case "info":
402
- breadcrumbInstance.setLevel(SentryLevel.INFO);
403
- break;
404
444
  case "debug":
405
445
  breadcrumbInstance.setLevel(SentryLevel.DEBUG);
406
446
  break;
407
447
  case "error":
408
448
  breadcrumbInstance.setLevel(SentryLevel.ERROR);
409
449
  break;
450
+ case "info":
410
451
  default:
411
- breadcrumbInstance.setLevel(SentryLevel.ERROR);
452
+ breadcrumbInstance.setLevel(SentryLevel.INFO);
412
453
  break;
413
454
  }
414
455
  }
415
456
 
416
457
  if (breadcrumb.hasKey("data")) {
417
- ReadableMap data = breadcrumb.getMap("data");
418
- ReadableMapKeySetIterator it = data.keySetIterator();
419
- while (it.hasNextKey()) {
420
- String key = it.nextKey();
421
- String value = data.getString(key);
422
-
423
- breadcrumbInstance.setData(key, value);
458
+ final ReadableMap data = breadcrumb.getMap("data");
459
+ for (final Map.Entry<String, Object> entry : data.toHashMap().entrySet()) {
460
+ final Object value = entry.getValue();
461
+ // data is ConcurrentHashMap and can't have null values
462
+ if (value != null) {
463
+ breadcrumbInstance.setData(entry.getKey(), entry.getValue());
464
+ }
424
465
  }
425
466
  }
426
467
 
@@ -428,21 +469,18 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
428
469
  });
429
470
  }
430
471
 
431
- @ReactMethod
432
472
  public void clearBreadcrumbs() {
433
473
  Sentry.configureScope(scope -> {
434
474
  scope.clearBreadcrumbs();
435
475
  });
436
476
  }
437
477
 
438
- @ReactMethod
439
478
  public void setExtra(String key, String extra) {
440
479
  Sentry.configureScope(scope -> {
441
480
  scope.setExtra(key, extra);
442
481
  });
443
482
  }
444
483
 
445
- @ReactMethod
446
484
  public void setContext(final String key, final ReadableMap context) {
447
485
  if (key == null || context == null) {
448
486
  return;
@@ -454,14 +492,12 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
454
492
  });
455
493
  }
456
494
 
457
- @ReactMethod
458
495
  public void setTag(String key, String value) {
459
496
  Sentry.configureScope(scope -> {
460
497
  scope.setTag(key, value);
461
498
  });
462
499
  }
463
500
 
464
- @ReactMethod
465
501
  public void closeNativeSdk(Promise promise) {
466
502
  Sentry.close();
467
503
 
@@ -470,7 +506,31 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
470
506
  promise.resolve(true);
471
507
  }
472
508
 
473
- @ReactMethod
509
+ public void enableNativeFramesTracking() {
510
+ androidXAvailable = checkAndroidXAvailability();
511
+
512
+ if (androidXAvailable) {
513
+ frameMetricsAggregator = new FrameMetricsAggregator();
514
+ final Activity currentActivity = getCurrentActivity();
515
+
516
+ if (frameMetricsAggregator != null && currentActivity != null) {
517
+ try {
518
+ frameMetricsAggregator.add(currentActivity);
519
+
520
+ logger.log(SentryLevel.INFO, "FrameMetricsAggregator installed.");
521
+ } catch (Throwable ignored) {
522
+ // throws ConcurrentModification when calling addOnFrameMetricsAvailableListener
523
+ // this is a best effort since we can't reproduce it
524
+ logger.log(SentryLevel.ERROR, "Error adding Activity to frameMetricsAggregator.");
525
+ }
526
+ } else {
527
+ logger.log(SentryLevel.INFO, "currentActivity isn't available.");
528
+ }
529
+ } else {
530
+ logger.log(SentryLevel.WARNING, "androidx.core' isn't available as a dependency.");
531
+ }
532
+ }
533
+
474
534
  public void disableNativeFramesTracking() {
475
535
  if (isFrameMetricsAggregatorAvailable()) {
476
536
  frameMetricsAggregator.stop();
@@ -485,10 +545,10 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
485
545
  // If the event is from capacitor js, it gets set there and we do not handle it
486
546
  // here.
487
547
  case "sentry.native":
488
- setEventEnvironmentTag(event, "android", "native");
548
+ setEventEnvironmentTag(event, "native");
489
549
  break;
490
550
  case "sentry.java.android":
491
- setEventEnvironmentTag(event, "android", "java");
551
+ setEventEnvironmentTag(event, "java");
492
552
  break;
493
553
  default:
494
554
  break;
@@ -496,8 +556,8 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
496
556
  }
497
557
  }
498
558
 
499
- private void setEventEnvironmentTag(SentryEvent event, String origin, String environment) {
500
- event.setTag("event.origin", origin);
559
+ private void setEventEnvironmentTag(SentryEvent event, String environment) {
560
+ event.setTag("event.origin", "android");
501
561
  event.setTag("event.environment", environment);
502
562
  }
503
563
 
@@ -1,30 +1,46 @@
1
1
  package io.sentry.react;
2
2
 
3
- import java.util.Arrays;
4
- import java.util.Collections;
5
- import java.util.List;
3
+ import androidx.annotation.Nullable;
4
+
5
+ import java.util.HashMap;
6
+ import java.util.Map;
6
7
 
7
- import com.facebook.react.ReactPackage;
8
8
  import com.facebook.react.bridge.NativeModule;
9
9
  import com.facebook.react.bridge.ReactApplicationContext;
10
- import com.facebook.react.uimanager.ViewManager;
11
- import com.facebook.react.bridge.JavaScriptModule;
10
+ import com.facebook.react.module.model.ReactModuleInfo;
11
+ import com.facebook.react.module.model.ReactModuleInfoProvider;
12
+ import com.facebook.react.TurboReactPackage;
12
13
 
13
- public class RNSentryPackage implements ReactPackage {
14
- public RNSentryPackage() {
15
- }
14
+ public class RNSentryPackage extends TurboReactPackage {
16
15
 
17
- @Override
18
- public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
19
- return Arrays.<NativeModule>asList(new RNSentryModule(reactContext));
16
+ @Nullable
17
+ @Override
18
+ public NativeModule getModule(String name, ReactApplicationContext reactContext) {
19
+ if (name.equals(RNSentryModuleImpl.NAME)) {
20
+ return new RNSentryModule(reactContext);
21
+ } else {
22
+ return null;
20
23
  }
24
+ }
21
25
 
22
- public List<Class<? extends JavaScriptModule>> createJSModules() {
23
- return Collections.emptyList();
24
- }
26
+ @Override
27
+ public ReactModuleInfoProvider getReactModuleInfoProvider() {
28
+ return () -> {
29
+ final Map<String, ReactModuleInfo> moduleInfos = new HashMap<>();
30
+ boolean isTurboModule = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
31
+ moduleInfos.put(
32
+ RNSentryModuleImpl.NAME,
33
+ new ReactModuleInfo(
34
+ RNSentryModuleImpl.NAME,
35
+ RNSentryModuleImpl.NAME,
36
+ false, // canOverrideExistingModule
37
+ false, // needsEagerInit
38
+ true, // hasConstants
39
+ false, // isCxxModule
40
+ isTurboModule // isTurboModule
41
+ ));
42
+ return moduleInfos;
43
+ };
44
+ }
25
45
 
26
- @Override
27
- public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
28
- return Collections.emptyList();
29
- }
30
46
  }