透過程式輔助方式修改遠端設定

本文件說明如何透過程式輔助方式,讀取及修改一組稱為「Remote Config 範本」的 JSON 格式參數和條件。這樣一來,您就能在後端進行範本變更,讓用戶端應用程式可使用用戶端程式庫擷取範本。

您可以使用本指南所述的 Remote Config REST APIAdmin SDK,略過在 Firebase 控制台中管理範本的麻煩,直接將 Remote Config 變更整合至自己的程序。舉例來說,您可以使用 Remote Config 後端 API 執行下列操作:

  • 安排Remote Config更新。您可以使用 API 呼叫搭配 cron 工作,定期變更 Remote Config 值。
  • 批次匯入設定值,以便從自有專屬系統順利轉換至 Firebase Remote Config
  • 搭配使用 Remote ConfigCloud Functions for Firebase,根據在伺服器端發生的事件變更應用程式中的值。舉例來說,您可以使用 Remote Config 在應用程式中宣傳新功能,然後在偵測到有足夠人數與新功能互動後,自動關閉該宣傳活動。

    這張圖表顯示遠端設定後端與自訂工具和伺服器的互動

本指南的以下各節說明您可以使用 Remote Config 後端 API 執行的作業。如要查看一些透過 REST API 執行這些工作的程式碼,請參閱下列其中一個範例應用程式:

使用 Firebase Admin SDK 修改遠端設定

Admin SDK 是一組伺服器程式庫,可讓您在特權環境中與 Firebase 互動。除了對 Remote Config 執行更新作業,Admin SDK 還可產生及驗證 Firebase 驗證權杖、讀取及寫入 Realtime Database 等。如要進一步瞭解 Admin SDK 的先決條件和設定,請參閱「將 Firebase Admin SDK 新增至伺服器」一文。

在典型的 Remote Config 流程中,您可能會取得目前的範本、修改部分參數或參數群組和條件、驗證範本,然後發布。進行這些 API 呼叫之前,您必須先授權來自 SDK 的要求。

初始化 SDK 並授權 API 要求

在沒有參數的情況下初始化 Admin SDK 時,SDK 會使用 Google 應用程式預設憑證,並從 FIREBASE_CONFIG 環境變數讀取選項。如果 FIREBASE_CONFIG 變數的內容以 { 開頭,系統會將其剖析為 JSON 物件。否則 SDK 會假設該字串是含有選項的 JSON 檔案名稱。

例如:

Node.js

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

Java

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 格式取得目前有效的 Remote Config 範本版本。

匯出的範本中不會包含 A/B Testing 實驗中專門做為變化版本建立的參數和參數值。

如要取得範本,請按照下列步驟操作:

Node.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);
      });
}

Java

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

修改遠端設定參數

您可以以程式輔助的方式修改及新增 Remote Config 參數和參數群組。舉例來說,您可以為名為「new_menu」的現有參數群組新增參數,用來控制季節性資訊的顯示方式:

Node.js

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

Java

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

這個 API 可讓您建立新的參數和參數群組,或是修改預設值、條件式值和說明。無論是哪種情況,您必須在修改後明確發布範本。

修改遠端設定條件

您可以透過程式輔助方式修改及新增 Remote Config 條件和條件值。舉例來說,如要新增條件,請按照下列步驟操作:

Node.js

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

Java

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

無論是哪種情況,您必須在修改後明確發布範本。

Remote Config 後端 API 提供多種條件和比較運算子,可用於變更應用程式的行為和外觀。如要進一步瞭解條件和這些條件支援的運算子,請參閱條件式運算式參考資料

驗證遠端設定範本

您可以選擇在發布更新前先驗證,如下所示:

Node.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);
      });
}

Java

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 復原至先前版本。為降低更新內容出現錯誤的風險,您可以在發布前進行驗證

