使用 Android 開發人員 ID 狀態 API 檢查應用程式註冊狀態

使用 Android 開發人員狀態 API,檢查 Android 應用程式套件名稱是否已向通過驗證的開發人員註冊。如果您建構軟體開發工具、IDE 或自動化 CI/CD 工作流程,可以整合這項伺服器對伺服器 API,執行下列操作:

  • 檢查應用程式套件名稱是否已向通過驗證的開發人員註冊
  • 驗證應用程式簽署憑證的 SHA-256 指紋是否與已註冊套件名稱的檔案憑證相符
  • 在工具介面中提示開發人員,在 Android 開發人員驗證計畫中註冊無法辨識的應用程式

這項 API 旨在支援各種開發人員工作流程:

用途 說明 API 端點
套件名稱資格 檢查套件名稱是否已註冊。如果套件名稱已連結至任何通過驗證的開發人員,則傳回 REGISTERED,否則傳回 NOT_REGISTERED CheckPackageRegistrationStatus
應用程式已註冊 檢查是否已註冊特定套件名稱和憑證指紋組合。如果套件名稱和憑證指紋配對已註冊,則傳回 REGISTERED;如果套件名稱和憑證指紋配對未註冊,則傳回 NOT_REGISTERED;如果套件名稱已使用其他憑證指紋註冊,則傳回 REGISTERED_WITH_ANOTHER_CERTIFICATE_FINGERPRINT CheckPackageRegistrationStatus

本指南說明如何完成下列工作:

  1. 設定 Google Cloud API 存取權和驗證。
  2. 驗證應用程式的套件名稱和公開憑證 SHA-256 指紋配對是否已由經過驗證的開發人員,透過提供的公開憑證 SHA-256 指紋或不同的公開憑證 SHA-256 指紋,向 Android 開發人員驗證計畫註冊。
  3. 在 IDE 或開發人員工具工作流程中處理 API 註冊狀態。

必要條件

這份文件適用於 Android 應用程式開發人員或軟體開發工具開發人員。開始前,請先確認下列事項:

  • Google Cloud 雲端專案的管理員存取權。
  • 對 RESTful API、JSON 和 SHA-256 憑證指紋有基本瞭解。

您也應熟悉下列詞彙:

字詞 定義
Android 開發人員驗證 Android 開發人員驗證是一項新措施,旨在將實際實體 (個人和機構) 與其 Android 應用程式連結。所有應用程式都必須由通過驗證的開發人員註冊,使用者才能在 Android 認證裝置上安裝。
憑證指紋 用來簽署應用程式的公開憑證 SHA-256 雜湊。
註冊狀態 API 針對應用程式套件名稱,或應用程式套件名稱和公用憑證 SHA-256 指紋配對傳回的狀態。這個狀態會決定您必須採取的動作 (例如 REGISTEREDNOT_REGISTERED)。

服務端點

服務端點是能指定 API 服務網路位址的基準網址。這項服務有下列服務端點,以及和該服務端點相關的所有 URI:

https://androiddeveloperidstatus.googleapis.com

啟用 API

如要使用 Android 開發人員 ID 狀態 API,請先完成設定步驟,建立專案並啟用 API。

建立 Google Cloud 專案

  1. 如果沒有,請建立 Google Cloud 帳戶
  2. 開啟 Google Cloud 控制台
  3. 建立 Google Cloud 專案

在專案中啟用 API

  1. 在 Google Cloud 控制台中,依序前往「API 和服務」>「程式庫」
  2. 從下拉式選單中選取您的專案。
  3. 搜尋「Android Developer ID Status API」
  4. 按一下「啟用」

驗證

這個 API 支援 API 金鑰憑證。如要取得 API 金鑰,請按照下列步驟操作:

  1. 在 Google Cloud 控制台中,依序前往「API 和服務」>「憑證」
  2. 按一下「+ 建立憑證」,然後選取「API 金鑰」
  3. 設定並複製金鑰。在要求標頭中使用這個金鑰。

查看應用程式註冊狀態

