获取我们在 Firebase 峰会上发布的所有信息,了解 Firebase 可如何帮助您加快应用开发速度并满怀信心地运行应用。了解详情

以编程方式修改远程配置

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

本文档描述了如何以编程方式读取和修改一组 JSON 格式的参数和条件,称为远程配置模板。这允许您在客户端应用程序可以使用客户端库获取的后端进行模板更改。

使用本指南中描述的Remote Config REST APIAdmin SDK ,您可以绕过在 Firebase 控制台中管理模板,将远程配置更改直接集成到您自己的流程中。例如,使用远程配置后端 API,您可以:

  • 安排远程配置更新。通过将 API 调用与 cron 作业结合使用,您可以定期更改远程配置值。
  • 批量导入配置值,以便有效地从您自己的专有系统过渡到 Firebase 远程配置。
  • 将 Remote Config 与 Cloud Functions for Firebase 结合使用,根据服务器端发生的事件更改应用中的值。例如,您可以使用远程配置来推广应用中的新功能,然后在检测到足够多的人与新功能进行交互后自动关闭该推广。

    显示远程配置后端与自定义工具和服务器交互的图表

本指南的以下部分描述了您可以使用远程配置后端 API 执行的操作。要查看通过 REST API 执行这些任务的一些代码,请参阅以下示例应用程序之一:

使用 Firebase Admin SDK 修改远程配置

Admin SDK 是一组服务器库,可让您在特权环境中与 Firebase 交互。除了对远程配置执行更新之外,Admin SDK 还支持生成和验证 Firebase 身份验证令牌、从实时数据库读取和写入等等。要详细了解 Admin SDK 先决条件和设置,请参阅将 Firebase Admin SDK 添加到您的服务器

在典型的远程配置流程中,您可能会获取当前模板,修改一些参数或参数组和条件,验证模板,然后发布它。在进行这些 API 调用之前,您必须授权来自 SDK 的请求。

初始化 SDK 并授权 API 请求

