فئات وواجهات LVL
يسرد الجدول 1 جميع الملفات المصدر في عملية "التحقّق من الترخيص"
المكتبة (LVL) المتاحة من خلال حزمة تطوير البرامج (SDK) لنظام التشغيل Android جميع الملفات جزء من
حزمة com.android.vending.licensing
.
الفئة | الاسم | الوصف |
---|---|---|
التحقّق من الترخيص ونتائجه | أداة التحقّق من التراخيص | الفئة التي تنشئ مثيلاً لها (أو فئة فرعية) لبدء فحص الترخيص. |
LicenseCheckerCallback | الواجهة التي تنفّذها لمعالجة نتائج فحص الترخيص. | |
السياسة | السياسة | الواجهة التي تنفّذها لتحديد ما إذا كان يجب السماح الوصول إلى التطبيق، استنادًا إلى استجابة الترخيص. |
سياسة مُدارة للخادم | عملية تنفيذ "Policy " التلقائية يتم استخدام الإعدادات التي توفّرها
لإدارة التخزين المحلي لبيانات الترخيص وصلاحية الترخيص
إعادة المحاولة. |
|
السياسة المتشددة | تنفيذ Policy بديل. يفرض الترخيص استنادًا إلى
استجابة الترخيص من الخادم فقط. لا حاجة للتخزين المؤقت أو طلب إعادة المحاولة. |
|
تشويش البيانات (اختياري) |
أداة إخفاء مفاتيح فك التشفير | تنفِّذها إذا كنت تستخدم Policy (مثل
Server ManagedPolicy) التي تخزّن بيانات استجابة الترخيص مؤقّتًا في متجر دائم.
تطبيق خوارزمية إخفاء مفاتيح فك التشفير لتشفير وفك ترميز البيانات التي تتم كتابتها أو
تَقْرَأ |
أداة AESObfuscator | تنفيذ أداة إخفاء مفاتيح فك التشفير التلقائية التي تستخدم تشفير/فك تشفير AES للتشويش على البيانات أو إلغاء تشويشها. | |
تقييد الأجهزة (اختياري) |
Devicelimiter | الواجهة التي تنفذها إذا كنت تريد تقييد استخدام التطبيق على جهاز محدد. تم طلب الإذن من LicenseValidator. التنفيذ لا يُنصح باستخدام تطبيق DeviceLimiter مع معظم التطبيقات لأنّه يتطلب إضافة. خادم الخلفية وقد يتسبب في فقدان المستخدم لإمكانية الوصول إلى التطبيقات المرخصة، ما لم يتم تصميمها بعناية. |
محدد الجهاز Null | تطبيق Devicelimiteder التلقائي الذي لا يمكن تنفيذه (يسمح بالوصول إلى جميع الأجهزة). | |
مكتبة أساسية، لا حاجة للدمج | بيانات الاستجابة | فئة تتضمن حقول استجابة الترخيص. |
مدقّق الترخيص | الصف الذي يفك تشفير الردود التي تم تلقّيها من الترخيص ويتحقّق منها الخادم. | |
التحقق من الاستثناء | فئة تشير إلى الأخطاء التي تحدث عند التحقق من سلامة البيانات التي يديرها مُبهج. | |
أداة PreferenceObfuscator | فئة الأداة التي تكتب/تقرأ البيانات المُشفَّرة إلى
متجر "SharedPreferences " |
|
ILicensingService | واجهة IPC أحادية الاتجاه التي يتم من خلالها تمرير طلب فحص الترخيص إلى Google Play. | |
ILicenseResultListener | تنفيذ استدعاء IPC أحادي الاتجاه الذي يتلقى التطبيق من خلاله استجابة غير متزامنة من خادم الترخيص |
استجابة الخادم
يسرد الجدول 2 جميع حقول استجابة الترخيص التي تم إرجاعها بواسطة خادم ترخيص.
الحقل | الوصف |
---|---|
responseCode |
رمز الاستجابة الذي يعرضه خادم الترخيص. رموز الاستجابة هي موضح في رموز استجابة الخادم. |
signedData |
تسلسل سلسلة تحتفظ بالبيانات التي يعرضها خادم الترخيص، على النحو التالي:
responseCode|nonce|packageName|versionCode|userId|timestamp:extras
|
signature |
توقيع signedData باستخدام مفتاح خاص بالتطبيق.
|
رموز استجابة الخادم
يسرد الجدول 3 جميع رموز استجابة الترخيص المتوافقة مع خادم ترخيص. بشكل عام، يجب أن يتعامل التطبيق مع كل هذه الاستجابات الرموز. وبشكل افتراضي، توفر فئة LicenseValidator في LVL جميع من أجل معالجة رموز الاستجابة هذه.
رمز الاستجابة | تمثيل عدد صحيح والقيمة | الوصف | هل تم التوقيع؟ | المحتوى الإضافي | التعليقات |
---|---|---|---|---|---|
LICENSED |
0 |
تم ترخيص التطبيق للمستخدم. اشترى المستخدم التطبيق، أو غير مصرح له بتنزيل الإصدار ألفا أو الإصدار التجريبي وتثبيته من التطبيق. | نعم | VT ، GT ، GR |
السماح بالوصول وفقًا لقيود Policy . |
LICENSED_OLD_KEY |
2 |
تم ترخيص التطبيق للمستخدم، ولكن يوجد تطبيق محدَّث يتوفر إصدار تم توقيعه باستخدام مفتاح مختلف. | نعم | VT ، GT ، GR ، UT |
يمكنك السماح بالوصول وفقًا لقيود Policy .
يمكن أن يشير إلى أنّ مفتاحَي التشفير المُستخدَمَين في أداة التثبيت إصدار التطبيق غير صالح أو مخترَق. يمكن أن يسمح التطبيق بالوصول إذا لزم الأمر، أو إبلاغ المستخدم بتوفر الترقية والحد من الاستخدام الإضافي حتى الترقية. |
NOT_LICENSED |
1 |
لم يتم ترخيص التطبيق للمستخدم. | لا | عدم السماح بالوصول | |
ERROR_CONTACTING_SERVER |
257 |
خطأ محلي — تعذّر على تطبيق Google Play الوصول إلى خادم الترخيص، ربما بسبب مشكلات توفر الشبكة. | لا | عليك إعادة محاولة التحقّق من الترخيص وفقًا لحدود إعادة المحاولة مع Policy . |
|
ERROR_SERVER_FAILURE |
4 |
خطأ في الخادم: تعذّر على الخادم تحميل مفتاح التطبيق للترخيص. | لا | عليك إعادة محاولة التحقّق من الترخيص وفقًا لحدود إعادة المحاولة مع Policy .
|
|
ERROR_INVALID_PACKAGE_NAME |
258 |
خطأ محلي — طلب التطبيق فحص الترخيص لحزمة غير المثبَّت على الجهاز. | لا | لا تعِد محاولة فحص الترخيص.
يحدث عادةً بسبب خطأ في التطوير. |
|
ERROR_NON_MATCHING_UID |
259 |
خطأ محلي — طلب التطبيق فحص الترخيص لحزمة الذي لا يطابق UID الخاص به (الحزمة، زوج معرّف المستخدم) معرّف الطلب التطبيق. | لا | لا تعِد محاولة فحص الترخيص.
يحدث عادةً بسبب خطأ في التطوير. |
|
ERROR_NOT_MARKET_MANAGED |
3 |
خطأ في الخادم - لم يتمّ التعرّف على التطبيق (اسم الحزمة) من خلال Google Play. | لا | لا تعِد محاولة فحص الترخيص.
يمكن أن يشير إلى أنه لم يتم نشر التطبيق. من خلال Google Play أو أن هناك خطأ في التطوير في عملية الترخيص التنفيذ. |
ملاحظة: كما هو موثّق في أثناء إعداد بيئة الاختبار، يمكن إدخال رمز الاستجابة يدويًا تم الإلغاء لمطوِّر التطبيق وأي مستخدمين اختباريين مسجَّلين من خلال Google Play Console
ملاحظة: كان بإمكانك في السابق اختبار أحد التطبيقات من خلال تحميل "مسودة" غير منشورة . لم تعُد هذه الوظيفة مدعوم؛ لكن يجب نشره في توزيع ألفا أو بيتا . لمزيد من المعلومات، يُرجى الاطّلاع على مسودة التطبيقات. لم تعُد متاحة.
الميزات الإضافية لاستجابة الخادم
لمساعدة تطبيقك في إدارة أذونات الوصول إلى التطبيق من خلال طلب استرداد الأموال ويقدمون معلومات أخرى، ويتضمن خادم الترخيص عدة أجزاء من المعلومات في ردود الترخيص. وعلى وجه التحديد، توفر الخدمة القيم الموصى بها فترة صلاحية ترخيص التطبيق، وفترة السماح لإعادة المحاولة، والحد الأقصى لعدد مرات إعادة المحاولة المسموح به، وغير ذلك الإعدادات. في حال كان تطبيقك يستخدم APK ملفات بيانات موسّعة، تتضمّن الاستجابة أيضًا أسماء الملفات وأحجامها وعناوين URL. يُلحق الخادم الإعدادات كأزواج المفتاح/القيمة في استجابة الترخيص "الإضافية" .
يمكن لأي تنفيذ Policy
استخراج الإعدادات الإضافية من الترخيص
الرد واستخدامها حسب الحاجة. تُعدّ عملية تنفيذ Policy
التلقائية في LVL، ServerManagedPolicy
، طريقة فعّالة
ورسم توضيحي لكيفية الحصول على ملف التعريف وتخزينه واستخدامه
الإعدادات.
منشئ محتوى إضافي | الوصف |
---|---|
VT |
الطابع الزمني لصلاحية الترخيص تحدد التاريخ/الوقت الذي (مخزّن مؤقتًا) تنتهي صلاحية استجابة الترخيص ويجب إعادة التحقق منها على خادم الترخيص. الاطّلاع على القسم أدناه حول فترة صلاحية الترخيص. |
GT |
الطابع الزمني لفترة السماح تحدد نهاية الفترة التي يتم خلالها
قد تسمح السياسة بالوصول إلى التطبيق، حتى إذا كانت حالة الاستجابة
RETRY يدير الخادم القيمة، إلا أن القيمة المعتادة ستكون 5. أو أكثر من ذلك. الاطّلاع على القسم أدناه حول فترة إعادة المحاولة والحد الأقصى لعدد مرات إعادة المحاولة. |
GR |
الحد الأقصى لعدد المحاولات تحدِّد هذه السياسة عدد عمليات التحقّق المتتالية للترخيص في "RETRY ".
يجب أن يسمح Policy ، قبل منع المستخدم من الوصول إلى التطبيق.
يدير الخادم القيمة، على الرغم من أن القيمة المعتادة ستكون "10". أو أعلى. الاطّلاع على القسم أدناه حول فترة إعادة المحاولة والحد الأقصى لعدد مرات إعادة المحاولة. |
UT |
الطابع الزمني للتحديث. تُحدِّد اليوم/الوقت عندما يكون آخر تعديل على
تم تحميل هذا التطبيق ونشره. يعرض الخادم هذه القيمة الإضافية
لردود |
FILE_URL1 أو FILE_URL2 |
عنوان URL لأحد ملفات البيانات الموسّعة (1 مخصص للملف الرئيسي، و2 هو ملف التصحيح). استخدام هذا من أجل لتنزيل الملف عبر HTTP. |
FILE_NAME1 أو FILE_NAME2 |
اسم ملف البيانات الموسّعة (1 مخصص للملف الرئيسي، و2 هو ملف التصحيح). يجب استخدام هذا الحقل. اسمك عند حفظ الملف على الجهاز. |
FILE_SIZE1 أو FILE_SIZE2 |
حجم الملف بالبايت (1 مخصص للملف الرئيسي، و2 هو ملف التصحيح). استخدام هذا من أجل والمساعدة في التنزيل وللتأكد من توفر مساحة كافية على ملف مساحة التخزين قبل التنزيل. |
مدة صلاحية الترخيص
يحدّد خادم ترخيص Google Play مدة صلاحية ترخيص لجميع المستخدمين.
التطبيقات التي تم تنزيلها. تعبر الفترة عن الفاصل الزمني الذي
اعتبار حالة ترخيص التطبيق غير قابلة للتغيير وقابلة للتخزين المؤقت من خلال
Policy
للترخيص في التطبيق. يتضمن خادم الترخيص
لمدة الصلاحية في استجابتها لجميع فحوصات الترخيص، مع إلحاق
الطابع الزمني لانتهاء صلاحية الردّ على شكل رمز إضافي ضمن المفتاح VT
حاسمة
يمكن لـ Policy
استخراج قيمة مفتاح VT واستخدامها للسماح بالوصول المشروط إلى
التقدم بطلب بدون إعادة مراجعة الترخيص، حتى فترة الصلاحية
تنتهي صلاحيته.
تشير صلاحية الترخيص إلى "Policy
" للترخيص عندما يجب إعادة التحقّق من
مع خادم الترخيص. لا يُقصد منه الإشارة ضمنًا إلى
ما إذا كان التطبيق قد حصل على ترخيص للاستخدام أم لا. أي، عندما تكون
بانتهاء صلاحية فترة صلاحية ترخيص الطلب، فهذا لا يعني أن
لم يعد مرخّصًا للاستخدام - وإنما يشير فقط إلى أن
على Policy
إعادة التحقّق من حالة الترخيص مع الخادم. ويتبع ذلك،
طالما لم تنتهِ فترة صلاحية الترخيص، فيتم قبولها
Policy
لتخزين حالة الترخيص الأولية محليًا وإرجاع الترخيص المُخزَّن مؤقتًا.
بدلاً من إرسال فحص جديد للترخيص إلى الخادم.
يدير خادم الترخيص فترة الصلاحية كوسيلة لمساعدة تطبيق الترخيص بشكل صحيح خلال فترة استرداد الأموال التي يوفرها Google Play للتطبيقات المدفوعة. يضبط فترة الصلاحية استنادًا إلى ما إذا كان التطبيق قد تم شراؤه أم لا، وإذا كان الأمر كذلك، كم من الوقت مضت. على وجه التحديد، يضبط الخادم فترة الصلاحية على النحو التالي:
- بالنسبة إلى أي تطبيق مدفوع، يضبط الخادم فترة صلاحية الترخيص الأولية.
لكي يظل استجابة الترخيص صالحة طوال مدّة صلاحية التطبيق
قابلة للاسترداد. قد يخزِّن
Policy
للترخيص في التطبيق نتيجة الفحص الأولي للترخيص ولا حاجة إلى إعادة التحقّق من الترخيص حتى انتهاء مدة الصلاحية. - عندما لا يمكن استرداد أموال أحد التطبيقات، يبدأ الخادم مدة صلاحية أطول — عادةً ما تكون عددًا من الأيام.
- بالنسبة إلى أي تطبيق مجاني، يضبط الخادم فترة الصلاحية على قيمة مرتفعة جدًا
القيمة (
long.MAX_VALUE
). ويضمن ذلك، شريطة أن يكون لدىPolicy
تخزين الطابع الزمني للصلاحية مؤقتًا محليًا، فلن تحتاج إلى إعادة التحقق حالة ترخيص الطلب في المستقبل.
تستخدم عملية تنفيذ ServerManagedPolicy
الطابع الزمني المستخرج.
(mValidityTimestamp
) كشرط أساسي لتحديد ما إذا كان
بإعادة التحقق من حالة الترخيص مع الخادم قبل السماح للمستخدم بالوصول إلى
التطبيق.
فترة إعادة المحاولة والحد الأقصى لعدد مرات إعادة المحاولة
في بعض الحالات، يمكن أن تمنع ظروف النظام أو الشبكة فحص الترخيص من الوصول إلى خادم الترخيص، أو منع وصول الخادم استجابة من الوصول إلى تطبيق عميل Google Play. على سبيل المثال، قد يشغِّل المستخدم تطبيقًا في حال عدم وجود شبكة خلوية أو بيانات اتصال متاح — مثل عند الصعود على متن طائرة — أو عند اتصال الشبكة غير مستقر أو إشارة الخلية ضعيفة.
عندما تحول مشكلات الشبكة دون فحص الترخيص أو تقاطعه، فإن Google
يُرسِل برنامج Play إشعارًا إلى التطبيق من خلال عرض رمز الاستجابة RETRY
على
طريقة processServerResponse()
لـ Policy
. في حالة استخدام النظام
وذلك مثل الحالات التي يتعذر فيها على التطبيق الارتباط
تنفيذ ILicensingService
، تستدعي مكتبة LicenseChecker
نفسها
طريقة processServerResponse()
للسياسة مع رمز الاستجابة RETRY
بشكل عام، يُعد رمز الاستجابة RETRY
إشارة إلى التطبيق بأن
حدث خطأ أدى إلى منع اكتمال عملية التحقق من الترخيص.
يساعد خادم Google Play التطبيق في إدارة الترخيص بموجب
حالات خطأ من خلال ضبط "فترة السماح" لإعادة المحاولة والحد الأقصى الموصى به
عدد مرات إعادة المحاولة. يقوم الخادم بتضمين هذه القيم في جميع استجابات التحقق من الترخيص،
إلحاقها كعناصر إضافية ضمن المفتاحين GT
وGR
.
يمكن لتطبيق "Policy
" استخراج إضافات GT
وGR
واستخدامها من أجل
السماح بالوصول إلى التطبيق بشكل مشروط على النحو التالي:
- بالنسبة إلى التحقّق من الترخيص الذي يؤدي إلى ظهور استجابة
RETRY
، يجب أن يعرضPolicy
. تخزين رمز الاستجابةRETRY
مؤقتًا وزيادة عددRETRY
ردود. - يجب أن تسمح
Policy
للمستخدم بالوصول إلى التطبيق، بشرط أن إما أن فترة السماح لإعادة المحاولة لا تزال نشطة أو أن الحد الأقصى لعدد مرات إعادة المحاولة لم يتم الوصول إليها.
يستخدِم ServerManagedPolicy
قيمتَي GT
وGR
التي يوفّرها الخادم كـ
الموضحة أعلاه. يوضح المثال أدناه المعالجة المشروطة لإعادة المحاولة.
الردود في طريقة allow()
. عدد RETRY
إجابة
بالطريقة processServerResponse()
، ولا يتم عرضها.
Kotlin
fun allowAccess(): Boolean { val ts = System.currentTimeMillis() return when(lastResponse) { LICENSED -> { // Check if the LICENSED response occurred within the validity timeout. ts <= validityTimestamp // Cached LICENSED response is still valid. } RETRY -> { ts < lastResponseTime + MILLIS_PER_MINUTE && // Only allow access if we are within the retry period // or we haven't used up our max retries. (ts <= retryUntil || retryCount <= maxRetries) } else -> false } }
Java
public boolean allowAccess() { long ts = System.currentTimeMillis(); if (lastResponse == LicenseResponse.LICENSED) { // Check if the LICENSED response occurred within the validity timeout. if (ts <= validityTimestamp) { // Cached LICENSED response is still valid. return true; } } else if (lastResponse == LicenseResponse.RETRY && ts < lastResponseTime + MILLIS_PER_MINUTE) { // Only allow access if we are within the retry period // or we haven't used up our max retries. return (ts <= retryUntil || retryCount <= maxRetries); } return false; }