Skip to content

Commit 5f0e223

Browse files
authored
[MOB-9146] Create Native Module for CrashReporting (#797)
* Create CrashReporting Android Native Module * Create CrashReporting iOS Native Module * Extract Android CR Unit Tests * Extract iOS CR Unit Tests * Rename iOS Module to `InstabugCrashReportingBridge` * Update JS Module and Tests * Rescope `currentReport` to private
1 parent f3b4cce commit 5f0e223

22 files changed

+278
-193
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package com.instabug.reactlibrary;
2+
3+
import static com.instabug.reactlibrary.utils.InstabugUtil.getMethod;
4+
5+
import com.facebook.react.bridge.ReactApplicationContext;
6+
import com.facebook.react.bridge.ReactContextBaseJavaModule;
7+
import com.facebook.react.bridge.ReactMethod;
8+
import com.instabug.crash.CrashReporting;
9+
import com.instabug.library.Feature;
10+
import com.instabug.reactlibrary.utils.MainThreadHandler;
11+
12+
import org.json.JSONObject;
13+
14+
import java.lang.reflect.InvocationTargetException;
15+
import java.lang.reflect.Method;
16+
17+
import javax.annotation.Nonnull;
18+
19+
public class RNInstabugCrashReportingModule extends ReactContextBaseJavaModule {
20+
21+
public RNInstabugCrashReportingModule(ReactApplicationContext reactApplicationContext) {
22+
super(reactApplicationContext);
23+
}
24+
25+
@Nonnull
26+
@Override
27+
public String getName() {
28+
return "IBGCrashReporting";
29+
}
30+
31+
/**
32+
* Sets whether crash reporting feature is Enabled or Disabled
33+
*
34+
* @param isEnabled Exception object to be sent to Instabug's servers
35+
*/
36+
@ReactMethod
37+
public void setEnabled(final boolean isEnabled) {
38+
MainThreadHandler.runOnMainThread(new Runnable() {
39+
@Override
40+
public void run() {
41+
try {
42+
if (isEnabled) {
43+
CrashReporting.setState(Feature.State.ENABLED);
44+
} else {
45+
CrashReporting.setState(Feature.State.DISABLED);
46+
}
47+
} catch (Exception e) {
48+
e.printStackTrace();
49+
}
50+
}
51+
});
52+
}
53+
54+
/**
55+
* Send unhandled JS error object
56+
*
57+
* @param exceptionObject Exception object to be sent to Instabug's servers
58+
*/
59+
@ReactMethod
60+
public void sendJSCrash(final String exceptionObject) {
61+
try {
62+
JSONObject jsonObject = new JSONObject(exceptionObject);
63+
sendJSCrashByReflection(jsonObject, false);
64+
} catch (Exception e) {
65+
e.printStackTrace();
66+
}
67+
}
68+
69+
/**
70+
* Send handled JS error object
71+
*
72+
* @param exceptionObject Exception object to be sent to Instabug's servers
73+
*/
74+
@ReactMethod
75+
public void sendHandledJSCrash(final String exceptionObject) {
76+
try {
77+
JSONObject jsonObject = new JSONObject(exceptionObject);
78+
sendJSCrashByReflection(jsonObject, true);
79+
} catch (Exception e) {
80+
e.printStackTrace();
81+
}
82+
}
83+
84+
private void sendJSCrashByReflection(final JSONObject exceptionObject, final boolean isHandled) {
85+
MainThreadHandler.runOnMainThread(new Runnable() {
86+
@Override
87+
public void run() {
88+
try {
89+
Method method = getMethod(Class.forName("com.instabug.crash.CrashReporting"), "reportException", JSONObject.class, boolean.class);
90+
if (method != null) {
91+
method.invoke(null, exceptionObject, isHandled);
92+
RNInstabugReactnativeModule.clearCurrentReport();
93+
}
94+
} catch (ClassNotFoundException e) {
95+
e.printStackTrace();
96+
} catch (IllegalAccessException e) {
97+
e.printStackTrace();
98+
} catch (InvocationTargetException e) {
99+
e.printStackTrace();
100+
}
101+
}
102+
});
103+
104+
}
105+
}

android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java

Lines changed: 4 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ public class RNInstabugReactnativeModule extends ReactContextBaseJavaModule {
8888
private static final String TAG = RNInstabugReactnativeModule.class.getSimpleName();
8989

9090
private InstabugCustomTextPlaceHolder placeHolders;
91-
private Report currentReport;
91+
private static Report currentReport;
9292

9393
/**
9494
* Instantiates a new Rn Instabug ReactNative module.
@@ -258,81 +258,6 @@ public void run() {
258258

259259
}
260260

261-
/**
262-
* Send unhandled JS error object
263-
*
264-
* @param exceptionObject Exception object to be sent to Instabug's servers
265-
*/
266-
@ReactMethod
267-
public void sendJSCrash(final String exceptionObject) {
268-
try {
269-
JSONObject jsonObject = new JSONObject(exceptionObject);
270-
sendJSCrashByReflection(jsonObject, false);
271-
} catch (Exception e) {
272-
e.printStackTrace();
273-
}
274-
}
275-
276-
/**
277-
* Send handled JS error object
278-
*
279-
* @param exceptionObject Exception object to be sent to Instabug's servers
280-
*/
281-
@ReactMethod
282-
public void sendHandledJSCrash(final String exceptionObject) {
283-
try {
284-
JSONObject jsonObject = new JSONObject(exceptionObject);
285-
sendJSCrashByReflection(jsonObject, true);
286-
} catch (Exception e) {
287-
e.printStackTrace();
288-
}
289-
}
290-
291-
/**
292-
* Sets whether crash reporting feature is Enabled or Disabled
293-
*
294-
* @param isEnabled Exception object to be sent to Instabug's servers
295-
*/
296-
@ReactMethod
297-
public void setCrashReportingEnabled(final boolean isEnabled) {
298-
MainThreadHandler.runOnMainThread(new Runnable() {
299-
@Override
300-
public void run() {
301-
try {
302-
if (isEnabled) {
303-
CrashReporting.setState(Feature.State.ENABLED);
304-
} else {
305-
CrashReporting.setState(Feature.State.DISABLED);
306-
}
307-
} catch (Exception e) {
308-
e.printStackTrace();
309-
}
310-
}
311-
});
312-
}
313-
314-
private void sendJSCrashByReflection(final JSONObject exceptionObject, final boolean isHandled) {
315-
MainThreadHandler.runOnMainThread(new Runnable() {
316-
@Override
317-
public void run() {
318-
try {
319-
Method method = getMethod(Class.forName("com.instabug.crash.CrashReporting"), "reportException", JSONObject.class, boolean.class);
320-
if (method != null) {
321-
method.invoke(null, exceptionObject, isHandled);
322-
currentReport = null;
323-
}
324-
} catch (ClassNotFoundException e) {
325-
e.printStackTrace();
326-
} catch (IllegalAccessException e) {
327-
e.printStackTrace();
328-
} catch (InvocationTargetException e) {
329-
e.printStackTrace();
330-
}
331-
}
332-
});
333-
334-
}
335-
336261
/**
337262
* Adds specific user data that you need to be added to the reports
338263
*
@@ -1045,7 +970,10 @@ public void onReportCreated(Report report) {
1045970
});
1046971
}
1047972
});
973+
}
1048974

975+
protected static void clearCurrentReport() {
976+
currentReport = null;
1049977
}
1050978

1051979
@ReactMethod

android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativePackage.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext r
2424
List<NativeModule> modules = new ArrayList<>();
2525
modules.add(new RNInstabugReactnativeModule(reactContext));
2626
modules.add(new RNInstabugBugReportingModule(reactContext));
27+
modules.add(new RNInstabugCrashReportingModule(reactContext));
2728
modules.add(new RNInstabugSurveysModule(reactContext));
2829
modules.add(new RNInstabugFeatureRequestsModule(reactContext));
2930
modules.add(new RNInstabugRepliesModule(reactContext));
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.instabug.reactlibrary;
2+
3+
import org.junit.Test;
4+
5+
6+
public class RNInstabugCrashReportingModuleTest {
7+
@Test
8+
public void givenString$sendHandledJSCrash_whenQuery_thenShouldCallNativeApiWithArgs() throws Exception {
9+
// JSONObject json = mock(JSONObject.class);
10+
// PowerMockito.whenNew(JSONObject.class).withArguments("exception").thenReturn(json);
11+
//
12+
// // given
13+
// PowerMockito.mockStatic(CrashReporting.class);
14+
// // when
15+
// rnModule.sendHandledJSCrash("exception");
16+
// // then
17+
// JSONObject jsonObject = new JSONObject("exception");
18+
// PowerMockito.verifyPrivate(CrashReporting.class, VerificationModeFactory.times(1)).invoke("reportException", jsonObject, true);
19+
}
20+
21+
@Test
22+
public void givenString$sendJSCrash_whenQuery_thenShouldCallNativeApiWithArgs() throws Exception {
23+
// JSONObject json = mock(JSONObject.class);
24+
// PowerMockito.whenNew(JSONObject.class).withArguments("exception").thenReturn(json);
25+
//
26+
// // given
27+
// PowerMockito.mockStatic(CrashReporting.class);
28+
// // when
29+
// rnModule.sendJSCrash("exception");
30+
// // then
31+
// JSONObject jsonObject = new JSONObject("exception");
32+
// PowerMockito.verifyPrivate(CrashReporting.class, VerificationModeFactory.times(1)).invoke("reportException", jsonObject, false);
33+
}
34+
}

android/src/test/java/com/instabug/reactlibrary/RNInstabugReactnativeModuleTest.java

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -91,40 +91,6 @@ public void tearDown() {
9191
mockInstabug.close();
9292
}
9393

94-
95-
/********CrashReporting*********/
96-
97-
//
98-
// @Test
99-
// public void givenString$sendHandledJSCrash_whenQuery_thenShouldCallNativeApiWithArgs() throws Exception {
100-
//
101-
// JSONObject json = mock(JSONObject.class);
102-
// PowerMockito.whenNew(JSONObject.class).withArguments("exception").thenReturn(json);
103-
//
104-
// // given
105-
// PowerMockito.mockStatic(CrashReporting.class);
106-
// // when
107-
// rnModule.sendHandledJSCrash("exception");
108-
// // then
109-
// JSONObject jsonObject = new JSONObject("exception");
110-
// PowerMockito.verifyPrivate(CrashReporting.class, VerificationModeFactory.times(1)).invoke("reportException", jsonObject, true);
111-
// }
112-
//
113-
// @Test
114-
// public void givenString$sendJSCrash_whenQuery_thenShouldCallNativeApiWithArgs() throws Exception {
115-
//
116-
// JSONObject json = mock(JSONObject.class);
117-
// PowerMockito.whenNew(JSONObject.class).withArguments("exception").thenReturn(json);
118-
//
119-
// // given
120-
// PowerMockito.mockStatic(CrashReporting.class);
121-
// // when
122-
// rnModule.sendJSCrash("exception");
123-
// // then
124-
// JSONObject jsonObject = new JSONObject("exception");
125-
// PowerMockito.verifyPrivate(CrashReporting.class, VerificationModeFactory.times(1)).invoke("reportException", jsonObject, false);
126-
// }
127-
12894
/********Instabug*********/
12995

13096
@Test

example/ios/InstabugSample.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
/* Begin PBXBuildFile section */
1010
00E356F31AD99517003FC87E /* InstabugSampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* InstabugSampleTests.m */; };
11+
0E2F487228F6B41B00EF4B9B /* InstabugCrashReportingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E2F487128F6B41B00EF4B9B /* InstabugCrashReportingTests.m */; };
1112
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
1213
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
1314
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
@@ -36,6 +37,7 @@
3637
00E356EE1AD99517003FC87E /* InstabugSampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InstabugSampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
3738
00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3839
00E356F21AD99517003FC87E /* InstabugSampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InstabugSampleTests.m; sourceTree = "<group>"; };
40+
0E2F487128F6B41B00EF4B9B /* InstabugCrashReportingTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InstabugCrashReportingTests.m; sourceTree = "<group>"; };
3941
13B07F961A680F5B00A75B9A /* InstabugSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = InstabugSample.app; sourceTree = BUILT_PRODUCTS_DIR; };
4042
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = InstabugSample/AppDelegate.h; sourceTree = "<group>"; };
4143
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = InstabugSample/AppDelegate.m; sourceTree = "<group>"; };
@@ -87,6 +89,7 @@
8789
63D4BF6D2715AA740039BE63 /* IBGConstants.m */,
8890
63D4BF6A2715AA740039BE63 /* InstabugAPMTests.m */,
8991
63D4BF6C2715AA740039BE63 /* InstabugBugReportingTests.m */,
92+
0E2F487128F6B41B00EF4B9B /* InstabugCrashReportingTests.m */,
9093
63D4BF692715AA740039BE63 /* InstabugFeatureRequestsTests.m */,
9194
63D4BF6B2715AA740039BE63 /* InstabugRepliesTests.m */,
9295
63D4BF682715AA740039BE63 /* InstabugSurveysTests.m */,
@@ -446,6 +449,7 @@
446449
63D4BF742715AA740039BE63 /* IBGConstants.m in Sources */,
447450
63D4BF712715AA740039BE63 /* InstabugAPMTests.m in Sources */,
448451
63D4BF702715AA740039BE63 /* InstabugFeatureRequestsTests.m in Sources */,
452+
0E2F487228F6B41B00EF4B9B /* InstabugCrashReportingTests.m in Sources */,
449453
63D4BF732715AA740039BE63 /* InstabugBugReportingTests.m in Sources */,
450454
00E356F31AD99517003FC87E /* InstabugSampleTests.m in Sources */,
451455
63D4BF6F2715AA740039BE63 /* InstabugSurveysTests.m in Sources */,
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#import <XCTest/XCTest.h>
2+
#import "Instabug/Instabug.h"
3+
#import "InstabugCrashReportingBridge.h"
4+
5+
@interface InstabugCrashReportingTests : XCTestCase
6+
@property (nonatomic, retain) InstabugCrashReportingBridge *bridge;
7+
@end
8+
9+
@implementation InstabugCrashReportingTests
10+
11+
- (void)setUp {
12+
self.bridge = [[InstabugCrashReportingBridge alloc] init];
13+
}
14+
15+
- (void)testSetEnabled {
16+
[self.bridge setEnabled:YES];
17+
XCTAssertTrue(IBGCrashReporting.enabled);
18+
19+
[self.bridge setEnabled:NO];
20+
XCTAssertFalse(IBGCrashReporting.enabled);
21+
}
22+
23+
@end

