Android Developer Console API

واجهة برمجة التطبيقات Android Developer Console API هي خدمة RESTful تتيح للمطوّرين المعتمَدين تنفيذ مهام سير عمل التحقّق من هوية مطوّر تطبيقات Android آليًا في Android Developer Console، بما في ذلك استرداد حسابات المطوّرين والتحقّق من متطلبات الأهلية الرئيسية وتسجيل أسماء حِزم Android وتسجيل مفاتيح توقيع التطبيقات والتحقّق من ملكية المفاتيح.

نظرة عامة وحالات الاستخدام وسياق التنفيذ

أبرز حالات الاستخدام والميزات

  • تسجيل أسماء الحِزم تلقائيًا من خلال CI/CD: يمكنك تسجيل العشرات أو المئات من أسماء حِزم Android آليًا (CreateAndroidPackage).
  • فحص سياسة المفاتيح السابقة قبل النشر: يتم الفحص آليًا لمعرفة ما إذا كانت Google قد رصدت اسم حزمة في المنظومة المتكاملة من قبل، وما إذا كان تسجيل شهادة توقيع معيّنة يتطلّب إثبات ملكية المفتاح (GetAndroidPackageRegistrationPolicy).
  • التسجيل الآلي لمفاتيح توقيع التطبيقات والتحقّق من ملكيتها: يمكنك تسجيل الملفات المرجعية لمعيار SHA-256 الخاصة بشهادات التوقيع العلنية (CreateAndroidPackageKey)، واسترداد رموز التحقّق الفريدة (verificationToken)، وإثبات حيازة المفتاح الخاص آليًا باستخدام عمليات تحميل حِزم APK الموقَّعة من خلال طلب واحد أو عمليات تحميل قابلة للاستئناف (VerifyAndroidPackageKeyOwnership).
  • إرسال مبررات برمجية: يمكنك إرسال مبررات الملكية (JustifyAndroidPackageKeyRegistration).
  • مراقبة الحالة: يمكنك مراقبة حالة التسجيل في جميع حسابات المطوّرين وأسماء الحزم ومفاتيح توقيع التطبيقات (GetDeveloperAccount وListDeveloperAccounts وGetAndroidPackage وListAndroidPackages وGetAndroidPackageKey وListAndroidPackageKeys).

سير عمل التنفيذ الشامل

  1. إثبات هوية المطوّر مرة واحدة في واجهة المستخدم: يجب إكمال عملية إثبات هوية المطوّر (INDIVIDUAL أو ORGANIZATION) في Android Developer Console لكي يصبح "verificationState" VERIFIED.
  2. تفعيل واجهة برمجة التطبيقات والمصادقة: فعِّل 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) وأي مفاتيح توقيع قديمة معروفة (knownKeys).
  5. إنشاء مورد حزمة Android: يمكنك طلب POST /v1/developerAccounts/{id}/androidPackages?androidPackageId={pkg} (CreateAndroidPackage) مع النص {"name": ""} (يتم إنشاء المورد في الحالة DRAFT).
  6. تسجيل الملف المرجعي لمفتاح توقيع التطبيق: يمكنك طلب POST /v1/developerAccounts/{id}/androidPackages/{pkg}/keys (CreateAndroidPackageKey) باستخدام نص JSON‏ {"certificateFingerprintSha256": "..."}. افحص الحالة التي تم إرجاعها:
    • ‫DRAFT: يجب تقديم إثبات ملكية المفتاح الخاص، ويتضمّن الردّ verificationToken فريدًا للخطوة 7.
    • ‫IN_REVIEW: يتم تخطّي إثبات الملكية والمبرّر تلقائيًا (على سبيل المثال، عند تسجيل اسم حزمة جديد لم يسبق استخدامه على Android، أو عند إثبات ملكية مفتاح التوقيع هذا لاسم حزمة آخر في DeveloperAccount نفسه). تخطَّ الخطوة 7 وطلب المبرّر في الخطوة 8، وانتقِل مباشرةً إلى استطلاع GetAndroidPackage وGetAndroidPackageKey.
  7. إنشاء حزمة APK لإثبات الملكية وتحميلها (إذا كانت الحالة DRAFT): يجب تضمين السلسلة verificationToken التي تم عرضها في assets/adi-registration.properties داخل حزمة APK صغيرة تتطابق مع packageName، وتوقيعها باستخدام مفتاح توقيع التطبيق الخاص، وتحميلها باستخدام 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 من ملف تخزين مفاتيح (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

إمكانات واجهة المستخدم وواجهة برمجة التطبيقات في Android Developer Console

المهمة واجهة مستخدم الويب في Android Developer Console‏ (android.google.com/developerconsole) Android Developer Console 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) تحميل حزمة APK للمقتطف الموقَّع في واجهة مستخدم Play Console ‫POST /upload/v1/{name}:verify ‎(VerifyAndroidPackageKeyOwnership)
إرسال مبرّر عندما يتطلّب المفتاح مراجعة يدوية طلب نصّي أثناء سير عمل تسجيل المفتاح ‫POST /v1/{name}:justifyAndroidPackageKeyRegistration ‎(JustifyAndroidPackageKeyRegistration)

