Skip to content

Commit cad58e1

Browse files
Aure77deecewanSalakar
authored
feat(crashlytics)!: upgrade to new Firebase Crashlytics SDK (#3580)
Goodbye Fabric, hello Firebase Crashlytics. BREAKING CHANGE: This is a breaking change to remove the use of the Fabric SDKs. Co-authored-by: David Buchan-Swanson <david.buchanswanson@gmail.com> Co-authored-by: Mike Diarmid <mike.diarmid@gmail.com> [publish]
1 parent c8f7c31 commit cad58e1

18 files changed

+175
-373
lines changed

docs/crashlytics/android-setup.md

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,23 @@ These steps are required, if you do not add these your app will most likely cras
1212
"The Crashlytics build ID is missing. This occurs when Crashlytics tooling is absent from your app's build configuration.
1313
Please review Crashlytics onboarding instructions and ensure you have a valid Crashlytics account."\_
1414

15-
## 1. Add the Fabric Maven repository
15+
## 1. Add the Google repository (if it's not there already)
1616

17-
Add the following line to the `android/build.gradle` file:
17+
Add the following line to the `android/build.gradle` file :
1818

1919
```groovy
2020
// ..
2121
buildscript {
2222
// ..
2323
repositories {
2424
// ..
25-
maven {
26-
url 'https://maven.fabric.io/public'
27-
}
25+
google()
2826
}
2927
// ..
3028
}
3129
```
3230

33-
## 2. Add the Fabric Tools Plugin dependency
31+
## 2. Add the Firebase Crashlytics Plugin dependency
3432

3533
Add the following dependency to the `android/build.gradle` file:
3634

@@ -40,19 +38,20 @@ buildscript {
4038
// ..
4139
dependencies {
4240
// ..
43-
classpath 'io.fabric.tools:gradle:1.28.1'
41+
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.0.0'
4442
}
4543
// ..
4644
}
4745
```
4846

49-
## 3. Apply the Fabric Tools Plugin to your app
47+
## 3. Apply the Firebase Crashlytics Plugin to your app
5048

51-
Apply the `io.fabric` plugin by adding the following to the top of your `android/app/build.gradle` file:
49+
Apply the `com.google.firebase.crashlytics` plugin by adding the following to the top of your `android/app/build.gradle` file:
5250

5351
```
54-
apply plugin: 'com.android.application' // apply after this line
55-
apply plugin: 'io.fabric'
52+
apply plugin: 'com.android.application'
53+
apply plugin: 'com.google.gms.google-services' // apply after this line
54+
apply plugin: 'com.google.firebase.crashlytics'
5655
// ..
5756
```
5857

@@ -61,11 +60,24 @@ apply plugin: 'io.fabric'
6160
Crashlytics NDK reporting allows you to capture Native Development Kit crashes, e.g. in React Native this will capture
6261
crashes originating from the Yoga layout engine.
6362

64-
Add the `crashlytics` block line to the `android/app/build.gradle` file:
63+
Add the `firebaseCrashlytics` block line to the `android/app/build.gradle` file:
6564

6665
```groovy
67-
crashlytics {
68-
enableNdk true
66+
android {
67+
// ...
68+
69+
buildTypes {
70+
release {
71+
/* Add the firebaseCrashlytics extension (by default,
72+
* it's disabled to improve build speeds) and set
73+
* nativeSymbolUploadEnabled to true. */
74+
75+
firebaseCrashlytics {
76+
nativeSymbolUploadEnabled true
77+
}
78+
// ...
79+
}
80+
}
6981
}
7082
```
7183

docs/crashlytics/ios-setup.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ add a 'New Run Script Phase':
1616
In the new build phase, add a new script into the text box:
1717

1818
```
19-
"${PODS_ROOT}/Fabric/run"
19+
"${PODS_ROOT}/FirebaseCrashlytics/run"
2020
```
2121

2222
![Script](https://prismic-io.s3.amazonaws.com/invertase%2Ff06cf5b3-884e-4cbc-8c3d-81072a254f1d_new+project+%281%29.png)

docs/index.md

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -192,13 +192,7 @@ project.ext {
192192
// Overriding Library SDK Versions
193193
firebase: [
194194
// Override Firebase SDK Version
195-
bom : "21.1.0",
196-
197-
// Override Crashlytics SDK Version
198-
crashlytics : "2.10.0",
199-
200-
// Override Crashlytics SDK Version
201-
crashlyticsNdk: "2.1.0"
195+
bom : "21.1.0"
202196
],
203197
],
204198
])
@@ -214,12 +208,6 @@ Open your projects `/ios/Podfile` and add any of the globals shown below to the
214208
```ruby
215209
# Override Firebase SDK Version
216210
$FirebaseSDKVersion = '6.13.0'
217-
218-
# Override Fabric SDK Version
219-
$FabricSDKVersion = '1.6.0'
220-
221-
# Override Crashlytics SDK Version
222-
$CrashlyticsSDKVersion = '3.1.0'
223211
```
224212

225213
Once changed, reinstall your projects pods via pod install and rebuild your project with `npx react-native run-ios`.

packages/app/ios_config.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ if [[ ${_SEARCH_RESULT} ]]; then
9999
if [[ $_CRASHLYTICS_AUTO_DISABLE_ENABLED == "true" ]]; then
100100
echo "Disabled Crashlytics auto disabler." # do nothing
101101
else
102-
_PLIST_ENTRY_KEYS+=("firebase_crashlytics_collection_enabled")
102+
_PLIST_ENTRY_KEYS+=("FirebaseCrashlyticsCollectionEnabled")
103103
_PLIST_ENTRY_TYPES+=("bool")
104104
_PLIST_ENTRY_VALUES+=("NO")
105105
fi

packages/crashlytics/RNFBCrashlytics.podspec

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,6 @@ if coreVersionDetected != coreVersionRequired
1414
Pod::UI.warn "NPM package '#{package['name']}' depends on '#{appPackage['name']}' v#{coreVersionRequired} but found v#{coreVersionDetected}, this might cause build issues or runtime crashes."
1515
end
1616

17-
# Fabric SDK Override
18-
fabric_sdk_version = '~> 1.10.2'
19-
20-
# Crashlytics SDK Override
21-
crashlytics_sdk_version = '~> 3.14.0'
22-
2317
Pod::Spec.new do |s|
2418
s.name = "RNFBCrashlytics"
2519
s.version = package["version"]
@@ -44,19 +38,9 @@ Pod::Spec.new do |s|
4438
firebase_sdk_version = $FirebaseSDKVersion
4539
end
4640

47-
if defined?($CrashlyticsSDKVersion)
48-
Pod::UI.puts "#{s.name}: Using user specified Crashlytics SDK version '#{$CrashlyticsSDKVersion}'"
49-
crashlytics_sdk_version = $CrashlyticsSDKVersion
50-
end
51-
52-
if defined?($FabricSDKVersion)
53-
Pod::UI.puts "#{s.name}: Using user specified Fabric SDK version '#{$FabricSDKVersion}'"
54-
fabric_sdk_version = $FabricSDKVersion
55-
end
56-
5741
# Firebase dependencies
58-
s.dependency 'Fabric', fabric_sdk_version
59-
s.dependency 'Crashlytics', crashlytics_sdk_version
42+
s.dependency 'Firebase/Core', firebase_sdk_version
43+
s.dependency 'Firebase/Crashlytics', firebase_sdk_version
6044

6145
if defined?($RNFirebaseAsStaticFramework)
6246
Pod::UI.puts "#{s.name}: Using overridden static_framework value of '#{$RNFirebaseAsStaticFramework}'"

packages/crashlytics/android/build.gradle

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,7 @@ project.ext {
5454
],
5555

5656
firebase: [
57-
crashlytics : "2.10.1",
58-
crashlyticsNdk: "2.1.1" // not in BoM
57+
bom: "25.3.0",
5958
],
6059
],
6160
])
@@ -82,10 +81,9 @@ repositories {
8281

8382
dependencies {
8483
api appProject
85-
// don't use firebase bom here as crashlytics-ndk is not included in the bom, trying to partially use bom here fails
86-
implementation "com.crashlytics.sdk.android:crashlytics:${ReactNative.ext.getVersion("firebase", "crashlytics")}"
87-
// ndk not in Firebase BoM
88-
implementation "com.crashlytics.sdk.android:crashlytics-ndk:${ReactNative.ext.getVersion("firebase", "crashlyticsNdk")}"
84+
implementation platform("com.google.firebase:firebase-bom:${ReactNative.ext.getVersion("firebase", "bom")}")
85+
implementation "com.google.firebase:firebase-crashlytics"
86+
implementation "com.google.firebase:firebase-crashlytics-ndk"
8987
}
9088

9189
ReactNative.shared.applyPackageVersion()

packages/crashlytics/android/src/main/java/io/invertase/firebase/crashlytics/ReactNativeFirebaseCrashlyticsInitProvider.java

Lines changed: 7 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,7 @@
1818
*/
1919

2020
import android.util.Log;
21-
import com.crashlytics.android.Crashlytics;
22-
import com.crashlytics.android.core.CrashlyticsCore;
23-
import com.crashlytics.android.ndk.CrashlyticsNdk;
24-
import io.fabric.sdk.android.Fabric;
21+
import com.google.firebase.crashlytics.FirebaseCrashlytics;
2522
import io.invertase.firebase.common.ReactNativeFirebaseInitProvider;
2623
import io.invertase.firebase.common.ReactNativeFirebaseJSON;
2724
import io.invertase.firebase.common.ReactNativeFirebaseMeta;
@@ -53,35 +50,12 @@ static boolean isCrashlyticsCollectionEnabled() {
5350
public boolean onCreate() {
5451
super.onCreate();
5552

56-
if (ReactNativeFirebaseCrashlyticsInitProvider.isCrashlyticsCollectionEnabled() && getContext() != null) {
57-
ReactNativeFirebaseJSON json = ReactNativeFirebaseJSON.getSharedInstance();
58-
boolean useNdk = json.getBooleanValue(KEY_CRASHLYTICS_NDK_ENABLED, true);
59-
boolean debug = json.getBooleanValue(KEY_CRASHLYTICS_DEBUG_ENABLED, false);
60-
61-
try {
62-
Fabric.Builder builder = new Fabric.Builder(getContext());
63-
64-
Crashlytics crashlyticsCore = new Crashlytics.Builder()
65-
.core(new CrashlyticsCore.Builder().disabled(!debug && BuildConfig.DEBUG).build())
66-
.build();
67-
68-
if (useNdk) {
69-
builder.kits(crashlyticsCore, new CrashlyticsNdk());
70-
} else {
71-
builder.kits(crashlyticsCore);
72-
}
73-
74-
builder.debuggable(debug);
75-
76-
Fabric.with(builder.build());
77-
78-
Log.i(TAG, "initialization successful");
79-
} catch (IllegalStateException exception) {
80-
Log.e(TAG, "initialization failed", exception);
81-
return false;
82-
}
83-
} else {
84-
Log.i(TAG, "auto collection disabled, skipping initialization");
53+
try {
54+
FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(ReactNativeFirebaseCrashlyticsInitProvider.isCrashlyticsCollectionEnabled());
55+
Log.i(TAG, "initialization successful");
56+
} catch (Exception exception) {
57+
Log.e(TAG, "initialization failed", exception);
58+
return false;
8559
}
8660

8761
return true;

packages/crashlytics/android/src/main/java/io/invertase/firebase/crashlytics/ReactNativeFirebaseCrashlyticsModule.java

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616
* limitations under the License.
1717
*
1818
*/
19+
20+
import android.os.Handler;
1921

20-
import com.crashlytics.android.Crashlytics;
21-
import com.crashlytics.android.core.CrashTest;
22-
import com.crashlytics.android.core.CrashlyticsCore;
22+
import com.google.firebase.crashlytics.FirebaseCrashlytics;
2323
import com.facebook.react.bridge.*;
2424
import io.invertase.firebase.common.ReactNativeFirebaseModule;
2525
import io.invertase.firebase.common.ReactNativeFirebasePreferences;
@@ -38,32 +38,36 @@ public class ReactNativeFirebaseCrashlyticsModule extends ReactNativeFirebaseMod
3838
@ReactMethod
3939
public void crash() {
4040
if (ReactNativeFirebaseCrashlyticsInitProvider.isCrashlyticsCollectionEnabled()) {
41-
Crashlytics.getInstance().core.log("Crash Test");
4241
// async task so as not to get caught by the React Native redbox handler in debug
43-
(new CrashTest()).crashAsyncTask(50);
42+
new Handler().postDelayed(new Runnable() {
43+
@Override
44+
public void run() {
45+
throw new RuntimeException("Crash Test");
46+
}
47+
}, 50);
4448
}
4549
}
4650

4751
@ReactMethod
4852
public void log(String message) {
4953
if (ReactNativeFirebaseCrashlyticsInitProvider.isCrashlyticsCollectionEnabled()) {
50-
Crashlytics.getInstance().core.log(message);
54+
FirebaseCrashlytics.getInstance().log(message);
5155
}
5256
}
5357

5458
// For internal use only.
5559
@ReactMethod
5660
public void logPromise(String message, Promise promise) {
5761
if (ReactNativeFirebaseCrashlyticsInitProvider.isCrashlyticsCollectionEnabled()) {
58-
Crashlytics.getInstance().core.log(message);
62+
FirebaseCrashlytics.getInstance().log(message);
5963
}
6064
promise.resolve(null);
6165
}
6266

6367
@ReactMethod
6468
public void setAttribute(String key, String value, Promise promise) {
6569
if (ReactNativeFirebaseCrashlyticsInitProvider.isCrashlyticsCollectionEnabled()) {
66-
Crashlytics.getInstance().core.setString(key, value);
70+
FirebaseCrashlytics.getInstance().setCustomKey(key, value);
6771
}
6872
promise.resolve(null);
6973
}
@@ -72,12 +76,12 @@ public void setAttribute(String key, String value, Promise promise) {
7276
public void setAttributes(ReadableMap keyValuesMap, Promise promise) {
7377
if (ReactNativeFirebaseCrashlyticsInitProvider.isCrashlyticsCollectionEnabled()) {
7478
ReadableMapKeySetIterator iterator = keyValuesMap.keySetIterator();
75-
CrashlyticsCore crashlyticsCore = Crashlytics.getInstance().core;
79+
FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
7680

7781
while (iterator.hasNextKey()) {
7882
String key = iterator.nextKey();
7983
String value = keyValuesMap.getString(key);
80-
crashlyticsCore.setString(key, value);
84+
crashlytics.setCustomKey(key, value);
8185
}
8286
}
8387

@@ -88,23 +92,7 @@ public void setAttributes(ReadableMap keyValuesMap, Promise promise) {
8892
@ReactMethod
8993
public void setUserId(String userId, Promise promise) {
9094
if (ReactNativeFirebaseCrashlyticsInitProvider.isCrashlyticsCollectionEnabled()) {
91-
Crashlytics.getInstance().core.setUserIdentifier(userId);
92-
}
93-
promise.resolve(null);
94-
}
95-
96-
@ReactMethod
97-
public void setUserName(String userName, Promise promise) {
98-
if (ReactNativeFirebaseCrashlyticsInitProvider.isCrashlyticsCollectionEnabled()) {
99-
Crashlytics.getInstance().core.setUserName(userName);
100-
}
101-
promise.resolve(null);
102-
}
103-
104-
@ReactMethod
105-
public void setUserEmail(String userEmail, Promise promise) {
106-
if (ReactNativeFirebaseCrashlyticsInitProvider.isCrashlyticsCollectionEnabled()) {
107-
Crashlytics.getInstance().core.setUserEmail(userEmail);
95+
FirebaseCrashlytics.getInstance().setUserId(userId);
10896
}
10997
promise.resolve(null);
11098
}
@@ -155,7 +143,7 @@ private void recordJavaScriptError(ReadableMap jsErrorMap) {
155143

156144
customException.setStackTrace(stackTraceElements);
157145

158-
Crashlytics.getInstance().core.logException(customException);
146+
FirebaseCrashlytics.getInstance().recordException(customException);
159147
}
160148

161149
@Override

packages/crashlytics/e2e/crashlytics.e2e.js

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -55,36 +55,6 @@ describe('crashlytics()', () => {
5555
});
5656
});
5757

58-
describe('setUserName()', () => {
59-
it('accepts string values', async () => {
60-
await firebase.crashlytics().setUserName('invertase');
61-
});
62-
63-
it('rejects none string values', async () => {
64-
try {
65-
await firebase.crashlytics().setUserName(666.1337);
66-
return Promise.reject(new Error('Did not throw.'));
67-
} catch (e) {
68-
e.message.should.containEql('must be a string');
69-
}
70-
});
71-
});
72-
73-
describe('setUserEmail()', () => {
74-
it('accepts string values', async () => {
75-
await firebase.crashlytics().setUserEmail('oss@invertase.io');
76-
});
77-
78-
it('rejects none string values', async () => {
79-
try {
80-
await firebase.crashlytics().setUserEmail(666.1337);
81-
return Promise.reject(new Error('Did not throw.'));
82-
} catch (e) {
83-
e.message.should.containEql('must be a string');
84-
}
85-
});
86-
});
87-
8858
describe('setAttribute()', () => {
8959
it('accepts string values', async () => {
9060
await firebase.crashlytics().setAttribute('invertase', '1337');

0 commit comments

Comments
 (0)