Android Developer Console API

Android Developer Console API เป็นบริการ RESTful ที่ช่วยให้นักพัฒนาแอปที่ได้รับการยืนยันสามารถทำให้เวิร์กโฟลว์การยืนยันนักพัฒนาแอป Android เป็นแบบอัตโนมัติใน Android Developer Console ซึ่งรวมถึงการดึงข้อมูลบัญชีนักพัฒนาแอป การตรวจสอบข้อกำหนดของการได้รับสิทธิ์ที่สำคัญ การลงทะเบียนชื่อแพ็กเกจ Android การลงทะเบียนคีย์ App Signing และการยืนยันการเป็นเจ้าของคีย์

ภาพรวม กรณีการใช้งาน และบริบทการใช้งาน

กรณีการใช้งานและฟีเจอร์หลัก

  • การลงทะเบียนชื่อแพ็กเกจ CI/CD อัตโนมัติ: ลงทะเบียนชื่อแพ็กเกจ Android หลายสิบหรือหลายร้อยรายการแบบเป็นโปรแกรม (CreateAndroidPackage)
  • การตรวจสอบนโยบายคีย์ที่ผ่านมาล่วงหน้า: ตรวจสอบแบบเป็นโปรแกรมว่า Google เคยพบชื่อแพ็กเกจในระบบนิเวศหรือไม่ และการลงทะเบียนใบรับรองการลงนามที่เฉพาะเจาะจงต้องมีการยืนยันการเป็นเจ้าของคีย์ (GetAndroidPackageRegistrationPolicy) หรือไม่
  • การลงทะเบียนคีย์ App Signing และการยืนยันการเป็นเจ้าของแบบอัตโนมัติ: ลงทะเบียนลายนิ้วมือ SHA-256 ของใบรับรองการลงนามสาธารณะ (CreateAndroidPackageKey) ดึงโทเค็นคำถามเพื่อยืนยันตัวตนที่ไม่ซ้ำกัน (verificationToken) และพิสูจน์การครอบครองคีย์ส่วนตัวโดยอัตโนมัติโดยใช้ การอัปโหลด APK ที่ลงนามแบบคำขอเดียวหรือแบบดำเนินการต่อได้ (VerifyAndroidPackageKeyOwnership)
  • การส่งเหตุผลรองรับแบบเป็นโปรแกรม: ส่งเหตุผลรองรับการเป็นเจ้าของ (JustifyAndroidPackageKeyRegistration)
  • การตรวจสอบสถานะ: ตรวจสอบสถานะการลงทะเบียนในบัญชีนักพัฒนาแอป ชื่อแพ็กเกจ และคีย์ App Signing (GetDeveloperAccount, ListDeveloperAccounts, GetAndroidPackage, ListAndroidPackages, GetAndroidPackageKey, ListAndroidPackageKeys)

