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

以编程方式修改远程配置

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

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

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

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

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

本指南的以下部分描述了您可以使用远程配置后端 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);

获取当前的远程配置模板

使用 Remote Config 模板时,请记住它们是版本化的,并且每个版本从创建时间到您用更新替换它的时间都有有限的生命周期: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));

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

Remote Config 后端 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 控制台中,打开设置 >服务帐户

  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 Auth 库一起使用,以检索短期 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 网络令牌或 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

修改远程配置模板

使用 Remote Config 模板时,请记住它们是版本化的,并且每个版本从创建时间到您用更新替换它的时间都有有限的生命周期: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用于版本控制目的。

Remote Config 后端 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 表示远程配置模板(项目的参数、值和条件)已更新,现在可供使用该项目的应用使用。其他状态码表示之前存在的 Remote Config 模板仍然有效。

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

ETag 使用和强制更新

Remote Config 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 控制台用户的更新冲突时。

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