当您在没有参数的情况下初始化 Admin SDK 时,SDK 使用Google 应用程序默认凭据并从FIREBASE_CONFIG环境变量中读取选项。如果FIREBASE_CONFIG变量的内容以{开头,它将被解析为 JSON 对象。否则,SDK 假定该字符串是包含选项的 JSON 文件的名称。

例如:

节点.js

const admin = require('firebase-admin');
admin.initializeApp();

爪哇

FileInputStream serviceAccount = new FileInputStream("service-account.json");
FirebaseOptions options = FirebaseOptions.builder()
        .setCredentials(GoogleCredentials.fromStream(serviceAccount))
        .build();
FirebaseApp.initializeApp(options);

获取当前的远程配置模板

使用远程配置模板时,请记住它们是版本化的,并且每个版本从创建时间到您用更新替换它的时间都有一个有限的生命周期:90 天,总共限制 300 个存储版本。有关详细信息,请参阅模板和版本控制

您可以使用后端 API 以 JSON 格式获取远程配置模板的当前活动版本。

在 A/B 测试实验中专门作为变体创建的参数和参数值不包含在导出的模板中。

获取模板:

节点.js

function getTemplate() {
  var config = admin.remoteConfig();
  config.getTemplate()
      .then(function (template) {
        console.log('ETag from server: ' + template.etag);
        var templateStr = JSON.stringify(template);
        fs.writeFileSync('config.json', templateStr);
      })
      .catch(function (err) {
        console.error('Unable to get template');
        console.error(err);
      });
}

爪哇

Template template = FirebaseRemoteConfig.getInstance().getTemplateAsync().get();
// See the ETag of the fetched template.
System.out.println("ETag from server: " + template.getETag());

修改远程配置参数

您可以通过编程方式修改和添加远程配置参数和参数组。例如,对于名为“new_menu”的现有参数组,您可以添加一个参数来控制季节性信息的显示:

节点.js

function addParameterToGroup(template) {
  template.parameterGroups['new_menu'].parameters['spring_season'] = {
    defaultValue: {
      useInAppDefault: true
    },
    description: 'spring season menu visibility.',
  };
}

爪哇

template.getParameterGroups().get("new_menu").getParameters()
        .put("spring_season", new Parameter()
                .setDefaultValue(ParameterValue.inAppDefault())
                .setDescription("spring season menu visibility.")
        );

API 允许您创建新参数和参数组,或修改默认值、条件值和描述。在所有情况下,您都必须在进行修改后显式发布模板。

修改远程配置条件

您可以以编程方式修改和添加远程配置条件和条件值。例如,要添加一个新条件:

节点.js

function addNewCondition(template) {
  template.conditions.push({
    name: 'android_en',
    expression: 'device.os == \'android\' && device.country in [\'us\', \'uk\']',
    tagColor: 'BLUE',
  });
}

爪哇

template.getConditions().add(new Condition("android_en",
        "device.os == 'android' && device.country in ['us', 'uk']", TagColor.BLUE));

在所有情况下,您都必须在进行修改后显式发布模板。

远程配置后端 API 提供了几个条件和比较运算符,您可以使用它们来更改应用程序的行为和外观。要了解有关条件和这些条件支持的运算符的更多信息,请参阅条件表达式参考

验证远程配置模板

或者,您可以在发布更新之前对其进行验证,如下所示:

节点.js

function validateTemplate(template) {
  admin.remoteConfig().validateTemplate(template)
      .then(function (validatedTemplate) {
        // The template is valid and safe to use.
        console.log('Template was valid and safe to use');
      })
      .catch(function (err) {
        console.error('Template is invalid and cannot be published');
        console.error(err);
      });
}

爪哇

try {
  Template validatedTemplate = FirebaseRemoteConfig.getInstance()
          .validateTemplateAsync(template).get();
  System.out.println("Template was valid and safe to use");
} catch (ExecutionException e) {
  if (e.getCause() instanceof FirebaseRemoteConfigException) {
    FirebaseRemoteConfigException rcError = (FirebaseRemoteConfigException) e.getCause();
    System.out.println("Template is invalid and cannot be published");
    System.out.println(rcError.getMessage());
  }
}

此验证过程检查错误,例如参数和条件的重复键、无效的条件名称或不存在的条件或格式错误的 etag。例如,包含超过允许的键数(2000)的请求将返回错误消息, Param count too large

发布远程配置模板

检索模板并使用所需的更新对其进行修改后,您可以发布它。按照本节中的说明发布模板会将整个现有配置模板替换为更新的文件,并且为新的活动模板分配比它替换的模板大一号的版本号。

如有必要,您可以使用 REST API回滚到以前的版本。为了降低更新中出错的风险,您可以在发布前进行验证

远程配置个性化和条件包含在下载的模板中,因此在尝试发布到其他项目时,请务必注意以下限制:

  • 个性化不能从一个项目导入到另一个项目。

    例如,如果您在项目中启用了个性化并下载和编辑模板,则可以将其发布到同一个项目,但不能将其发布到不同的项目,除非您从模板中删除个性化。

  • 条件可以从一个项目导入到另一个项目,但请注意,任何特定的条件值(如应用 ID 或受众)在发布之前都应该存在于目标项目中。

    例如,如果您有一个 Remote Config 参数,该参数使用指定iOS平台值的条件,则可以将模板发布到另一个项目,因为任何项目的平台值都是相同的。但是,如果它包含依赖于特定应用 ID 或目标项目中不存在的用户受众的条件,则验证将失败。

  • 如果您计划发布的模板包含依赖 Google Analytics 的条件,则必须在目标项目中启用 Analytics。

节点.js

function publishTemplate() {
  var config = admin.remoteConfig();
  var template = config.createTemplateFromJSON(
      fs.readFileSync('config.json', 'UTF8'));
  config.publishTemplate(template)
      .then(function (updatedTemplate) {
        console.log('Template has been published');
        console.log('ETag from server: ' + updatedTemplate.etag);
      })
      .catch(function (err) {
        console.error('Unable to publish template.');
        console.error(err);
      });
}

爪哇

try {
  Template publishedTemplate = FirebaseRemoteConfig.getInstance()
          .publishTemplateAsync(template).get();
  System.out.println("Template has been published");
  // See the ETag of the published template.
  System.out.println("ETag from server: " + publishedTemplate.getETag());
} catch (ExecutionException e) {
  if (e.getCause() instanceof FirebaseRemoteConfigException) {
    FirebaseRemoteConfigException rcError = (FirebaseRemoteConfigException) e.getCause();
    System.out.println("Unable to publish template.");
    System.out.println(rcError.getMessage());
  }
}

使用 REST API 修改远程配置

本节介绍远程配置 REST API 的主要功能,网址为https://firebaseremoteconfig.googleapis.com 。有关完整的详细信息,请参阅API 参考

获取访问令牌以对 API 请求进行身份验证和授权

Firebase 项目支持 Google服务帐户,您可以使用它从您的应用服务器或受信任的环境中调用 Firebase 服务器 API。如果您在本地开发代码或在本地部署应用程序,则可以使用通过此服务帐户获得的凭据来授权服务器请求。

要对服务帐号进行身份验证并授权其访问 Firebase 服务,您必须生成 JSON 格式的私钥文件。

要为您的服务帐户生成私钥文件:

  1. 在 Firebase 控制台中,打开Settings > Service Accounts

  2. 单击Generate New Private Key ,然后单击Generate Key进行确认。

  3. 安全地存储包含密钥的 JSON 文件。

通过服务帐户进行授权时,您有两种选择来向您的应用程序提供凭据。您可以设置GOOGLE_APPLICATION_CREDENTIALS环境变量,也可以在代码中将路径显式传递给服务帐户密钥。第一个选项更安全,强烈推荐。

设置环境变量:

将环境变量GOOGLE_APPLICATION_CREDENTIALS设置为包含您的服务帐号密钥的 JSON 文件的文件路径。此变量仅适用于您当前的 shell 会话,因此如果您打开一个新会话,请再次设置该变量。

Linux 或 macOS

export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/service-account-file.json"

视窗

使用 PowerShell:

$env:GOOGLE_APPLICATION_CREDENTIALS="C:\Users\username\Downloads\service-account-file.json"

完成上述步骤后,应用程序默认凭据 (ADC) 能够隐式确定您的凭据,允许您在测试或在非 Google 环境中运行时使用服务帐户凭据。

将您的 Firebase 凭据与您的首选语言的Google 身份验证库一起使用,以检索短期 OAuth 2.0 访问令牌:

节点.js

 function getAccessToken() {
  return admin.credential.applicationDefault().getAccessToken()
      .then(accessToken => {
        return accessToken.access_token;
      })
      .catch(err => {
        console.error('Unable to get access token');
        console.error(err);
      });
}

在此示例中,Google API 客户端库使用 JSON Web 令牌或 JWT 对请求进行身份验证。有关更多信息,请参阅JSON Web 令牌

Python

def _get_access_token():
  """Retrieve a valid access token that can be used to authorize requests.

  :return: Access token.
  """
  credentials = ServiceAccountCredentials.from_json_keyfile_name(
      'service-account.json', SCOPES)
  access_token_info = credentials.get_access_token()
  return access_token_info.access_token

爪哇

private static String getAccessToken() throws IOException {
  GoogleCredentials googleCredentials = GoogleCredentials
          .fromStream(new FileInputStream("service-account.json"))
          .createScoped(Arrays.asList(SCOPES));
  googleCredentials.refreshAccessToken();
  return googleCredentials.getAccessToken().getTokenValue();
}

访问令牌过期后,会自动调用令牌刷新方法来检索更新的访问令牌。

要授权访问远程配置,请请求范围https://www.googleapis.com/auth/firebase.remoteconfig

修改远程配置模板

使用远程配置模板时,请记住它们是版本化的,并且每个版本从创建时间到您用更新替换它的时间都有一个有限的生命周期:90 天,总共限制 300 个存储版本。有关详细信息,请参阅模板和版本控制

获取当前的远程配置模板

您可以使用后端 API 以 JSON 格式获取远程配置模板的当前活动版本。

在 A/B 测试实验中专门作为变体创建的参数和参数值不包含在导出的模板中。

使用以下命令:

卷曲

curl --compressed -D headers -H "Authorization: Bearer token" -X GET https://firebaseremoteconfig.googleapis.com/v1/projects/my-project-id/remoteConfig -o filename

此命令将 JSON 有效负载输出到一个文件,并将标头(包括 Etag)输出到一个单独的文件。

原始 HTTP 请求

Host: firebaseremoteconfig.googleapis.com

GET /v1/projects/my-project-id/remoteConfig HTTP/1.1
Authorization: Bearer token
Accept-Encoding: gzip

此 API 调用返回以下 JSON,以及一个包含用于后续请求的ETag的单独标头。

验证远程配置模板

或者,您可以在发布更新之前对其进行验证。通过将 URL 参数?validate_only=true附加到您的发布请求来验证模板更新。在响应中,状态代码 200 和带有后缀-0的更新 etag 表示您的更新已成功验证。任何非 200 响应都表示 JSON 数据包含您必须在发布前更正的错误。

更新远程配置模板

检索模板并使用所需更新修改 JSON 内容后,您可以发布它。按照本节中的说明发布模板会将整个现有配置模板替换为更新的文件,并且为新的活动模板分配比它替换的模板大一号的版本号。

如有必要,您可以使用 REST API回滚到以前的版本。为了降低更新中出错的风险,您可以在发布前进行验证

远程配置个性化和条件包含在下载的模板中,因此在尝试发布到其他项目时,请务必注意以下限制:

  • 个性化不能从一个项目导入到另一个项目。

    例如,如果您在项目中启用了个性化并下载和编辑模板,则可以将其发布到同一个项目,但不能将其发布到不同的项目,除非您从模板中删除个性化。

  • 条件可以从一个项目导入到另一个项目,但请注意,任何特定的条件值(如应用 ID 或受众)在发布之前都应该存在于目标项目中。

    例如,如果您有一个 Remote Config 参数,该参数使用指定iOS平台值的条件,则可以将模板发布到另一个项目,因为任何项目的平台值都是相同的。但是,如果它包含依赖于特定应用 ID 或目标项目中不存在的用户受众的条件,则验证将失败。

  • 如果您计划发布的模板包含依赖 Google Analytics 的条件,则必须在目标项目中启用 Analytics。

卷曲

curl --compressed -H "Content-Type: application/json; UTF8" -H "If-Match: last-returned-etag" -H "Authorization: Bearer token" -X PUT https://firebaseremoteconfig.googleapis.com/v1/projects/my-project-id/remoteConfig -d @filename

对于此curl命令,您可以使用“@”字符后跟文件名来指定内容。

原始 HTTP 请求

Host: firebaseremoteconfig.googleapis.com
PUT /v1/projects/my-project-id/remoteConfig HTTP/1.1
Content-Length: size
Content-Type: application/json; UTF8
Authorization: Bearer token
If-Match: expected ETag
Accept-Encoding: gzip
JSON_HERE

因为这是一个写请求,所以该命令修改了ETag ,并在下一个PUT命令的响应标头中提供了更新的 ETag。

修改远程配置条件

您可以以编程方式修改远程配置条件和条件值。使用 REST API,您必须在发布模板之前直接编辑模板以修改条件。

{
  "conditions": [{
    "name": "android_english",
    "expression": "device.os == 'android' && device.country in ['us', 'uk']",
    "tagColor": "BLUE"
  }, {
    "name": "tenPercent",
    "expression": "percent <= 10",
    "tagColor": "BROWN"
  }],
  "parameters": {
    "welcome_message": {
      "defaultValue": {
        "value": "Welcome to this sample app"
      },
      "conditionalValues": {
        "tenPercent": {
          "value": "Welcome to this new sample app"
        }
      },
      "description": "The sample app's welcome message"
    },
    "welcome_message_caps": {
      "defaultValue": {
        "value": "false"
      },
      "conditionalValues": {
        "android_english": {
          "value": "true"
        }
      },
      "description": "Whether the welcome message should be displayed in all capital letters."
    }
  }
}

上面的修改首先定义了一组条件,然后为每个参数定义了默认值和基于条件的参数( conditional values )值。它还为每个元素添加了可选描述;像代码注释一样,这些是供开发人员使用的,不会显示在应用程序中。还提供了一个ETag用于版本控制。

远程配置后端 API 提供了几个条件和比较运算符,您可以使用它们来更改应用程序的行为和外观。要了解有关条件和这些条件支持的运算符的更多信息,请参阅条件表达式参考

HTTP 错误代码

状态码意义
200成功更新
400发生验证错误。例如,包含超过允许数量的键(2000)的请求将返回 400(错误请求)以及错误消息Param count too large 。此外,此 HTTPS 状态代码可能会在以下两种情况下出现:
  • 发生版本不匹配错误,因为自您上次检索 ETag 值以来已更新了一组值和条件。要解决此问题,您应该使用GET命令获取新模板和 ETag 值,更新模板,然后使用该模板和新 ETag 值提交。
  • 在未指定If-Match标头的情况下发出了PUT命令(更新远程配置模板请求)。
401发生授权错误(未提供访问令牌或 Firebase Remote Config REST API 未添加到您在 Cloud Developer Console 中的项目中)
403发生身份验证错误(提供了错误的访问令牌)
500发生了内部错误。如果发生此错误,请提交 Firebase 支持票证

状态码 200 表示远程配置模板(项目的参数、值和条件)已更新,现在可供使用此项目的应用程序使用。其他状态码表示之前存在的远程配置模板仍然有效。

向模板提交更新后,请转到 Firebase 控制台以验证您的更改是否按预期显示。这很关键,因为条件的顺序会影响它们的评估方式(评估为true的第一个条件生效)。

ETag 使用和强制更新

远程配置 REST API 使用实体标签 (ETag) 来防止竞争条件和资源的重叠更新。要了解有关 ETag 的更多信息,请参阅ETag - HTTP

对于 REST API,Google 建议您缓存最新的GET命令提供的 ETag,并在发出PUT命令时在If-Match请求标头中使用该 ETag 值。如果您的PUT命令导致 HTTPS 状态代码 409,您应该发出一个新的GET命令来获取一个新的 ETag 和模板以与您的下一个PUT命令一起使用。

您可以通过强制按如下方式更新远程配置模板来规避 ETag 及其提供的保护: If-Match: *但是,不建议使用此方法,因为它有可能导致远程配置更新丢失如果多个客户端正在更新远程配置模板,则为模板。这种冲突可能发生在使用 API 的多个客户端,或者来自 API 客户端和 Firebase 控制台用户的更新冲突。

有关管理远程配置模板版本的指南,请参阅远程配置模板和版本控制