使用 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 |
本指南介绍了如何完成以下任务:
- 设置 Google Cloud API 访问权限和身份验证。
- 验证应用软件包名称和公共证书 SHA-256 指纹对是否已由经过验证的开发者通过所提供的公共证书 SHA-256 指纹或其他公共证书 SHA-256 指纹向 Android 开发者验证计划注册。
- 在 IDE 或开发者工具工作流程中处理 API 注册状态。
前提条件
本文档适用于 Android 应用开发者或软件开发工具开发者。在开始之前,您应该具备以下条件:
- 对 Google Cloud 项目的管理员访问权限。
- 对 RESTful API、JSON 和 SHA-256 证书指纹有基本的了解。
您还应熟悉以下术语:
| 术语 | 定义 |
|---|---|
| Android 开发者验证 | Android 开发者验证是一项新要求,旨在将现实世界中的实体(个人和组织)与其 Android 应用相关联。Android 将要求所有应用都必须由经过验证的开发者注册,才可供用户在已获认证的 Android 设备上安装。 |
| 证书指纹 | 用于对应用进行签名的公共证书的 SHA-256 哈希。 |
| 注册状态 | API 针对应用的软件包名称或应用的软件包名称与公钥证书 SHA-256 指纹对返回的状态。此状态决定了您必须采取的操作(例如,REGISTERED、NOT_REGISTERED)。 |
服务端点
服务端点是一个基础网址,指定了 API 服务的网络地址。此服务具有以下服务端点,所有 URI 都与此服务端点相关:
https://androiddeveloperidstatus.googleapis.com
启用 API
如需使用 Android 开发者 ID 状态 API,您必须完成设置步骤,以创建项目并启用该 API。
创建 Google Cloud 项目
- 如果您还没有 Google Cloud 账号,请创建一个。
- 打开 Google Cloud Console。
- 创建 Google Cloud 项目。
在项目中启用 API
- 在 Google Cloud 控制台中,前往 API 和服务 > 库。
- 从下拉菜单中选择您的项目。
- 搜索 Android Developer ID Status API。
- 点击启用。
身份验证
该 API 支持 API 密钥凭据。要获取 API 密钥,请执行以下操作:
- 在 Google Cloud 控制台中,依次前往 API 和服务 > 凭据。
- 点击 + 创建凭据,然后选择 API 密钥。
- 配置密钥并复制。在请求标头中使用此密钥。
查看应用注册状态
您可以查询 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 状态代码(例如400、403、500)。message:面向开发者的英文错误说明。此消息不稳定,可能会发生变化,因此请勿围绕此消息构建解析逻辑。status:以程序化方式标识错误类型的规范错误代码(例如INVALID_ARGUMENT、PERMISSION_DENIED)。您的错误处理逻辑应基于此稳定标识符构建。
下表列出了 API 返回的最常见错误以及建议的应对措施。
| HTTP 状态 | 规范错误代码 (status) |
含义和常见原因 | 推荐措施 | 可以重试吗? |
|---|---|---|---|---|
400 Bad Request |
INVALID_ARGUMENT |
请求格式不正确。 | 不重试。检查错误响应中的“details”字段,以确定具体字段违规情况。更正请求载荷,然后重新发送。 | 否 |
401 Unauthorized |
UNAUTHENTICATED |
访问令牌缺失、已过期或无效。 | 不立即重试。确保您使用的是正确的访问令牌或密钥。 | 否 |
403 Forbidden |
PERMISSION_DENIED |
您已通过身份验证,但您的项目无权访问该 API。最常见的原因是您尚未在 Google Cloud 项目中启用该 API。 | 不重试。验证您使用的是正确的项目 ID,并且该 API 已启用。 | 否 |
429 请求过多 |
RESOURCE_EXHAUSTED |
您已超出项目的 API 配额。 | 停止发送请求,并在延迟后重试。在 Google Cloud 控制台中查看项目的配额。 | 是 |
500 内部服务器错误 |
INTERNAL |
Google 服务器上发生了意外错误。 | 这很可能是暂时性问题。使用指数退避算法策略重试请求。如果错误仍然存在,请与支持团队联系。 | 是 |
503 Service Unavailable |
UNAVAILABLE |
该服务暂不可用。 | 使用指数退避算法策略重试请求。 | 是 |
配额限制
为了确保服务可靠性,系统会按项目强制执行使用配额。
| API 方法 | 默认限额(每个项目) | 备注 |
|---|---|---|
CheckPackageRegistrationStatus |
每天 1000 个请求 | 调用方需要管理内部速率限制,以防止滥用。 |
监控您的用量
您可以在 Google Cloud 控制台中直接监控项目的当前 API 用量,并了解剩余的配额。
- 前往 API 和服务 > 信息中心页面。
- 选择 Android 开发者 ID 状态 API。
- 点击配额标签。
此信息中心详细显示了您的请求量随时间的变化情况。