Firebase Crashlytics Sdk接入流程(Android)

Firebase Crashlytics Sdk接入流程

Firebase Crashlytics是收购了Fabric而来的,服务器也是Fabric的,所以虽然Firebase中很多功能在国内是不能用的,但是 Crashlytics 这个功能却是可以用的。 大家可以放心的使用Firebase来做Crash统计分析。

考拉刚刚把crash统计平台迁移到了firebase上,在此记录一下接入Firebase Crashlytics Sdk的流程,以供大家参考。

接入一个新的SDK,最重要的文档就是官方手册,Firebase Crashlytics的官方手册是这个Firebase Crashlytics 使用入门 | Firebase,一定要注意看的是Crashlytics的文档,而不是“Firebase 崩溃报告(Firebase Crash Reporting)”,后者是firebase已经不维护的产品。

步骤一 接入Firebase

Crashlytics作为Firebase的一部分,要使用Crashlytics必须先接入Firebase。

官方文档写明的步骤本文就不再重复了,这部分的官方文档链接如下,请点击链接阅读。
将 Firebase 添加到您的 Android 项目 | Firebase

可选择使用Firebase Assistant自动配置和手动接入Firebase两种方式,推荐先尝试Firebase 智能助理自动配置,如果不能自动配置成功,再尝试手动配置。

上面按照官方文档的操作的步骤中,如果使用Firebase Assistant 要注意一定不要选“Crash Reporting”,这是firebase已经废弃的服务,然而现在新的Crashlytics却不在Assistant列表内。这一步就选Analytics就好了,不用担心选了Analytics多了冗余的依赖,使用Firebase的任何服务都要先依赖Analytics,Analytics是必需的依赖。

另外即使使用了Firebase Assistant 也建议看一遍手动添加的步骤,然后检查一下Firebase 智能助理自动生成的代码是否与手动添加的代码一致,不能完全依赖工具。

这一步完成后,当前下项目的代码情况应该是这样的:

  • 工程级 build.gradle 文件
buildscript {
    // ...
    dependencies {
        // ...
        classpath 'com.google.gms:google-services:4.1.0' // google-services plugin
    }
}

allprojects {
    // ...
    repositories {
        // ...
        google() // Google's Maven repository
    }
}
  • application级 build.gradle文件(通常是 app/build.gradle)
apply plugin: 'com.android.application'

android {
  // ...
}

dependencies {
  // ...
  implementation 'com.google.firebase:firebase-core:16.0.4'

  // Getting a "Could not find" error? Make sure you have
  // added the Google maven respository to your root build.gradle
}

// ADD THIS AT THE BOTTOM
apply plugin: 'com.google.gms.google-services'
  • google-services.json文件一定要放在application级 build.gradle(通常是 app/build.gradle)同级目录下
.
├── app
│   ├── build.gradle
│   ├── google-services.json
│   └── src
├── build.gradle
├── gradle.properties
├── local.properties
└── settings.gradle

此时可以sync一遍gradle依赖,运行一下你的app,如果在应用启动时出现如下log
I/FirebaseInitProvider: FirebaseApp initialization successful
则表示,app正常接入了,接下来,就该接入Crashlytics了。

步骤二 Crashlytics SDK接入

