تتيح لك وحدات الميزات فصل بعض الميزات والموارد. من الوحدة الأساسية في تطبيقك وتضمينها في حِزمة التطبيق. من خلال عرض الميزات في Play، يمكن للمستخدمين مثلاً تنزيل تلك الميزات وتثبيتها المكونات عند الطلب بعد تثبيت حزمة APK الأساسية لتطبيقك.
على سبيل المثال، لنفترض أنّ هناك تطبيقًا للرسائل النصية يتضمّن وظائف لالتقاط الرسائل المزوّدة بالصور وإرسالها، ولكن نسبة صغيرة فقط من المستخدمين تُرسِل رسائل مزوّدة بالصور. قد يكون من المنطقي تضمين رسائل مصورة وحدة الميزات القابلة للتنزيل. بهذه الطريقة، يكون حجم تنزيل التطبيق الأولي أصغر لجميع المستخدمين، ولا يحتاج سوى المستخدمين الذين يرسلون رسائل صور إلى تنزيل هذا المكوّن الإضافي.
يُرجى العِلم أنّ هذا النوع من التقسيم إلى وحدات يتطلّب المزيد من الجهد وقد يتطلّب بإعادة هيكلة التعليمات البرمجية الحالية لتطبيقك، لذا فكّر بعناية في أي من الاستفادة القصوى من ميزات التطبيق من التوافر للمستخدمين عند الطلب. للتعرّف بشكل أفضل على حالات الاستخدام والإرشادات المتعلّقة بالميزات المتاحة عند الطلب، اطّلِع على أفضل ممارسات تجربة المستخدم للتسليم عند الطلب.
إذا أردت تقسيم ميزات التطبيق تدريجيًا إلى وحدات مع مرور الوقت، بدون تفعيل خيارات التوصيل المتقدّمة، مثل التوصيل عند الطلب، ضبط التسليم في وقت التثبيت
تساعدك هذه الصفحة في إضافة وحدة ميزات إلى مشروع تطبيقك و إعدادها للتسليم عند الطلب. قبل أن تبدأ، تأكد من باستخدام الإصدار 3.5 من "استوديو Android" أو الإصدارات الأحدث والإصدار 3.5.0 من المكوّن الإضافي لنظام Gradle المتوافق مع Android أو أعلى.
ضبط وحدة جديدة للعرض عند الطلب
تتمثل أسهل طريقة لإنشاء وحدة ميزات جديدة في استخدام الإصدار 3.5 من "استوديو Android" أو إصدار أحدث بما أنّ وحدات الميزات تعتمد بشكلٍ أساسي على وحدة التطبيق الأساسية، لا يمكنك إضافتها إلا إلى مشاريع التطبيقات الحالية.
لإضافة وحدة ميزة إلى مشروع تطبيقك باستخدام "استوديو Android"، يُرجى اتّباع الخطوات التالية: والمتابعة على النحو التالي:
- افتح مشروع تطبيقك في بيئة التطوير المتكاملة (IDE)، إذا لم يسبق لك إجراء ذلك.
- اختَر ملف > جديد > وحدة جديدة من شريط القوائم.
- في مربّع الحوار إنشاء وحدة جديدة، اختَر وحدة ميزة ديناميكية وانقر على التالي.
- في قسم تهيئة الوحدة الجديدة، أكمل
التالي:
- اختَر وحدة التطبيق الأساسية لمشروع تطبيقك من. القائمة المنسدلة.
- حدِّد اسم الوحدة. يستخدم IDE هذا الاسم لتحديد
باعتبارها مشروعًا فرعيًا من Gradle في
ملف إعدادات Gradle عند
إنشاء حِزمة تطبيقك، يستخدم Gradle العنصر الأخير من اسم
المشروع الفرعي لإدراج سمة
<manifest split>
في بيان وحدة الميزات. - حدِّد اسم الحزمة للوحدة. "استوديو Android" بشكل تلقائي اسم حزمة يضم اسم الحزمة الجذر الوحدة الأساسية واسم الوحدة الذي حددته في الخطوة السابقة.
- اختَر الحد الأدنى لمستوى واجهة برمجة التطبيقات الذي تريد أن تتيحه الوحدة. يجب أن تتطابق هذه القيمة مع قيمة الوحدة الأساسية.
- انقر على التالي.
في قسم خيارات تنزيل الوحدة، أكمل ما يلي:
حدِّد عنوان الوحدة باستخدام ما يصل إلى 50 حرفًا. يستخدم النظام الأساسي هذا العنوان لتعريف الوحدة للمستخدمين عند، على سبيل المثال، تأكيد ما إذا كان المستخدم يريد تنزيل الوحدة. لهذا السبب، يجب أن تتضمّن الوحدة الأساسية لتطبيقك عنوان الوحدة بصفتها مورد سلسلة يمكنك ترجمته. عند إنشاء الوحدة باستخدام "استوديو Android"، يتمكن بيئة التطوير المتكاملة (IDE) من تضيف مورد السلسلة إلى الوحدة الأساسية من أجلك وتُدخل السمة الإدخال التالي في بيان وحدة الميزات:
<dist:module ... dist:title="@string/feature_title"> </dist:module>
في القائمة المنسدلة ضمن تضمين وقت التثبيت، اختَر عدم تضمين الوحدة أثناء التثبيت. يُدخل Android Studio العناصر التالية في ملف بيان الوحدة لتعكس اختيارك:
<dist:module ... > <dist:delivery> <dist:on-demand/> </dist:delivery> </dist:module>
ضَع علامة في المربّع بجانب دمج إذا كنت تريد أن تكون هذه الوحدة متاحة للأجهزة التي تعمل بنظام التشغيل Android 4.4 (المستوى 20 لواجهة برمجة التطبيقات) والإصدارات الأقدم وأن تكون مضمّنة في حِزم APK متعددة. يعني هذا أنّه يمكنك تفعيل السلوك عند الطلب لهذه الوحدة. وإيقاف الدمج لحذفه من الأجهزة غير المتوافقة تنزيل حِزم APK مجزّأة وتثبيتها يُدخل Android Studio العناصر التالية في ملف بيان الوحدة لتعكس اختيارك:
<dist:module ...> <dist:fusing dist:include="true | false" /> </dist:module>
انقر على إنهاء.
بعد انتهاء "استوديو Android" من إنشاء الوحدة، افحص محتوياتها بنفسك من جزء المشروع (اختَر عرض > نوافذ الأدوات > المشروع من شريط القوائم). يجب أن يكون الرمز الافتراضي والموارد والمؤسسة المشابهة لتلك الخاصة بوحدة التطبيق القياسية.
بعد ذلك، عليك تنفيذ وظيفة التثبيت عند الطلب باستخدام مكتبة "عرض الميزات في Play".
تضمين مكتبة عرض الميزات في Play في مشروعك
قبل البدء، عليك أولاً إضافة "مكتبة إرسال ميزات Play" إلى مشروعك.
طلب وحدة عند الطلب
عندما يحتاج تطبيقك إلى استخدام وحدة ميزة، يمكنه طلب وحدة أثناء
ظهوره في المقدّمة من خلال فئة
SplitInstallManager
. عند إجراء
طلب، يجب أن يحدِّد تطبيقك اسم الوحدة كما هو محدَّد في عنصر
split
في بيان الوحدة المستهدَفة. عندما تريد
إنشاء وحدة ميزة
باستخدام "استوديو Android"، سيستخدم نظام التصميم اسم الوحدة الذي توفّره.
لإدخال هذه الخاصية في بيان الوحدة أثناء وقت التجميع.
لمزيد من المعلومات، يمكنك الاطّلاع على
بيانات وحدة الميزات
على سبيل المثال، يمكنك استخدام تطبيق يتضمّن وحدة عند الطلب لتسجيل المحتوى وإرساله.
رسائل مصوّرة باستخدام كاميرا الجهاز، وهذه الوحدة عند الطلب
يحدد split="pictureMessages"
في ملف البيان الخاص به. يستخدم المثال التالي SplitInstallManager
لطلب وحدة pictureMessages
(بالإضافة إلى وحدة إضافية لبعض الفلاتر الترويجية):
Kotlin
// Creates an instance of SplitInstallManager. val splitInstallManager = SplitInstallManagerFactory.create(context) // Creates a request to install a module. val request = SplitInstallRequest .newBuilder() // You can download multiple on demand modules per // request by invoking the following method for each // module you want to install. .addModule("pictureMessages") .addModule("promotionalFilters") .build() splitInstallManager // Submits the request to install the module through the // asynchronous startInstall() task. Your app needs to be // in the foreground to submit the request. .startInstall(request) // You should also be able to gracefully handle // request state changes and errors. To learn more, go to // the section about how to Monitor the request state. .addOnSuccessListener { sessionId -> ... } .addOnFailureListener { exception -> ... }
Java
// Creates an instance of SplitInstallManager. SplitInstallManager splitInstallManager = SplitInstallManagerFactory.create(context); // Creates a request to install a module. SplitInstallRequest request = SplitInstallRequest .newBuilder() // You can download multiple on demand modules per // request by invoking the following method for each // module you want to install. .addModule("pictureMessages") .addModule("promotionalFilters") .build(); splitInstallManager // Submits the request to install the module through the // asynchronous startInstall() task. Your app needs to be // in the foreground to submit the request. .startInstall(request) // You should also be able to gracefully handle // request state changes and errors. To learn more, go to // the section about how to Monitor the request state. .addOnSuccessListener(sessionId -> { ... }) .addOnFailureListener(exception -> { ... });
عندما يطلب تطبيقك وحدة عند الطلب، تستخدم مكتبة عرض الميزات في Play استراتيجية "الإطفاء والنسيان". أي أنّه يرسل الطلب لتنزيل بالنظام الأساسي، غير أنه لا يراقب ما إذا كان التثبيت تم بنجاح. للمضي قدمًا برحلة المستخدم بعد التثبيت أو التعامل مع الأخطاء بسلاسة، احرص على مراقبة الطلب الولاية.
ملاحظة: يمكنك طلب الجديدة التي تم تثبيتها من قبل على الجهاز. تُعتبر واجهة برمجة التطبيقات الطلب مكتملاً على الفور إذا رصدت أنّه سبق تثبيت الوحده . بالإضافة إلى ذلك، بعد تثبيت أي وحدة، يُبقيها Google Play محدّثة. تلقائيًا. أي عندما تحمّل إصدارًا جديدًا من حِزمة تطبيقك، فإن المنصة لتحديث جميع حِزم APK المثبَّتة التي تنتمي إلى تطبيقك. لمزيد من المعلومات، يُرجى قراءة إدارة تحديثات التطبيقات
للوصول إلى رمز الوحدة ومواردها، يحتاج التطبيق إلى تفعيل SegmentCompat تجدر الإشارة إلى أنّ SegmentCompat لا مطلوبة لتطبيقات Android الفورية.
تأجيل تثبيت الوحدات المتوفّرة عند الطلب
إذا لم تكن بحاجة إلى تنزيل تطبيقك وتثبيته على الفور عند الطلب يمكنك تأجيل التثبيت عندما يكون التطبيق في الخلفية. بالنسبة إذا كنت تريد تحميل بعض المواد الترويجية مسبقًا لإطلاقها في وقت لاحق تطبيقك.
يمكنك تحديد وحدة لتنزيلها لاحقًا باستخدام
deferredInstall()
كما هو موضح أدناه. وعلى عكس
SplitInstallManager.startInstall()
،
لا يحتاج تطبيقك إلى أن يكون في المقدّمة لبدء طلب للقيام بأحد عمليات
التثبيت المؤجّل.
Kotlin
// Requests an on demand module to be downloaded when the app enters // the background. You can specify more than one module at a time. splitInstallManager.deferredInstall(listOf("promotionalFilters"))
Java
// Requests an on demand module to be downloaded when the app enters // the background. You can specify more than one module at a time. splitInstallManager.deferredInstall(Arrays.asList("promotionalFilters"));
تمثل طلبات التثبيت المؤجلة أفضل جهد ولا يمكنك تتبع
التقدم. لذلك، قبل محاولة الوصول إلى وحدة حددّتها للتثبيت المُؤجَّل، عليك
التحقّق من تثبيت الوحدة. إذا
كنت بحاجة إلى توفّر الوحدة على الفور، استخدِم بدلاً من ذلك
SplitInstallManager.startInstall()
لطلبها، كما هو موضّح في القسم السابق
.
مراقبة حالة الطلب
لتتمكّن من تعديل شريط التقدم، أو تنشيط نية بعد
التثبيت، أو معالجة خطأ في الطلب بشكل سلس، عليك الاستماع إلى
تعديلات الحالة من مهمة SplitInstallManager.startInstall()
غير المتزامنة.
قبل أن تتمكن من بدء تلقي تحديثات لطلب التثبيت، سجّل
المستمع والحصول على معرّف الجلسة للطلب، كما هو موضح أدناه.
Kotlin
// Initializes a variable to later track the session ID for a given request. var mySessionId = 0 // Creates a listener for request status updates. val listener = SplitInstallStateUpdatedListener { state -> if (state.sessionId() == mySessionId) { // Read the status of the request to handle the state update. } } // Registers the listener. splitInstallManager.registerListener(listener) ... splitInstallManager .startInstall(request) // When the platform accepts your request to download // an on demand module, it binds it to the following session ID. // You use this ID to track further status updates for the request. .addOnSuccessListener { sessionId -> mySessionId = sessionId } // You should also add the following listener to handle any errors // processing the request. .addOnFailureListener { exception -> // Handle request errors. } // When your app no longer requires further updates, unregister the listener. splitInstallManager.unregisterListener(listener)
Java
// Initializes a variable to later track the session ID for a given request. int mySessionId = 0; // Creates a listener for request status updates. SplitInstallStateUpdatedListener listener = state -> { if (state.sessionId() == mySessionId) { // Read the status of the request to handle the state update. } }; // Registers the listener. splitInstallManager.registerListener(listener); ... splitInstallManager .startInstall(request) // When the platform accepts your request to download // an on demand module, it binds it to the following session ID. // You use this ID to track further status updates for the request. .addOnSuccessListener(sessionId -> { mySessionId = sessionId; }) // You should also add the following listener to handle any errors // processing the request. .addOnFailureListener(exception -> { // Handle request errors. }); // When your app no longer requires further updates, unregister the listener. splitInstallManager.unregisterListener(listener);
التعامل مع أخطاء الطلبات
يُرجى العِلم أنّه قد يفشل تثبيت وحدات الميزات عند الطلب مثلما لا ينجح تثبيت التطبيقات دائمًا. يمكن أن يكون سبب تعذُّر التثبيت بمشكلات مثل انخفاض مساحة التخزين على الجهاز أو عدم وجود اتصال بالشبكة أو عدم تسجيل الدخول إلى "متجر Google Play" للحصول على اقتراحات حول كيفية التعامل مع هذه المواقف بطريقة سلسة من وجهة نظر المستخدم، اطّلِع على إرشادات تجربة المستخدم للعرض عند الطلب.
من حيث الرمز، عليك معالجة حالات تعذُّر تنزيل وحدة أو تثبيتها باستخدام addOnFailureListener()
، كما هو موضّح أدناه:
Kotlin
splitInstallManager .startInstall(request) .addOnFailureListener { exception -> when ((exception as SplitInstallException).errorCode) { SplitInstallErrorCode.NETWORK_ERROR -> { // Display a message that requests the user to establish a // network connection. } SplitInstallErrorCode.ACTIVE_SESSIONS_LIMIT_EXCEEDED -> checkForActiveDownloads() ... } } fun checkForActiveDownloads() { splitInstallManager // Returns a SplitInstallSessionState object for each active session as a List. .sessionStates .addOnCompleteListener { task -> if (task.isSuccessful) { // Check for active sessions. for (state in task.result) { if (state.status() == SplitInstallSessionStatus.DOWNLOADING) { // Cancel the request, or request a deferred installation. } } } } }
Java
splitInstallManager .startInstall(request) .addOnFailureListener(exception -> { switch (((SplitInstallException) exception).getErrorCode()) { case SplitInstallErrorCode.NETWORK_ERROR: // Display a message that requests the user to establish a // network connection. break; case SplitInstallErrorCode.ACTIVE_SESSIONS_LIMIT_EXCEEDED: checkForActiveDownloads(); ... }); void checkForActiveDownloads() { splitInstallManager // Returns a SplitInstallSessionState object for each active session as a List. .getSessionStates() .addOnCompleteListener( task -> { if (task.isSuccessful()) { // Check for active sessions. for (SplitInstallSessionState state : task.getResult()) { if (state.status() == SplitInstallSessionStatus.DOWNLOADING) { // Cancel the request, or request a deferred installation. } } } }); }
يوضّح الجدول التالي حالات الخطأ التي قد يحتاج تطبيقك إلى معالجتها:
رمز الخطأ | الوصف | الإجراء المقترَح |
---|---|---|
ACTIVE_SESSIONS_LIMIT_EXCEEDED | يتم رفض الطلب لأنّ هناك طلبًا واحدًا على الأقل جارٍ تنزيله حاليًا. | تحقّق مما إذا كانت هناك أي طلبات لا تزال قيد التنزيل، كما هو موضّح في المثال أعلاه. |
الوحدة_غير متوفرة | يتعذَّر على Google Play العثور على الوحدة المطلوبة استنادًا إلى الوحدة المطلوبة على الإصدار الحالي المثبَّت من التطبيق والجهاز وحساب Google Play للمستخدم الحساب. | وإذا لم يتمكّن المستخدم من الوصول إلى الوحدة، عليك إبلاغه بذلك. |
طلب_غير صالح | تلقّى Google Play الطلب، ولكن لم يتم قبوله. غير صالح. | تأكَّد من أنّ المعلومات المضمّنة في الطلب كاملة ودقيقة. |
SESSION_NOT_FOUND | لم يتم العثور على جلسة لرقم تعريف جلسة معيّن. | في حال كنت تحاول مراقبة حالة طلب باستخدام معرّف الجلسة، تأكّد من أنّ رقم تعريف الجلسة صحيح. |
API_NOT_AVAILABLE | مكتبة عرض الميزات في Play غير متاحة على الجهاز الحالي. وهذا يعني أنّ الجهاز لا يمكنه تنزيل الميزات المثبَّتة وتثبيتها عند الطلب. | بالنسبة إلى الأجهزة التي تعمل بالإصدار 4.4 من نظام التشغيل Android (المستوى 20 من واجهة برمجة التطبيقات) أو الإصدارات الأقدم، عليك:
تضمين وحدات الميزات أثناء التثبيت باستخدام
سمة dist:fusing في البيان. لمزيد من المعلومات، يُرجى الاطّلاع على بيان وحدة الميزات.
|
خطأ_الشبكة | تعذّرت تلبية الطلب بسبب خطأ في الشبكة. | طلب إنشاء اتصال بالشبكة من المستخدم أو الانتقال إلى شبكة مختلفة. |
ACCESS_DENIED | يتعذّر على التطبيق تسجيل الطلب بسبب عدم توفّر أذونات كافية. | ويحدث ذلك عادةً عندما يكون التطبيق في الخلفية. حاوِل إجراء الطلب عندما يعود التطبيق إلى المقدّمة. |
INCOMPATIBLE_WITH_EXISTING_SESSION | يحتوي الطلب على وحدة واحدة أو أكثر سبق أن تم طلبها ولكن لم يتم تثبيتها بعد. | يمكنك إنشاء طلب جديد لا يتضمّن الوحدات التي سبق لتطبيقك طلبها، أو الانتظار إلى أن تنتهي عملية تثبيت كل الوحدات المطلوبة حاليًا قبل إعادة محاولة إرسال الطلب.
يُرجى العِلم أنّ طلب وحدة سبق أن تم تثبيتها لا يؤدي إلى ظهور خطأ. |
SERVICE_DIED | توقف الخدمة المسؤولة عن التعامل مع الطلب. | يُرجى إعادة محاولة إرسال الطلب.
يتلقّى |
سعة التخزين غير متوفرة | لا تتوفّر مساحة تخزين مجانية كافية على الجهاز لتثبيت الميزة واحدة. | يجب إبلاغ المستخدم بأنّه لا تتوفّر لديه مساحة تخزين كافية لتثبيت هذه الإضافة. الجديدة. |
SPLITCOMPAT_VERIFICATION_ERROR وSPLITCOMPAT_EMULATION_ERROR وSPLITCOMPAT_COPY_ERROR | تعذّر على SplitCompat تحميل وحدة الميزات. | من المفترض أن يتم حل هذه الأخطاء تلقائيًا بعد التطبيق التالي إعادة التشغيل. |
متجر Play لم يتم العثور عليه | تطبيق "متجر Play" غير مثبّت على الجهاز. | إبلاغ المستخدم بضرورة تنزيل تطبيق "متجر Play" الجديدة. |
APP_NOT_OWNED | لم يتم تثبيت التطبيق من خلال Google Play ولا يمكن تنزيل الميزة. لا يمكن أن يحدث هذا الخطأ إلا لعمليات التثبيت المؤجلة. | إذا أردت أن يكتسب المستخدم التطبيق على Google Play، استخدم
startInstall() التي يمكنها الحصول على البيانات اللازمة
تأكيد المستخدم. |
خطأ_داخلي | حدث خطأ داخلي في "متجر Play". | يُرجى إعادة محاولة إرسال الطلب. |
إذا طلب أحد المستخدمين تنزيل وحدة عند الطلب وحدث خطأ، ننصحك بعرض مربّع حوار يقدّم خيارَين للمستخدم: تجربة مرة أخرى (التي تحاول إرسال الطلب مرة أخرى) وإلغاء (التي تلغي ). للحصول على دعم إضافي، يجب أيضًا تقديم رابط المساعدة يوجه المستخدمين إلى صفحة مركز مساعدة Google Play
التعامل مع التعديلات على الحالة
بعد أن تقوم بتسجيل مستمع وتسجيل معرّف الجلسة لطلبك،
استخدام StateUpdatedListener.onStateUpdate()
لمعالجة تغييرات الحالة، كما هو موضّح أدناه.
Kotlin
override fun onStateUpdate(state : SplitInstallSessionState) { if (state.status() == SplitInstallSessionStatus.FAILED && state.errorCode() == SplitInstallErrorCode.SERVICE_DIED) { // Retry the request. return } if (state.sessionId() == mySessionId) { when (state.status()) { SplitInstallSessionStatus.DOWNLOADING -> { val totalBytes = state.totalBytesToDownload() val progress = state.bytesDownloaded() // Update progress bar. } SplitInstallSessionStatus.INSTALLED -> { // After a module is installed, you can start accessing its content or // fire an intent to start an activity in the installed module. // For other use cases, see access code and resources from installed modules. // If the request is an on demand module for an Android Instant App // running on Android 8.0 (API level 26) or higher, you need to // update the app context using the SplitInstallHelper API. } } } }
Java
@Override public void onStateUpdate(SplitInstallSessionState state) { if (state.status() == SplitInstallSessionStatus.FAILED && state.errorCode() == SplitInstallErrorCode.SERVICE_DIES) { // Retry the request. return; } if (state.sessionId() == mySessionId) { switch (state.status()) { case SplitInstallSessionStatus.DOWNLOADING: int totalBytes = state.totalBytesToDownload(); int progress = state.bytesDownloaded(); // Update progress bar. break; case SplitInstallSessionStatus.INSTALLED: // After a module is installed, you can start accessing its content or // fire an intent to start an activity in the installed module. // For other use cases, see access code and resources from installed modules. // If the request is an on demand module for an Android Instant App // running on Android 8.0 (API level 26) or higher, you need to // update the app context using the SplitInstallHelper API. } } }
في الجدول أدناه، يتم توضيح الحالات المحتمَلة لطلب التثبيت.
حالة الطلب | الوصف | الإجراء المقترَح |
---|---|---|
في انتظار المراجعة | تم قبول الطلب ومن المفترض أن يبدأ التنزيل بعد قليل. | يمكنك بدء مكونات واجهة المستخدم، مثل شريط التقدم، لإطلاع المستخدم على معلومات حول عملية التنزيل. |
REQUIRES_USER_CONFIRMATION | يتطلب التنزيل تأكيد المستخدم. وغالبًا ما تحدث هذه الحالة إذا لم يتم تثبيت التطبيق من خلال Google Play. | اطلب من المستخدم تأكيد تنزيل الميزة من خلال Google Play. لمزيد من المعلومات، انتقِل إلى القسم الخاص بكيفية الحصول على تأكيد المستخدم. |
التنزيل | لا تزال عملية التنزيل جارية. | إذا كنت تقدّم شريط تقدّم للتنزيل، استخدِم SplitInstallSessionState.bytesDownloaded()
وSplitInstallSessionState.totalBytesToDownload()
لتعديل واجهة المستخدم (اطّلِع على نموذج الرمز البرمجي أعلاه هذا الجدول). |
تم التنزيل | نزَّل الجهاز الوحدة ولكن لم يبدأ التثبيت بعد. | يجب أن تفعِّل التطبيقات حزمة SplitCompat للوصول إلى الوحدات التي تم تنزيلها وتجنُّب ظهور هذه الحالة. هذا الإجراء مطلوب للوصول إلى رمز وحدة الميزات و مواردها. |
جارٍ التثبيت | يُثبِّت الجهاز الوحدة حاليًا. | عدِّل شريط التقدّم. وعادةً ما تكون هذه الحالة قصيرة. |
تم التثبيت | يتم تثبيت الوحدة على الجهاز. | رمز الوصول والمورد في الوحدة
لمواصلة رحلة المستخدم.
إذا كانت الوحدة مخصّصة لتطبيق Android فوري يعمل على الإصدار 8.0 من نظام التشغيل Android (المستوى 26 لواجهة برمجة التطبيقات)
أو إصدار أحدث، عليك استخدام |
فشل | تعذّر الطلب قبل تثبيت الوحدة على الجهاز. | اطلب من المستخدم إعادة محاولة الطلب أو إلغائه. |
جارٍ الإلغاء | الجهاز في مرحلة إلغاء الطلب. | لمزيد من المعلومات، انتقِل إلى القسم الذي يتناول كيفية إلغاء طلب تثبيت. |
تم إلغاؤها | تم إلغاء الطلب. |
الحصول على تأكيد من المستخدم
في بعض الحالات، قد يطلب Google Play تأكيدًا من المستخدم قبل تنفيذ
طلب تنزيل البيانات. على سبيل المثال، إذا لم تثبّت Google تطبيقك.
التشغيل أو ما إذا كنت تحاول إجراء تنزيل كبير الحجم عبر بيانات الجوّال. في هذه الحالات،
تُبلغ حالة الطلب عن REQUIRES_USER_CONFIRMATION
، ويجب أن يحصل تطبيقك
على تأكيد من المستخدم قبل أن يتمكّن الجهاز من تنزيل الوحدات في الطلب
وتثبيتها. للحصول على تأكيد، يجب أن يطلب تطبيقك من المستخدم تأكيد الموافقة على النحو التالي:
Kotlin
override fun onSessionStateUpdate(state: SplitInstallSessionState) { if (state.status() == SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION) { // Displays a confirmation for the user to confirm the request. splitInstallManager.startConfirmationDialogForResult( state, // an activity result launcher registered via registerForActivityResult activityResultLauncher) } ... }
Java
@Override void onSessionStateUpdate(SplitInstallSessionState state) { if (state.status() == SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION) { // Displays a confirmation for the user to confirm the request. splitInstallManager.startConfirmationDialogForResult( state, // an activity result launcher registered via registerForActivityResult activityResultLauncher); } ... }
يمكنك تسجيل مشغّل نتائج نشاط باستخدام العقدة المضمّنة
ActivityResultContracts.StartIntentSenderForResult
. اطّلِع على واجهات برمجة التطبيقات لنتائج الأنشطة.
يتم تعديل حالة الطلب استنادًا إلى ردّ المستخدم:
- إذا وافق المستخدم على التأكيد، تتغير حالة الطلب إلى
PENDING
ويستمر التنزيل. - إذا رفض المستخدم التأكيد، تتغير حالة الطلب إلى
CANCELED
- إذا لم يحدد المستخدم قبل أن يتم تلف مربع الحوار،
ستظل حالة الطلب هي
REQUIRES_USER_CONFIRMATION
. يمكن لتطبيقك أن يطلب من المستخدم مرة أخرى إكمال الطلب.
لتلقي معاودة الاتصال مع رد المستخدم، يمكنك إلغاء ActivityResultCallback كما هو موضح أدناه.
Kotlin
registerForActivityResult(StartIntentSenderForResult()) { result: ActivityResult -> { // Handle the user's decision. For example, if the user selects "Cancel", // you may want to disable certain functionality that depends on the module. } }
Java
registerForActivityResult( new ActivityResultContracts.StartIntentSenderForResult(), new ActivityResultCallback<ActivityResult>() { @Override public void onActivityResult(ActivityResult result) { // Handle the user's decision. For example, if the user selects "Cancel", // you may want to disable certain functionality that depends on the module. } });
إلغاء طلب تثبيت
إذا كان تطبيقك بحاجة إلى إلغاء طلب قبل تثبيته، يمكن أن يستدعي
طريقة cancelInstall()
باستخدام معرّف جلسة الطلب، كما هو موضّح أدناه.
Kotlin
splitInstallManager // Cancels the request for the given session ID. .cancelInstall(mySessionId)
Java
splitInstallManager // Cancels the request for the given session ID. .cancelInstall(mySessionId);
وحدات الوصول
للوصول إلى الرمز والموارد من الوحدة النمطية التي تم تنزيلها بعد تنزيلها، يحتاج تطبيقك إلى تفعيل مكتبة divCompat لكل من تطبيقك ولكل نشاط في وحدات الميزات الخاصة بتطبيقك عمليات التنزيل.
مع ذلك، تجدر الإشارة إلى أنّ المنصة تخضع لما يلي: القيود المفروضة على الوصول إلى محتويات وحدة ما، لبعض الوقت (أيام، في بعض الحالات) بعد تنزيل الوحدة:
- لا يمكن للنظام الأساسي تطبيق أي إدخالات جديدة في البيان تقدّمها الوحدة.
- لا يمكن للمنصة الوصول إلى موارد الوحدة لمكونات واجهة المستخدم للنظام، مثل الإشعارات. إذا كنت بحاجة إلى استخدام هذه الموارد على الفور، ننصحك بتضمين هذه الموارد في الوحدة الأساسية لتطبيقك.
تفعيل SplitCompat
لكي يتمكّن تطبيقك من الوصول إلى الرموز البرمجية والموارد من وحدة تم تنزيلها، عليك تفعيل SplitCompat باستخدام إحدى الطريقتَين الموضّحتَين في القسمَين التاليَين فقط.
بعد تفعيل SegmentCompat للتطبيق، عليك أيضًا تفعيل splitCompat. لكل نشاط في وحدات الميزات التي التي يريد التطبيق الوصول إليها.
تعريف فئة SplitCompatApplication في البيان
إنّ أبسط طريقة لتفعيل SplitCompat هي تحديد SplitCompatApplication
كالفئة الفرعية Application
في
ملف بيان تطبيقك، كما هو موضّح أدناه:
<application
...
android:name="com.google.android.play.core.splitcompat.SplitCompatApplication">
</application>
بعد تثبيت التطبيق على جهاز، يمكنك الوصول إلى الرموز البرمجية والموارد من وحدات الميزات التي تم تنزيلها تلقائيًا.
استدعاء splitCompat في وقت التشغيل
يمكنك أيضًا تفعيل SplitCompat في أنشطة أو خدمات معيّنة أثناء التشغيل.
يجب تفعيل SplitCompat بهذه الطريقة لتشغيل الأنشطة المضمّنة في
وحدات الميزات. ولإجراء ذلك، يمكنك إلغاء attachBaseContext
كما هو موضّح أدناه.
إذا كانت لديك فئة Application مخصّصة،
اجعلها بدلاً من ذلك تمتد من
SplitCompatApplication
لتفعيل SplitCompat لتطبيقك، كما هو موضّح أدناه:
Kotlin
class MyApplication : SplitCompatApplication() { ... }
Java
public class MyApplication extends SplitCompatApplication { ... }
تتجاهل SplitCompatApplication
ببساطة ContextWrapper.attachBaseContext()
لتضمين SplitCompat.install(Context applicationContext)
. إذا كنت لا تريد
أن توسّع فئة Application
SplitCompatApplication
، يمكنك إلغاءattachBaseContext()
الطريقة يدويًا على النحو التالي:
Kotlin
override fun attachBaseContext(base: Context) { super.attachBaseContext(base) // Emulates installation of future on demand modules using SplitCompat. SplitCompat.install(this) }
Java
@Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); // Emulates installation of future on demand modules using SplitCompat. SplitCompat.install(this); }
إذا كانت الوحدة المتوفّرة عند الطلب متوافقة مع كل من التطبيقات الفورية والتطبيقات المثبّتة، يمكنك استدعاء splitCompat بشروط، على النحو التالي:
Kotlin
override fun attachBaseContext(base: Context) { super.attachBaseContext(base) if (!InstantApps.isInstantApp(this)) { SplitCompat.install(this) } }
Java
@Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); if (!InstantApps.isInstantApp(this)) { SplitCompat.install(this); } }
تفعيل SplitCompat لأنشطة الوحدات
بعد تفعيل حزمة SplitCompat لتطبيقك الأساسي، عليك تفعيل حزمة SplitCompat
لكل نشاط ينزّله تطبيقك في وحدة ميزة. لإجراء ذلك،
استخدِم طريقة SplitCompat.installActivity()
على النحو التالي:
Kotlin
override fun attachBaseContext(base: Context) { super.attachBaseContext(base) // Emulates installation of on demand modules using SplitCompat. SplitCompat.installActivity(this) }
Java
@Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); // Emulates installation of on demand modules using SplitCompat. SplitCompat.installActivity(this); }
الوصول إلى المكوّنات المحدّدة في وحدات الميزات
بدء نشاط محدّد في وحدة ميزة
يمكنك إطلاق الأنشطة المحدّدة في وحدات الميزات باستخدام
startActivity()
بعد تفعيل SplitCompat.
Kotlin
startActivity(Intent() .setClassName("com.package", "com.package.module.MyActivity") .setFlags(...))
Java
startActivity(new Intent() .setClassName("com.package", "com.package.module.MyActivity") .setFlags(...));
المَعلمة الأولى التي يتم تمريرها إلى setClassName
هي اسم حِزمة التطبيق، والملفَّق المَعلمة الثانية هي اسم الفئة الكامل للنشاط.
عندما يكون لديك نشاط في وحدة ميزة نزّلته عند الطلب، عليك تفعيل SplitCompat في النشاط.
بدء خدمة محدّدة في وحدة ميزة
يمكنك تشغيل الخدمات المحددة في وحدات الميزات باستخدام
startService()
بعد تفعيل splitCompat.
Kotlin
startService(Intent() .setClassName("com.package", "com.package.module.MyService") .setFlags(...))
Java
startService(new Intent() .setClassName("com.package", "com.package.module.MyService") .setFlags(...));
تصدير مكوّن محدّد في وحدة ميزة
يجب عدم تضمين مكونات Android التي تم تصديرها في الوحدات الاختيارية.
يدمج نظام الإنشاء إدخالات البيان لجميع الوحدات في الوحدة الأساسية. إذا كانت الوحدة الاختيارية تحتوي على مكوّن تم تصديره، يمكن الوصول إليه حتى قبل تثبيت الوحدة، ويمكن أن يؤدي ذلك إلى حدوث عطل بسبب عدم توفّر الرمز البرمجي عند استدعائه من تطبيق آخر.
هذه ليست مشكلة للمكونات الداخلية؛ لا يتم الوصول إليها إلا بواسطة التطبيق، حتى يتمكن التطبيق التحقق من تثبيت الوحدة قبل الوصول إلى المكون.
إذا كنت بحاجة إلى مكوّن تم تصديره وأردت أن يكون محتواه في وحدة
اختيارية، ننصحك بتنفيذ نمط وكيل.
يمكنك القيام بذلك عن طريق إضافة مكون خادم وكيل تم تصديره في القاعدة؛
عند الوصول إليه، يمكن لمكوِّن الخادم الوكيل التحقق من وجود الوحدة التي
الذي يحتوي على المحتوى. إذا كانت الوحدة متوفّرة، يمكن للمكوّن الوكيل
بدء المكوّن الداخلي من الوحدة من خلال Intent
،
مع إعادة توجيه النية من التطبيق المُرسِل. إذا لم تكن الوحدة متوفّرة، يمكن للمكوّن
تنزيل الوحدة أو عرض رسالة خطأ مناسبة للتطبيق
المُرسِل.
رمز الدخول والموارد من الوحدات المثبَّتة
في حال تفعيل splitCompat للقاعدة سياق التطبيق والأنشطة ضمن وحدة الميزات، يمكنك استخدام والموارد من وحدة خاصة كما لو كانت جزءًا من حزمة APK الأساسية، بمجرد تثبيت الوحدة الاختيارية.
رمز الدخول من وحدة مختلفة
الوصول إلى الرمز الأساسي من وحدة معيّنة
يمكن للوحدات الأخرى استخدام الرمز البرمجي المتوفّر داخل الوحدة الأساسية مباشرةً. لست بحاجة إلى القيام بأي شيء خاص؛ ما عليك سوى استيراد الفصول الدراسية التي تحتاجها واستخدامها.
رمز وحدة الوصول من وحدة أخرى
لا يمكن الوصول إلى كائن أو فئة داخل وحدة بشكلٍ ثابت من وحدة أخرى مباشرةً، ولكن يمكن الوصول إليه بشكلٍ غير مباشر باستخدام ميزة "العرض المرجعي".
يجب الانتباه إلى عدد المرات التي يحدث فيها ذلك، بسبب تكاليف الأداء للتأمل. بالنسبة إلى حالات الاستخدام المعقدة، استخدم أطر عمل حقن التبعية مثل أداة السحب 2 لضمان استدعاء انعكاس واحد لكل عمر التطبيق.
لتبسيط التفاعلات مع الكائن بعد إنشاء المثيل، ننصح بتحديد واجهة في الوحدة الأساسية وتنفيذها وحدة الميزة. على سبيل المثال:
Kotlin
// In the base module interface MyInterface { fun hello(): String } // In the feature module object MyInterfaceImpl : MyInterface { override fun hello() = "Hello" } // In the base module, where we want to access the feature module code val stringFromModule = (Class.forName("com.package.module.MyInterfaceImpl") .kotlin.objectInstance as MyInterface).hello();
Java
// In the base module public interface MyInterface { String hello(); } // In the feature module public class MyInterfaceImpl implements MyInterface { @Override public String hello() { return "Hello"; } } // In the base module, where we want to access the feature module code String stringFromModule = ((MyInterface) Class.forName("com.package.module.MyInterfaceImpl").getConstructor().newInstance()).hello();
الوصول إلى المراجع ومواد العرض من وحدة مختلفة
بعد تثبيت إحدى الوحدات، يمكنك الوصول إلى الموارد ومواد العرض ضمن الوحدة بالطريقة العادية، مع مراعاة أمرَين:
- إذا كنت تصل إلى مورد من وحدة مختلفة، لن تتمكّن الوحده من الوصول إلى معرّف المورد، إلا أنّه سيظل بإمكانك الوصول إلى المورد بالاسم. لاحظ أن الحزمة المراد استخدامها للإشارة إلى المورد هي حزمة الوحدة التي يتم فيها تحديد المورد.
- إذا كنت تريد الوصول إلى مواد العرض أو الموارد المتوفّرة في ملف برمجي مثبَّت حديثًا من ملف برمجي مختلف مثبَّت في تطبيقك، عليك إجراء ذلك باستخدام سياق التطبيق. سياق المكون الذي يحاول الوصول إلى الموارد لم يتم بعد تحديث التطبيق. وبدلاً من ذلك، يمكنك إعادة إنشاء هذا المكون (على سبيل المثال، استدعاء Activity.recreate()) أو أعِد تثبيت divCompat عليه بعد انتهاء وحدة الميزات التثبيت.
تحميل رمز برمجي أصلي في تطبيق باستخدام ميزة التسليم عند الطلب
نقترح استخدام ReLinker لتحميل جميع مكتباتك الأصلية عند استخدام التسليم عند الطلب لوحدات الميزات. يحلّ ReLinker مشكلة في تحميل المكتبات المجمّعة من رموز برمجية أصلية بعد تثبيت وحدة ميزة. يمكنك الاطّلاع على مزيد من المعلومات عن ReLinker في مقالة نصائح حول واجهة برمجة التطبيقات JNI في Android.
تحميل رمز أصلي من وحدة اختيارية
بعد تثبيت التقسيم، ننصحك بتحميل الرمز الأصلي من خلال ReLinker مع التطبيقات الفورية، يجب استخدام هذه الطريقة الخاصة.
إذا كنت تستخدم System.loadLibrary()
لتحميل الرمز الأصلي وكانت مكتبتك
الأصلية تعتمد على مكتبة أخرى في الوحدة، عليك أولاً
تحميل تلك المكتبة الأخرى يدويًا.
في حال استخدام ReLinker، تكون العملية المكافئة هي
Relinker.recursively().loadLibrary()
إذا كنت تستخدم dlopen()
في الرمز البرمجي الأصلي لتحميل مكتبة محدّدة في ملف
وحدة اختيارية، لن تعمل مع مسارات المكتبات النسبية.
أفضل حلّ هو استرداد المسار المطلق للمكتبة من رمز Java
من خلال ClassLoader.findLibrary()
ثم استخدامه في طلب dlopen()
.
يمكنك إجراء ذلك قبل إدخال الرمز البرمجي الأصلي أو استخدام طلب JNI من
الرمز البرمجي الأصلي إلى Java.
الوصول إلى تطبيقات Android الفورية المثبَّتة
بعد الإبلاغ عن وحدة "تطبيق Android الفوري" على أنّها INSTALLED
، يمكنك الوصول إلى
الرموز البرمجية والموارد باستخدام تطبيق مُحدَّث
السياق: حاسمة
سياق ينشئه تطبيقك قبل تثبيت إحدى الوحدات (على سبيل المثال، إحدى
المخزن بالفعل في متغير) لا يحتوي على محتوى الملف
واحدة. أمّا السياق الجديد، فيؤدي إلى ذلك، ويمكن الحصول عليه مثلاً باستخدام
createPackageContext
.
Kotlin
// Generate a new context as soon as a request for a new module // reports as INSTALLED. override fun onStateUpdate(state: SplitInstallSessionState ) { if (state.sessionId() == mySessionId) { when (state.status()) { ... SplitInstallSessionStatus.INSTALLED -> { val newContext = context.createPackageContext(context.packageName, 0) // If you use AssetManager to access your app’s raw asset files, you’ll need // to generate a new AssetManager instance from the updated context. val am = newContext.assets } } } }
Java
// Generate a new context as soon as a request for a new module // reports as INSTALLED. @Override public void onStateUpdate(SplitInstallSessionState state) { if (state.sessionId() == mySessionId) { switch (state.status()) { ... case SplitInstallSessionStatus.INSTALLED: Context newContext = context.createPackageContext(context.getPackageName(), 0); // If you use AssetManager to access your app’s raw asset files, you’ll need // to generate a new AssetManager instance from the updated context. AssetManager am = newContext.getAssets(); } } }
تطبيقات Android الفورية على الإصدار 8.0 من نظام التشغيل Android والإصدارات الأحدث
عند طلب وحدة عند الطلب لتطبيق Android الفوري على Android 8.0
(المستوى 26 من واجهة برمجة التطبيقات) والإصدارات الأحدث، بعد الإبلاغ عن طلب التثبيت على أنه INSTALLED
، عليك
تحتاج إلى تحديث التطبيق بسياق الوحدة الجديدة من خلال استدعاء
SplitInstallHelper.updateAppInfo(Context context)
بخلاف ذلك، لا يكون التطبيق على دراية برمز الوحدة بعد.
والموارد. بعد تعديل البيانات الوصفية للتطبيق، عليك تحميل محتويات الوحدات أثناء حدث الخيط الرئيسي التالي من خلال استدعاء Handler
جديد، كما هو موضّح أدناه:
Kotlin
override fun onStateUpdate(state: SplitInstallSessionState ) { if (state.sessionId() == mySessionId) { when (state.status()) { ... SplitInstallSessionStatus.INSTALLED -> { // You need to perform the following only for Android Instant Apps // running on Android 8.0 (API level 26) and higher. if (BuildCompat.isAtLeastO()) { // Updates the app’s context with the code and resources of the // installed module. SplitInstallHelper.updateAppInfo(context) Handler().post { // Loads contents from the module using AssetManager val am = context.assets ... } } } } } }
Java
@Override public void onStateUpdate(SplitInstallSessionState state) { if (state.sessionId() == mySessionId) { switch (state.status()) { ... case SplitInstallSessionStatus.INSTALLED: // You need to perform the following only for Android Instant Apps // running on Android 8.0 (API level 26) and higher. if (BuildCompat.isAtLeastO()) { // Updates the app’s context with the code and resources of the // installed module. SplitInstallHelper.updateAppInfo(context); new Handler().post(new Runnable() { @Override public void run() { // Loads contents from the module using AssetManager AssetManager am = context.getAssets(); ... } }); } } } }
تحميل مكتبات C/C++
إذا كنت تريد تحميل مكتبات C/C++ من وحدة سبق أن حمّلها الجهاز في تطبيق فوري، استخدِم SplitInstallHelper.loadLibrary(Context context, String libName)
، كما هو موضّح أدناه:
Kotlin
override fun onStateUpdate(state: SplitInstallSessionState) { if (state.sessionId() == mySessionId) { when (state.status()) { SplitInstallSessionStatus.INSTALLED -> { // Updates the app’s context as soon as a module is installed. val newContext = context.createPackageContext(context.packageName, 0) // To load C/C++ libraries from an installed module, use the following API // instead of System.load(). SplitInstallHelper.loadLibrary(newContext, “my-cpp-lib”) ... } } } }
Java
public void onStateUpdate(SplitInstallSessionState state) { if (state.sessionId() == mySessionId) { switch (state.status()) { case SplitInstallSessionStatus.INSTALLED: // Updates the app’s context as soon as a module is installed. Context newContext = context.createPackageContext(context.getPackageName(), 0); // To load C/C++ libraries from an installed module, use the following API // instead of System.load(). SplitInstallHelper.loadLibrary(newContext, “my-cpp-lib”); ... } } }
القيود المعروفة
- لا يمكن استخدام Android WebView في نشاط يصل إلى الموارد أو الأصول من وحدة اختيارية. ويعود السبب في ذلك إلى عدم التوافق بين WebView وSplitCompat على المستوى 28 من واجهة برمجة التطبيقات لنظام التشغيل Android والإصدارات الأقدم.
- لا يمكنك تخزين عناصر
ApplicationInfo
في Android أو محتوياتها أو العناصر التي تحتوي عليها في ذاكرة التخزين المؤقت داخل تطبيقك. يجب جلب هذه العناصر دائمًا حسب الحاجة من سياق التطبيق. قد يؤدي التخزين المؤقت لهذه العناصر إلى تعطُّل التطبيق. عند تثبيت وحدة من الميزات.
إدارة الوحدات المثبَّتة
للتحقّق من وحدات الميزات المثبَّتة حاليًا على الجهاز،
يمكنك استدعاء
SplitInstallManager.getInstalledModules()
،
الذي يعرض Set<String>
لأسماء الوحدات المثبَّتة، كما هو موضّح
أدناه.
Kotlin
val installedModules: Set<String> = splitInstallManager.installedModules
Java
Set<String> installedModules = splitInstallManager.getInstalledModules();
إلغاء تثبيت الوحدات
يمكنك طلب إلغاء تثبيت الوحدات على الجهاز من خلال استدعاء SplitInstallManager.deferredUninstall(List<String> moduleNames)
، كما هو موضّح أدناه.
Kotlin
// Specifies two feature modules for deferred uninstall. splitInstallManager.deferredUninstall(listOf("pictureMessages", "promotionalFilters"))
Java
// Specifies two feature modules for deferred uninstall. splitInstallManager.deferredUninstall(Arrays.asList("pictureMessages", "promotionalFilters"));
لا تحدث عمليات إلغاء تثبيت الوحدات على الفور. وهذا يعني أنّه
يزيل الجهاز هذه التطبيقات في الخلفية حسب الحاجة لتوفير مساحة تخزين.
يمكنك التأكد من أن الجهاز يحتوي على
وحدة من خلال استدعاء
SplitInstallManager.getInstalledModules()
وفحص النتيجة، كما هو موضح في القسم السابق.
تنزيل مراجع لغوية إضافية
باستخدام حِزم التطبيقات، لا تنزِّل الأجهزة سوى الرموز البرمجية والموارد التي تحتاج إليها لتشغيل تطبيقك. وبالنسبة إلى موارد اللغة، لا ينزِّل جهاز المستخدم سوى موارد اللغة في تطبيقك التي تتطابق مع لغة واحدة أو أكثر تم اختيارها حاليًا في إعدادات الجهاز.
إذا أردت أن يتمكن تطبيقك من الوصول إلى موارد لغوية إضافية، على سبيل المثال، لاستخدام أداة اختيار اللغة داخل التطبيق، يمكنك استخدام ميزة "عرض الميزات في Play" مكتبة لتنزيلها عند الطلب. وتتشابه هذه العملية مع عملية تنزيل وحدة ميزة، كما هو موضّح أدناه.
Kotlin
// Captures the user’s preferred language and persists it // through the app’s SharedPreferences. sharedPrefs.edit().putString(LANGUAGE_SELECTION, "fr").apply() ... // Creates a request to download and install additional language resources. val request = SplitInstallRequest.newBuilder() // Uses the addLanguage() method to include French language resources in the request. // Note that country codes are ignored. That is, if your app // includes resources for “fr-FR” and “fr-CA”, resources for both // country codes are downloaded when requesting resources for "fr". .addLanguage(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION))) .build() // Submits the request to install the additional language resources. splitInstallManager.startInstall(request)
Java
// Captures the user’s preferred language and persists it // through the app’s SharedPreferences. sharedPrefs.edit().putString(LANGUAGE_SELECTION, "fr").apply(); ... // Creates a request to download and install additional language resources. SplitInstallRequest request = SplitInstallRequest.newBuilder() // Uses the addLanguage() method to include French language resources in the request. // Note that country codes are ignored. That is, if your app // includes resources for “fr-FR” and “fr-CA”, resources for both // country codes are downloaded when requesting resources for "fr". .addLanguage(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION))) .build(); // Submits the request to install the additional language resources. splitInstallManager.startInstall(request);
يتم التعامل مع الطلب كما لو كان طلبًا لوحدة ميزة. وهذا يعني أنّه يمكنك مراقبة حالة الطلب كالمعتاد.
إذا لم يكن تطبيقك يتطلب موارد اللغة الإضافية على الفور، يمكنك تأجيل التثبيت إلى وقت تشغيل التطبيق في الخلفية، كما هو موضّح أدناه.
Kotlin
splitInstallManager.deferredLanguageInstall( Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)))
Java
splitInstallManager.deferredLanguageInstall( Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)));
الوصول إلى المراجع اللغوية التي تم تنزيلها
للوصول إلى موارد اللغة التي تم تنزيلها، يجب أن يشغّل تطبيقك SplitCompat.installActivity()
ضمن attachBaseContext()
لكل نشاط يتطلب الوصول إلى هذه الموارد، كما هو موضّح أدناه.
Kotlin
override fun attachBaseContext(base: Context) { super.attachBaseContext(base) SplitCompat.installActivity(this) }
Java
@Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); SplitCompat.installActivity(this); }
لكل نشاط تريد استخدام موارد لغوية نزّلها تطبيقك،
عدِّل السياق الأساسي واضبط لغة جديدة من خلال
Configuration
:
Kotlin
override fun attachBaseContext(base: Context) { val configuration = Configuration() configuration.setLocale(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION))) val context = base.createConfigurationContext(configuration) super.attachBaseContext(context) SplitCompat.install(this) }
Java
@Override protected void attachBaseContext(Context base) { Configuration configuration = new Configuration(); configuration.setLocale(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION))); Context context = base.createConfigurationContext(configuration); super.attachBaseContext(context); SplitCompat.install(this); }
ولكي تسري هذه التغييرات، يجب إعادة إنشاء نشاطك
بعد تثبيت اللغة الجديدة وإتاحتها للاستخدام يمكنك استخدام الطريقة
Activity#recreate()
.
Kotlin
when (state.status()) { SplitInstallSessionStatus.INSTALLED -> { // Recreates the activity to load resources for the new language // preference. activity.recreate() } ... }
Java
switch (state.status()) { case SplitInstallSessionStatus.INSTALLED: // Recreates the activity to load resources for the new language // preference. activity.recreate(); ... }
إلغاء تثبيت موارد اللغة الإضافية
على غرار وحدات الميزات، يمكنك إلغاء تثبيت الموارد الإضافية في أي وقت. قبل طلب إلغاء التثبيت، ننصحك أولاً بتحديد الكلمات المعجمية المثبَّتة حاليًا، على النحو التالي.
Kotlin
val installedLanguages: Set<String> = splitInstallManager.installedLanguages
Java
Set<String> installedLanguages = splitInstallManager.getInstalledLanguages();
يمكنك بعد ذلك تحديد اللغات التي تريد إلغاء تثبيتها باستخدام الطريقة
deferredLanguageUninstall()
، كما هو موضّح أدناه.
Kotlin
splitInstallManager.deferredLanguageUninstall( Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)))
Java
splitInstallManager.deferredLanguageUninstall( Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)));
اختبار عمليات تثبيت الوحدات على الجهاز
تتيح لك "مكتبة إرسال الميزات" في Play اختبار قدرة تطبيقك على تنفيذ ما يلي محليًا بدون الاتصال بـ "متجر Play":
- طلب عمليات تثبيت الوحدات وتتبُّعها
- التعامل مع أخطاء التثبيت.
- استخدِم
SplitCompat
للوصول إلى الوحدات.
توضّح هذه الصفحة كيفية نشر حِزم APK المجزّأة لتطبيقك على جهازك التجريبي كي تتمكّن ميزة "عرض الميزات في Play" من استخدام هذه الحِزم تلقائيًا لمحاكاة طلب الوحدات وتنزيلها وتثبيتها من "متجر Play".
على الرغم من أنّه ليس عليك إجراء أي تغييرات على منطق تطبيقك، عليك استيفاء المتطلبات التالية:
- نزِّل أحدث إصدار من
bundletool
وثبِّته. تحتاج إلىbundletool
لإنشاء مجموعة جديدة من حِزم APK القابلة للتثبيت من حِزمة تطبيقك.
إنشاء مجموعة من حِزم APK
أنشئ حِزم APK المجزّأة لتطبيقك، إذا لم يسبق لك إجراء ذلك، على النحو التالي:
- أنشئ حِزمة تطبيق لتطبيقك باستخدام إحدى الطريقتَين التاليتَين:
- استخدِم "استوديو Android" والمكوّن الإضافي لنظام Gradle المتوافق مع Android من أجل إنشاء حِزمة تطبيق Android وتوقيعها .
- أنشِئ حِزمة تطبيقك باستخدام سطر الأوامر.
استخدام
bundletool
لإنشاء مجموعة من حِزم APK لجميع الأجهزة من خلال الأمر التالي:bundletool build-apks --local-testing --bundle my_app.aab --output my_app.apks
تتضمّن العلامة --local-testing
بيانات وصفية في حِزم APK الخاصة بك أن
يتيح لمكتبة عرض الميزات في Play معرفة كيفية استخدام حِزم APK المجزّأة على الجهاز لاختبار حزمة APK.
تثبيت وحدات الميزات بدون الاتصال بـ "متجر Play".
نشر تطبيقك على الجهاز
بعد إنشاء مجموعة من حِزم APK باستخدام العلامة --local-testing
،
استخدِم bundletool
لتثبيت الإصدار الأساسي من تطبيقك ونقل ملف APK إضافي
إلى مساحة التخزين المتوفّرة على جهازك. يمكنك تنفيذ كلا الإجراءَين باستخدام
الأمر التالي:
bundletool install-apks --apks my_app.apks
والآن، عند بدء تشغيل التطبيق وإكمال مسار المستخدم لتنزيل التطبيق وتثبيته
وحدة ميزة، تستخدم مكتبة عرض الميزات في Play حِزم APK التي bundletool
تم نقله إلى مساحة التخزين المحلية للجهاز.
محاكاة خطأ في الشبكة
لمحاكاة عمليات تثبيت الوحدات من "متجر Play"، تستخدم مكتبة عرض الميزات في Play
بديلاً عن SplitInstallManager
، يسمى
FakeSplitInstallManager
,
لطلب الوحدة. عند استخدام bundletool
مع علامة --local-testing
لإنشاء مجموعة من ملفات APK ونشرها على جهازك الاختباري
يتضمّن بيانات وصفية تطلب من "مكتبة عرض الميزات في Play" التبديل تلقائيًا
طلبات البيانات من واجهة برمجة التطبيقات في تطبيقك لاستدعاء FakeSplitInstallManager
، بدلاً من
SplitInstallManager
يتضمّن FakeSplitInstallManager
علامة منطقية يمكنك تفعيلها
أن تحاكي خطأ في الشبكة عندما يطلب تطبيقك تثبيت وحدة ما. للوصول إلى FakeSplitInstallManager
في اختباراتك، يمكنك الحصول على مثيل منه باستخدام FakeSplitInstallManagerFactory
، كما هو موضّح أدناه:
Kotlin
// Creates an instance of FakeSplitInstallManager with the app's context. val fakeSplitInstallManager = FakeSplitInstallManagerFactory.create(context) // Tells Play Feature Delivery Library to force the next module request to // result in a network error. fakeSplitInstallManager.setShouldNetworkError(true)
Java
// Creates an instance of FakeSplitInstallManager with the app's context. FakeSplitInstallManager fakeSplitInstallManager = FakeSplitInstallManagerFactory.create(context); // Tells Play Feature Delivery Library to force the next module request to // result in a network error. fakeSplitInstallManager.setShouldNetworkError(true);