เวิร์กโฟลว์การติดตั้งใช้งานตั้งแต่ต้นจนจบ

  1. ยืนยันตัวตนของนักพัฒนาแอปใน UI เพียงครั้งเดียว: ยืนยันตัวตนของนักพัฒนาแอป (INDIVIDUAL หรือ ORGANIZATION) ให้เสร็จสมบูรณ์ใน Android Developer Console เพื่อให้ verificationState VERIFIED
  2. เปิดใช้ API และตรวจสอบสิทธิ์: เปิดใช้ androiddeveloperconsole.googleapis.com ในโปรเจ็กต์ Google Cloud และรับโทเค็นเพื่อการเข้าถึง Bearer ของ OAuth 2.0 ที่ได้รับมอบสิทธิ์จากผู้ใช้ซึ่งมีขอบเขต https://www.googleapis.com/auth/androiddeveloperconsole
  3. ค้นหาชื่อทรัพยากรของบัญชีนักพัฒนาแอป: เรียกใช้ GET /v1/developerAccounts (ListDeveloperAccounts) เพื่อดึงข้อมูล developerAccounts/{developer_account} และยืนยันว่า verificationState คือ VERIFIED
  4. ตรวจสอบนโยบายการลงทะเบียนสำหรับชื่อแพ็กเกจ: เรียกใช้ GET /v1/developerAccounts/{id}/androidPackages/{pkg}/registrationPolicy (GetAndroidPackageRegistrationPolicy) เพื่อตรวจสอบ keySelectionStrategy (SELECT_KEY_FROM_LIST หรือ USE_ANY_KEY) และคีย์ Signing ที่รู้จักในอดีต (knownKeys)
  5. สร้างทรัพยากรแพ็กเกจ Android: เรียกใช้ POST /v1/developerAccounts/{id}/androidPackages?androidPackageId={pkg} (CreateAndroidPackage) โดยมีเนื้อหา {"name": ""} (สร้างทรัพยากรในสถานะ DRAFT)
  6. ลงทะเบียนลายนิ้วมือของคีย์ App Signing: เรียกใช้ POST /v1/developerAccounts/{id}/androidPackages/{pkg}/keys (CreateAndroidPackageKey) ด้วยเนื้อหา JSON {"certificateFingerprintSha256": "..."} ตรวจสอบสถานะที่แสดงผลดังนี้
    • DRAFT: ต้องมีหลักฐานการเป็นเจ้าของคีย์ส่วนตัว และการตอบกลับจะมี verificationToken ที่ไม่ซ้ำกันสำหรับขั้นตอนที่ 7
    • IN_REVIEW: ระบบจะข้ามหลักฐานการเป็นเจ้าของและเหตุผลโดยอัตโนมัติ (เช่น เมื่อลงทะเบียนชื่อแพ็กเกจใหม่ที่ไม่เคยเห็นใน Android หรือเมื่อคุณยืนยันการเป็นเจ้าของคีย์ Signing นี้สำหรับชื่อแพ็กเกจอื่นใน DeveloperAccount เดียวกันแล้ว) ข้ามขั้นตอนที่ 7 และการเรียกเหตุผลในขั้นตอนที่ 8 แล้วดำเนินการต่อโดยตรงไปยังการสำรวจความคิดเห็น GetAndroidPackage และ GetAndroidPackageKey
  7. สร้างและอัปโหลด APK สำหรับการยืนยัน (หากสถานะเป็น DRAFT): ฝังสตริง verificationToken ที่แสดงผลลงใน assets/adi-registration.properties ภายใน APK ขั้นต่ำที่ตรงกับ packageName, รับรองด้วยคีย์ App Signing ส่วนตัว และอัปโหลดโดยใช้ POST /upload/v1/developerAccounts/{id}/androidPackages/{pkg}/keys/{sha256}:verify (VerifyAndroidPackageKeyOwnership)
  8. ส่งเหตุผล (หากจำเป็น) และตรวจสอบสถานะการลงทะเบียน: หากคีย์อยู่ในสถานะ OWNERSHIP_VERIFIED และ registrationJustificationRequired เป็น true ให้เรียกใช้ POST /v1/developerAccounts/{id}/androidPackages/{pkg}/keys/{sha256}:justifyAndroidPackageKeyRegistration (JustifyAndroidPackageKeyRegistration) ตรวจสอบ GetAndroidPackage และ GetAndroidPackageKey จนกว่า state จะเป็น REGISTERED

คำสั่ง CLI ในเครื่องสำหรับการเตรียมฟิงเกอร์ปรินต์ของคีย์และ APK สำหรับการยืนยัน

  • ดึงข้อมูลลายนิ้วมือของใบรับรอง SHA-256 จาก Keystore (keytool):

    keytool -list -v -keystore release-key.jks -alias my-key-alias
  • ยืนยันไดเจสต์ใบรับรองการลงนาม SHA-256 ใน APK ที่สร้างขึ้น (apksigner)

    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

ความสามารถของ UI และ API ของ Android Developer Console

