海外App 崩溃率监控 之 FireBase 接入

背景: 海外 App 需要接入 FireBase SDK, 用来 监控崩溃率,需要上架 谷歌商店,所以只考虑了 谷歌自家的。

根据 FireBase 后台教程 大概就是三步走:

第 1 步:将 Firebase Crashlytics SDK 添加到您的应用

dependencies {
    // Import the BoM for the Firebase platform
    implementation platform('com.google.firebase:firebase-bom:30.3.1')

    // Declare the dependencies for the Crashlytics and Analytics libraries
    // When using the BoM, you don't specify versions in Firebase library dependencies
    implementation 'com.google.firebase:firebase-crashlytics'
    implementation 'com.google.firebase:firebase-analytics'
}

第 2 步:将 Firebase Crashlytics 插件添加到您的应用

在项目级 build.gradle 文件中,将 Crashlytics Gradle 插件作为 buildscript 依赖项添加。
buildscript {
    repositories {
        // Check that you have Google's Maven repository (if not, add it).
        google()
    }

    dependencies {
        // ...

        // Check that you have the Google services Gradle plugin v4.3.2 or later
        // (if not, add it).
        classpath 'com.google.gms:google-services:4.3.13'

        // Add the Crashlytics Gradle plugin
        classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.1'
    }
}

allprojects {
    repositories {
        // Check that you have Google's Maven repository (if not, add it).
        google()
    }
}
在应用级 build.gradle 文件中,应用 Crashlytics Gradle 插件:

apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services' // Google services Gradle plugin

// Apply the Crashlytics Gradle plugin
apply plugin: 'com.google.firebase.crashlytics'

第 3 步:强制造成一次测试崩溃以完成设置

Button crashButton = new Button(this);
crashButton.setText("Test Crash");
crashButton.setOnClickListener(new View.OnClickListener() {
   public void onClick(View view) {
       throw new RuntimeException("Test Crash"); // Force a crash
   }
});

addContentView(crashButton, new ViewGroup.LayoutParams(
       ViewGroup.LayoutParams.MATCH_PARENT,
       ViewGroup.LayoutParams.WRAP_CONTENT));

 

解决问题过程记录,以及总结

1、由于 原来使用 google serviece API, 直接导入了 implementation 'com.google.android.gms:play-services:12.0.1' 这个版本是 比较老的,现在需要使用 更新版本的 

//    implementation 'com.google.firebase:firebase-crashlytics:18.2.12'
//    implementation 'com.google.firebase:firebase-analytics:21.1.0'

然而这个版本又太新了, 我们的原有的部分 sdk 升级兼容成本太高,又需要 将 crashlytics 和 analytics 进行版本降级。最终 妥协到了 

    implementation 'com.google.firebase:firebase-crashlytics:17.2.2' 
    implementation 'com.google.firebase:firebase-analytics:16.0.5'

这个版本。

这里有一个 关于如何确定 版本号的问题,Google 推荐使用  Firebase Android BoM  来确定具体使用哪个版本,但是默认他都会使用最新版本,最新版本 对其他引用 升级造成较大的升级成本,所以我们通过自己指定版本来使用。

不过 具体指定哪个版本我们仍然可以通过 BoM 来比较 各个版本之间的区别。

在这里:https://firebase.google.com/docs/android/learn-more

从而确定  使用哪个版本,我这里就是通过这个确定。 这样可以避免很多  版本兼容性问题。

 

20220921 更新:

以上 通过 demo 中 能够获取 Java 层的崩溃以及堆栈,但是添加后  implementation 'com.google.firebase:firebase-crashlytics-ndk:17.2.2'  依然无法获取 C++ 层的 崩溃,找了很多原因以后,才发现,很可能还是这个版本适配的的问题

最终还是通过 bom 来管理,这也是反反复复 查看 google 文档后才找到问题。  google 强烈 推荐 使用 bom 来管理 FireBase 相关组件之间的版本  是有道理的!