Remote Config 下載的範本包含個人化設定和條件,因此嘗試將內容發布至其他專案時,請務必注意下列限制:

  • 個人化資料無法從一個專案匯入另一個專案。

    舉例來說,如果您在專案中啟用個人化功能,並下載及編輯範本,則可以將範本發布至相同專案,但無法發布至其他專案,除非您從範本中刪除個人化功能。

  • 您可以從一個專案匯入條件,並套用到其他專案,但請注意,任何特定條件值 (例如應用程式 ID 或目標對象) 都必須先存在於目標專案中,才能發布。

    舉例來說,如果您有 Remote Config 參數,且使用指定 iOS 平台值的條件,則可將範本發布至其他專案,因為任何專案的平台值都相同。不過,如果條件依賴特定應用程式 ID 或目標專案中不存在的使用者目標對象,驗證作業就會失敗。

  • 如果您計劃發布的範本包含依賴 Google Analytics 的條件,則必須在目標專案中啟用 Analytics

Node.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);
      });
}

Java

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 修改遠端設定

本節將說明 https://firebaseremoteconfig.googleapis.com 中的 Remote Config REST API 主要功能。詳情請參閱 API 參考資料

取得存取權杖,以便驗證及授權 API 要求

Firebase 專案支援 Google 服務帳戶,您可以透過這個帳戶從應用程式伺服器或受信任的環境呼叫 Firebase 伺服器 API。如果您在本機開發程式碼,或將應用程式部署到內部部署,則可以使用透過此服務帳戶取得的憑證,授權伺服器要求。

如要驗證服務帳戶並授權存取 Firebase 服務,您必須以 JSON 格式產生私密金鑰檔案。

如何產生服務帳戶的私密金鑰檔案:

  1. Firebase 控制台中,開啟「Settings」(設定) >「Service Accounts」(服務帳戶)

  2. 按一下「產生新的私密金鑰」,然後點選「產生金鑰」確認。

  3. 妥善儲存含有金鑰的 JSON 檔案。

透過服務帳戶授權時,您可以透過兩種方式向應用程式提供憑證。您可以設定 GOOGLE_APPLICATION_CREDENTIALS 環境變數,也可以在程式碼中明確傳遞服務帳戶金鑰的路徑。第一個選項較為安全,強烈建議您採用。

如何設定環境變數:

將環境變數 GOOGLE_APPLICATION_CREDENTIALS 設為包含服務帳戶金鑰的 JSON 檔案路徑。這個變數僅適用於您目前的殼層工作階段,因此如果您開啟新的工作階段,請再次設定變數。

Linux 或 macOS

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

Windows

使用 PowerShell:

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

完成上述步驟後,應用程式預設憑證 (ADC) 就能以隱密的方式判斷您的憑證,讓您在非 Google 環境中測試或執行時使用服務帳戶憑證。

將 Firebase 憑證與慣用語言的 Google 驗證程式庫搭配使用,以擷取短期 OAuth 2.0 存取權杖:

node.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 Token 或 JWT 驗證要求。詳情請參閱 JSON 網頁符記

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

Java

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

存取權杖到期後,系統會自動呼叫權杖重新整理方法,以便擷取更新的存取權杖。

如要授權存取 Remote Config,請要求 https://www.googleapis.com/auth/firebase.remoteconfig 範圍。

修改遠端設定範本

請注意,使用 Remote Config 範本時,這些範本是版本化的,且每個版本在建立時到更換更新後的生命週期有限 (90 天,總儲存限制為 300 個)。詳情請參閱範本和版本管理

取得目前的遠端設定範本

您可以使用後端 API,取得 JSON 格式的目前有效版本 Remote Config

匯出的範本中不會包含 A/B Testing 實驗中專門做為變化版本建立的參數和參數值。

請使用下列指令:

cURL

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 的獨立標頭。

驗證遠端設定範本