งาน UI บนเว็บของ Android Developer Console (android.google.com/developerconsole) Android Developer Console API
การยืนยันตัวตนของนักพัฒนาแอป (KYC/KYB) และการชำระค่าธรรมเนียม รองรับ (ต้องมีข้อกำหนดเบื้องต้นแบบครั้งเดียว) ไม่รองรับการใช้ API (การตรวจสอบสถานะแบบอ่านอย่างเดียวโดยใช้ GetDeveloperAccount และ ListDeveloperAccounts)
ดูบัญชีนักพัฒนาแอปที่ลิงก์ ตัวสลับบัญชีในส่วนหัวของคอนโซล GET /v1/developerAccounts (ListDeveloperAccounts)
ตรวจสอบคีย์ Signing และนโยบายที่ผ่านมาสำหรับชื่อแพ็กเกจ แสดงระหว่างวิซาร์ด "ลงทะเบียนชื่อแพ็กเกจ" GET /v1/.../registrationPolicy (GetAndroidPackageRegistrationPolicy)
ลงทะเบียนชื่อแพ็กเกจ Android ใหม่ ชื่อแพ็กเกจ > ลงทะเบียนชื่อแพ็กเกจ POST /v1/{parent}/androidPackages?androidPackageId=... (CreateAndroidPackage)
ดูหรือแสดงรายการชื่อแพ็กเกจที่ลงทะเบียนและฉบับร่าง ตารางแดชบอร์ดชื่อแพ็กเกจ GET /v1/{name} (GetAndroidPackage), GET /v1/{parent}/androidPackages (ListAndroidPackages)
เพิ่มคีย์ App Signing และสร้างโทเค็นคำถาม รายละเอียดแพ็กเกจ > เพิ่มคีย์ Signing POST /v1/{parent}/keys (CreateAndroidPackageKey)
พิสูจน์การเป็นเจ้าของคีย์ส่วนตัว (adi-registration.properties) อัปโหลด APK ของข้อมูลโค้ดที่รับรองแล้วใน UI ของคอนโซล POST /upload/v1/{name}:verify (VerifyAndroidPackageKeyOwnership)
ส่งเหตุผลเมื่อคีย์ต้องได้รับการตรวจสอบด้วยตนเอง พรอมต์ข้อความระหว่างเวิร์กโฟลว์การลงทะเบียนคีย์ POST /v1/{name}:justifyAndroidPackageKeyRegistration (JustifyAndroidPackageKeyRegistration)

การกำหนดค่าบริการและการตรวจสอบสิทธิ์

คำขอ API ทั้งหมดต้องใช้ HTTPS และมีส่วนหัว Authorization: Bearer ACCESS_TOKEN ที่ได้รับโดยใช้ขั้นตอนของเว็บเซิร์ฟเวอร์ OAuth 2.0 สำหรับบัญชี Google ที่ยืนยันตัวตนนักพัฒนาแอปใน Android Developer Console เสร็จสมบูรณ์แล้ว

พร็อพเพอร์ตี้ ค่า
ปลายทาง REST พื้นฐาน https://androiddeveloperconsole.googleapis.com
ปลายทางการอัปโหลดสื่อ https://androiddeveloperconsole.googleapis.com/upload
เวอร์ชัน API v1
ขอบเขต OAuth 2.0 ที่จำเป็น https://www.googleapis.com/auth/androiddeveloperconsole
ขีดจำกัดโควต้าเริ่มต้น คำขอ 2,000 รายการต่อวันต่อโปรเจ็กต์ Google Cloud ต่อเมธอด

ทรัพยากรและปลายทาง 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

แสดงบัญชีใน Android Developer Console ที่เชื่อมโยงกับข้อมูลประจำตัวของนักพัฒนาแอป

ช่อง ประเภท คำอธิบาย
name string ตัวระบุ ชื่อทรัพยากรในรูปแบบ developerAccounts/{developer_account}
displayName string เอาต์พุตเท่านั้น ชื่อที่มนุษย์อ่านได้ซึ่งเชื่อมโยงกับบัญชีนักพัฒนาแอป (ชื่อบุคคลธรรมดาหรือชื่อองค์กร)
verificationState enum (VerificationState) เอาต์พุตเท่านั้น สถานะการยืนยันตัวตนของนักพัฒนาแอปปัจจุบันของบัญชี

Enum: DeveloperAccount.VerificationState

ค่า คำอธิบาย
VERIFIED การยืนยันตัวตนของนักพัฒนาแอปเสร็จสมบูรณ์แล้ว บัญชีสามารถลงทะเบียนชื่อแพ็กเกจและคีย์ App Signing ได้
NOT_VERIFIED การยืนยันตัวตนของนักพัฒนาแอปยังไม่เสร็จสมบูรณ์ใน Android Developer Console

วิธีการ: DeveloperAccount

