Android Developer Console API는 인증된 개발자가 Android Developer Console에서 Android 개발자 인증 워크플로를 자동화할 수 있는 RESTful 서비스입니다. 여기에는 개발자 계정 검색, 주요 자격 요건 확인, Android 패키지 이름 등록, 앱 서명 키 등록, 키 소유권 확인이 포함됩니다.
개요, 사용 사례, 구현 컨텍스트
주요 사용 사례 및 기능
- 자동화된 CI/CD 패키지 이름 등록: 수십 또는 수백 개의 Android 패키지 이름을 프로그래매틱 방식으로 등록합니다 (
CreateAndroidPackage). - 사전 기록 키 정책 검사: Google이 이전에 생태계에서 패키지 이름을 관찰했는지, 특정 서명 인증서를 등록하려면 키 소유권 확인 (
GetAndroidPackageRegistrationPolicy)이 필요한지 프로그래매틱 방식으로 검사합니다. - 자동화된 앱 서명 키 등록 및 소유권 확인: 공개 서명 인증서 SHA-256 디지털 지문(
CreateAndroidPackageKey)을 등록하고, 고유한 확인 질문 토큰(verificationToken)을 가져오고, 단일 요청 또는 재개 가능한 서명된 APK 업로드(VerifyAndroidPackageKeyOwnership)를 사용하여 비공개 키 소유 증명을 자동화합니다. - 프로그래매틱 근거 제출: 소유권 근거를 제출합니다(
JustifyAndroidPackageKeyRegistration). - 상태 모니터링: 개발자 계정, 패키지 이름, 앱 서명 키 (
GetDeveloperAccount,ListDeveloperAccounts,GetAndroidPackage,ListAndroidPackages,GetAndroidPackageKey,ListAndroidPackageKeys) 전반에서 등록 상태를 모니터링합니다.
엔드 투 엔드 구현 워크플로
- UI에서 개발자 신원 한 번 인증: Android Developer Console에서 개발자 신원 인증 (
INDIVIDUAL또는ORGANIZATION)을 완료하여verificationState가VERIFIED가 되도록 합니다. - API 사용 설정 및 인증: Google Cloud 프로젝트에서
androiddeveloperconsole.googleapis.com를 사용 설정하고https://www.googleapis.com/auth/androiddeveloperconsole범위의 사용자 위임 OAuth 2.0 Bearer 액세스 토큰을 가져옵니다. - 개발자 계정 리소스 이름 검색:
GET /v1/developerAccounts(ListDeveloperAccounts)를 호출하여developerAccounts/{developer_account}를 검색하고verificationState가VERIFIED인지 확인합니다. - 패키지 이름의 등록 정책 확인:
GET /v1/developerAccounts/{id}/androidPackages/{pkg}/registrationPolicy(GetAndroidPackageRegistrationPolicy)를 호출하여keySelectionStrategy(SELECT_KEY_FROM_LIST또는USE_ANY_KEY) 및 알려진 이전 서명 키 (knownKeys)를 검사합니다. - Android 패키지 리소스 만들기: 본문
{"name": ""}를 사용하여POST /v1/developerAccounts/{id}/androidPackages?androidPackageId={pkg}(CreateAndroidPackage)를 호출합니다 (DRAFT상태에서 리소스 생성). - 앱 서명 키 디지털 지문 등록: JSON 본문
{"certificateFingerprintSha256": "..."}을 사용하여POST /v1/developerAccounts/{id}/androidPackages/{pkg}/keys(CreateAndroidPackageKey)를 호출합니다. 반환된 상태를 검사합니다.DRAFT: 비공개 키 소유권 증명이 필요하며 응답에는 7단계의 고유한verificationToken가 포함됩니다.IN_REVIEW: 소유권 증빙 및 근거가 자동으로 건너뛰어집니다 (예: Android에서 한 번도 사용된 적이 없는 새 패키지 이름을 등록하는 경우 또는 동일한DeveloperAccount에서 다른 패키지 이름에 대해 이 서명 키의 소유권을 이미 인증한 경우). 7단계와 8단계의 근거 호출을 건너뛰고GetAndroidPackage및GetAndroidPackageKey폴링으로 바로 진행합니다.
- 확인 APK 빌드 및 업로드 (상태가
DRAFT인 경우): 반환된verificationToken문자열을packageName과 일치하는 최소 APK 내의assets/adi-registration.properties에 삽입하고 비공개 앱 서명 키로 서명한 후POST /upload/v1/developerAccounts/{id}/androidPackages/{pkg}/keys/{sha256}:verify(VerifyAndroidPackageKeyOwnership)를 사용하여 업로드합니다. - 근거 제출 (필요한 경우) 및 등록 상태 폴링: 키가
OWNERSHIP_VERIFIED상태이고registrationJustificationRequired가true인 경우POST /v1/developerAccounts/{id}/androidPackages/{pkg}/keys/{sha256}:justifyAndroidPackageKeyRegistration(JustifyAndroidPackageKeyRegistration)를 호출합니다.state가REGISTERED에 도달할 때까지GetAndroidPackage및GetAndroidPackageKey를 폴링합니다.
키 지문 및 인증 APK를 준비하기 위한 로컬 CLI 명령어
키 저장소에서 SHA-256 인증서 지문 추출 (
keytool):keytool -list -v -keystore release-key.jks -alias my-key-alias빌드된 APK (
apksigner)에서 SHA-256 서명 인증서 다이제스트 확인:apksigner verify --print-certs app-release.apk업로드 전에 APK 패키지 이름과 삽입된 토큰 파일 (
aapt2및unzip)을 검사합니다.aapt2 dump badging app-release.apk | head -n 1 unzip -p app-release.apk assets/adi-registration.properties
Android Developer Console UI 및 API 기능
| 작업 | Android Developer Console 웹 UI (android.google.com/developerconsole) |
Android Developer Console API |
|---|---|---|
| 개발자 본인 인증 (KYC/KYB) 및 수수료 결제 | 지원됨 (일회성 기본 요건 필요) | API를 사용한 지원 안 됨 (GetDeveloperAccount 및 ListDeveloperAccounts를 사용한 읽기 전용 상태 확인) |
| 연결된 개발자 계정 보기 | 콘솔 헤더의 계정 전환 도구 | GET /v1/developerAccounts(ListDeveloperAccounts) |
| 패키지 이름의 이전 서명 키 및 정책 검사 | '패키지 이름 등록' 마법사 중에 표시됨 | GET /v1/.../registrationPolicy(GetAndroidPackageRegistrationPolicy) |
| 새 Android 패키지 이름 등록 | 패키지 이름 > 패키지 이름 등록 | POST /v1/{parent}/androidPackages?androidPackageId=...(CreateAndroidPackage) |
| 등록된 패키지 이름 및 초안 패키지 이름 보기 또는 나열 | 패키지 이름 대시보드 표 | GET /v1/{name} (GetAndroidPackage), GET /v1/{parent}/androidPackages (ListAndroidPackages) |
| 앱 서명 키 추가 및 챌린지 토큰 생성 | 패키지 세부정보 > 서명 키 추가 | POST /v1/{parent}/keys(CreateAndroidPackageKey) |
비공개 키 소유권 증명 (adi-registration.properties) |
콘솔 UI에서 서명된 스니펫 APK 업로드 | POST /upload/v1/{name}:verify(VerifyAndroidPackageKeyOwnership) |
| 키에 수동 검토가 필요한 경우 근거 제출 | 키 등록 워크플로 중 텍스트 프롬프트 | POST /v1/{name}:justifyAndroidPackageKeyRegistration(JustifyAndroidPackageKeyRegistration) |
서비스 구성 및 인증
모든 API 요청은 HTTPS를 사용해야 하며 Android Developer Console에서 개발자 본인 인증을 완료한 Google 계정의 OAuth 2.0 웹 서버 흐름을 사용하여 가져온 Authorization: Bearer
ACCESS_TOKEN 헤더를 포함해야 합니다.
| 속성 | 값 |
|---|---|
| 기본 REST 엔드포인트 | https://androiddeveloperconsole.googleapis.com |
| 미디어 업로드 엔드포인트 | https://androiddeveloperconsole.googleapis.com/upload |
| API 버전 | v1 |
| 필수 OAuth 2.0 범위 | https://www.googleapis.com/auth/androiddeveloperconsole |
| 기본 할당량 한도 | Google Cloud 프로젝트별 메서드당 일일 요청 2,000개 |
API 리소스 및 엔드포인트
Android Developer Console API는 다음 계층 구조로 리소스를 구성합니다.
DeveloperAccount(developerAccounts/{developer_account})AndroidPackage(developerAccounts/{developer_account}/androidPackages/{android_package})AndroidPackageRegistrationPolicy(developerAccounts/{developer_account}/androidPackages/{android_package}/registrationPolicy)AndroidPackageKey(developerAccounts/{developer_account}/androidPackages/{android_package}/keys/{key})
리소스: DeveloperAccount
개발자 ID와 연결된 Android Developer Console의 계정을 나타냅니다.
| 필드 | 유형 | 설명 |
|---|---|---|
name |
string |
식별자. developerAccounts/{developer_account} 형식의 리소스 이름입니다. |
displayName |
string |
출력 전용입니다. 개발자 계정과 연결된, 사람이 읽을 수 있는 이름 (개인 이름 또는 조직 이름)입니다. |
verificationState |
enum (VerificationState) |
출력 전용입니다. 계정의 현재 개발자 본인 인증 상태입니다. |
Enum: DeveloperAccount.VerificationState
| 값 | 설명 |
|---|---|
VERIFIED |
Developer 본인 인증이 완료되었습니다. 계정에서 패키지 이름과 앱 서명 키를 등록할 수 있습니다. |
NOT_VERIFIED |
Android Developer Console에서 개발자 본인 인증이 완료되지 않았습니다. |
메서드: DeveloperAccount
| 메서드 | HTTP 요청 | 설명 |
|---|---|---|
GetDeveloperAccount |
GET /v1/{name=developerAccounts/*} |
단일 DeveloperAccount의 메타데이터 및 인증 상태를 가져옵니다. |
ListDeveloperAccounts |
GET /v1/developerAccounts |
인증된 Google 계정에서 액세스할 수 있는 모든 DeveloperAccount 객체를 나열합니다 (페이지로 나누지 않음). |
리소스: AndroidPackage
DeveloperAccount에 등록되었거나 등록 중인 Android 패키지 이름을 나타냅니다.
| 필드 | 유형 | 설명 |
|---|---|---|
name |
string |
식별자. developerAccounts/{developer_account}/androidPackages/{android_package} 형식의 리소스 이름입니다. 여기서 {android_package}은 Android 패키지 이름입니다 (예: com.example.myapp). |
packageName |
string |
출력 전용입니다. Android 패키지 이름 (예: com.example.myapp) |
state |
enum (AndroidPackage.State) |
출력 전용입니다. 패키지 이름의 현재 등록 수명 주기 상태입니다. |
registeredAppStore |
boolean |
출력 전용입니다. 이 패키지 이름이 현재 등록된 앱 스토어로 활성 상태인지 여부를 나타냅니다. |
Enum: AndroidPackage.State
| 값 | 설명 |
|---|---|
DRAFT |
패키지 이름 리소스가 생성되었으며 앱 서명 키 등록 또는 소유권 확인이 아직 진행 중입니다. |
IN_REVIEW |
패키지 이름 등록 및 필수 키 사유가 제출되었으며 Google에서 검토 중입니다. 패키지는 CreateAndroidPackageKey 직후 (키 소유권 확인을 건너뛰는 경우, 동일한 DeveloperAccount의 다른 패키지 이름에 대해 키가 이미 확인된 경우 포함) 또는 VerifyAndroidPackageKeyOwnership 및 필요한 경우 JustifyAndroidPackageKeyRegistration를 완료한 후 DRAFT에서 IN_REVIEW로 전환됩니다. |
REGISTERED |
패키지 이름이 Android 개발자 인증을 위해 이 개발자 계정에 활성 상태로 등록되어 있습니다. |
PENDING_TRANSFER |
패키지 이름이 다른 개발자 계정으로의 소유권 이전 완료를 기다리고 있습니다. |
리소스: AndroidPackageRegistrationPolicy
패키지 이름에 대해 감지된 이전 공개 서명 키와 지정된 서명 키로 패키지 이름을 등록하는 데 서면 근거가 필요한지 여부를 설명하는 GetAndroidPackageRegistrationPolicy에서 반환하는 싱글톤 리소스입니다.
| 필드 | 유형 | 설명 |
|---|---|---|
name |
string |
식별자. developerAccounts/{developer_account}/androidPackages/{android_package}/registrationPolicy 형식의 리소스 이름입니다. |
knownKeys[] |
object (KnownKey) |
이 패키지 이름으로 앱을 배포하는 것으로 이전에 확인된 이전 앱 서명 키 목록으로, certificateFingerprintSha256를 기준으로 사전순으로 정렬됩니다. |
knownKeys[].certificateFingerprintSha256 |
string |
출력 전용입니다. 이전 서명 인증서의 정규화된 64자 소문자 16진수 SHA-256 디지털 지문입니다 (콜론 없음). |
knownKeys[].justificationRequirement |
enum (JustificationRequirement) |
출력 전용입니다. 이 키를 등록하려면 JustifyAndroidPackageKeyRegistration (REQUIRED 또는 NOT_REQUIRED)를 호출해야 하는지 나타냅니다. 서명 키가 이전에 동일한 DeveloperAccount의 다른 패키지 이름에서 확인된 경우 justificationRequirement가 REQUIRED인 경우에도 VerifyAndroidPackageKeyOwnership와 JustifyAndroidPackageKeyRegistration가 모두 건너뛰어집니다. |
keySelectionStrategy |
enum (KeySelectionStrategy) |
출력 전용입니다. 이 패키지 이름을 등록하기 위한 키 선택 정책: SELECT_KEY_FROM_LIST (knownKeys의 키를 등록해야 함) 또는 USE_ANY_KEY (개발자가 소유한 유효한 앱 서명 키를 등록할 수 있음) |
enum: KnownKey.JustificationRequirement
| 값 | 설명 |
|---|---|
REQUIRED |
이 알려진 키를 등록하려면 VerifyAndroidPackageKeyOwnership를 완료한 후 JustifyAndroidPackageKeyRegistration를 사용하여 서면 근거를 제출해야 합니다 (키가 동일한 DeveloperAccount의 다른 패키지 이름에서 이전에 확인된 경우는 제외되며, 이 경우 VerifyAndroidPackageKeyOwnership 및 JustifyAndroidPackageKeyRegistration가 모두 건너뛰어짐). |
NOT_REQUIRED |
이 알려진 키를 등록하는 데는 사유가 필요하지 않습니다. 키는 VerifyAndroidPackageKeyOwnership 후에 (또는 키가 이전에 동일한 DeveloperAccount의 다른 패키지 이름에서 확인된 경우 CreateAndroidPackageKey 직후에) IN_REVIEW로 직접 전환됩니다. |
Enum: AndroidPackageRegistrationPolicy.KeySelectionStrategy
| 값 | 설명 |
|---|---|
SELECT_KEY_FROM_LIST |
호출자는 knownKeys에 나열된 이전 키 중 하나를 등록해야 합니다. |
USE_ANY_KEY |
호출자는 knownKeys의 키 외에도 이전에 Android 생태계에서 관찰되지 않은 유효한 앱 서명 키를 등록할 수 있습니다. |
메서드: AndroidPackage
| 메서드 | HTTP 요청 | 설명 |
|---|---|---|
GetAndroidPackageRegistrationPolicy |
GET /v1/{name=developerAccounts/*/androidPackages/*/registrationPolicy} |
패키지 이름의 키 선택 전략과 알려진 이전 서명 키를 가져옵니다. |
CreateAndroidPackage |
POST /v1/{parent=developerAccounts/*}/androidPackages?androidPackageId={package_name} |
DRAFT 상태에서 새 AndroidPackage 리소스를 만들어 패키지 이름 등록을 시작합니다. |
GetAndroidPackage |
GET /v1/{name=developerAccounts/*/androidPackages/*} |
기존 AndroidPackage의 세부정보와 현재 등록 상태를 가져옵니다. |
ListAndroidPackages |
GET /v1/{parent=developerAccounts/*}/androidPackages |
DeveloperAccount 아래에 있는 AndroidPackage 객체를 나열합니다 (pageSize 최대 1000, pageToken). |
리소스: AndroidPackageKey
AndroidPackage와 연결된 공개 앱 서명 인증서 지문을 나타내고 소유권 확인 및 등록 검토 상태를 추적합니다.
| 필드 | 유형 | 설명 |
|---|---|---|
name |
string |
식별자. developerAccounts/{developer_account}/androidPackages/{android_package}/keys/{key} 형식의 서버 할당 리소스 이름입니다. 여기서 {key}은 콜론이 없는 정규화된 64자 소문자 16진수 SHA-256 지문입니다. CreateAndroidPackageKey를 호출할 때 생략하거나 비워 두어야 합니다. |
certificateFingerprintSha256 |
string |
필수 항목입니다. 변경할 수 없습니다. 앱 서명 인증서의 SHA-256 해시입니다. CreateAndroidPackageKey의 입력에서 일반 64자 16진수 (60e860e8...) 또는 콜론으로 구분된 16진수 (60:E8:60:E8:...)를 허용합니다. 출력에서는 항상 콜론이 없는 64자 소문자 16진수로 정규화됩니다. |
state |
enum (AndroidPackageKey.State) |
출력 전용입니다. 키의 현재 확인 및 등록 수명 주기 상태입니다. |
verificationToken |
string |
출력 전용입니다. Google에서 생성한 고유한 챌린지 토큰입니다. 상태가 DRAFT인 경우에만 사용됩니다 (CreateAndroidPackageKey에서 키를 IN_REVIEW로 직접 전환하는 경우 무시할 수 있음). 상태가 DRAFT인 경우 서명된 APK의 assets/adi-registration.properties 내에 이 문자열을 삽입하여 VerifyAndroidPackageKeyOwnership를 완료합니다. |
registrationJustificationRequired |
boolean |
출력 전용입니다. true이고 키가 OWNERSHIP_VERIFIED 상태인 경우 등록이 IN_REVIEW로 진행되기 전에 JustifyAndroidPackageKeyRegistration를 사용하여 서면 근거를 제출해야 합니다. CreateAndroidPackageKey가 키를 IN_REVIEW로 직접 전환하는 경우 (키가 이전에 동일한 DeveloperAccount의 다른 패키지 이름에서 확인되었기 때문) 근거가 건너뛰어집니다. |
Enum: AndroidPackageKey.State
| 값 | 설명 |
|---|---|
DRAFT |
키 리소스가 생성되었으며, 이 DeveloperAccount의 패키지 이름에서 이 키의 소유권이 아직 확인되지 않았으므로 서명된 APK 업로드 (VerifyAndroidPackageKeyOwnership)를 사용한 비공개 키 소유 증명이 여전히 필요합니다. |
OWNERSHIP_VERIFIED |
서명된 APK 업로드를 사용하여 비공개 키 소유권이 확인되었습니다. registrationJustificationRequired가 true인 경우 검토가 시작되기 전에 사유가 필요합니다. |
IN_REVIEW |
Google에서 키 등록을 검토 중입니다. 소유권 증명이 필요하지 않은 경우 (예: Android에서 사용된 적이 없는 새 패키지 이름 또는 동일한 DeveloperAccount의 다른 패키지 이름에서 이전에 키가 확인된 경우, 이 경우 JustifyAndroidPackageKeyRegistration도 건너뜀) CreateAndroidPackageKey 직후에, VerifyAndroidPackageKeyOwnership 직후에 (registrationJustificationRequired가 false인 경우) 또는 JustifyAndroidPackageKeyRegistration 후에 (registrationJustificationRequired가 true인 경우) 키가 여기로 전환됩니다. |
REGISTERED |
앱 서명 키가 Android 개발자 인증을 위해 이 패키지 이름에 활성 상태로 등록되어 있습니다. |
PENDING_TRANSFER |
앱 서명 키 등록이 이전 완료를 기다리고 있습니다. |
메서드: AndroidPackageKey
| 메서드 | HTTP 요청 | 설명 |
|---|---|---|
CreateAndroidPackageKey |
POST /v1/{parent=developerAccounts/*/androidPackages/*}/keys |
AndroidPackage 아래에 새 앱 서명 인증서 SHA-256 지문을 등록합니다. DRAFT 상태 (VerifyAndroidPackageKeyOwnership를 사용한 소유권 증명이 필요한 경우) 또는 IN_REVIEW 상태 (Android에서 사용된 적이 없는 새 패키지 이름이나 동일한 DeveloperAccount의 다른 패키지 이름에서 이미 확인된 키와 같이 소유권 확인을 건너뛰는 경우)로 키를 반환합니다. |
GetAndroidPackageKey |
GET /v1/{name=developerAccounts/*/androidPackages/*/keys/*} |
특정 AndroidPackageKey의 상태, 디지털 지문, 확인 메타데이터를 가져옵니다. |
ListAndroidPackageKeys |
GET /v1/{parent=developerAccounts/*/androidPackages/*}/keys |
AndroidPackage (pageSize 최대 1000, pageToken)에 등록된 모든 AndroidPackageKey 객체를 나열합니다. |
VerifyAndroidPackageKeyOwnership |
POST /upload/v1/{name=developerAccounts/*/androidPackages/*/keys/*}:verify |
assets/adi-registration.properties에 verificationToken이 포함된 서명된 최소 APK를 업로드하여 비공개 키 소유권을 확인하고 검토를 위해 준비된 키를 제출합니다. |
JustifyAndroidPackageKeyRegistration |
POST /v1/{name=developerAccounts/*/androidPackages/*/keys/*}:justifyAndroidPackageKeyRegistration |
registrationJustificationRequired가 true인 경우 추가 근거 컨텍스트를 제출하고 검토를 위해 확인된 키를 제출합니다. |
오류 처리
API 요청이 실패하면 Android Developer Console API는 HTTP 4xx 또는 5xx 상태 코드와 표준 google.rpc.Status JSON 오류 본문을 반환합니다.
{
"error": {
"code": 400,
"message": "Invalid certificate fingerprint SHA256 format.",
"status": "INVALID_ARGUMENT",
"details": []
}
}
HTTP 상태 코드 및 일반적인 해결 방법
| HTTP 코드 | gRPC 상태 | 일반적인 원인 | 해상도 |
|---|---|---|---|
400 Bad Request |
INVALID_ARGUMENT |
Java 스타일 androidPackageId가 누락되었거나 잘못되었습니다. certificateFingerprintSha256 형식이 잘못되었습니다. CreateAndroidPackage 또는 CreateAndroidPackageKey의 name 필드가 비어 있지 않습니다. 업로드된 APK가 서명되지 않았거나, 손상되었거나, assets/adi-registration.properties가 누락되었거나, 일치하는 verificationToken가 누락되었거나, 일치하지 않는 인증서로 서명되었습니다. |
리소스 스키마를 기준으로 요청 형식을 검증하고, 생성 호출 시 name를 생략하거나 비워 두고, 업로드하기 전에 apksigner verify --print-certs 및 unzip -p app-release.apk assets/adi-registration.properties를 사용하여 APK 서명과 삽입된 토큰을 확인합니다. |
400 Bad Request |
FAILED_PRECONDITION |
DeveloperAccount에 verificationState: NOT_VERIFIED이(가) 있습니다. 키 선택이 AndroidPackageRegistrationPolicy(SELECT_KEY_FROM_LIST)을(를) 위반합니다. 부적격 상태에서 VerifyAndroidPackageKeyOwnership 또는 JustifyAndroidPackageKeyRegistration을(를) 호출합니다. |
Android Developer Console에서 개발자 본인 인증을 완료하고 먼저 GetAndroidPackageRegistrationPolicy를 확인한 후 리소스의 현재 state를 검사합니다. |
401 Unauthorized |
UNAUTHENTICATED |
OAuth 2.0 Bearer 액세스 토큰이 누락되었거나 만료되었거나 잘못되었거나 API 키 또는 서비스 계정을 사용하여 인증을 시도했습니다. | 범위가 https://www.googleapis.com/auth/androiddeveloperconsole인 새로운 사용자 위임 OAuth 2.0 Bearer 액세스 토큰을 가져옵니다. |
403 Forbidden |
PERMISSION_DENIED |
인증된 사용자에게 대상 DeveloperAccount 또는 AndroidPackage에 대한 권한이 없거나 Google Cloud 프로젝트에서 Android Developer Console API가 사용 설정되어 있지 않습니다. |
ListDeveloperAccounts를 사용하여 계정 멤버십을 확인하고 Google Cloud 콘솔에서 androiddeveloperconsole.googleapis.com가 사용 설정되어 있는지 확인합니다. |
404 Not Found |
NOT_FOUND |
지정된 DeveloperAccount, AndroidPackage 또는 AndroidPackageKey 리소스 경로가 없습니다. |
ListDeveloperAccounts, ListAndroidPackages 또는 ListAndroidPackageKeys를 사용하여 리소스 경로를 확인합니다. {key} ID는 콜론 없이 소문자 16진수를 사용해야 합니다. |
409 Conflict |
ALREADY_EXISTS |
패키지 이름 또는 SHA-256 인증서 지문이 이 개발자 계정 또는 다른 개발자 계정에 이미 등록되어 있습니다. | GetAndroidPackage 또는 GetAndroidPackageKey를 사용하여 기존 등록을 검사하거나 GetAndroidPackageRegistrationPolicy를 사용하여 이전 소유권을 확인합니다. |
429 Too Many Requests |
RESOURCE_EXHAUSTED |
Google Cloud 프로젝트당 일일 요청 2,000개의 메서드별 할당량을 초과했습니다. |
지터로 지수 백오프를 구현하고 고주파 폴링 루프를 방지합니다. |
500/503 |
INTERNAL/UNAVAILABLE |
일시적인 백엔드 오류 또는 일시적인 서비스 사용 불가 | 잘린 지수 백오프로 멱등 요청을 재시도합니다. |
HTTP 요청 및 응답 예시
ACCESS_TOKEN, 1234567890, com.example.myapp, 60e860e8...와 같은 플레이스홀더 값을 자체 값으로 바꿉니다.
1. GetDeveloperAccount
curl -X GET \
-H "Authorization: Bearer ACCESS_TOKEN" \
"https://androiddeveloperconsole.googleapis.com/v1/developerAccounts/1234567890"대답:
{
"name": "developerAccounts/1234567890",
"displayName": "Example Developer",
"verificationState": "VERIFIED"
}
2. ListDeveloperAccounts
curl -X GET \
-H "Authorization: Bearer ACCESS_TOKEN" \
"https://androiddeveloperconsole.googleapis.com/v1/developerAccounts"대답:
{
"developerAccounts": [
{
"name": "developerAccounts/1234567890",
"displayName": "Example Developer",
"verificationState": "VERIFIED"
}
]
}
3. GetAndroidPackageRegistrationPolicy
curl -X GET \
-H "Authorization: Bearer ACCESS_TOKEN" \
"https://androiddeveloperconsole.googleapis.com/v1/developerAccounts/1234567890/androidPackages/com.example.myapp/registrationPolicy"대답:
{
"name": "developerAccounts/1234567890/androidPackages/com.example.myapp/registrationPolicy",
"knownKeys": [
{
"certificateFingerprintSha256": "60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123",
"justificationRequirement": "NOT_REQUIRED"
}
],
"keySelectionStrategy": "SELECT_KEY_FROM_LIST"
}
4. CreateAndroidPackage
curl -X POST \
-H "Authorization: Bearer ACCESS_TOKEN" \
-H "Content-Type: application/json; charset=utf-8" \
-d '{"name": ""}' \
"https://androiddeveloperconsole.googleapis.com/v1/developerAccounts/1234567890/androidPackages?androidPackageId=com.example.myapp"대답:
{
"name": "developerAccounts/1234567890/androidPackages/com.example.myapp",
"packageName": "com.example.myapp",
"state": "DRAFT",
"registeredAppStore": false
}
5. GetAndroidPackage
curl -X GET \
-H "Authorization: Bearer ACCESS_TOKEN" \
"https://androiddeveloperconsole.googleapis.com/v1/developerAccounts/1234567890/androidPackages/com.example.myapp"대답:
{
"name": "developerAccounts/1234567890/androidPackages/com.example.myapp",
"packageName": "com.example.myapp",
"state": "REGISTERED",
"registeredAppStore": false
}
6. ListAndroidPackages
curl -X GET \
-H "Authorization: Bearer ACCESS_TOKEN" \
"https://androiddeveloperconsole.googleapis.com/v1/developerAccounts/1234567890/androidPackages?pageSize=100"대답:
{
"androidPackages": [
{
"name": "developerAccounts/1234567890/androidPackages/com.example.myapp",
"packageName": "com.example.myapp",
"state": "REGISTERED",
"registeredAppStore": false
}
],
"nextPageToken": ""
}
7. CreateAndroidPackageKey
curl -X POST \
-H "Authorization: Bearer ACCESS_TOKEN" \
-H "Content-Type: application/json; charset=utf-8" \
-d '{
"certificateFingerprintSha256": "60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123"
}' \
"https://androiddeveloperconsole.googleapis.com/v1/developerAccounts/1234567890/androidPackages/com.example.myapp/keys"대답:
{
"name": "developerAccounts/1234567890/androidPackages/com.example.myapp/keys/60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123",
"certificateFingerprintSha256": "60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123",
"state": "DRAFT",
"verificationToken": "token_xyz987654321"
}
8. GetAndroidPackageKey
curl -X GET \
-H "Authorization: Bearer ACCESS_TOKEN" \
"https://androiddeveloperconsole.googleapis.com/v1/developerAccounts/1234567890/androidPackages/com.example.myapp/keys/60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123"대답:
{
"name": "developerAccounts/1234567890/androidPackages/com.example.myapp/keys/60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123",
"certificateFingerprintSha256": "60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123",
"state": "REGISTERED"
}
9. ListAndroidPackageKeys
curl -X GET \
-H "Authorization: Bearer ACCESS_TOKEN" \
"https://androiddeveloperconsole.googleapis.com/v1/developerAccounts/1234567890/androidPackages/com.example.myapp/keys?pageSize=100"대답:
{
"androidPackageKeys": [
{
"name": "developerAccounts/1234567890/androidPackages/com.example.myapp/keys/60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123",
"certificateFingerprintSha256": "60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123",
"state": "REGISTERED"
}
],
"nextPageToken": ""
}
10. VerifyAndroidPackageKeyOwnership
옵션 A: 단일 요청 미디어 업로드
curl -X POST \
-H "Authorization: Bearer ACCESS_TOKEN" \
-H "Content-Type: application/octet-stream" \
--data-binary @app-release.apk \
"https://androiddeveloperconsole.googleapis.com/upload/v1/developerAccounts/1234567890/androidPackages/com.example.myapp/keys/60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123:verify?uploadType=media"옵션 B: 재개 가능한 업로드 프로토콜 (대형 APK 또는 CI/CD에 권장)
1단계: 재개 가능한 업로드 세션을 시작하고 반환된 X-Goog-Upload-URL 헤더를 추출합니다.
curl -i -X POST \
"https://androiddeveloperconsole.googleapis.com/upload/v1/developerAccounts/1234567890/androidPackages/com.example.myapp/keys/60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123:verify" \
-H "Authorization: Bearer ACCESS_TOKEN" \
-H "X-Goog-Upload-Protocol: resumable" \
-H "X-Goog-Upload-Command: start" \
-H "X-Goog-Upload-Header-Content-Length: FILE_SIZE_IN_BYTES" \
-H "X-Goog-Upload-Header-Content-Type: application/vnd.android.package-archive" \
-H "Content-Type: application/json" \
-d '{
"name": "developerAccounts/1234567890/androidPackages/com.example.myapp/keys/60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123"
}'2단계: 서명된 APK 바이너리를 UPLOAD_SESSION_URI에 업로드하고 세션을 완료합니다.
curl -X PUT \
"UPLOAD_SESSION_URI" \
-H "Content-Length: FILE_SIZE_IN_BYTES" \
-H "X-Goog-Upload-Offset: 0" \
-H "X-Goog-Upload-Command: upload, finalize" \
--data-binary "@app-release.apk"대답:
{
"name": "developerAccounts/1234567890/androidPackages/com.example.myapp/keys/60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123",
"certificateFingerprintSha256": "60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123",
"state": "IN_REVIEW"
}
11. JustifyAndroidPackageKeyRegistration
curl -X POST \
-H "Authorization: Bearer ACCESS_TOKEN" \
-H "Content-Type: application/json; charset=utf-8" \
-d '{
"justification": "We previously distributed com.example.myapp directly from https://downloads.example.com and are migrating to our rotated production key."
}' \
"https://androiddeveloperconsole.googleapis.com/v1/developerAccounts/1234567890/androidPackages/com.example.myapp/keys/60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123:justifyAndroidPackageKeyRegistration"대답:
{
"name": "developerAccounts/1234567890/androidPackages/com.example.myapp/keys/60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123",
"certificateFingerprintSha256": "60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123",
"state": "IN_REVIEW",
"registrationJustificationRequired": true
}
추가 리소스
- Android Developer Console API로 패키지 이름 등록하기
- Android 개발자 ID 상태 API로 앱 등록 상태 확인하기
- Android Developer Console에 등록하기
- Google Play Console에 등록하기