如果你之前的项目使用的是Fabric Crashlytics,那你可以直接使用[Fabric迁移流程](https://fabric.io/firebase_migration)来快速迁移到Firebase Crashlytics。
否则,请继续看下面的步骤。

首先点击Firebase 控制台中的 Crashlytics按钮来开启Crashlytics服务。

  • 然后,在项目级 build.gradle 中,添加 Crashlytics 代码库和依赖项
buildscript {
    repositories {
        // ...

        // Add repository
        maven {
           url 'https://maven.fabric.io/public'
        }
    }
    dependencies {
        // ...

        // Check for v3.1.2 or higher
        classpath 'com.google.gms:google-services:4.1.0'

        // Add dependency
        classpath 'io.fabric.tools:gradle:1.26.1'
    }
}

allprojects {
    // ...
    repositories {
       // ...

       // Add repository
       maven {
           url 'https://maven.google.com/'
       }
    }
}

  • 在应用级 build.gradle 中,添加 Crashlytics 相关配置
apply plugin: 'com.android.application'
apply plugin: 'io.fabric'

dependencies {
    // ...

    // Check for v11.4.2 or higher
    implementation 'com.google.firebase:firebase-core:16.0.6'

    // Add dependency
    implementation 'com.crashlytics.sdk.android:crashlytics:2.9.8'
}

做完这一步后,就可以启动app并制造一个crash,到Firebase 控制台中的 Crashlytics页面查看是否有数据上报即可。Firebase的数据上报实时性很高,尤其是新建的项目,数据量很少,出现crash后几秒钟就能在Firebase Crashlytics的平台上看到了。

建议在debug模式下添加 ext.alwaysUpdateBuildId = false标志来阻止 Crashlytics 不断更新其构建 ID,优化日常开发的编译速度。

android {
  ...
  buildTypes {
    debug {
      ext.alwaysUpdateBuildId = false
    }
}

步骤三 (可选) Crashlytics SDK NDK Crash监控

Firebase Crashlytics的官方文档只列出来了Java代码的Crash监控使用方式,并没有提及NDK Crash的监控。
对于大部分Android开发者来说,NDK的Crash也确实没有监控的必要,但是考拉这边用了很多第三方so库,这些so库也是有必要监控起来的。
Firebase Crashlytics是由Firebase收购Fabric而来的项目,技术方案也几乎没有变化,所以可以用Fabric监控NDK Crash的使用方式使用Firebase Crashlytics。
Fabric NDK Crash Reporting

  • 在应用级 build.gradle 中,添加 Crashlytics NDK Crash Reporting 相关配置
apply plugin: 'com.android.application'
apply plugin: 'io.fabric'

// set NDK Crash Reporting enable
crashlytics {
    enableNdk true
}

dependencies {
    // ...
    implementation 'com.google.firebase:firebase-core:16.0.6'

    implementation 'com.crashlytics.sdk.android:crashlytics:2.9.8'
    // Add ndk dependency
    implementation 'com.crashlytics.sdk.android:crashlytics-ndk:2.0.5'
}

在manifest中声明Crashlytics手动初始化

		
        

根据自身app启动流程,选择合适时机手动初始化Crashlytics

   Fabric.with(context, new Crashlytics(), new CrashlyticsNdk());

如果是本地源码编译的so而不是直接使用第三方提供的so,可以生成并上传符号表来辅助分析crash信息,执行 ./gradlew crashlyticsUploadSymbolsRelease即可上传符号表。

以上,就完成了Crashlytics SDK NDK Crash监控的配置,可以手动引发一个Ndk Crash来测试,到统计平台上看是否有对于的Crash。

打包NDK代码引发native crash比较麻烦,在此提供一个从java代码引发NDK Crash的方式:

 public void crashNatively() {
        try {
            Class.forName("dalvik.system.VMDebug").getMethod("crash").invoke(null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

步骤四 添加辅助数据帮助分析

通过以上步骤的配置,现在Firebase Crashlytics已经可以正常工作了。并且还附带了发生Crash的时间,机型,系统版本,应用版本等信息以供分析。
Firebase Crashlytics Sdk接入流程(Android)_第1张图片
然而实际使用过程中,我们都期望能得到更详细的用户信息,这时可以自定义添加更多数据,下面是一些考拉中添加的一些常用信息。

//用户id
Crashlytics.setUserIdentifier(builder.getUserId());
//用户渠道
Crashlytics.setString("Channel", builder.getChannelInfo());
//用户补丁版本
Crashlytics.setString("Version", builder.getUserTag());
//用户当前WebView UA
Crashlytics.setString("WebView UA", WebViewSettings.getUserAgent());
//打包机名称
Crashlytics.setString("BuildHost", BuildInfo.BUILD_HOST);
//打包时间
Crashlytics.setString("BuildTime", BuildInfo.BUILD_TIME);
//最新提交commit id
Crashlytics.setString("GitLog", BuildInfo.BUILD_GIT_LOG);         

这些自定义的数据可以在,Firebase Crashlytics的“键”选项卡下面看到。
Firebase Crashlytics Sdk接入流程(Android)_第2张图片
通过setUserIdentifier所设置的用户Id还可以用于搜索。
Firebase Crashlytics Sdk接入流程(Android)_第3张图片
还可以通过Crashlytics.log方法,打入自定义日志用于分析。
Firebase Crashlytics Sdk接入流程(Android)_第4张图片

开发过程中,还会遇到通过try catch捕获了异常,不造成崩溃,但是又希望能够统计上报该异常的情况。这个时候,可以使用Crashlytics.logException(throwable)方法将异常统计上来。
在Firebase的过滤条件中选择,不严重的事件类型,即可过滤该异常。

Firebase Crashlytics Sdk接入流程(Android)_第5张图片

步骤五 修改ProGuard混淆规则

参考官方文档 获取经过反混淆处理的崩溃报告 配置即可。

-keepattributes *Annotation*
-keepattributes SourceFile,LineNumberTable
-keep public class * extends java.lang.Exception
-keep class com.crashlytics.** { *; }
-dontwarn com.crashlytics.**

// 删除-printmapping mapping.txt 这一行
// -printmapping mapping.txt

步骤六(可选) oppo部分机型谷歌服务框架弹框优化

做完以上所有步骤,基本就可以上线了。但是实际使用中发现,有用户反馈在oppo手机上会提示需要先下载谷歌服务框架才能运行。按照oppo手机的提示操作,下载好谷歌服务框架就能正常使用。
这个现象有些影响用户体验,虽然实际出现这个现象的手机是极少数(找了很多天,才在一台旧版的oppo A53m上复现了这个问题,怀疑是oppo旧版系统并且很久没有更新过才会出现),但是秉着提升用户体验的角度,还是专门做了优化。

这个弹框是这样的。

一般这种问题,只要在这种手机上,关掉crash分析即可。
然而在出现这个弹框后,app无法得到任何通知,就直接被oppo系统杀掉了,并且也找不到可靠的途径来判断是否会弹这个框。
经过一番debug加测试,基本确定,是有Activity变化的时候,会触发Firebase的统计上报功能,这时会触发com.google.android.gms.measurement.AppMeasurementReceiver这个Receiver,然后触发com.google.android.gms.measurement.AppMeasurementService这个service,然后调用gms上传数据到服务器。国内手机一般都没有gms框架,正常情况下这里发现没有gms的时候,就会走Firebase SDK内置的应用内上传逻辑。但是oppo手机比较奇怪,它应该是内置了gms上传事件的接收器,然而这个接收器的作用,不是上传数据,而是把app进程杀死,然后弹个窗(我也是醉了)。

看起来app是无法对这个现象做任何处理了,即使是通过机型来做黑名单,都不能很好的判断,毕竟即使是同一个机型,也仅有极少数会出现这个弹框,存在很大的误伤概率。
这种情况下,只剩下了一种办法,先让这个现象出现,然后下次启动时再通过上次是否出现了这个现象,来规避问题。虽然会至少出现一次不友好现象,但至少比用户一直不下载谷歌服务框架就一直出现弹窗要好一些。
Firebase Crashlytics Sdk接入流程(Android)_第6张图片
新建了一个Int类型SharePreference值,默认是0,当app第一次启动的时候,设为-1,MainActivity启动成功后,设为1。
这样,下次启动时,如果发现没有这个SharePreference值为-1,则表示上次没有成功启动,就关闭Firebase。
这里的关闭还有些特殊,直接不初始化Firebase的话,会完全失去Crash监控效果,我们只把AppMeasurementReceiver这个Receiver diasble,这样只是失去了用户信息上报,少了些log和轻微影响数据百分比准确度,不影响正常crash上报功能,最大程度保留了功能完整性。

int activityInitSuccessFlag = PreferencesUtils.getInt(CrashCollector.ACTIVITY_INIT_SUCCESS_FLAG, 0);
                        if (activityInitSuccessFlag == 0) {
                            PreferencesUtils.saveInt(CrashCollector.ACTIVITY_INIT_SUCCESS_FLAG, -1);
                            CrashCollector.setGmsReceiverEnable(getApplication(), true);
                        } else if (activityInitSuccessFlag == 1) {
                            CrashCollector.setGmsReceiverEnable(getApplication(), true);
                        } else if (activityInitSuccessFlag == -1) {
                            CrashCollector.setGmsReceiverEnable(getApplication(), false);
                        }
    private void MainActivityInitSuccess() {
        if (CrashCollector.sGmsReceiverEnableEnable) {
            PreferencesUtils.saveInt(CrashCollector.ACTIVITY_INIT_SUCCESS_FLAG, 1);
        }
    }
    public static void setGmsReceiverEnable(Context context, boolean enable) {
        sGmsReceiverEnableEnable = enable;
        PackageManager pm = context.getApplicationContext().getPackageManager();
        ComponentName componentName = new ComponentName(context.getPackageName(),
                "com.google.android.gms.measurement.AppMeasurementReceiver");
        int state = enable ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
                : PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
        pm.setComponentEnabledSetting(componentName, state, PackageManager.DONT_KILL_APP);
    }

以上,就是全部Firebase Crashlytics的接入步骤,以供参考。

引用:

  1. Firebase Crashlytics 使用入门 | Firebase
  2. 将 Firebase 添加到您的 Android 项目 | Firebase
  3. Fabric NDK Crash Reporting
  4. 获取经过反混淆处理的崩溃报告

你可能感兴趣的:(Android,技术)