المكوّن الإضافي لنظام Gradle المتوافق مع Android (AGP) هو نظام التصميم الرسمي لتطبيقات Android. يتضمّن هذا الإصدار إمكانية تجميع العديد من أنواع المصادر المختلفة وربطها معًا في تطبيق يمكنك تشغيله على جهاز Android فعلي أو محاكي.
يحتوي AGP على نقاط إضافة تتيح للمكوّنات الإضافية التحكّم في مدخلات التصميم وتوسيع وظائفه من خلال خطوات جديدة يمكن دمجها مع مهام التصميم العادية. لم تتضمّن الإصدارات السابقة من "مكوّن Android الإضافي في Gradle" واجهات برمجة تطبيقات رسمية منفصلة بوضوح عن عمليات التنفيذ الداخلية. بدءًا من الإصدار 7.0، يتضمّن المكوّن الإضافي لنظام Gradle المتوافق مع Android مجموعة من واجهات برمجة التطبيقات الرسمية والثابتة التي يمكنك الاعتماد عليها.
دورة حياة واجهة برمجة التطبيقات في "مكوّن Android Gradle الإضافي"
يتّبع المكوّن الإضافي لنظام Gradle المتوافق مع Android دورة حياة ميزات Gradle لتحديد حالة واجهات برمجة التطبيقات:
- داخلي: غير مخصّص للاستخدام العلني
- في مرحلة التجربة: متاحة للاستخدام العام ولكنها ليست نهائية، ما يعني أنّها قد لا تكون متوافقة مع الإصدارات القديمة في الإصدار النهائي
- الإصدار المتاح للجميع: متاح للاستخدام من قِبل الجميع ومستقر
- متوقّفة نهائيًا: لم يعُد يتم توفيرها، وتم استبدالها بواجهات برمجة تطبيقات جديدة
سياسة الإيقاف النهائي
يتطوّر AGP مع إيقاف واجهات برمجة التطبيقات القديمة واستبدالها بواجهات برمجة تطبيقات جديدة وثابتة ولغة جديدة خاصة بالمجال (DSL). ستستغرق عملية التطوير هذه عدة إصدارات من "مكوّنات Android Gradle"، ويمكنك الاطّلاع على مزيد من المعلومات حولها في المخطط الزمني لنقل بيانات واجهة برمجة التطبيقات/لغة DSL في "مكوّنات Android Gradle".
عند إيقاف واجهات برمجة التطبيقات في AGP نهائيًا، سواء كان ذلك بسبب عملية نقل البيانات أو لأي سبب آخر، ستظل هذه الواجهات متاحة في الإصدار الرئيسي الحالي، ولكن سيتم عرض تحذيرات بشأنها. ستتم إزالة واجهات برمجة التطبيقات المتوقّفة نهائيًا من "المكوّن الإضافي لنظام Gradle المتوافق مع Android" في الإصدار الرئيسي التالي. على سبيل المثال، إذا تم إيقاف واجهة برمجة تطبيقات نهائيًا في الإصدار 7.0 من "مكوّن Android الإضافي لبرنامج Gradle"، ستظل متاحة في هذا الإصدار وسيتم عرض تحذيرات بشأنها. لن تكون واجهة برمجة التطبيقات هذه متاحة في الإصدار 8.0 من "مكوّن Android الإضافي في Gradle".
للاطّلاع على أمثلة على واجهات برمجة التطبيقات الجديدة المستخدَمة في عمليات التخصيص الشائعة للإصدارات، يمكنك الاطّلاع على وصفات مكوّن Android Gradle الإضافي. وهي تقدّم أمثلة على عمليات التخصيص الشائعة. يمكنك أيضًا العثور على مزيد من التفاصيل حول واجهات برمجة التطبيقات الجديدة في المستندات المرجعية.
أساسيات إنشاء Gradle
لا يغطّي هذا الدليل نظام إنشاء Gradle بالكامل. ومع ذلك، تتضمّن هذه الصفحة الحد الأدنى من المفاهيم اللازمة لمساعدتك في الدمج مع واجهات برمجة التطبيقات، كما تتضمّن روابط تؤدي إلى مستندات Gradle الرئيسية لمزيد من القراءة.
نفترض أنّ لديك معرفة أساسية بطريقة عمل Gradle، بما في ذلك كيفية ضبط إعدادات المشاريع وتعديل ملفات الإنشاء وتطبيق المكوّنات الإضافية وتنفيذ المهام. للتعرّف على أساسيات Gradle في ما يتعلق بمكوّن AGP، ننصحك بمراجعة مقالة ضبط إعدادات الإصدار. للتعرّف على الإطار العام لتخصيص إضافات Gradle، راجِع تطوير إضافات Gradle المخصّصة.
مسرد مصطلحات أنواع Gradle الكسولة
يوفّر نظام Gradle عددًا من الأنواع التي تعمل "ببطء" أو تساعد في تأجيل العمليات الحسابية المعقّدة أو إنشاء Task إلى مراحل لاحقة من عملية الإنشاء. تشكّل هذه الأنواع أساس العديد من واجهات برمجة التطبيقات في Gradle وAGP. تتضمّن القائمة التالية أنواع Gradle الرئيسية المعنية بالتنفيذ المؤجّل وطرقها الأساسية.
Provider<T>- توفّر قيمة من النوع
T(حيث يشير "T" إلى أي نوع)، ويمكن قراءتها أثناء مرحلة التنفيذ باستخدامget()أو تحويلها إلىProvider<S>جديد (حيث يشير "S" إلى نوع آخر) باستخدام الطرقmap()وflatMap()وzip(). يُرجى العِلم أنّه يجب عدم استدعاءget()مطلقًا خلال مرحلة الإعداد.-
map(): تقبل lambda وتنتجProviderمن النوعS،Provider<S>. يأخذ وسيط lambda في الدالةmap()القيمةTوينتج القيمةS. لا يتم تنفيذ تعبير lambda على الفور، بل يتم تأجيل تنفيذه إلى حين استدعاءget()علىProvider<S>الناتج، ما يجعل السلسلة بأكملها غير نشطة. flatMap(): تقبل هذه السمة أيضًا دالة lambda وتنتجProvider<S>، ولكن الدالة lambda تأخذ القيمةTوتنتجProvider<S>(بدلاً من إنتاج القيمةSمباشرةً). استخدِم flatMap() عندما يتعذّر تحديد S في وقت الإعداد ولا يمكنك الحصول إلا علىProvider<S>. من الناحية العملية، إذا استخدمتmap()وحصلت على نوع نتيجةProvider<Provider<S>>، يعني ذلك على الأرجح أنّه كان عليك استخدامflatMap()بدلاً من ذلك.zip(): تتيح لك هذه السمة دمج مثيلَين منProviderلإنشاءProviderجديد، بقيمة يتم احتسابها باستخدام دالة تجمع القيم من مثيلَي الإدخالProviders.
-
Property<T>- تنفّذ
Provider<T>، لذا توفّر أيضًا قيمة من النوعT. على عكسProvider<T>التي تكون للقراءة فقط، يمكنك أيضًا ضبط قيمةProperty<T>. يمكنك إجراء ذلك بإحدى الطريقتَين التاليتَين:- اضبط قيمة من النوع
Tمباشرةً عند توفّرها، بدون الحاجة إلى عمليات حسابية مؤجّلة. - اضبط
Provider<T>أخرى كمصدر لقيمةProperty<T>. في هذه الحالة، لا يتم إنشاء القيمةTإلا عند استدعاءProperty.get().
- اضبط قيمة من النوع
TaskProvider- تنفيذ
Provider<Task>لإنشاءTaskProvider، استخدِمtasks.register()وليسtasks.create()، وذلك لضمان إنشاء مثيل للمهام بشكل غير مباشر عند الحاجة إليها فقط. يمكنك استخدامflatMap()للوصول إلى نواتجTaskقبل إنشاءTask، وهو ما قد يكون مفيدًا إذا أردت استخدام النواتج كمدخلات إلى مثيلاتTaskأخرى.
تُعدّ أدوات توفير البيانات وطرق تحويلها ضرورية لإعداد مدخلات ومخرجات المهام بطريقة مؤجّلة، أي بدون الحاجة إلى إنشاء جميع المهام مسبقًا وحلّ القيم.
تحتوي الجهات المقدّمة للخدمة أيضًا على معلومات حول تبعية المهام. عند إنشاء Provider من خلال تحويل ناتج Task، يصبح Task تابعًا ضمنيًا لـ Provider ويتم إنشاؤه وتشغيله كلما تم تحديد قيمة Provider، مثلاً عندما يتطلبه Task آخر.
في ما يلي مثال على تسجيل مهمتَين، GitVersionTask وManifestProducerTask، مع تأجيل إنشاء مثيلات Task إلى حين الحاجة إليها فعليًا. يتم ضبط قيمة الإدخال ManifestProducerTask على Provider تم الحصول عليها من ناتج GitVersionTask، لذا فإنّ ManifestProducerTask يعتمد ضمنيًا على GitVersionTask.
// Register a task lazily to get its TaskProvider.
val gitVersionProvider: TaskProvider =
project.tasks.register("gitVersionProvider", GitVersionTask::class.java) {
it.gitVersionOutputFile.set(
File(project.buildDir, "intermediates/gitVersionProvider/output")
)
}
...
/**
* Register another task in the configuration block (also executed lazily,
* only if the task is required).
*/
val manifestProducer =
project.tasks.register(variant.name + "ManifestProducer", ManifestProducerTask::class.java) {
/**
* Connect this task's input (gitInfoFile) to the output of
* gitVersionProvider.
*/
it.gitInfoFile.set(gitVersionProvider.flatMap(GitVersionTask::gitVersionOutputFile))
}
ولن يتم تنفيذ هاتين المهمّتَين إلا إذا تم طلبهما بشكل صريح. يمكن أن يحدث ذلك كجزء من استدعاء Gradle، مثلاً، إذا شغّلت ./gradlew
debugManifestProducer، أو إذا كان ناتج ManifestProducerTask مرتبطًا بمهمة أخرى وأصبحت قيمته مطلوبة.
مع أنّك ستكتب مهامًا مخصّصة تستهلك مدخلات و/أو تنتج مخرجات، لا يتيح AGP الوصول إلى مهامه الخاصة بشكل مباشر. وهي تفاصيل تنفيذية قابلة للتغيير من إصدار إلى آخر. بدلاً من ذلك، يوفّر AGP واجهة برمجة التطبيقات Variant API وإمكانية الوصول إلى ناتج مهامه، أو عناصر الإنشاء، التي يمكنك قراءتها وتحويلها. لمزيد من المعلومات، يُرجى الاطّلاع على Variant API، والنتائج، والمهام في هذا المستند.
مراحل إنشاء Gradle
إنّ إنشاء مشروع هو عملية معقّدة وتتطلّب موارد كثيرة، وهناك ميزات مختلفة، مثل تجنُّب إعداد المهام، وعمليات التحقّق الحديثة، وميزة التخزين المؤقت للإعدادات، تساعد في تقليل الوقت المستغرَق في العمليات الحسابية المتكرّرة أو غير الضرورية.
لتطبيق بعض هذه التحسينات، يجب أن تلتزم نصوص Gradle البرمجية والمكوّنات الإضافية بقواعد صارمة خلال كل مرحلة من مراحل تصميم Gradle المميّزة، وهي: التهيئة والإعداد والتنفيذ. في هذا الدليل، سنركّز على مرحلتَي الإعداد والتنفيذ. يمكنك الاطّلاع على مزيد من المعلومات حول جميع المراحل في دليل دورة حياة إنشاء Gradle.
مرحلة الإعداد
أثناء مرحلة الإعداد، يتم تقييم نصوص البرامج الإنشائية لجميع المشاريع التي تشكّل جزءًا من عملية الإنشاء، ويتم تطبيق المكوّنات الإضافية، ويتم تحديد تبعيات الإنشاء. يجب استخدام هذه المرحلة لإعداد الإصدار باستخدام عناصر DSL ولتسجيل المهام ومدخلاتها بشكل غير مباشر.
بما أنّ مرحلة الإعداد يتم تنفيذها دائمًا، بغض النظر عن المهمة المطلوب تنفيذها، من المهم بشكل خاص أن تكون هذه المرحلة بسيطة وأن يتم حصر أي عمليات حسابية لتعتمد على مدخلات أخرى غير نصوص البرامج الخاصة بالتصميم.
أي أنّه يجب عدم تنفيذ برامج خارجية أو القراءة من الشبكة أو إجراء عمليات حسابية طويلة يمكن تأجيلها إلى مرحلة التنفيذ كعمليات Task مناسبة.
مرحلة التنفيذ
في مرحلة التنفيذ، يتم تنفيذ المهام المطلوبة والمهام التابعة لها. على وجه التحديد، يتم تنفيذ طرق الفئة Task التي تم وضع علامة @TaskAction عليها. أثناء تنفيذ المهمة، يُسمح لك بالقراءة من المدخلات (مثل الملفات) وحلّ المشاكل المتعلقة بموفّري البيانات غير الفورية من خلال استدعاء Provider<T>.get(). يؤدي حلّ المشاكل المتعلقة بموفّري التحميل الكسول بهذه الطريقة إلى بدء سلسلة من طلبات map() أو flatMap() التي تتّبع معلومات تبعية المهمة الواردة في الموفّر. يتم تنفيذ المهام بشكل غير مباشر لتوفير القيم المطلوبة.
Variant API والعناصر والمهام
واجهة برمجة التطبيقات Variant هي آلية توسيع في المكوّن الإضافي لنظام Android Gradle تتيح لك تعديل الخيارات المختلفة التي يتم ضبطها عادةً باستخدام لغة DSL في ملفات إعدادات الإصدار التي تؤثر في إصدار Android. تتيح لك واجهة برمجة التطبيقات Variant API أيضًا الوصول إلى العناصر الوسيطة والنهائية التي يتم إنشاؤها من خلال عملية الإنشاء، مثل ملفات الفئات أو البيان المدمج أو ملفات APK/AAB.
مسار إنشاء Android ونقاط الإضافة
عند التفاعل مع AGP، استخدِم نقاط إضافة مصمَّمة خصيصًا بدلاً من تسجيل عمليات معاودة الاتصال العادية لدورة حياة Gradle (مثل afterEvaluate()) أو إعداد تبعيات Task صريحة. تُعد المهام التي ينشئها AGP تفاصيل تنفيذية ولا يتم عرضها كواجهة برمجة تطبيقات عامة. يجب تجنُّب محاولة الحصول على مثيلات لعناصر Task أو تخمين أسماء Task وإضافة عمليات ردّ الاتصال أو التبعيات إلى عناصر Task هذه مباشرةً.
تُكمل "إضافة Android Gradle" الخطوات التالية لإنشاء وتنفيذ مثيلاتها من Task،
والتي بدورها تنتج عناصر الإصدار. تتضمّن الخطوات الرئيسية لإنشاء عناصر Variant عمليات ردّ الاتصال التي تتيح لك إجراء تغييرات على عناصر معيّنة تم إنشاؤها كجزء من عملية إنشاء. يُرجى العِلم أنّ جميع عمليات معاودة الاتصال تحدث أثناء مرحلة الإعداد (الموضّحة في هذه الصفحة)، ويجب أن تتم بسرعة، مع تأجيل أي عمل معقّد إلى مثيلات Task المناسبة أثناء مرحلة التنفيذ بدلاً من ذلك.
- تحليل DSL: يحدث ذلك عند تقييم نصوص البرمجة الخاصة بعملية الإنشاء، وعند إنشاء وضبط الخصائص المختلفة لعناصر Android DSL من الحزمة
android. يتم أيضًا تسجيل عمليات معاودة الاتصال الخاصة بواجهة برمجة التطبيقات Variant API الموضّحة في الأقسام التالية خلال هذه المرحلة.
finalizeDsl(): دالة رد الاتصال التي تتيح لك تغيير عناصر DSL قبل أن يتم قفلها لإنشاء المكوّن (الصيغة). يتم إنشاء عناصرVariantBuilderاستنادًا إلى البيانات الواردة في عناصر DSL.قفل DSL: تم الآن قفل DSL ولم يعُد من الممكن إجراء تغييرات.
beforeVariants(): يمكن أن يؤثّر هذا الإجراء على العناصر التي يتم إنشاؤها، وعلى بعض خصائصها، من خلالVariantBuilder. ويظل بإمكانك إجراء تعديلات على مسار الإنشاء والنتائج التي يتم إنتاجها.إنشاء صيغة مختلفة: تم الآن الانتهاء من قائمة المكوّنات والعناصر التي سيتم إنشاؤها، ولا يمكن تغييرها.
onVariants(): في دالة معاودة الاتصال هذه، يمكنك الوصول إلى عناصرVariantالتي تم إنشاؤها، ويمكنك ضبط القيم أو موفّري القيم الخاصة بقيمPropertyالتي تحتوي عليها، ليتم احتسابها بشكل غير مباشر.قفل النُسخ المتغيرة: تم الآن قفل عناصر النُسخ المتغيرة ولم يعُد من الممكن إجراء تغييرات عليها.
المهام التي تم إنشاؤها: يتم استخدام عناصر
VariantوقيمPropertyالخاصة بها لإنشاء مثيلاتTaskاللازمة لتنفيذ عملية الإنشاء.
يقدّم المكوّن الإضافي لنظام Gradle المتوافق مع Android
AndroidComponentsExtension يتيح
لك تسجيل عمليات ردّ الاتصال لكل من finalizeDsl() وbeforeVariants() وonVariants().
تتوفّر الإضافة في نصوص البرامج الإنشائية من خلال الحظر androidComponents:
// This is used only for configuring the Android build through DSL.
android { ... }
// The androidComponents block is separate from the DSL.
androidComponents {
finalizeDsl { extension ->
...
}
}
ومع ذلك، ننصحك بإبقاء نصوص البرامج الخاصة بالإنشاء مخصّصة فقط للإعدادات التعريفية باستخدام DSL الخاص بحزمة android، ونقل أي منطق إلزامي مخصّص إلى buildSrc أو إلى مكوّنات إضافية خارجية. يمكنك أيضًا الاطّلاع على buildSrc
الأمثلة في مستودع GitHub الخاص بوصفات Gradle لمعرفة كيفية إنشاء إضافة في مشروعك. في ما يلي مثال على تسجيل عمليات معاودة الاتصال من رمز المكوّن الإضافي:
abstract class ExamplePlugin: Plugin<Project> {
override fun apply(project: Project) {
val androidComponents = project.extensions.getByType(AndroidComponentsExtension::class.java)
androidComponents.finalizeDsl { extension ->
...
}
}
}
لنتعرّف على عمليات الرجوع المتاحة وأنواع حالات الاستخدام التي يمكن أن تتوافق معها الإضافة في كل عملية:
finalizeDsl(callback: (DslExtensionT) -> Unit)
في دالة معاودة الاتصال هذه، يمكنك الوصول إلى عناصر DSL التي تم إنشاؤها من خلال تحليل المعلومات من الحظر android في ملفات الإنشاء وتعديلها.
سيتم استخدام عناصر DSL هذه لتهيئة المتغيرات وضبطها في المراحل اللاحقة من عملية الإنشاء. على سبيل المثال، يمكنك إنشاء إعدادات جديدة أو تجاهل خصائص بشكل آلي، ولكن تذكَّر أنّه يجب تحديد جميع القيم في وقت الإعداد، لذا يجب ألا تعتمد على أي مدخلات خارجية.
بعد انتهاء تنفيذ وظيفة رد الاتصال هذه، لن تكون عناصر DSL مفيدة،
ويجب ألا تحتفظ بعد ذلك بمراجع لها أو تعدّل قيمها.
abstract class ExamplePlugin: Plugin<Project> {
override fun apply(project: Project) {
val androidComponents = project.extensions.getByType(AndroidComponentsExtension::class.java)
androidComponents.finalizeDsl { extension ->
extension.buildTypes.create("extra").let {
it.isJniDebuggable = true
}
}
}
}
beforeVariants()
في هذه المرحلة من عملية الإنشاء، يمكنك الوصول إلى عناصر VariantBuilder التي تحدّد أشكال المنتج التي سيتم إنشاؤها وخصائصها. على سبيل المثال، يمكنك إيقاف بعض الصيغ أو اختباراتها أو تغيير قيمة إحدى السمات (مثل minSdk) آليًا لصيغة محدّدة فقط. على غرار
finalizeDsl()، يجب أن يتم تحديد جميع القيم التي تقدّمها في وقت الضبط، ويجب ألا تعتمد على مدخلات خارجية. يجب عدم تعديل عناصر VariantBuilder بعد انتهاء تنفيذ معاودة الاتصال beforeVariants().
androidComponents {
beforeVariants { variantBuilder ->
variantBuilder.minSdk = 23
}
}
يمكن أن تتضمّن عملية ردّ الاتصال beforeVariants() بشكل اختياري VariantSelector، ويمكنك الحصول عليها من خلال الطريقة selector() في androidComponentsExtension. يمكنك استخدامها لفلترة المكوّنات المشارِكة في استدعاء دالة الرجوع استنادًا إلى اسمها أو نوع الإصدار أو نوع المنتج.
androidComponents {
beforeVariants(selector().withName("adfree")) { variantBuilder ->
variantBuilder.minSdk = 23
}
}
onVariants()
عند استدعاء onVariants()، تكون جميع العناصر التي سيتم إنشاؤها بواسطة AGP قد تم تحديدها بالفعل، وبالتالي لن يعود بإمكانك إيقافها. ومع ذلك، يمكنك تعديل بعض القيم المستخدَمة في المهام من خلال ضبطها لسمات Property في عناصر Variant. بما أنّه لن يتم تحديد قيم Property إلا عند تنفيذ مهام "مكوّن Android الإضافي لبرنامج Gradle"، يمكنك ربطها بأمان بموفّري البيانات من مهامك المخصّصة التي ستنفّذ أي عمليات حسابية مطلوبة، بما في ذلك القراءة من المدخلات الخارجية، مثل الملفات أو الشبكة.
// onVariants also supports VariantSelectors:
onVariants(selector().withBuildType("release")) { variant ->
// Gather the output when we are in single mode (no multi-apk).
val mainOutput = variant.outputs.single { it.outputType == OutputType.SINGLE }
// Create version code generating task
val versionCodeTask = project.tasks.register("computeVersionCodeFor${variant.name}", VersionCodeTask::class.java) {
it.outputFile.set(project.layout.buildDirectory.file("${variant.name}/versionCode.txt"))
}
/**
* Wire version code from the task output.
* map() will create a lazy provider that:
* 1. Runs just before the consumer(s), ensuring that the producer
* (VersionCodeTask) has run and therefore the file is created.
* 2. Contains task dependency information so that the consumer(s) run after
* the producer.
*/
mainOutput.versionCode.set(versionCodeTask.map { it.outputFile.get().asFile.readText().toInt() })
}
المساهمة في إنشاء مصادر للإنشاء
يمكن أن يساهم المكوّن الإضافي في توفير بعض أنواع المصادر التي يتم إنشاؤها، مثل:
- رمز التطبيق في الدليل
java - مراجع Android في الدليل
res - مراجع Java
في الدليل
resources - مواد عرض Android في المجلد
assets
للاطّلاع على القائمة الكاملة بالمصادر التي يمكنك إضافتها، راجِع Sources API.
يوضّح مقتطف الرمز هذا كيفية إضافة مجلد مصدر مخصّص باسم
${variant.name} إلى مجموعة مصادر Java باستخدام الدالة addStaticSourceDirectory(). بعد ذلك، تعالج مجموعة أدوات Android هذا المجلد.
onVariants { variant ->
variant.sources.java?.let { java ->
java.addStaticSourceDirectory("custom/src/kotlin/${variant.name}")
}
}
لمزيد من التفاصيل، راجِع وصفة addJavaSource.
يوضّح مقتطف الرمز هذا كيفية إضافة دليل يحتوي على موارد Android
تم إنشاؤها من مهمة مخصّصة إلى مجموعة المصادر res. وتتشابه العملية مع أنواع المستندات المصدر الأخرى.
onVariants(selector().withBuildType("release")) { variant ->
// Step 1. Register the task.
val resCreationTask =
project.tasks.register<ResCreatorTask>("create${variant.name}Res")
// Step 2. Register the task output to the variant-generated source directory.
variant.sources.res?.addGeneratedSourceDirectory(
resCreationTask,
ResCreatorTask::outputDirectory)
}
...
// Step 3. Define the task.
abstract class ResCreatorTask: DefaultTask() {
@get:OutputFiles
abstract val outputDirectory: DirectoryProperty
@TaskAction
fun taskAction() {
// Step 4. Generate your resources.
...
}
}
يمكنك الاطّلاع على وصفة addCustomAsset لمزيد من التفاصيل.
الوصول إلى العناصر وتعديلها
بالإضافة إلى السماح لك بتعديل الخصائص البسيطة في عناصر Variant، يحتوي AGP أيضًا على آلية إضافة تتيح لك قراءة أو تحويل العناصر الوسيطة والنهائية التي يتم إنتاجها أثناء عملية الإنشاء. على سبيل المثال، يمكنك قراءة محتويات ملف AndroidManifest.xml المدمج النهائي في Task مخصّص لتحليله، أو يمكنك استبدال محتواه بالكامل بمحتوى ملف بيان تم إنشاؤه بواسطة Task المخصّص.
يمكنك العثور على قائمة بالعناصر التي تتوافق حاليًا مع مستندات Artifact المرجعية. لكل نوع من أنواع العناصر بعض الخصائص التي من المفيد معرفتها:
عدد القيم الفريدة للسمة
تمثّل العلاقة الأساسية Artifact عدد مثيلات FileSystemLocation أو عدد الملفات أو الدلائل من نوع العنصر. يمكنك الحصول على معلومات حول عدد العناصر الأساسية لعنصر ما من خلال التحقّق من فئته الرئيسية: ستكون العناصر التي تتضمّن FileSystemLocation واحدًا فئة فرعية من Artifact.Single، بينما ستكون العناصر التي تتضمّن عدة مثيلات من FileSystemLocation فئة فرعية من Artifact.Multiple.
نوع واحد FileSystemLocation
يمكنك التحقّق مما إذا كان Artifact يمثّل ملفات أو أدلة من خلال النظر إلى نوع FileSystemLocation المحدّد المعلمات، والذي يمكن أن يكون إما RegularFile أو Directory.
العمليات المتوافقة
يمكن لكل فئة Artifact تنفيذ أي من الواجهات التالية للإشارة إلى العمليات التي تتوافق معها:
-
Transformable: يسمح باستخدامArtifactكإدخال إلىTaskالذي ينفّذ عمليات تحويل عشوائية عليه ويُخرج نسخة جديدة منArtifact. -
Appendable: تنطبق هذه السمة فقط على العناصر التي تكون فئات فرعية منArtifact.Multiple. وهذا يعني أنّه يمكن إلحاقArtifact، أي أنّTaskمخصّص يمكنه إنشاء مثيلات جديدة من نوعArtifactهذا، والتي ستتم إضافتها إلى القائمة الحالية. -
Replaceable: تنطبق هذه السمة فقط على العناصر التي تكون فئات فرعية منArtifact.Single. يمكن استبدالArtifactقابل للاستبدال بمثيل جديد تمامًا، يتم إنتاجه كنتيجةTask.
بالإضافة إلى العمليات الثلاث التي تعدّل العناصر، يتيح كل عنصر عملية get() (أو getAll())، التي تعرض Provider مع الإصدار النهائي من العنصر (بعد الانتهاء من جميع العمليات عليه).
يمكن أن تضيف العديد من المكوّنات الإضافية أي عدد من العمليات على العناصر إلى مسار التنفيذ من خلال معاودة الاتصال onVariants()، وسيضمن "مكوّن Android الإضافي لبرنامج Gradle" ربطها بشكل صحيح حتى يتم تنفيذ جميع المهام في الوقت المناسب وإنشاء العناصر وتعديلها بشكل صحيح. وهذا يعني أنّه عندما تغيّر عملية ما أي مخرجات من خلال إلحاقها أو استبدالها أو تحويلها، ستشاهد العملية التالية الإصدار المعدَّل من هذه العناصر كمدخلات، وهكذا.
نقطة الدخول إلى عمليات التسجيل هي الفئة Artifacts.
يوضّح مقتطف الرمز التالي كيفية الوصول إلى مثيل من Artifacts من إحدى الخصائص في العنصر Variant في معاودة الاتصال onVariants().
يمكنك بعد ذلك إدخال TaskProvider المخصّص للحصول على عنصر TaskBasedOperation (1)، واستخدامه لربط مدخلاته ومخرجاته باستخدام إحدى طرق wiredWith* (2).
تعتمد الطريقة المحدّدة التي عليك اختيارها على عدد العناصر الأساسية وFileSystemLocation النوع الذي تم تنفيذه بواسطة Artifact الذي تريد تحويله.
وأخيرًا، يمكنك تمرير النوع Artifact إلى طريقة تمثّل العملية المحدّدة على العنصر *OperationRequest الذي تحصل عليه في المقابل، على سبيل المثال، toAppendTo() أو toTransform() أو toCreate() (3).
androidComponents.onVariants { variant ->
val manifestUpdater = // Custom task that will be used for the transform.
project.tasks.register(variant.name + "ManifestUpdater", ManifestTransformerTask::class.java) {
it.gitInfoFile.set(gitVersionProvider.flatMap(GitVersionTask::gitVersionOutputFile))
}
// (1) Register the TaskProvider w.
val variant.artifacts.use(manifestUpdater)
// (2) Connect the input and output files.
.wiredWithFiles(
ManifestTransformerTask::mergedManifest,
ManifestTransformerTask::updatedManifest)
// (3) Indicate the artifact and operation type.
.toTransform(SingleArtifact.MERGED_MANIFEST)
}
في هذا المثال، MERGED_MANIFEST هو SingleArtifact، وهو RegularFile. لهذا السبب، علينا استخدام طريقة wiredWithFiles التي تقبل مرجع RegularFileProperty واحدًا للإدخال ومرجع RegularFileProperty واحدًا للإخراج. تتوفّر طرق wiredWith* أخرى في الفئة TaskBasedOperation يمكن استخدامها مع مجموعات أخرى من Artifact عدد العناصر وFileSystemLocation أنواعها.
لمزيد من المعلومات حول توسيع نطاق "المكوّن الإضافي لنظام Gradle المتوافق مع Android"، ننصحك بقراءة الأقسام التالية من دليل نظام الإصدار Gradle:
- تطوير مكوّنات Gradle الإضافية المخصّصة
- تنفيذ مكوّنات Gradle الإضافية
- تطوير أنواع مهام Gradle المخصّصة
- Lazy Configuration
- تجنُّب إعداد المهام