7

我们有几个 Firebase 项目,它们通过构建类型和风格共享相同的代码库。我们的目标是通过 Gradle 使用应用程序分发并使用服务帐户凭据进行身份验证。

docs中,显示了firebaseAppDistributionblock 可用于配置参数,服务凭证文件路径就是其中之一。由于每个变体都是一个 Firebase 项目,并且每个项目都有自己的服务凭证,据我所知,我们需要在 Gradle 配置中指向单独的服务凭证文件路径。

我尝试根据变体使用 gradle 任务更新文件路径,但无法使其正常工作。当前的构建文件如下所示:

...

apply plugin: 'com.google.firebase.appdistribution'

class StringExtension {
  String value

  StringExtension(String value) {
    this.value = value
  }

  public void setValue(String value) {
    this.value = value
  }

  public String getValue() {
    return value
  }
}

android {

  ...

  productFlavors.whenObjectAdded {
    flavor -> flavor.extensions.create("service_key_prefix", StringExtension, '')
  }

  productFlavors {

    flavor1 {
      ...
      service_key_prefix.value = "flavor1"
    }

    flavor2 {
      ...
      service_key_prefix.value = "flavor2"
    }
  }

  buildTypes {

    debug {
      firebaseAppDistribution {
        releaseNotesFile = file("internal_release_notes.txt").path
        groupsFile = file("group_aliases_debug_fb.txt").path
      }
    }

    release {
      firebaseAppDistribution {
        releaseNotesFile = file("release_notes.txt").path
        groupsFile = file("group_aliases_prod_fb.txt").path
      }
    }
  }
}

...

android.applicationVariants.all { variant ->

  task("firebaseCredentials${variant.name.capitalize()}", overwrite: true) {
    variant.productFlavors.each { flavor ->

      doLast {
        firebaseAppDistribution {

          def serviceKeyFile = file(
              "../${flavor.service_key_prefix.value}-${variant.buildType.name}-service-key.json")
          if (serviceKeyFile != null) {
            serviceCredentialsFile = serviceKeyFile.path
          }
        }
      }
    }
  }
}

android.applicationVariants.all { variant ->
  def distTask = tasks.named("appDistributionUpload${variant.name.capitalize()}")
  def configTask = tasks.named("firebaseCredentials${variant.name.capitalize()}")
  distTask.configure {
    dependsOn(configTask)
  }
}

apply plugin: 'com.google.gms.google-services'

任务似乎运行正确,但我猜文件路径没有更新,因为它在我运行时仍然给出以下错误appDistributionUpload

找不到凭据。要进行身份验证,您有几个选项:

  1. serviceCredentialsFile在你的 gradle 插件中设置属性

  2. 使用 FIREBASE_TOKEN 环境变量设置刷新令牌

  3. 使用 Firebase CLI 登录

  4. 使用 GOOGLE_APPLICATION_CREDENTIALS 环境变量设置服务凭据

关于如何实现这种分布配置的任何想法?

4

2 回答 2

4

在与支持团队联系后,我了解到此配置尚未开箱即用,并且截至目前作为功能请求存在。

这是 Firebase 支持团队的解决方法,它在每个上传任务开始时修改内存中的相关环境变量:

android {

  applicationVariants.all { variant ->

    final uploadTaskName = "appDistributionUpload${variant.name.capitalize()}"
    final uploadTask = project.tasks.findByName(uploadTaskName)

    if (uploadTask != null) {
      uploadTask.doFirst {
        resetCredentialsCache()
        final value = "$projectDir/src/${variant.name}/app-distribution-key.json"
        setEnvInMemory('GOOGLE_APPLICATION_CREDENTIALS', value)
      }
    }
  }
}

private static void setEnvInMemory(String name, String val) {
  // There is no way to dynamically set environment params, but we can update it in memory
  final env = System.getenv()
  final field = env.getClass().getDeclaredField("m")
  field.setAccessible(true)
  field.get(env).put(name, val)
}

private static void resetCredentialsCache() {
  // Google caches credentials provided by environment param, we are going to reset it
  final providerClass = Class.forName(
      'com.google.firebase.appdistribution.buildtools.reloc.com.google.api.client.googleapis.auth.oauth2.DefaultCredentialProvider')
  final providerCtor = providerClass.getDeclaredConstructor()
  providerCtor.setAccessible(true)
  final provider = providerCtor.newInstance()

  final credsClass = Class.forName(
      'com.google.firebase.appdistribution.buildtools.reloc.com.google.api.client.googleapis.auth.oauth2.GoogleCredential')
  final field = credsClass.getDeclaredField('defaultCredentialProvider')
  field.setAccessible(true)
  field.set(null, provider)
}

编辑:上述解决方案仅适用于应用分发插件版本 1.3.1。

我没有进一步联系支持并GOOGLE_APPLICATION_CREDENTIALS在 Jenkins CI 上使用了环境变量,如此处所述

于 2020-02-18T19:18:59.923 回答
0

真的需要为每个 Variant 定义不同的 serivceAccount 文件吗?还是为每个风味/构建类型拥有单独的文件就足够了?

因为通过buildTypeproductFlavors访问时是只读的android.applicationVariants,这将在评估阶段之后执行。但是您可以在 gradle 的配置阶段直接设置 BuildType 或 Flavor 的值。

目前这是我让它为我工作的唯一方法。

构建类型:

android.buildTypes.all{
    File serviceAccountFile = file("/path/to/file-${it.name}.json")
    if (serviceAccountFile.exists()) {
        it.firebaseAppDistribution {
            serviceCredentialsFile = serviceAccountFile.path
        }
    }
}

口味:

android.productFlavors.all{
    File serviceAccountFile = file("/path/to/file-${it.name}.json")
    if (serviceAccountFile.exists()) {
        it.firebaseAppDistribution {
            serviceCredentialsFile = serviceAccountFile.path
        }
    }
}
于 2020-01-24T07:47:22.937 回答