Crashlytics(Fabric)为应用程序变体(构建类型、产品口味)提供单独的组织。

32

这是我分享知识的自问自答问题。

我的项目有多个产品口味,我想使用不同的组织为每个产品口味集成Fabric。

我尝试使用Android Studio Fabric插件来集成Fabric。它会添加

<meta-data
    android:name="io.fabric.ApiKey"
    android:value="DEFAULT_ORGANIZATION_API_KEY" />
< p > main源集的AndroidManifest.xml条目。

我决定将这个条目重写到应用程序变体特定的源集中:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application>
        <meta-data
            android:name="io.fabric.ApiKey"
            android:value="SECOND_ORGANIZATION_API_KEY"
            tools:replace="android:value" />
    </application>
</manifest>

后来我发现 Fabric Gradle 插件会在构建过程中生成 crashlytics.properties 文件,并且该文件包含 Fabric API 密钥(也称为 build secret)。因此我应该将此文件包含在源代码控制中。但由于每个应用程序的 API 密钥都是唯一的,所以每次构建特定的应用程序变体时都会覆盖此文件。

我如何使用不同的组织为每个应用程序变体集成 Fabric 呢?

3个回答

27

在构建过程中,调用了fabricGenerateResources任务,并查找名为fabric.properties的文件,其内容如下:

apiSecret=YOUR_BUILD_SECRET
apiKey=YOUR_API_KEY

所以我们需要在此之前生成fabric.properties文件。

我发现了这个解决方案,并进行了轻微修改,以完全支持应用程序变体而不仅仅是构建类型。

将此代码添加到build.gradleandroid部分:

File crashlyticsProperties = new File("${project.projectDir.absolutePath}/fabric.properties")
applicationVariants.all { variant ->
    variant.productFlavors.each { flavor ->
        def variantSuffix = variant.name.capitalize()
        def generatePropertiesTask = task("fabricGenerateProperties${variantSuffix}") << {
            Properties properties = new Properties()
            properties.put("apiKey", flavor.fabricApiKey)
            properties.put("apiSecret", flavor.fabricApiSecret)
            properties.store(new FileWriter(crashlyticsProperties), "")
        }

        def generateResourcesTask = project.tasks.getByName("fabricGenerateResources${variantSuffix}")
        generateResourcesTask.dependsOn generatePropertiesTask
        generateResourcesTask.doLast {
            println "Removing fabric.properties"
            crashlyticsProperties.delete()
        }
    }
}

它遍历应用程序变体,并为每个应用程序变体创建生成fabric.properties文件的任务以及在Fabric Gradle插件生成应用程序资源后删除此文件的任务。

现在,您只需要定义特定于产品风格或构建类型的fabricApiKeyfabricApiSecret:

productFlavors {
    flavor1 {
        ext.fabricApiKey = "FLAVOR1_API_KEY"
        ext.fabricApiSecret = "FLAVOR1_API_SECRET"
    }
}

ext是由每个ExtensionAware对象提供的一个ExtraPropertiesExtention对象,它允许向现有对象添加新属性。在我的情况下,flavor1是一个ExtensionAware对象,可以使用ext.someProperty = "value"语法来扩展它,稍后这些属性可以作为flavor.someProperty,flavor.fabricApiKey使用。

此外,最好将fabric.properties包含在.gitignore中。

如果您在调试期间使用了ext.enableCrashlytics=false来禁用Crashlytics,请不要忘记从调试版本中删除它。相反,您可以在Application.onCreate中禁用它:

Fabric.with(this, new Crashlytics.Builder().core(
    new CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build()).build());

什么是ext对象? - You Qi
1
好的,我明白了。我需要从调试构建类型中删除 ext.enableCrashlytics = false 才能生成那个 gradle 任务。现在正在测试它。我有一个问题,就是 fabric.properties 中的 apiKey 是如何工作的?这是否替代了在 AndroidManifest.xml 中拥有它的必要性? - Jeff Lockhart
1
Gradle 抱怨没有 fabricGenerateResourcesDevelopmentDebug 任务.. 我该怎么办? - atlanteh
@atlanteh,你能否创建一个单独的问题,并附上你的 build.gradle 文件? - mixel
实际上我没有注意到@JeffLockhart已经在评论中发布了解决方案。 - atlanteh
显示剩余5条评论

8

如果您不反对使用应用程序ID后缀,那么您不需要单独的组织。崩溃和答案将被视为不同的应用程序。

例如,假设我的应用程序ID是io.example

在您的build.gradle中:

buildTypes {
  debug {
    applicationIdSuffix ".debug"
  }
  release {
    //options
  }
}

当您将调试版本部署到设备或模拟器上后,在 Fabric 网站上您将看到两个应用程序:

  • io.example
  • io.example.debug

这种方法的一个好处是您还可以单独跟踪其他构建类型,例如:io.exmaple.freeio.exmaple.paidio.example.enterprise等。


这个错误是“找不到与包名com.xxx.xxx.debug相匹配的客户端”。这个错误是由于“:app:processLiveGoogleServices”引起的。 - Cerlin
2
@CerlinBoss 这是一个不同的错误。您还没有为这个“新”应用程序设置Google APIs。.debug是一个新应用程序! - Radu
我认为问题是关于在不同的风味中使用不同的组织(即不同的API密钥)的时候。 - Muhammad Muzammil

0
一个更简单的解决方案,也适用于Gradle 5.x+,是为需要独特的Fabric API密钥和密钥的每个构建变体创建单独的fabric.properties文件。创建fabric.properties文件如下:
#Contains API Secret used to validate your application. Commit to internal source control; avoid making secret public.
apiSecret=YOUR_API_SECRET
apiKey=YOUR_API_KEY

YOUR_API_SECRET替换为构建变体的API密钥,将YOUR_API_KEY替换为构建变体的API密钥。

然后将每个变体的fabric.properties放置在项目的src/variant文件夹下,例如app/src/debugapp/src/release。有关更多详细信息,请参阅文档中的构建变体部分。

在构建时,将使用正在构建的变体的fabric.properties


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接