إعداد الخدمة والمصادقة

يجب أن تستخدم جميع طلبات البيانات من واجهة برمجة التطبيقات بروتوكول HTTPS وأن تتضمّن عنوان Authorization: Bearer ACCESS_TOKEN يتم الحصول عليه باستخدام مسار خادم الويب OAuth 2.0 لحساب Google الذي أكمل عملية إثبات هوية المطوّر في Android Developer Console.

الخاصية القيمة
نقطة نهاية REST الأساسية https://androiddeveloperconsole.googleapis.com
نقطة نهاية تحميل الوسائط https://androiddeveloperconsole.googleapis.com/upload
إصدار واجهة برمجة التطبيقات v1
نطاق OAuth 2.0 المطلوب https://www.googleapis.com/auth/androiddeveloperconsole
حد الحصة التلقائي ‫2,000 طلب في اليوم لكل مشروع على Google Cloud لكل طريقة

موارد واجهة برمجة التطبيقات ونقاط النهاية

تُنظّم واجهة برمجة التطبيقات 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) للعرض فقط. حالة إثبات هوية المطوّر الحالية للحساب

قيم التعداد: DeveloperAccount.VerificationState

القيمة الوصف
VERIFIED اكتملت عملية إثبات هوية المطوّر. يمكن للحساب تسجيل أسماء الحِزم ومفاتيح توقيع التطبيقات.
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 للعرض فقط. يشير هذا الحقل إلى ما إذا كان اسم الحزمة هذا نشطًا حاليًا كمتجر تطبيقات مسجَّل.

Enum: AndroidPackage.State

القيمة الوصف
DRAFT تم إنشاء مورد اسم الحزمة، ولا يزال تسجيل مفتاح توقيع التطبيق أو إثبات الملكية قيد التقدم.
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) قائمة بمفاتيح توقيع التطبيقات السابقة التي تم رصدها سابقًا أثناء توزيع التطبيقات التي تحمل اسم الحزمة هذا، ويتم ترتيبها معجميًا حسب certificateFingerprintSha256.
knownKeys[].certificateFingerprintSha256 string للعرض فقط. الملف المرجعي لشهادة التوقيع السابقة بتنسيق SHA-256، وهو ملف عادي يتألف من 64 حرفًا صغيرًا بنظام العد الستة عشري (بدون نقطتَين رأسيتَين).
knownKeys[].justificationRequirement enum (JustificationRequirement) للعرض فقط. يشير هذا الحقل إلى ما إذا كان تسجيل هذا المفتاح يتطلّب استدعاء JustifyAndroidPackageKeyRegistration (REQUIRED أو NOT_REQUIRED). إذا سبق التحقّق من مفتاح التوقيع في اسم حزمة آخر ضمن DeveloperAccount نفسه، يتم تخطّي كل من VerifyAndroidPackageKeyOwnership وJustifyAndroidPackageKeyRegistration حتى إذا كانت قيمة justificationRequirement هي REQUIRED.
keySelectionStrategy enum (KeySelectionStrategy) للعرض فقط. سياسة اختيار المفتاح لتسجيل اسم الحزمة هذا: SELECT_KEY_FROM_LIST (يجب تسجيل مفتاح من knownKeys) أو USE_ANY_KEY (يمكن تسجيل أي مفتاح توقيع تطبيق صالح يملكه المطوّر).

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، يمكن للمتصل تسجيل أي مفتاح توقيع تطبيق صالح لم يتم رصده سابقًا في منظومة Android المتكاملة.

