يشرح هذا الدليل كيفية رصد هدف Android والتفاعل معه وضبطه في مشروع Kotlin Multiplatform (KMP) من مكوّن إضافي مخصّص لنظام Gradle. استخدِم واجهات برمجة التطبيقات هذه عند كتابة مكوّنات إضافية تقليدية لعملية الإنشاء أو نشر مكوّنات Gradle الإضافية لمشاريع KMP.
التحقّق مما إذا كان المشروع يستخدم المكوّن الإضافي Kotlin Multiplatform
لتجنُّب الأخطاء والتأكّد من أنّ المكوّن الإضافي لا يعمل إلا في حال توفُّر KMP،
عليك التحقّق مما إذا كان المشروع يستخدم المكوّن الإضافي KMP. من أفضل الممارسات استخدام
plugins.withId() للتفاعل مع المكوّن الإضافي KMP الذي يتم تطبيقه، بدلاً من
التحقّق منه على الفور. يمنع هذا النهج التفاعلي المكوّن الإضافي من أن يكون هشًا بالنسبة إلى الترتيب الذي يتم فيه تطبيق المكوّنات الإضافية في نصوص الإنشاء البرمجية الخاصة بالمستخدم.
import org.gradle.api.Plugin
import org.gradle.api.Project
class MyPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.plugins.withId("org.jetbrains.kotlin.multiplatform") {
// The KMP plugin is applied, you can now configure your KMP integration.
}
}
}
الوصول إلى النموذج
نقطة الدخول لجميع إعدادات Kotlin Multiplatform هي إضافة KotlinMultiplatformExtension.
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
class MyPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.plugins.withId("org.jetbrains.kotlin.multiplatform") {
val kmpExtension = project.extensions.getByType(KotlinMultiplatformExtension::class.java)
}
}
}
التفاعل مع أهداف Kotlin Multiplatform
استخدِم حاوية targets لضبط المكوّن الإضافي بشكل تفاعلي لكل هدف
يضيفه المستخدم.
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
class MyPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.plugins.withId("org.jetbrains.kotlin.multiplatform") {
val kmpExtension = project.extensions.getByType(KotlinMultiplatformExtension::class.java)
kmpExtension.targets.configureEach { target ->
// 'target' is an instance of KotlinTarget
val targetName = target.name // for example, "android", "iosX64", "jvm"
val platformType = target.platformType // for example, androidJvm, jvm, native, js
}
}
}
}
تطبيق منطق خاص بالهدف
إذا كان المكوّن الإضافي يحتاج إلى تطبيق المنطق على أنواع معيّنة من المنصات فقط، من الشائع التحقّق من السمة platformType. هذا تعداد يصنّف
الهدف على نطاق واسع.
على سبيل المثال، استخدِم هذا الخيار إذا كان المكوّن الإضافي يحتاج فقط إلى التمييز على نطاق واسع (مثل التشغيل فقط على أهداف تشبه JVM):
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
class MyPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.plugins.withId("org.jetbrains.kotlin.multiplatform") {
val kmpExtension = project.extensions.getByType(KotlinMultiplatformExtension::class.java)
kmpExtension.targets.configureEach { target ->
when (target.platformType) {
KotlinPlatformType.jvm -> { /* Standard JVM */ }
KotlinPlatformType.androidJvm -> { /* Android */ }
KotlinPlatformType.js -> { /* JavaScript */ }
KotlinPlatformType.native -> { /* Any Native (iOS, Linux, Windows, etc.) */ }
KotlinPlatformType.wasm -> { /* WebAssembly */ }
KotlinPlatformType.common -> { /* Metadata target (rarely needs direct plugin interaction) */ }
}
}
}
}
}
تفاصيل خاصة بنظام Android
على الرغم من أنّ جميع أهداف Android تحتوي على المؤشر platformType.androidJvm، فإنّ KMP يتضمّن نقطتَي تكامل مختلفتَين استنادًا إلى المكوّن الإضافي لنظام Gradle المتوافق مع Android المستخدَم: KotlinAndroidTarget للمشاريع التي تستخدم com.android.library أو com.android.application، وKotlinMultiplatformAndroidLibraryTarget للمشاريع التي تستخدم com.android.kotlin.multiplatform.library.
تمت إضافة واجهة برمجة التطبيقات KotlinMultiplatformAndroidLibraryTarget في الإصدار 8.8.0 من "المكوّن الإضافي لنظام Gradle المتوافق مع Android"، لذا إذا
كان مستخدمو المكوّن الإضافي يستخدمون إصدارًا أقدم من "المكوّن الإضافي لنظام Gradle المتوافق مع Android"، قد يؤدي التحقّق من
target is KotlinMultiplatformAndroidLibraryTarget إلى ظهور
ClassNotFoundException. لجعل هذا آمنًا، تحقق من
AndroidPluginVersion.getCurrent() قبل التحقق من نوع الاستهداف.
يتطلّب الإصدار AndroidPluginVersion.getCurrent() استخدام الإصدار 8.3.1 من "مكوّن Android الإضافي في Gradle" أو إصدار أحدث.
import com.android.build.api.AndroidPluginVersion
import com.android.build.api.dsl.KotlinMultiplatformAndroidLibraryTarget
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget
class MyPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.plugins.withId("org.jetbrains.kotlin.multiplatform") {
val kmpExtension = project.extensions.getByType(KotlinMultiplatformExtension::class.java)
kmpExtension.targets.configureEach { target ->
if (target is KotlinAndroidTarget) {
// Old kmp android integration using com.android.library or com.android.application
} else if (
// Check platformType first, so AGP classes load only for Android targets
target.platformType == KotlinPlatformType.androidJvm &&
AndroidPluginVersion.getCurrent() >= AndroidPluginVersion(8, 8) &&
target is KotlinMultiplatformAndroidLibraryTarget
) {
// New kmp android integration using com.android.kotlin.multiplatform.library
}
}
}
}
}
الوصول إلى إضافة Android KMP وخصائصها
يتفاعل المكوّن الإضافي بشكل أساسي مع إضافة Kotlin التي يوفّرها مكوّن Kotlin Multiplatform الإضافي وإضافة Android التي يوفّرها مكوّن AGP الإضافي لهدف KMP Android. يتم تمثيل مجموعة android {} ضمن إضافة Kotlin
في مشروع KMP من خلال واجهة KotlinMultiplatformAndroidLibraryTarget
التي تمدّد أيضًا KotlinMultiplatformAndroidLibraryExtension.
وهذا يعني أنّه يمكنك الوصول إلى كلّ من سمات DSL الخاصة بالهدف وسمات DSL الخاصة بنظام التشغيل Android من خلال هذا العنصر الفردي.
import com.android.build.api.dsl.KotlinMultiplatformAndroidLibraryTarget
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper
class MyPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.plugins.withId("com.android.kotlin.multiplatform.library") {
val kmpExtension = project.extensions.getByType(KotlinMultiplatformExtension::class.java)
// Access the Android target, which also serves as the Android-specific DSL extension
kmpExtension.targets.withType(KotlinMultiplatformAndroidLibraryTarget::class.java).configureEach { androidTarget ->
// You can now access properties and methods from both
// KotlinMultiplatformAndroidLibraryTarget and KotlinMultiplatformAndroidLibraryExtension
androidTarget.compileSdk = 34
androidTarget.namespace = "com.example.myplugin.library"
androidTarget.withJava() // enable Java sources
}
}
}
}
على عكس المكوّنات الإضافية الأخرى المتوافقة مع Android (مثل com.android.library أو
com.android.application)، لا يسجّل المكوّن الإضافي KMP المتوافق مع Android إضافة DSL الرئيسية
على مستوى المشروع. ويتم تضمينها في التسلسل الهرمي لأهداف KMP
لضمان تطبيقها فقط على هدف Android المحدّد في إعداداتك
متعدّدة المنصات.
التعامل مع عمليات التجميع ومجموعات رموز المصدر
غالبًا ما تحتاج المكوّنات الإضافية إلى العمل على مستوى أكثر دقة من الهدف فقط،
وتحديدًا على مستوى التجميع. يحتوي
KotlinMultiplatformAndroidLibraryTarget على
مثيلات KotlinMultiplatformAndroidCompilation (على سبيل المثال، main وhostTest وdeviceTest). يرتبط كل تجميع بمجموعات رموز المصدر
في Kotlin. ويمكن للمكوّنات الإضافية التفاعل مع هذه العناصر لإضافة مصادر أو تبعيات أو ضبط
مهام التجميع.
import com.android.build.api.dsl.KotlinMultiplatformAndroidCompilation
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
class MyPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.plugins.withId("com.android.kotlin.multiplatform.library") {
val kmpExtension = project.extensions.getByType(KotlinMultiplatformExtension::class.java)
kmpExtension.targets.configureEach { target ->
target.compilations.configureEach { compilation ->
// standard compilations are usually 'main' and 'test'
// android target has 'main', 'hostTest', 'deviceTest'
val compilationName = compilation.name
// Access the default source set for this compilation
val defaultSourceSet = compilation.defaultSourceSet
// Access the Android-specific compilation DSL
if (compilation is KotlinMultiplatformAndroidCompilation) {
}
// Access and configure the Kotlin compilation task
compilation.compileTaskProvider.configure { compileTask ->
}
}
}
}
}
}
ضبط عمليات تجميع الاختبارات في المكوّنات الإضافية الخاصة بالاتفاقيات
عند ضبط القيم التلقائية لعمليات تجميع الاختبارات (مثل targetSdk لاختبارات قياس حالة التطبيق) في مكوّن إضافي تقليدي، تجنَّب استخدام طرق التفعيل مثل withDeviceTest { } أو withHostTest { }. يؤدي استدعاء هذه الطرق بشكل استباقي إلى إنشاء نُسخ اختبار Android المقابلة وعمليات التجميع لكل وحدة تطبّق المكوّن الإضافي الخاص بالاتفاقية، وهو ما قد لا يكون مناسبًا. لا يمكن أيضًا استدعاء هذه الطرق مرة ثانية في وحدة معينة لتحسين الإعدادات، لأن القيام بذلك يؤدي إلى حدوث خطأ يفيد بأنه قد تم إنشاء التجميع بالفعل.
بدلاً من ذلك، استخدِم مجموعة configureEach تفاعلية في حاوية المجموعات.
يتيح لك ذلك توفير إعدادات تلقائية لا تنطبق إلا إذا كانت الوحدة تفعّل تجميع الاختبار بشكل صريح:
import com.android.build.api.dsl.KotlinMultiplatformAndroidDeviceTestCompilation
import com.android.build.api.dsl.KotlinMultiplatformAndroidLibraryTarget
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
class MyPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.plugins.withId("com.android.kotlin.multiplatform.library") {
val kmpExtension =
project.extensions.getByType(KotlinMultiplatformExtension::class.java)
kmpExtension.targets.withType(KotlinMultiplatformAndroidLibraryTarget::class.java)
.configureEach { androidTarget ->
androidTarget.compilations.withType(
KotlinMultiplatformAndroidDeviceTestCompilation::class.java
).configureEach {
it.targetSdk { version = release(34) }
}
}
}
}
}
يضمن هذا النمط بقاء المكوّن الإضافي للاتفاقية في وضع التحميل الكسول ويسمح
للوحدات الفردية باستدعاء withDeviceTest { } لتفعيل اختباراتها وتخصيصها بشكل أكبر
بدون التعارض مع الإعدادات التلقائية.
التفاعل مع Variant API
بالنسبة إلى المهام التي تتطلّب ضبطًا في مرحلة متأخرة أو الوصول إلى العناصر (مثل
ملفات البيان أو رمز البايت) أو إمكانية تفعيل أو إيقاف مكوّنات
محدّدة، يجب استخدام Android Variant API. في مشاريع KMP، تكون الإضافة من النوع KotlinMultiplatformAndroidComponentsExtension.
يتم تسجيل الإضافة على مستوى المشروع عند تطبيق المكوّن الإضافي المتوافق مع Android KMP.
استخدِم beforeVariants للتحكّم في إنشاء الصيغ أو مكوّنات الاختبار
المتداخلة (hostTests وdeviceTests). هذا هو المكان الصحيح
لإيقاف الاختبارات آليًا أو تغيير قيم خصائص DSL.
import com.android.build.api.variant.KotlinMultiplatformAndroidComponentsExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
class MyPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.plugins.withId("com.android.kotlin.multiplatform.library") {
val androidComponents = project.extensions.findByType(KotlinMultiplatformAndroidComponentsExtension::class.java)
androidComponents?.beforeVariants { variantBuilder ->
// Disable all tests for this module
variantBuilder.hostTests.values.forEach { it.enable = false }
variantBuilder.deviceTests.values.forEach { it.enable = false }
}
}
}
}
استخدِم onVariants للوصول إلى عنصر الصيغة النهائية
(KotlinMultiplatformAndroidVariant). يمكنك من خلاله فحص السمات
التي تم حلّها أو تسجيل عمليات التحويل على العناصر، مثل ملفات البيان المدمجة
أو فئات المكتبة.
import com.android.build.api.variant.KotlinMultiplatformAndroidComponentsExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
class MyPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.plugins.withId("com.android.kotlin.multiplatform.library") {
val androidComponents = project.extensions.findByType(KotlinMultiplatformAndroidComponentsExtension::class.java)
androidComponents?.onVariants { variant ->
// 'variant' is a KotlinMultiplatformAndroidVariant
val variantName = variant.name
// Access the artifacts API
val manifest = variant.artifacts.get(com.android.build.api.artifact.SingleArtifact.MERGED_MANIFEST)
}
}
}
}
التطبيقات المقترَحة لك
- ملاحظة: يتم عرض نص الرابط عندما يكون JavaScript غير مفعَّل
- إعداد البيئة
- إضافة وحدة KMP إلى مشروع
- إعداد المكوّن الإضافي لمكتبة Gradle لنظام التشغيل Android لمشاريع KMP