您可以查詢 PackageRegistrationStatus 資源,單獨驗證套件名稱,或檢查與特定憑證指紋配對的套件名稱。

檢查套件名稱

如要檢查應用程式套件名稱是否已由任何已驗證的開發人員註冊,請向 packageRegistrationStatus:check 端點發出經過驗證的 GET 要求,其中包含 Android 應用程式的套件名稱 (例如 com.example.app),且不含選用參數:

要求:

curl -X GET "https://androiddeveloperidstatus.googleapis.com/v1/packages/com.example.app/packageRegistrationStatus:check" \
  -H "X-Goog-Api-Key: [key]"

結果

回覆 (已註冊):

如果套件名稱已註冊,您會收到下列 HTTP 回應主體,以及 HTTP 回應代碼 200

{
  "name": "packages/com.example.app/packageRegistrationStatus",
  "state": "REGISTERED"
}

應變措施建議:通知開發人員該套件名稱已註冊。

回覆 (未註冊):

如果套件名稱未註冊,您會收到下列 HTTP 回應內容,以及 HTTP 回應代碼 200

{
  "name": "packages/com.example.app/packageRegistrationStatus",
  "state": "NOT_REGISTERED"
}

驗證套件名稱和憑證指紋配對

如要檢查應用程式套件名稱是否已向特定公開憑證 SHA-256 指紋註冊,請傳遞 certificateFingerprint 查詢參數:

要求:

curl -X GET "https://androiddeveloperidstatus.googleapis.com/v1/packages/com.example.app/packageRegistrationStatus:check?certificateFingerprint=d6ac89ed1d0a805aad4b087d06d5f41645b814480b133fbc867ef7498d069e06" \
  -H "X-Goog-Api-Key: [key]"

結果

回應 (已註冊相符的憑證指紋):

如果套件名稱已使用提供的公開憑證 SHA-256 指紋註冊,您會收到下列 HTTP 回應內文,以及 HTTP 回應代碼 200

{
  "name": "packages/com.example.app/packageRegistrationStatus",
  "state": "REGISTERED"
}

回應 (以不同憑證指紋註冊):

如果套件名稱已註冊,但使用的憑證 SHA-256 指紋與您提供的不同,您會收到下列 HTTP 回應主體,以及 HTTP 回應代碼 200

{
  "name": "packages/com.example.app/packageRegistrationStatus",
  "state": "REGISTERED_WITH_ANOTHER_CERTIFICATE_FINGERPRINT"
}

回覆 (未註冊):

如果套件名稱未以提供的公用憑證 SHA-256 指紋註冊,您會收到下列 HTTP 回應內容,以及 HTTP 回應代碼 200

{
  "name": "packages/com.example.app/packageRegistrationStatus",
  "state": "NOT_REGISTERED"
}

Java 導入範例

下列 Java 類別示範如何使用 Java 11 的標準 HttpClient 呼叫 API。

import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;

public class DeveloperIdStatusClient {

  private static final String API_ENDPOINT = "https://androiddeveloperidstatus.googleapis.com";

  public static void main(String[] args) {
    String apiKey = "YOUR_API_KEY";
    String packageName = "com.example.app";
    String certificateFingerprint = "d6ac89ed1d0a805aad4b087d06d5f41645b814480b133fbc867ef7498d069e06";

    try {
      String response = checkPackageRegistrationStatus(apiKey, packageName, certificateFingerprint);
      System.out.println("Response: " + response);
    } catch (IOException | InterruptedException e) {
      e.printStackTrace();
    }
  }

