অ্যান্ড্রয়েড কেএমপির জন্য কাস্টম গ্রেডল প্লাগইন তৈরি করুন

এই ডকুমেন্টটি প্লাগইন লেখকদের জন্য KMP প্রকল্পের মধ্যে Android টার্গেটের সাথে ইন্টিগ্রেশনের উপর বিশেষ মনোযোগ দিয়ে Kotlin Multiplatform (KMP) সেটআপ সঠিকভাবে সনাক্ত, ইন্টারঅ্যাক্ট এবং কনফিগার করার একটি নির্দেশিকা প্রদান করে। KMP বিকশিত হওয়ার সাথে সাথে, KotlinMultiplatformExtension , KotlinTarget প্রকার এবং Android-নির্দিষ্ট ইন্টিগ্রেশন ইন্টারফেসের মতো সঠিক হুক এবং API-গুলি বোঝা অপরিহার্য, যা একটি মাল্টিপ্ল্যাটফর্ম প্রকল্পে সংজ্ঞায়িত সমস্ত প্ল্যাটফর্ম জুড়ে নির্বিঘ্নে কাজ করে এমন শক্তিশালী এবং ভবিষ্যত-প্রমাণ টুলিং তৈরির জন্য অপরিহার্য।

কোনও প্রকল্প কোটলিন মাল্টিপ্ল্যাটফর্ম প্লাগইন ব্যবহার করে কিনা তা পরীক্ষা করুন

ত্রুটি এড়াতে এবং KMP উপস্থিত থাকলেই আপনার প্লাগইনটি যাতে কাজ করে তা নিশ্চিত করতে, আপনাকে অবশ্যই পরীক্ষা করতে হবে যে প্রকল্পটি KMP প্লাগইন ব্যবহার করে কিনা। KMP প্লাগইন প্রয়োগ করা হলে প্রতিক্রিয়া জানাতে plugins.withId() ব্যবহার করা সর্বোত্তম অনুশীলন, তাৎক্ষণিকভাবে এটি পরীক্ষা করার পরিবর্তে। এই প্রতিক্রিয়াশীল পদ্ধতিটি ব্যবহারকারীর বিল্ড স্ক্রিপ্টগুলিতে প্লাগইনগুলি যে ক্রমে প্রয়োগ করা হয় সেভাবে আপনার প্লাগইনটিকে ভঙ্গুর হতে বাধা দেয়।

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.
        }
    }
}

মডেলটি অ্যাক্সেস করুন

সমস্ত কোটলিন মাল্টিপ্ল্যাটফর্ম কনফিগারেশনের প্রবেশ বিন্দু হল 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)
        }
    }
}

কোটলিন মাল্টিপ্ল্যাটফর্ম টার্গেটগুলিতে প্রতিক্রিয়া জানান

ব্যবহারকারীর যোগ করা প্রতিটি টার্গেটের জন্য আপনার প্লাগইনটি প্রতিক্রিয়াশীলভাবে কনফিগার করতে 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 প্রপার্টি পরীক্ষা করা। এটি একটি enum যা লক্ষ্যবস্তুকে বিস্তৃতভাবে শ্রেণীবদ্ধ করে।

উদাহরণস্বরূপ, যদি আপনার প্লাগইনটি কেবল বিস্তৃতভাবে আলাদা করার প্রয়োজন হয় (উদাহরণস্বরূপ, শুধুমাত্র 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 or Android */ }
                    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) */ }
                }
            }
        }
    }
}

অ্যান্ড্রয়েড-নির্দিষ্ট বিবরণ

যদিও সমস্ত অ্যান্ড্রয়েড টার্গেটের platformType.androidJvm ইন্ডিকেটর থাকে, KMP-এর দুটি স্বতন্ত্র ইন্টিগ্রেশন পয়েন্ট রয়েছে যা Android Gradle প্লাগইনের উপর নির্ভর করে: com.android.library বা com.android.application ব্যবহার করে প্রজেক্টের জন্য KotlinAndroidTarget , এবং com.android.kotlin.multiplatform.library ব্যবহার করে প্রজেক্টের জন্য KotlinMultiplatformAndroidLibraryTarget

KotlinMultiplatformAndroidLibraryTarget API AGP 8.8.0 তে যোগ করা হয়েছে, তাই যদি আপনার প্লাগইনের গ্রাহকরা AGP এর নিম্ন সংস্করণ ব্যবহার করেন, target is KotlinMultiplatformAndroidLibraryTarget পরীক্ষা করলে ClassNotFoundException দেখা দিতে পারে। এটি নিরাপদ করার জন্য, টার্গেট টাইপ চেক করার আগে AndroidPluginVersion.getCurrent() চেক করুন। মনে রাখবেন যে AndroidPluginVersion.getCurrent() জন্য AGP 7.1 বা তার বেশি প্রয়োজন।

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.mpp.KotlinAndroidTarget

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 ->
                if (target is KotlinAndroidTarget) {
                    // Old kmp android integration using com.android.library or com.android.application
                }
                if (AndroidPluginVersion.getCurrent() >= AndroidPluginVersion(8, 8) &&
                    target is KotlinMultiplatformAndroidLibraryTarget
                ) {
                    // New kmp android integration using com.android.kotlin.multiplatform.library
                }
            }
        }
    }
}

অ্যান্ড্রয়েড কেএমপি এক্সটেনশন এবং এর বৈশিষ্ট্যগুলি অ্যাক্সেস করুন

