|
45 | 45 | import io.sentry.android.core.InternalSentrySdk; |
46 | 46 | import io.sentry.android.core.SentryAndroidDateProvider; |
47 | 47 | import io.sentry.android.core.SentryAndroidOptions; |
| 48 | +import io.sentry.android.core.SentryShakeDetector; |
48 | 49 | import io.sentry.android.core.ViewHierarchyEventProcessor; |
49 | 50 | import io.sentry.android.core.internal.debugmeta.AssetsDebugMetaLoader; |
50 | 51 | import io.sentry.android.core.internal.util.SentryFrameMetricsCollector; |
@@ -122,6 +123,9 @@ public class RNSentryModuleImpl { |
122 | 123 |
|
123 | 124 | private final @NotNull Runnable emitNewFrameEvent; |
124 | 125 |
|
| 126 | + private static final String ON_SHAKE_EVENT = "rn_sentry_on_shake"; |
| 127 | + private @Nullable SentryShakeDetector shakeDetector; |
| 128 | + |
125 | 129 | /** Max trace file size in bytes. */ |
126 | 130 | private long maxTraceFileSize = 5 * 1024 * 1024; |
127 | 131 |
|
@@ -208,10 +212,58 @@ public void addListener(String eventType) { |
208 | 212 | } |
209 | 213 |
|
210 | 214 | public void removeListeners(double id) { |
211 | | - // Is must be defined otherwise the generated interface from TS won't be |
212 | | - // fulfilled |
213 | | - logger.log( |
214 | | - SentryLevel.ERROR, "removeListeners of NativeEventEmitter can't be used on Android!"); |
| 215 | + // removeListeners does not carry event-type information, so it cannot be used |
| 216 | + // to track shake listeners selectively. Shake detection is managed exclusively |
| 217 | + // via enableShakeDetection / disableShakeDetection. |
| 218 | + } |
| 219 | + |
| 220 | + private void startShakeDetection() { |
| 221 | + if (shakeDetector != null) { |
| 222 | + return; |
| 223 | + } |
| 224 | + |
| 225 | + try { // NOPMD - We don't want to crash in any case |
| 226 | + final ReactApplicationContext context = getReactApplicationContext(); |
| 227 | + shakeDetector = new SentryShakeDetector(logger); |
| 228 | + shakeDetector.start( |
| 229 | + context, |
| 230 | + () -> { |
| 231 | + try { // NOPMD - We don't want to crash in any case |
| 232 | + final ReactApplicationContext ctx = getReactApplicationContext(); |
| 233 | + if (ctx.hasActiveReactInstance()) { |
| 234 | + ctx.getJSModule( |
| 235 | + com.facebook.react.modules.core.DeviceEventManagerModule |
| 236 | + .RCTDeviceEventEmitter.class) |
| 237 | + .emit(ON_SHAKE_EVENT, null); |
| 238 | + } |
| 239 | + } catch (Throwable e) { // NOPMD - We don't want to crash in any case |
| 240 | + logger.log(SentryLevel.WARNING, "Failed to emit shake event.", e); |
| 241 | + } |
| 242 | + }); |
| 243 | + } catch (Throwable e) { // NOPMD - We don't want to crash in any case |
| 244 | + logger.log(SentryLevel.WARNING, "Failed to start shake detection.", e); |
| 245 | + shakeDetector = null; |
| 246 | + } |
| 247 | + } |
| 248 | + |
| 249 | + private void stopShakeDetection() { |
| 250 | + try { // NOPMD - We don't want to crash in any case |
| 251 | + if (shakeDetector != null) { |
| 252 | + shakeDetector.stop(); |
| 253 | + shakeDetector = null; |
| 254 | + } |
| 255 | + } catch (Throwable e) { // NOPMD - We don't want to crash in any case |
| 256 | + logger.log(SentryLevel.WARNING, "Failed to stop shake detection.", e); |
| 257 | + shakeDetector = null; |
| 258 | + } |
| 259 | + } |
| 260 | + |
| 261 | + public void enableShakeDetection() { |
| 262 | + startShakeDetection(); |
| 263 | + } |
| 264 | + |
| 265 | + public void disableShakeDetection() { |
| 266 | + stopShakeDetection(); |
215 | 267 | } |
216 | 268 |
|
217 | 269 | public void fetchModules(Promise promise) { |
|
0 commit comments