example/ios/InstabugSampleTests/InstabugSampleTests.m

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -311,22 +311,6 @@ - (void)testShow {
311311
}
312312

313313

314-
/*
315-
+------------------------------------------------------------------------+
316-
| Crash Reporting Module |
317-
+------------------------------------------------------------------------+
318-
*/
319-
320-
- (void)testSetCrashReportingEnabled {
321-
id mock = OCMClassMock([Instabug class]);
322-
323-
[self.instabugBridge setCrashReportingEnabled:YES];
324-
XCTAssertTrue(IBGCrashReporting.enabled);
325-
326-
[self.instabugBridge setCrashReportingEnabled:NO];
327-
XCTAssertFalse(IBGCrashReporting.enabled);
328-
}
329-
330314
/*
331315
+------------------------------------------------------------------------+
332316
| Log Module |
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#import <Foundation/Foundation.h>
2+
#import <React/RCTBridgeModule.h>
3+
#import <React/RCTEventEmitter.h>
4+
5+
@interface InstabugCrashReportingBridge : RCTEventEmitter <RCTBridgeModule>
6+
7+
- (void)setEnabled:(BOOL) isEnabled;
8+
- (void)sendJSCrash:(NSDictionary *)stackTrace;
9+
- (void)sendHandledJSCrash:(NSDictionary *)stackTrace;
10+
11+
@end

0 commit comments

Comments
 (0)