您可以選擇在發布更新前先驗證。如要驗證範本更新,請在發布要求中附加網址參數 ?validate_only=true。在回應中,狀態碼 200 和結尾為 -0 的更新版 etag 代表更新已成功驗證。任何非 200 的回應都表示 JSON 資料含有錯誤,您必須先修正這些錯誤,才能發布。

更新遠端設定範本

擷取範本並修改 JSON 內容後,您就可以發布。按照本節所述,發布範本會將整個現有設定範本替換為更新的檔案,而新有效範本會指派一個比所取代的範本高一個數字的版本號碼。

如有需要,您可以使用 REST API 復原至先前版本。如要降低更新時發生錯誤的風險,您可以在發布前進行驗證

Remote Config 下載的範本包含個人化設定和條件,因此嘗試將內容發布至其他專案時,請務必注意下列限制:

  • 個人化資料無法從一個專案匯入另一個專案。

    舉例來說,如果您在專案中啟用個人化功能,並下載及編輯範本,則可以將範本發布至相同專案,但無法發布至其他專案,除非您從範本中刪除個人化功能。

  • 您可以從一個專案匯入條件,並套用到其他專案,但請注意,任何特定條件值 (例如應用程式 ID 或目標對象) 都必須先存在於目標專案中,才能發布。

    舉例來說,如果您有 Remote Config 參數,且使用指定 iOS 平台值的條件,則可將範本發布至其他專案,因為任何專案的平台值都相同。不過,如果條件依賴特定應用程式 ID 或目標專案中不存在的使用者目標對象,驗證作業就會失敗。

  • 如果您要發布的範本包含依賴 Google Analytics 的條件,則必須在目標專案中啟用 Analytics

cURL

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。

修改遠端設定條件

您可以透過程式輔助方式修改 Remote Config 條件和條件值。如果使用 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."
    }
  }
}

上述的修改會先定義一組條件,然後為每個參數定義預設值和條件式參數 (條件式值) 值。它也會為每個元素新增選用的說明;就像程式碼註解一樣,這些說明供開發人員使用,不會顯示在應用程式中。此外,系統也會提供 ETag,以便控管版本。

Remote Config 後端 API 提供數種條件和比較運算子,可用來變更應用程式的行為和外觀。如要進一步瞭解條件以及支援這些條件的運算子,請參閱條件運算式參考資料

HTTP 錯誤代碼

狀態碼 意義
200 更新成功
400 發生驗證錯誤。舉例來說,如果要求包含的鍵數超過允許的數量 (2000),系統會傳回 400 (Bad Request),並顯示錯誤訊息 Param count too large。此外,這類 HTTPS 狀態碼也可能出現在以下兩種情況:
  • 自上次擷取 ETag 值以來,值和條件組合已更新,因此發生版本不相符錯誤。如要解決這個問題,請使用 GET 指令取得新的範本和 ETag 值,更新範本,然後使用該範本和新的 ETag 值提交。
  • 已執行 PUT 指令 (更新 Remote Config 範本要求),但未指定 If-Match 標頭。
401 發生授權錯誤 (未提供存取權杖,或是尚未將 Firebase Remote Config REST API 新增至 Cloud Developer Console 的專案)
403 發生驗證錯誤 (提供的存取權杖有誤)
500 發生內部錯誤,如果發生此錯誤,請 提交 Firebase 支援單

狀態碼 200 表示 Remote Config 範本 (專案的參數、值和條件) 已更新,現已可供使用此專案的應用程式使用。其他狀態碼則代表先前存在的 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 及其提供的保護措施,您可以強制更新 Remote Config 範本,如下所示:If-Match: * 不過,我們不建議使用這種做法,因為如果多個用戶端更新 Remote Config 範本,這可能會導致您的 Remote Config 範本更新遺失。這種衝突可能發生在使用 API 的多個用戶端,或是 API 用戶端和 Firebase 主控台使用者的更新內容發生衝突時。

如需管理 Remote Config 範本版本的指引,請參閱「遠端設定範本和版本管理」一文。