আপনার প্লাগইনটি মূলত KMP অ্যান্ড্রয়েড টার্গেটের জন্য Kotlin মাল্টিপ্ল্যাটফর্ম প্লাগইন দ্বারা প্রদত্ত Kotlin এক্সটেনশন এবং AGP দ্বারা প্রদত্ত Android এক্সটেনশনের সাথে ইন্টারঅ্যাক্ট করবে। KMP প্রকল্পে Kotlin এক্সটেনশনের মধ্যে থাকা android {} ব্লকটি KotlinMultiplatformAndroidLibraryTarget ইন্টারফেস দ্বারা প্রতিনিধিত্ব করা হয়, যা KotlinMultiplatformAndroidLibraryExtension ও প্রসারিত করে। এর অর্থ হল আপনি এই একক বস্তুর মাধ্যমে লক্ষ্য-নির্দিষ্ট এবং Android-নির্দিষ্ট DSL উভয় বৈশিষ্ট্যই অ্যাক্সেস করতে পারবেন।

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
            }
        }
    }
}

অন্যান্য অ্যান্ড্রয়েড প্লাগইন (যেমন com.android.library অথবা com.android.application ) এর বিপরীতে, KMP অ্যান্ড্রয়েড প্লাগইনটি প্রকল্প স্তরে তার প্রধান DSL এক্সটেনশন নিবন্ধন করে না। এটি KMP টার্গেট হায়ারার্কির মধ্যে থাকে যাতে এটি নিশ্চিত করা যায় যে এটি শুধুমাত্র আপনার মাল্টিপ্ল্যাটফর্ম সেটআপে সংজ্ঞায়িত নির্দিষ্ট অ্যান্ড্রয়েড টার্গেটের ক্ষেত্রে প্রযোজ্য।

সংকলন এবং উৎস সেট পরিচালনা করুন

প্রায়শই, প্লাগইনগুলিকে কেবল লক্ষ্যমাত্রার চেয়ে আরও ক্ষুদ্র স্তরে কাজ করতে হয়—বিশেষ করে, তাদের সংকলন স্তরে কাজ করতে হয়। KotlinMultiplatformAndroidLibraryTargetKotlinMultiplatformAndroidCompilation উদাহরণ থাকে (উদাহরণস্বরূপ, 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 { } এর মতো সক্ষমকারী পদ্ধতি ব্যবহার করা এড়িয়ে চলা উচিত। এই পদ্ধতিগুলি কল করার ফলে কনভেনশন প্লাগইন প্রয়োগকারী প্রতিটি মডিউলের জন্য সংশ্লিষ্ট অ্যান্ড্রয়েড টেস্ট ভেরিয়েন্ট এবং কম্পাইলেশন তৈরি হয়, যা উপযুক্ত নাও হতে পারে। তদুপরি, সেটিংস সংশোধন করার জন্য এই পদ্ধতিগুলিকে দ্বিতীয়বার কোনও নির্দিষ্ট মডিউলে কল করা যাবে না, কারণ এটি করার ফলে কম্পাইলেশনটি ইতিমধ্যেই তৈরি হয়েছে বলে একটি ত্রুটি দেখা দেবে।

পরিবর্তে, আমরা কম্পাইলেশন কন্টেইনারে একটি reactive 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 {
                        targetSdk { version = release(34) }
                    }
                }
        }
    }
}

এই প্যাটার্নটি নিশ্চিত করে যে আপনার কনভেনশন প্লাগইনটি অলস থাকে এবং পৃথক মডিউলগুলিকে withDeviceTest { } কল করার অনুমতি দেয় যাতে ডিফল্টের সাথে বিরোধ না করে তাদের পরীক্ষাগুলি সক্ষম এবং আরও কাস্টমাইজ করা যায়।

ভেরিয়েন্ট API এর সাথে ইন্টারঅ্যাক্ট করুন

যেসব কাজের জন্য দেরী-পর্যায়ের কনফিগারেশন, আর্টিফ্যাক্ট অ্যাক্সেস (যেমন ম্যানিফেস্ট বা বাইট-কোড), অথবা নির্দিষ্ট উপাদানগুলিকে সক্ষম বা অক্ষম করার ক্ষমতা প্রয়োজন, সেগুলির জন্য আপনাকে অবশ্যই Android Variant API ব্যবহার করতে হবে। KMP প্রকল্পগুলিতে, এক্সটেনশনটি KotlinMultiplatformAndroidComponentsExtension ধরণের।

KMP অ্যান্ড্রয়েড প্লাগইন প্রয়োগ করা হলে এক্সটেনশনটি প্রকল্প স্তরে নিবন্ধিত হয়।

ভেরিয়েন্ট বা তাদের নেস্টেড টেস্ট কম্পোনেন্ট ( hostTests এবং deviceTests ) তৈরি নিয়ন্ত্রণ করতে beforeVariants ব্যবহার করুন। এটি প্রোগ্রাম্যাটিকভাবে পরীক্ষা নিষ্ক্রিয় করার বা 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 }
            }
        }
    }
}

চূড়ান্ত ভেরিয়েন্ট অবজেক্ট ( KotlinMultiplatformAndroidVariant ) অ্যাক্সেস করতে onVariants ব্যবহার করুন। এখানে আপনি সমাধান করা বৈশিষ্ট্যগুলি পরিদর্শন করতে পারেন অথবা মার্জড ম্যানিফেস্ট বা লাইব্রেরি ক্লাসের মতো আর্টিফ্যাক্টগুলিতে রূপান্তর নিবন্ধন করতে পারেন।

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.variant.SingleArtifact.MERGED_MANIFEST)
            }
        }
    }
}
{% অক্ষরে অক্ষরে %} {% এন্ডভারব্যাটিম %} {% অক্ষরে অক্ষরে %} {% এন্ডভারব্যাটিম %}