الطرق: AndroidPackage

الطريقة طلب HTTP الوصف
GetAndroidPackageRegistrationPolicy GET /v1/{name=developerAccounts/*/androidPackages/*/registrationPolicy} تسترد هذه الطريقة استراتيجية اختيار المفتاح ومفاتيح التوقيع السابقة المعروفة لاسم حزمة معيّن.
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

تمثّل هذه السمة الملف المرجعي لشهادة توقيع التطبيق المتاحة للجميع والمرتبطة بـ AndroidPackage وتتتبّع حالة إثبات الملكية ومراجعة التسجيل.

الحقل النوع الوصف
name string المعرّف: اسم المورد الذي يحدّده الخادم بالتنسيق developerAccounts/{developer_account}/androidPackages/{android_package}/keys/{key}، حيث يمثّل {key} ملفًا مرجعيًا عاديًا لشهادة SHA-256 يتألف من 64 حرفًا صغيرًا بنظام العد الستة عشري بدون نقطتَين رأسيتَين. يجب حذف هذه السمة أو تركها فارغة عند طلب CreateAndroidPackageKey.
certificateFingerprintSha256 string مطلوب. غير قابل للتغيير تجزئة SHA-256 لشهادة توقيع التطبيق عند الإدخال في CreateAndroidPackageKey، يتم قبول إما نظام العد الستة عشري العادي المكوّن من 64 حرفًا (60e860e8...) أو نظام العد الستة عشري المفصول بنقطتين (60:E8:60:E8:...). وعند الإخراج، يتم دائمًا توحيد نظام العد الستة عشري المكوّن من 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 تم تسجيل مفتاح توقيع التطبيق بشكل نشط لاسم الحزمة هذا من أجل التحقّق من هوية مطوّر تطبيقات Android.
PENDING_TRANSFER إنّ عملية تسجيل مفتاح توقيع التطبيق في انتظار اكتمال عملية النقل.

الطرق: AndroidPackageKey

الطريقة طلب HTTP الوصف
CreateAndroidPackageKey POST /v1/{parent=developerAccounts/*/androidPackages/*}/keys يتم تسجيل ملف مرجعي جديد لشهادة توقيع التطبيق SHA-256 ضمن 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"، ويتم إرسال المفاتيح التي تم التحقّق منها للمراجعة.

معالجة الأخطاء

عند تعذُّر طلب بيانات من واجهة برمجة التطبيقات، تعرض واجهة برمجة تطبيقات Android Developer Console رمز حالة 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 رمز الدخول الحامل لبروتوكول OAuth 2.0 مفقود أو منتهي الصلاحية أو غير صالح، أو محاولة المصادقة باستخدام مفتاح واجهة برمجة التطبيقات أو حساب خدمة. احصل على رمز دخول جديد لحامل OAuth 2.0 مفوَّض من المستخدم مع النطاق https://www.googleapis.com/auth/androiddeveloperconsole.
403 Forbidden PERMISSION_DENIED لا يملك المستخدم الذي تمت مصادقته إذنًا على DeveloperAccount أو AndroidPackage المستهدَفَين، أو أنّ واجهة برمجة التطبيقات Android Developer Console API غير مفعَّلة في مشروع Google Cloud. يُرجى التحقّق من عضوية الحساب باستخدام ListDeveloperAccounts والتأكّد من تفعيل androiddeveloperconsole.googleapis.com في Google Cloud Console.
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. استخدِم خوارزمية الرقود الأسي الثنائي مع التفاوت وتجنَّب حلقات الاستطلاع العالية التردد.
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

الخيار "أ": تحميل الوسائط بطلب واحد

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
}

مراجع إضافية