  /**
   *   Checks the registration status of an Android package.
   *
   *   @param apiKey The Google API key for authentication.
   *   @param packageName The fully-qualified Android package name (for example, "com.example.app").
   *   @param certificateFingerprint Optional SHA-256 certificate fingerprint. Pass null or empty to omit.
   *   @return The JSON response string from the API.
   */
  public static String checkPackageRegistrationStatus(
      String apiKey, String packageName, String certificateFingerprint)
      throws IOException, InterruptedException {

    // 1. Build the URL path (accepts dots directly)
    // Format: /v1/packages/{package}/packageRegistrationStatus:check
    String path = String.format("/v1/packages/%s/packageRegistrationStatus:check", packageName);

    // 2. Build query parameters (only certificateFingerprint if provided)
    StringBuilder queryBuilder = new StringBuilder();
    if (certificateFingerprint != null && !certificateFingerprint.isEmpty()) {
      queryBuilder.append("certificateFingerprint=")
          .append(URLEncoder.encode(certificateFingerprint, StandardCharsets.UTF_8));
    }

    String fullUrl = API_ENDPOINT + path;
    if (queryBuilder.length() > 0) {
      fullUrl += "?" + queryBuilder.toString();
    }

    // 3. Create and send the HTTP GET request with API Key header
    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create(fullUrl))
        .header("Accept", "application/json")
        .header("X-Goog-Api-Key", apiKey)
        .GET()
        .build();

    HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

    if (response.statusCode() != 200) {
      throw new IOException("Unexpected response code: " + response.statusCode() + ", body: " + response.body());
    }

    return response.body();
  }
}

瞭解註冊狀態和錯誤處理

如果 API 要求失敗,Android 開發人員 ID 狀態 API 會在回應本文中傳回標準的 Google Cloud JSON 錯誤物件。這個物件提供一致的結構,可供瞭解及處理錯誤。

錯誤回應範例:

{
  "error": {
    "code": 400,
    "message": "Request contains an invalid argument.",
    "status": "INVALID_ARGUMENT"
  }
}

錯誤物件包含下列重要欄位:

  • code:HTTP 狀態碼 (例如 400403500)。
  • message:以英文向開發人員說明錯誤。這則訊息不穩定且可能會變更,因此請勿根據這則訊息建構剖析邏輯。
  • status:以程式輔助方式識別錯誤類型的標準化錯誤代碼 (例如 INVALID_ARGUMENTPERMISSION_DENIED)。錯誤處理邏輯應以這個穩定 ID 為基礎建構。

下表列出 API 最常傳回的錯誤,以及建議採取的行動。

HTTP 狀態 標準化錯誤代碼 (status) 意義和常見原因 建議做法 可以重試嗎?
400 不正確的要求 INVALID_ARGUMENT 要求格式錯誤。 請勿重試。檢查錯誤回應中的詳細資料欄位,找出具體欄位違規事項。修正要求酬載內容,然後再次傳送。
401 未經授權 UNAUTHENTICATED 存取權杖遺失、過期或無效。 請勿立即重試。確認您使用的存取權杖或金鑰正確無誤。
403 禁止 PERMISSION_DENIED 您已通過驗證,但專案沒有存取 API 的權限。最常見的原因是您未在 Google Cloud 專案中啟用 API。 請勿重試。確認您使用的專案 ID 正確,且 API 已啟用。
429 要求數超量 RESOURCE_EXHAUSTED 您已超過專案的 API 配額。 停止傳送要求,稍後再重試。在 Google Cloud 控制台中查看專案配額。
500 內部伺服器錯誤 INTERNAL Google 伺服器發生未預期的錯誤。 這可能是暫時性問題。使用指數輪詢策略重試要求。如果錯誤持續發生,請與支援團隊聯絡。
503 服務無法使用 UNAVAILABLE 暫時無法提供服務。 使用指數輪詢策略重試要求。

配額限制

系統會根據個別專案強制執行使用配額,確保服務可靠性。

API 方法 預設限制 (每個專案) 附註
CheckPackageRegistrationStatus 每日 1,000 個要求 呼叫端必須管理內部頻率限制,以防濫用。

監控用量

您可以在 Google Cloud 控制台中,直接監控專案目前的 API 用量,並查看剩餘的配額。

  1. 前往「APIs & Services」(API 和服務) >「Dashboard」(資訊主頁) 頁面。
  2. 選取 Android 開發人員 ID 狀態 API。
  3. 按一下 [Quotas] (配額) 分頁標籤。

這個資訊主頁會詳細列出一段時間內的要求量。