最终版本定为:

    implementation platform('com.google.firebase:firebase-bom:26.0.0')
    implementation 'com.google.firebase:firebase-analytics'
    implementation 'com.google.firebase:firebase-crashlytics'
    implementation 'com.google.firebase:firebase-crashlytics-ndk'
    implementation 'com.google.android.gms:play-services-base:17.6.0'

通过bom,各组件实际的版本是:

后台是能够捕获堆栈的。

 

其他问题:

google service 只使用了    implementation 'com.google.android.gms:play-services-ads:15.0.1'  这个组件,我们就可以移除     // implementation 'com.google.android.gms:play-services:12.0.1'  这个 萝卜白菜一箩筐的 大包。

在 我们当前选择的 crashlytics 和 analytics 版本中,已经包含了  okhttp 等模块,我们又需要移除 目前项目gradle配置中的

//    implementation files('libs/okhttp-3.4.1.jar')
//    implementation files('libs/okio-1.8.0.jar')

这两个库,需要将libs 文件夹下的 这两个库文件删除。(否则会报库文件冗余的错)总的操作下来,包体减小了大约 5M。 

 

20220922 更新:

Android Gradle Plugin: 3.3.1
Gradle Version5.6.4
    
classpath 'com.google.gms:google-services:4.2.0'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.1'
    
* What went wrong:
A problem was found with the configuration of task ':CoinGames:uploadCrashlyticsSymbolFileLekaRelease'.
> Directory 'xxxxx\proj.android-studio\app\build\generated\res\google-services\lekaRelease' specified for property 'googleServicesResourceRoot' does not exist.

在 GitHub 上查找到的解决方案 是 升级  Android Gradle Plugin 到 4.0.1, 对应 Gradle Version 升级到 6.1.1

确实这个问题解决了,但是  升级过程 巨蛋疼无比,要改的东西太多了,无奈又退回来。

后面根据以上路径 'xxxxx\proj.android-studio\app\build\generated\res\google-services\lekaRelease' 这个路径进去找了一下,

发现  我本地是存在 'xxxx\app\build\generated\res\google-services\leka\release' 这个路径的,经过 Gradle 升级这一趟,发现  Gradle 的 改动 就有 把  {buildType}/{productFlavor} 变成  {buildType}{productFlavor} 这一个改动

所以我 果断把  'xxxx\app\build\generated\res\google-services\leka\release'  这个路径 改成   'xxxxx\proj.android-studio\app\build\generated\res\google-services\lekaRelease' ,并且把里面对应内容拷贝进去

重新执行,需要将要以下命令中的项目名称换成你当前的项目

.\gradlew app:assemblelekaRelease app:uploadCrashlyticsSymbolFilelekaRelease

上面 的错误解决了。 (后来,当我把以上配置中 classpath 'com.google.gms:google-services:4.3.13' 修改以后)以上错误直接消失了

 

出现了新问题, 以下

com.google.firebase.crashlytics.buildtools.reloc.org.apache.http.conn.HttpHostConnectException: 
Connect to firebasecrashlyticssymbols.googleapis.com:443 [firebasecrashlyticssymbols.googleapis.com/172.217.160.106] failed:
Connection timed out: connect

这个就很明显了, 上传 符号失败,需要 FQ。   FQ后,  填入你的FQ Proxy  ip 及端口,可以  打开 ie => 工具 => internet选项 => 连接 => 局域网设置 => 代理服务器 查看 ip 以及 port

在gradlew 的 gradle.properties 文件中添加

systemProp.http.proxyHost=proxy.com
systemProp.http.proxyPort=80
systemProp.https.proxyHost=proxy.com
systemProp.https.proxyPort=80

然后重新执行就成功了。

搞这个 ndk 符号上传过程中遇到的 其他问题解决:

1、 后台看不到上报,连接手机打开调试日志发现以下报错
FirebaseCrashlytics: Settings request failed.
FirebaseCrashlytics: javax.net.ssl.SSLHandshakeException: Chain validation failed

看上去证书过期。实际上 是由于 手机的时间调整问题导致的。
https://github.com/square/okhttp/issues/3180