วิธีการ คำขอ HTTP คำอธิบาย
GetDeveloperAccount GET /v1/{name=developerAccounts/*} เรียกข้อมูลเมตาและสถานะการยืนยันสำหรับ DeveloperAccount รายการเดียว
ListDeveloperAccounts GET /v1/developerAccounts แสดงรายการออบเจ็กต์ DeveloperAccount ทั้งหมดที่บัญชี Google ที่ตรวจสอบสิทธิ์แล้วเข้าถึงได้ (ไม่มีการแบ่งหน้า)

ทรัพยากร: AndroidPackage

แสดงชื่อแพ็กเกจ Android ที่ลงทะเบียนหรือกำลังลงทะเบียนภายใต้ DeveloperAccount

ช่อง ประเภท คำอธิบาย
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 เอาต์พุตเท่านั้น ระบุว่าชื่อแพ็กเกจนี้ใช้งานอยู่ในปัจจุบันในฐานะ App Store ที่ลงทะเบียนหรือไม่

Enum: AndroidPackage.State

ค่า คำอธิบาย
DRAFT สร้างทรัพยากรชื่อแพ็กเกจแล้ว และการลงทะเบียนคีย์ App Signing หรือการยืนยันการเป็นเจ้าของยังอยู่ระหว่างดำเนินการ
IN_REVIEW ส่งการลงทะเบียนชื่อแพ็กเกจและการให้เหตุผลเกี่ยวกับคีย์ที่จำเป็นแล้ว และ Google กำลังตรวจสอบ แพ็กเกจจะเปลี่ยนสถานะจากDRAFTเป็นIN_REVIEWทันทีเมื่อCreateAndroidPackageKey (เมื่อข้ามการยืนยันการเป็นเจ้าของคีย์ รวมถึงเมื่อคีย์ได้รับการยืนยันแล้วสำหรับชื่อแพ็กเกจอื่นในDeveloperAccountเดียวกัน) หรือหลังจากทำVerifyAndroidPackageKeyOwnershipและJustifyAndroidPackageKeyRegistration (หากจำเป็น) เสร็จสมบูรณ์
REGISTERED ชื่อแพ็กเกจได้รับการลงทะเบียนอย่างสม่ำเสมอกับบัญชีนักพัฒนาแอปนี้สำหรับการยืนยันนักพัฒนาแอป Android
PENDING_TRANSFER ชื่อแพ็กเกจกำลังรอการโอนความเป็นเจ้าของไปยังบัญชีนักพัฒนาแอปอื่นให้เสร็จสมบูรณ์

ทรัพยากร: AndroidPackageRegistrationPolicy

ทรัพยากร Singleton ที่แสดงผลโดย GetAndroidPackageRegistrationPolicy ซึ่งอธิบายคีย์การลงนามสาธารณะที่ผ่านมาซึ่งตรวจพบสำหรับชื่อแพ็กเกจ และการลงทะเบียนชื่อแพ็กเกจด้วยคีย์การลงนามที่ระบุต้องมีเหตุผลเป็นลายลักษณ์อักษรหรือไม่

ช่อง ประเภท คำอธิบาย
name string ตัวระบุ ชื่อทรัพยากรในรูปแบบ developerAccounts/{developer_account}/androidPackages/{android_package}/registrationPolicy
knownKeys[] object (KnownKey) รายการคีย์ App Signing ที่ใช้ในอดีตซึ่งก่อนหน้านี้พบว่ามีการเผยแพร่แอปที่มีชื่อแพ็กเกจนี้ โดยจัดเรียงตามพจนานุกรมตาม certificateFingerprintSha256
knownKeys[].certificateFingerprintSha256 string เอาต์พุตเท่านั้น ลายนิ้วมือ SHA-256 เลขฐาน 16 ตัวพิมพ์เล็ก 64 อักขระที่แปลงเป็นรูปแบบมาตรฐานของใบรับรองการลงนามที่ผ่านมา (ไม่มีโคลอน)
knownKeys[].justificationRequirement enum (JustificationRequirement) เอาต์พุตเท่านั้น ระบุว่าการลงทะเบียนคีย์นี้ต้องเรียกใช้ JustifyAndroidPackageKeyRegistration (REQUIRED หรือ NOT_REQUIRED) หรือไม่ หากคีย์ Signing ได้รับการยืนยันก่อนหน้านี้ในชื่อแพ็กเกจอื่นภายใต้ DeveloperAccount เดียวกัน ระบบจะข้ามทั้ง VerifyAndroidPackageKeyOwnership และ JustifyAndroidPackageKeyRegistration แม้ว่า justificationRequirement จะเป็น REQUIRED ก็ตาม
keySelectionStrategy enum (KeySelectionStrategy) เอาต์พุตเท่านั้น นโยบายการเลือกคีย์สำหรับการลงทะเบียนชื่อแพ็กเกจนี้: SELECT_KEY_FROM_LIST (ต้องลงทะเบียนคีย์จาก knownKeys) หรือ USE_ANY_KEY (ลงทะเบียนคีย์ App Signing ที่ถูกต้องซึ่งนักพัฒนาแอปเป็นเจ้าของได้)

Enum: KnownKey.JustificationRequirement

ค่า คำอธิบาย
REQUIRED การลงทะเบียนคีย์ที่รู้จักนี้ต้องส่งเหตุผลเป็นลายลักษณ์อักษรโดยใช้ JustifyAndroidPackageKeyRegistration หลังจากทำ VerifyAndroidPackageKeyOwnership เสร็จแล้ว (เว้นแต่ว่าคีย์ได้รับการยืนยันก่อนหน้านี้ในชื่อแพ็กเกจอื่นภายใต้ DeveloperAccount เดียวกัน ซึ่งในกรณีนี้จะข้ามทั้ง VerifyAndroidPackageKeyOwnership และ JustifyAndroidPackageKeyRegistration)
NOT_REQUIRED การลงทะเบียนคีย์ที่รู้จักนี้ไม่จำเป็นต้องระบุเหตุผลรองรับ คีย์จะเปลี่ยนไปใช้ IN_REVIEW โดยตรงหลังจากวันที่ VerifyAndroidPackageKeyOwnership (หรือทันทีในวันที่ CreateAndroidPackageKey หากคีย์ได้รับการยืนยันก่อนหน้านี้ในชื่อแพ็กเกจอื่นภายใต้ DeveloperAccount เดียวกัน)

Enum: AndroidPackageRegistrationPolicy.KeySelectionStrategy

ค่า คำอธิบาย
SELECT_KEY_FROM_LIST ผู้โทรต้องลงทะเบียนคีย์ย้อนหลังรายการใดรายการหนึ่งที่แสดงใน knownKeys
USE_ANY_KEY นอกเหนือจากคีย์ใน knownKeys แล้ว ผู้โทรสามารถลงทะเบียนคีย์ App Signing ที่ถูกต้องซึ่งไม่เคยพบในระบบนิเวศของ Android มาก่อน

วิธีการ: AndroidPackage

วิธีการ คำขอ HTTP คำอธิบาย
GetAndroidPackageRegistrationPolicy GET /v1/{name=developerAccounts/*/androidPackages/*/registrationPolicy} ดึงข้อมูลกลยุทธ์การเลือกคีย์และคีย์ Signing ที่ทราบในอดีตสำหรับชื่อแพ็กเกจ
CreateAndroidPackage POST /v1/{parent=developerAccounts/*}/androidPackages?androidPackageId={package_name} สร้างทรัพยากร AndroidPackage ใหม่ในสถานะ DRAFT เพื่อเริ่มลงทะเบียนชื่อแพ็กเกจ
GetAndroidPackage GET /v1/{name=developerAccounts/*/androidPackages/*} ดึงข้อมูลรายละเอียดและสถานะการลงทะเบียนปัจจุบันของ AndroidPackage ที่มีอยู่
ListAndroidPackages GET /v1/{parent=developerAccounts/*}/androidPackages แสดงรายการออบเจ็กต์ AndroidPackage รายการภายใต้ DeveloperAccount (pageSize สูงสุด 1000, pageToken)

ทรัพยากร: AndroidPackageKey

แสดงลายนิ้วมือของใบรับรอง App Signing สาธารณะที่เชื่อมโยงกับ AndroidPackage และติดตามสถานะการยืนยันการเป็นเจ้าของและการตรวจสอบการลงทะเบียน

ช่อง ประเภท คำอธิบาย
name string ตัวระบุ ชื่อทรัพยากรที่เซิร์ฟเวอร์กำหนดในรูปแบบ developerAccounts/{developer_account}/androidPackages/{android_package}/keys/{key} โดยที่ {key} คือลายนิ้วมือ SHA-256 เลขฐาน 16 ตัวพิมพ์เล็ก 64 อักขระที่แปลงเป็นรูปแบบมาตรฐานโดยไม่มีโคลอน ต้องละเว้นหรือเว้นว่างไว้เมื่อเรียกใช้ CreateAndroidPackageKey
certificateFingerprintSha256 string จำเป็น เปลี่ยนแปลงไม่ได้ แฮช SHA-256 ของใบรับรอง App Signing เมื่อป้อนข้อมูลใน CreateAndroidPackageKey ระบบจะยอมรับเลขฐาน 16 แบบธรรมดา 64 อักขระ (60e860e8...) หรือเลขฐาน 16 ที่คั่นด้วยโคลอน (60:E8:60:E8:...) เมื่อแสดงผลลัพธ์ ระบบจะปรับให้เป็นเลขฐาน 16 ตัวพิมพ์เล็ก 64 อักขระที่ไม่มีโคลอนเสมอ
state enum (AndroidPackageKey.State) เอาต์พุตเท่านั้น สถานะวงจรการยืนยันและการลงทะเบียนปัจจุบันของคีย์
verificationToken string เอาต์พุตเท่านั้น โทเค็นคำถามที่ไม่ซ้ำกันซึ่ง Google สร้างขึ้น ใช้เฉพาะเมื่อสถานะเป็น DRAFT (สามารถละเว้นได้เมื่อ CreateAndroidPackageKey เปลี่ยนคีย์เป็น IN_REVIEW โดยตรง) เมื่อสถานะเป็น DRAFT ให้ฝังสตริงนี้ไว้ใน assets/adi-registration.properties ใน APK ที่รับรองแล้วเพื่อดำเนินการ VerifyAndroidPackageKeyOwnership ให้เสร็จสมบูรณ์
registrationJustificationRequired boolean เอาต์พุตเท่านั้น หาก true และคีย์อยู่ในสถานะ OWNERSHIP_VERIFIED คุณต้องส่งเหตุผลที่เป็นลายลักษณ์อักษรโดยใช้ JustifyAndroidPackageKeyRegistration ก่อนที่การลงทะเบียนจะดำเนินการต่อใน IN_REVIEW หาก CreateAndroidPackageKey เปลี่ยนคีย์เป็น IN_REVIEW โดยตรง (เนื่องจากคีย์ได้รับการยืนยันก่อนหน้านี้ในชื่อแพ็กเกจอื่นใน DeveloperAccount เดียวกัน) ระบบจะข้ามการให้เหตุผล

Enum: AndroidPackageKey.State

ค่า คำอธิบาย
DRAFT สร้างทรัพยากรคีย์แล้ว และยังคงต้องใช้หลักฐานการครอบครองคีย์ส่วนตัวโดยใช้การอัปโหลด APK ที่รับรอง (VerifyAndroidPackageKeyOwnership) เนื่องจากยังไม่ได้ยืนยันการเป็นเจ้าของคีย์นี้ในชื่อแพ็กเกจใดๆ ภายใต้ DeveloperAccount นี้
OWNERSHIP_VERIFIED ยืนยันการเป็นเจ้าของคีย์ส่วนตัวแล้วโดยใช้การอัปโหลด APK ที่รับรอง หาก registrationJustificationRequired เป็น true คุณยังคงต้องระบุเหตุผลก่อนเริ่มการตรวจสอบ
IN_REVIEW การลงทะเบียนคีย์อยู่ระหว่างตรวจสอบโดย Google คีย์จะเปลี่ยนสถานะมาที่นี่ทันทีเมื่อ CreateAndroidPackageKey หากไม่จำเป็นต้องใช้หลักฐานการเป็นเจ้าของ (เช่น ในชื่อแพ็กเกจใหม่ที่ไม่เคยเห็นใน Android หรือเมื่อคีย์ได้รับการยืนยันก่อนหน้านี้ในชื่อแพ็กเกจอื่นภายใต้ DeveloperAccount เดียวกัน ซึ่งจะข้าม JustifyAndroidPackageKeyRegistration ด้วย) โดยตรงหลังจาก VerifyAndroidPackageKeyOwnership (หาก registrationJustificationRequired เป็น false) หรือหลังจาก JustifyAndroidPackageKeyRegistration (หาก registrationJustificationRequired เป็น true)
REGISTERED คีย์ App Signing ได้รับการลงทะเบียนอย่างสม่ำเสมอกับชื่อแพ็กเกจนี้สำหรับการยืนยันนักพัฒนาแอป Android
PENDING_TRANSFER การลงทะเบียนคีย์ App Signing กำลังรอให้การโอนเสร็จสมบูรณ์

วิธีการ: AndroidPackageKey

วิธีการ คำขอ HTTP คำอธิบาย
CreateAndroidPackageKey POST /v1/{parent=developerAccounts/*/androidPackages/*}/keys ลงทะเบียนลายนิ้วมือ SHA-256 ของใบรับรอง App Signing ใหม่ภายใต้ AndroidPackage แสดงผลคีย์ในสถานะ DRAFT (เมื่อต้องใช้หลักฐานการเป็นเจ้าของโดยใช้ VerifyAndroidPackageKeyOwnership) หรือแสดงผลคีย์ในสถานะ IN_REVIEW โดยตรง (เมื่อข้ามการยืนยันการเป็นเจ้าของ เช่น สำหรับชื่อแพ็กเกจใหม่ที่ไม่เคยเห็นใน Android หรือคีย์ที่ยืนยันแล้วในชื่อแพ็กเกจอื่นใน DeveloperAccount เดียวกัน)
GetAndroidPackageKey GET /v1/{name=developerAccounts/*/androidPackages/*/keys/*} ดึงข้อมูลสถานะ ฟิงเกอร์ปรินต์ และข้อมูลเมตาการยืนยันของ AndroidPackageKey ที่เฉพาะเจาะจง
ListAndroidPackageKeys GET /v1/{parent=developerAccounts/*/androidPackages/*}/keys แสดงรายการออบเจ็กต์ AndroidPackageKey ทั้งหมดที่ลงทะเบียนภายใต้ AndroidPackage (pageSize สูงสุด 1000, pageToken)
VerifyAndroidPackageKeyOwnership POST /upload/v1/{name=developerAccounts/*/androidPackages/*/keys/*}:verify อัปโหลด APK ขั้นต่ำที่รับรองแล้วซึ่งมี verificationToken ใน assets/adi-registration.properties เพื่อยืนยันการเป็นเจ้าของคีย์ส่วนตัวและส่งคีย์ที่พร้อมใช้งานเพื่อรับการตรวจสอบ
JustifyAndroidPackageKeyRegistration POST /v1/{name=developerAccounts/*/androidPackages/*/keys/*}:justifyAndroidPackageKeyRegistration ส่งบริบทเหตุผลเพิ่มเติมเมื่อ registrationJustificationRequired เป็น true และส่งคีย์ที่ยืนยันแล้วเพื่อรับการตรวจสอบ

การจัดการข้อผิดพลาด

เมื่อคำขอ API ไม่สำเร็จ Android Developer Console API จะแสดงรหัสสถานะ HTTP 4xx หรือ 5xx และเนื้อหาข้อผิดพลาด JSON มาตรฐาน google.rpc.Status ดังนี้

{
  "error": {
    "code": 400,
    "message": "Invalid certificate fingerprint SHA256 format.",
    "status": "INVALID_ARGUMENT",
    "details": []
  }
}

รหัสสถานะ HTTP และการแก้ไขที่พบบ่อย

โค้ด HTTP สถานะ gRPC สาเหตุที่พบบ่อย ความละเอียด
400 Bad Request INVALID_ARGUMENT ไม่มี androidPackageId สไตล์ Java หรือไม่ถูกต้อง รูปแบบ certificateFingerprintSha256 ไม่ถูกต้อง ช่อง name ไม่ว่างเปล่าใน CreateAndroidPackage หรือ CreateAndroidPackageKey APK ที่อัปโหลดไม่ได้ลงนาม เสียหาย ไม่มี assets/adi-registration.properties ไม่มี verificationToken ที่ตรงกัน หรือลงนามด้วยใบรับรองที่ไม่ตรงกัน ตรวจสอบรูปแบบคำขอกับสคีมาทรัพยากร ละเว้นหรือเว้นว่าง name ในการเรียกใช้การสร้าง และยืนยันลายเซ็น APK และโทเค็นที่ฝังไว้โดยใช้ apksigner verify --print-certs และ unzip -p app-release.apk assets/adi-registration.properties ก่อนอัปโหลด
400 Bad Request FAILED_PRECONDITION DeveloperAccount มี verificationState: NOT_VERIFIED; การเลือกคีย์ละเมิด AndroidPackageRegistrationPolicy (SELECT_KEY_FROM_LIST); การเรียกใช้ VerifyAndroidPackageKeyOwnership หรือ JustifyAndroidPackageKeyRegistration ในสถานะที่ไม่มีสิทธิ์ ทำการยืนยันตัวตนของนักพัฒนาแอปให้เสร็จสมบูรณ์ใน Android Developer Console โดยตรวจสอบ GetAndroidPackageRegistrationPolicy ก่อน แล้วจึงตรวจสอบ state ปัจจุบันของทรัพยากร
401 Unauthorized UNAUTHENTICATED โทเค็นเพื่อการเข้าถึง Bearer ของ OAuth 2.0 หายไป หมดอายุ หรือไม่ถูกต้อง หรือพยายามตรวจสอบสิทธิ์โดยใช้คีย์ API หรือบัญชีบริการ รับโทเค็นเพื่อการเข้าถึง OAuth 2.0 Bearer ที่ผู้ใช้มอบสิทธิ์ใหม่ซึ่งมีขอบเขต https://www.googleapis.com/auth/androiddeveloperconsole
403 Forbidden PERMISSION_DENIED ผู้ใช้ที่ตรวจสอบสิทธิ์แล้วไม่มีสิทธิ์ใน DeveloperAccount หรือ AndroidPackage เป้าหมาย หรือไม่ได้เปิดใช้ Android Developer Console API ในโปรเจ็กต์ที่อยู่ในระบบคลาวด์ของ Google ยืนยันการเป็นสมาชิกบัญชีโดยใช้ ListDeveloperAccounts และตรวจสอบว่าเปิดใช้ androiddeveloperconsole.googleapis.com ในคอนโซล Google Cloud แล้ว
404 Not Found NOT_FOUND ไม่มีเส้นทางทรัพยากร DeveloperAccount, AndroidPackage หรือ AndroidPackageKey ที่ระบุ ยืนยันเส้นทางทรัพยากรโดยใช้ ListDeveloperAccounts, ListAndroidPackages หรือ ListAndroidPackageKeys ตรวจสอบว่ารหัส {key} ใช้เลขฐานสิบหกตัวพิมพ์เล็กโดยไม่มีโคลอน
409 Conflict ALREADY_EXISTS มีการลงทะเบียนชื่อแพ็กเกจหรือลายนิ้วมือของใบรับรอง SHA-256 ภายใต้บัญชีนักพัฒนาแอปนี้หรือบัญชีอื่นแล้ว ตรวจสอบการจดทะเบียนที่มีอยู่โดยใช้ GetAndroidPackage หรือ GetAndroidPackageKey หรือตรวจสอบการเป็นเจ้าของที่ผ่านมาโดยใช้ GetAndroidPackageRegistrationPolicy
429 Too Many Requests RESOURCE_EXHAUSTED เกินโควต้าต่อเมธอด 2,000 คำขอต่อวันต่อโปรเจ็กต์ Google Cloud ใช้ Exponential Backoff ที่มี Jitter และหลีกเลี่ยงลูปการโพลความถี่สูง
500 / 503 INTERNAL / UNAVAILABLE ข้อผิดพลาดของแบ็กเอนด์ชั่วคราวหรือบริการไม่พร้อมใช้งานชั่วคราว ลองส่งคำขอ Idempotent อีกครั้งโดยใช้ Exponential Backoff แบบตัดปลาย

ตัวอย่างคำขอ 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

ตัวเลือก ก: การอัปโหลดสื่อแบบคำขอเดียว

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"

ตัวเลือก ข: โปรโตคอลการอัปโหลดที่ดำเนินการต่อได้ (แนะนำสำหรับ 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
}

แหล่งข้อมูลเพิ่มเติม