We see this issue on Android 7.0 with the latest version 3.8.1.
It happens only in the first time when we try to make a https post request after device bootups.
After that, it just works fine.
自动获取网络时间,问题解决。

2FirebaseCrashlytics: Could not generate ID for file /memfd:jit-zygote-cache (deleted)
FirebaseCrashlytics: java.io.FileNotFoundException: /memfd:jit-zygote-cache (deleted): open failed: ENOENT (No such file or directory)

升级  FireBase Crashlytics 17.3.0 解决,也就是 FireBase-bom 升级到 com.google.firebase:firebase-bom:26.1.1,即可解决

3* What went wrong:
Execution failed for task ':CoinGames:uploadCrashlyticsSymbolFileLekaRelease'.
> java.io.IOException: Could not find valid module record for Breakpad file: xxxx\proj.android-studio\app\build\crashlytics\leka\release\nativeSymbols\cocos2dlua-arm-2506246354190b0b5dcb61a9a34b00723746d0e1.gz Clean your build directory and try again. Contact Firebase support if the problem persists.


进入此目录, 删除这个文件,重新执行就好了。如果删不掉 那么就 任务管理器 => kill Java 进程,然后重新执行就好了

 

在 gradle.properties 文件中,添加

android.useAndroidX=true
android.enableJetifier=true

来避免版本兼容的一些问题,比如:

java.lang.RuntimeException: java.lang.RuntimeException: com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives: 
Learn how to resolve the issue at https://developer.android.com/studio/build/dependencies#duplicate_classes.
Program type already present: android.support.v4.app.INotificationSideChannel
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)

 

Android X 是用来 优化统一 各种 android support 库的。
为了解决 support 上面的问题,在 2018 Google I/O 大会上推出了 AndroidX 来替换了 Android Support Library  。在 Android 9.0 (API级别 28) 正式发布后,新版本的支持库 AndroidX 就诞生了。它属于 Jetpack,除了现有的支持库以外,AndroidX 库还包含了最新的 JetPack 组件,在 Api27及更早版本,依然可以使用 Support Library 但是之后新开发的所有库都将在 AndroidX 库中进行了。
因此 AndroidX 库是 Support Library 库的替换,在 API 28 及以后就要使用 AndroidX 库来彻底替换 Support Library 库了。

android.useAndroidX:设置true为时,此标志表示您要从现在开始使用AndroidX。如果该标志不存在,则Android Studio的行为就像标志设置为一样false。
android.enableJetifier:设置true为时,此标志表示您希望获得工具支持(来自Android Gradle插件)以自动转换现有的第三方库,就像它们是为AndroidX编写的一样。如果该标志不存在,则Android Studio的行为就像标志设置为一样false。

android.enableR8=true
Android Studio 稳定版 3.3版本更新,带来的新特性之一是新一代的代码压缩工具 R8
传统的 Java 编译器将源代码编译为 Java 字节码(.class)。 ProGuard 可以选择优化此代码,从而生成更小,更快的 Java 字节码。 dx 编译器最终可以将此 Java 字节码转换为 Dalvik 字节码(.dex)。 Dalvik 字节码打包在 apk 文件中,最终安装在设备上。 根据 Android 的版本,字节码被及时(Dalvik VM),提前(ART)或两者的组合(Android P)解释、编译。 

D8 已经产生比 dx 更好的字节码,具有更少的指令和更好的寄存器分配。
R8 是 D8 的衍生产品,旨在集成 ProGuard 和 D8 的功能:
R8 和当前的代码缩减解决方案 Proguard 相比,R8 可以更快地缩减代码,同时改善输出大小。
R8 可以 更好的 压缩混淆 java 代码

 

参考:

作者:Yun丶Lei
链接:https://www.jianshu.com/p/14ff3c6fe0cb
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

作者:JasonWuuu
链接:https://juejin.cn/post/6844903773144350734
来源:稀土掘金

作者:sydMobile
链接:https://juejin.cn/post/6850037267760611336
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

posted @   lesten  阅读(2086)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 一文读懂知识蒸馏
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示