অ্যান্ড্রয়েড গ্রেডল প্লাগইন (এজিপি) হল অ্যান্ড্রয়েড অ্যাপ্লিকেশনের জন্য অফিসিয়াল বিল্ড সিস্টেম। এতে বিভিন্ন ধরণের উৎস সংকলন করার এবং সেগুলিকে একটি অ্যাপ্লিকেশনে সংযুক্ত করার জন্য সমর্থন রয়েছে যা আপনি একটি ফিজিক্যাল অ্যান্ড্রয়েড ডিভাইস বা এমুলেটরে চালাতে পারেন।
AGP-তে প্লাগইনগুলির জন্য এক্সটেনশন পয়েন্ট রয়েছে যা বিল্ড ইনপুট নিয়ন্ত্রণ করে এবং নতুন পদক্ষেপের মাধ্যমে এর কার্যকারিতা প্রসারিত করে যা স্ট্যান্ডার্ড বিল্ড টাস্কের সাথে একীভূত করা যেতে পারে। AGP-এর পূর্ববর্তী সংস্করণগুলিতে অফিসিয়াল API গুলি অভ্যন্তরীণ বাস্তবায়ন থেকে স্পষ্টভাবে পৃথক করা হয়নি। 7.0 সংস্করণ থেকে শুরু করে, AGP-তে অফিসিয়াল, স্থিতিশীল API গুলির একটি সেট রয়েছে যার উপর আপনি নির্ভর করতে পারেন।
AGP API জীবনচক্র
AGP তার API গুলির অবস্থা নির্ধারণের জন্য Gradle বৈশিষ্ট্যের জীবনচক্র অনুসরণ করে:
- অভ্যন্তরীণ : জনসাধারণের ব্যবহারের জন্য নয়
- ইনকিউবেটিং : সর্বজনীন ব্যবহারের জন্য উপলব্ধ কিন্তু চূড়ান্ত নয়, যার অর্থ হল চূড়ান্ত সংস্করণে এগুলি পিছনে সামঞ্জস্যপূর্ণ নাও হতে পারে।
- সর্বজনীন : সর্বজনীন ব্যবহারের জন্য উপলব্ধ এবং স্থিতিশীল
- বন্ধ করা হয়েছে : আর সমর্থিত নয়, এবং নতুন API দিয়ে প্রতিস্থাপিত হয়েছে
অবচয় হ্রাস নীতি
AGP পুরাতন API গুলি বাতিল করে নতুন, স্থিতিশীল API এবং একটি নতুন ডোমেন স্পেসিফিক ল্যাঙ্গুয়েজ (DSL) দিয়ে প্রতিস্থাপনের মাধ্যমে বিকশিত হচ্ছে। এই বিবর্তনটি একাধিক AGP রিলিজকে বিস্তৃত করবে এবং আপনি AGP API/DSL মাইগ্রেশন টাইমলাইনে এটি সম্পর্কে আরও জানতে পারবেন।
যখন AGP API গুলি এই মাইগ্রেশনের জন্য অথবা অন্য কোনও কারণে বন্ধ করা হয়, তখন সেগুলি বর্তমান প্রধান রিলিজে উপলব্ধ থাকবে কিন্তু সতর্কতা তৈরি করবে। পরবর্তী প্রধান রিলিজে বন্ধ করা API গুলি AGP থেকে সম্পূর্ণরূপে সরানো হবে। উদাহরণস্বরূপ, যদি AGP 7.0 তে একটি API বন্ধ করা হয়, তবে এটি সেই সংস্করণে উপলব্ধ থাকবে এবং সতর্কতা তৈরি করবে। সেই API আর AGP 8.0 তে উপলব্ধ থাকবে না।
সাধারণ বিল্ড কাস্টমাইজেশনে ব্যবহৃত নতুন API গুলির উদাহরণ দেখতে, Android Gradle প্লাগইন রেসিপিগুলি দেখুন। তারা সাধারণ বিল্ড কাস্টমাইজেশনের উদাহরণ প্রদান করে। আপনি আমাদের রেফারেন্স ডকুমেন্টেশনে নতুন API গুলি সম্পর্কে আরও বিশদ জানতে পারেন।
গ্রেডল বিল্ডের মূল বিষয়গুলি
এই নির্দেশিকাটি সম্পূর্ণ গ্রেডল বিল্ড সিস্টেম সম্পর্কে নয়। তবে, এটি আমাদের API গুলির সাথে একীভূত করতে সাহায্য করার জন্য ন্যূনতম প্রয়োজনীয় ধারণাগুলির সেটটি কভার করে এবং আরও পড়ার জন্য মূল গ্রেডল ডকুমেন্টেশনের সাথে লিঙ্ক করে।
আমরা গ্রেডল কীভাবে কাজ করে সে সম্পর্কে প্রাথমিক জ্ঞান ধরে নিই, যার মধ্যে রয়েছে প্রকল্পগুলি কীভাবে কনফিগার করতে হয়, বিল্ড ফাইলগুলি সম্পাদনা করতে হয়, প্লাগইন প্রয়োগ করতে হয় এবং কাজগুলি চালানো যায়। AGP সম্পর্কিত গ্রেডলের মূল বিষয়গুলি সম্পর্কে জানতে, আমরা আপনার বিল্ড কনফিগার করার পরামর্শ দিচ্ছি। গ্রেডল প্লাগইনগুলি কাস্টমাইজ করার জন্য সাধারণ কাঠামো সম্পর্কে জানতে, কাস্টম গ্রেডল প্লাগইনগুলি তৈরি করা দেখুন।
গ্রেডল অলস ধরণের শব্দকোষ
গ্র্যাডেল এমন অনেক ধরণের অফার করে যা "অলসভাবে" কাজ করে, অথবা ভারী গণনা বা Task তৈরিকে পরবর্তী পর্যায়ে বিল্ডে পিছিয়ে দিতে সাহায্য করে। এই ধরণেরগুলি অনেক গ্র্যাডেল এবং এজিপি এপিআইয়ের মূল অংশ। নিম্নলিখিত তালিকায় অলস এক্সিকিউশনে জড়িত প্রধান গ্র্যাডেল প্রকার এবং তাদের মূল পদ্ধতিগুলি অন্তর্ভুক্ত রয়েছে।
-
Provider<T> -
Tটাইপের একটি মান প্রদান করে (যেখানে "T" অর্থ যেকোনো প্রকার), যাget()ব্যবহার করে এক্সিকিউশন পর্যায়ে পড়া যেতে পারে অথবাmap(),flatMap(), এবংzip()পদ্ধতি ব্যবহার করে একটি নতুনProvider<S>(যেখানে "S" অর্থ অন্য কোন প্রকার) তে রূপান্তরিত করা যেতে পারে। মনে রাখবেন যে কনফিগারেশন পর্যায়েget()কখনই কল করা উচিত নয়।-
map(): একটি ল্যাম্বডা গ্রহণ করে এবংSটাইপের একটিProviderতৈরি করে,Provider<S>।map()এর জন্য lambda আর্গুমেন্টTমান নেয় এবংSমান তৈরি করে। ল্যাম্বডা তাৎক্ষণিকভাবে কার্যকর করা হয় না; পরিবর্তে, এর এক্সিকিউশনটি সেই মুহুর্ত পর্যন্ত পিছিয়ে দেওয়া হয় যখনget()ফলাফলপ্রাপ্তProvider<S>তে কল করা হয়, যার ফলে পুরো চেইনটি অলস হয়ে যায়। -
flatMap(): এছাড়াও একটি ল্যাম্বডা গ্রহণ করে এবংProvider<S>তৈরি করে, কিন্তু ল্যাম্বডা একটি মানTনেয় এবংProvider<S>তৈরি করে (সরাসরিSমান তৈরি করার পরিবর্তে)। কনফিগারেশনের সময় যখন S নির্ধারণ করা না যায় এবং আপনি কেবলProvider<S>পেতে পারেন তখন flatMap() ব্যবহার করুন। বাস্তবিকভাবে বলতে গেলে, যদি আপনিmap()ব্যবহার করেন এবং একটিProvider<Provider<S>>ফলাফল টাইপ পেয়ে থাকেন, তাহলে সম্ভবত এর অর্থ হল আপনার পরিবর্তেflatMap()ব্যবহার করা উচিত ছিল। -
zip(): আপনাকে দুটিProviderইনস্ট্যান্স একত্রিত করে একটি নতুনProviderতৈরি করতে দেয়, যেখানে একটি ফাংশন ব্যবহার করে একটি মান গণনা করা হয় যা দুটি ইনপুটProvidersইনস্ট্যান্স থেকে মানগুলিকে একত্রিত করে।
-
-
Property<T> -
Provider<T>প্রয়োগ করে, তাই এটিTধরণের একটি মানও প্রদান করে।Provider<T>এর বিপরীতে, যা শুধুমাত্র পঠনযোগ্য, আপনিProperty<T>এর জন্য একটি মানও সেট করতে পারেন। এটি করার দুটি উপায় রয়েছে:- যখনই
Tটাইপের মান পাওয়া যাবে, তখনই সরাসরি সেট করুন, বিলম্বিত গণনার প্রয়োজন ছাড়াই। -
Property<T>এর মানের উৎস হিসেবে অন্যProvider<T>সেট করুন। এই ক্ষেত্রে,Tমানটি তখনই বাস্তবায়িত হয় যখনProperty.get()কল করা হয়।
- যখনই
-
TaskProvider -
Provider<Task>ইমপ্লিমেন্ট করে।TaskProviderতৈরি করতে,tasks.register()ব্যবহার করুন,tasks.create()ব্যবহার না করে, যাতে কাজগুলি শুধুমাত্র প্রয়োজনের সময় অলসভাবে তাৎক্ষণিকভাবে সম্পন্ন হয়।Taskতৈরি হওয়ার আগে আপনিflatMap()ব্যবহার করে একটিTaskএর আউটপুট অ্যাক্সেস করতে পারেন, যা আপনি যদি অন্যান্যTaskইনস্ট্যান্সের ইনপুট হিসাবে আউটপুট ব্যবহার করতে চান তবে কার্যকর হতে পারে।
অলসভাবে কাজের ইনপুট এবং আউটপুট সেট আপ করার জন্য সরবরাহকারী এবং তাদের রূপান্তর পদ্ধতিগুলি অপরিহার্য, অর্থাৎ, সমস্ত কাজ আগে থেকেই তৈরি করার এবং মানগুলি সমাধান করার প্রয়োজন ছাড়াই।
প্রোভাইডাররা টাস্ক নির্ভরতা তথ্যও বহন করে। যখন আপনি একটি Task আউটপুট রূপান্তর করে একটি Provider তৈরি করেন, তখন সেই Task Provider একটি অন্তর্নিহিত নির্ভরতা হয়ে ওঠে এবং যখনই Provider মান সমাধান করা হয়, যেমন যখন অন্য কোনও Task প্রয়োজন হয় তখন এটি তৈরি এবং চালানো হবে।
এখানে দুটি টাস্ক, GitVersionTask এবং ManifestProducerTask নিবন্ধনের একটি উদাহরণ দেওয়া হল, যেখানে Task ইনস্ট্যান্স তৈরি স্থগিত রাখা হয়েছে যতক্ষণ না সেগুলো আসলে প্রয়োজন হয়। ManifestProducerTask ইনপুট মান GitVersionTask এর আউটপুট থেকে প্রাপ্ত একটি Provider এ সেট করা আছে, তাই 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 ভ্যারিয়েন্ট API এবং তার টাস্কগুলির আউটপুট অ্যাক্সেস, অথবা আর্টিফ্যাক্ট তৈরি করে , যা আপনি পড়তে এবং রূপান্তর করতে পারেন। আরও তথ্যের জন্য এই ডকুমেন্টে ভ্যারিয়েন্ট API, আর্টিফ্যাক্ট এবং টাস্ক দেখুন।
গ্রেডল বিল্ড পর্যায়গুলি
একটি প্রকল্প তৈরি করা স্বভাবতই একটি জটিল এবং সম্পদের চাহিদাপূর্ণ প্রক্রিয়া, এবং এর বিভিন্ন বৈশিষ্ট্য রয়েছে যেমন টাস্ক কনফিগারেশন এড়ানো, হালনাগাদ পরীক্ষা এবং কনফিগারেশন ক্যাশিং বৈশিষ্ট্য যা পুনরুৎপাদনযোগ্য বা অপ্রয়োজনীয় গণনায় ব্যয় করা সময় কমাতে সাহায্য করে।
এই অপ্টিমাইজেশনগুলির কিছু প্রয়োগ করার জন্য, গ্রেডল স্ক্রিপ্ট এবং প্লাগইনগুলিকে প্রতিটি স্বতন্ত্র গ্রেডল বিল্ড পর্যায়ে কঠোর নিয়ম মেনে চলতে হবে: ইনিশিয়ালাইজেশন, কনফিগারেশন এবং এক্সিকিউশন। এই নির্দেশিকায়, আমরা কনফিগারেশন এবং এক্সিকিউশন পর্যায়ের উপর ফোকাস করব। আপনি গ্রেডল বিল্ড লাইফসাইকেল গাইডে সমস্ত পর্যায় সম্পর্কে আরও তথ্য পেতে পারেন।
কনফিগারেশন ফেজ
কনফিগারেশন পর্যায়ে, বিল্ডের অংশ হিসেবে থাকা সমস্ত প্রকল্পের বিল্ড স্ক্রিপ্টগুলি মূল্যায়ন করা হয়, প্লাগইনগুলি প্রয়োগ করা হয় এবং বিল্ড নির্ভরতা সমাধান করা হয়। এই পর্যায়টি DSL অবজেক্ট ব্যবহার করে বিল্ড কনফিগার করতে এবং কাজ এবং তাদের ইনপুটগুলি অলসভাবে নিবন্ধন করার জন্য ব্যবহার করা উচিত।
যেহেতু কনফিগারেশন ফেজ সর্বদা চলে, কোন টাস্ক চালানোর জন্য অনুরোধ করা হোক না কেন, এটিকে ঝুঁকে রাখা এবং বিল্ড স্ক্রিপ্ট ছাড়া অন্য ইনপুটের উপর নির্ভর করে যেকোনো গণনা সীমাবদ্ধ করা বিশেষভাবে গুরুত্বপূর্ণ। অর্থাৎ, আপনার বাহ্যিক প্রোগ্রাম চালানো বা নেটওয়ার্ক থেকে পড়া উচিত নয়, অথবা দীর্ঘ গণনা করা উচিত নয় যা যথাযথ Task ইনস্ট্যান্স হিসাবে এক্সিকিউশন ফেজে স্থগিত করা যেতে পারে।
কার্যকরকরণ পর্যায়
এক্সিকিউশন পর্যায়ে, অনুরোধকৃত কাজ এবং তাদের উপর নির্ভরশীল কাজগুলি কার্যকর করা হয়। বিশেষ করে, @TaskAction চিহ্নিত Task ক্লাস পদ্ধতি(গুলি) কার্যকর করা হয়। টাস্ক এক্সিকিউশনের সময়, আপনি Provider<T>.get() কল করে ইনপুট (যেমন ফাইল) থেকে পড়তে এবং lazy providers সমাধান করতে পারবেন। এইভাবে lazy providers সমাধান করার ফলে map() বা flatMap() কলের একটি ক্রম শুরু হয় যা প্রোভিডারের মধ্যে থাকা টাস্ক নির্ভরতা তথ্য অনুসরণ করে। প্রয়োজনীয় মানগুলি বাস্তবায়িত করার জন্য টাস্কগুলি অলসভাবে চালানো হয়।
ভেরিয়েন্ট API, আর্টিফ্যাক্ট এবং টাস্ক
ভেরিয়েন্ট API হল অ্যান্ড্রয়েড গ্রেডল প্লাগইনের একটি এক্সটেনশন মেকানিজম যা আপনাকে বিভিন্ন বিকল্পগুলি পরিচালনা করতে দেয়, সাধারণত বিল্ড কনফিগারেশন ফাইলগুলিতে DSL ব্যবহার করে সেট করা হয়, যা অ্যান্ড্রয়েড বিল্ডকে প্রভাবিত করে। ভেরিয়েন্ট API আপনাকে বিল্ড দ্বারা তৈরি মধ্যবর্তী এবং চূড়ান্ত শিল্পকর্মগুলিতে অ্যাক্সেস দেয়, যেমন ক্লাস ফাইল, মার্জড ম্যানিফেস্ট, অথবা APK/AAB ফাইল।
অ্যান্ড্রয়েড বিল্ড ফ্লো এবং এক্সটেনশন পয়েন্ট
AGP এর সাথে ইন্টারঅ্যাক্ট করার সময়, সাধারণ Gradle লাইফসাইকেল কলব্যাক (যেমন afterEvaluate() ) নিবন্ধন করার পরিবর্তে বা স্পষ্ট Task নির্ভরতা সেট আপ করার পরিবর্তে বিশেষভাবে তৈরি এক্সটেনশন পয়েন্ট ব্যবহার করুন। AGP দ্বারা তৈরি টাস্কগুলিকে বাস্তবায়নের বিবরণ হিসাবে বিবেচনা করা হয় এবং একটি পাবলিক API হিসাবে প্রকাশ করা হয় না। আপনাকে অবশ্যই Task অবজেক্টের উদাহরণ পাওয়ার চেষ্টা করা বা Task নাম অনুমান করা এবং সরাসরি সেই Task অবজেক্টগুলিতে কলব্যাক বা নির্ভরতা যোগ করা এড়িয়ে চলতে হবে।
AGP তার Task ইনস্ট্যান্স তৈরি এবং এক্সিকিউট করার জন্য নিম্নলিখিত ধাপগুলি সম্পন্ন করে, যা পরবর্তীতে বিল্ড আর্টিফ্যাক্ট তৈরি করে। Variant অবজেক্ট তৈরির সাথে জড়িত প্রধান ধাপগুলি কলব্যাক দ্বারা অনুসরণ করা হয় যা আপনাকে বিল্ডের অংশ হিসাবে তৈরি নির্দিষ্ট অবজেক্টে পরিবর্তন করতে দেয়। এটি মনে রাখা গুরুত্বপূর্ণ যে সমস্ত কলব্যাক কনফিগারেশন পর্যায়ে ঘটে (এই পৃষ্ঠায় বর্ণিত) এবং দ্রুত চলতে হবে, পরিবর্তে এক্সিকিউটেশন পর্যায়ে যেকোন জটিল কাজকে যথাযথ Task ইনস্ট্যান্সে স্থগিত করে।
- DSL পার্সিং : এটি তখনই হয় যখন বিল্ড স্ক্রিপ্টগুলি মূল্যায়ন করা হয়, এবং যখন
androidব্লক থেকে অ্যান্ড্রয়েড DSL অবজেক্টের বিভিন্ন বৈশিষ্ট্য তৈরি এবং সেট করা হয়। নিম্নলিখিত বিভাগগুলিতে বর্ণিত ভেরিয়েন্ট API কলব্যাকগুলিও এই পর্যায়ে নিবন্ধিত হয়। finalizeDsl(): কলব্যাক যা আপনাকে কম্পোনেন্ট (ভেরিয়েন্ট) তৈরির জন্য লক করার আগে DSL অবজেক্টগুলি পরিবর্তন করতে দেয়।VariantBuilderঅবজেক্টগুলি DSL অবজেক্টে থাকা ডেটার উপর ভিত্তি করে তৈরি করা হয়।DSL লকিং : DSL এখন লক করা আছে এবং পরিবর্তন আর সম্ভব নয়।
beforeVariants(): এই কলব্যাকVariantBuilderমাধ্যমে কোন উপাদানগুলি তৈরি করা হবে এবং তাদের কিছু বৈশিষ্ট্যকে প্রভাবিত করতে পারে। এটি এখনও বিল্ড প্রবাহ এবং উৎপাদিত শিল্পকর্মগুলিতে পরিবর্তন করার অনুমতি দেয়।ভেরিয়েন্ট তৈরি : তৈরি করা হবে এমন উপাদান এবং শিল্পকর্মের তালিকা এখন চূড়ান্ত এবং পরিবর্তন করা যাবে না।
onVariants(): এই কলব্যাকে, আপনি তৈরি করাVariantঅবজেক্টগুলিতে অ্যাক্সেস পাবেন এবং আপনি তাদের ধারণকৃতPropertyমানগুলির জন্য মান বা প্রোভাইডার সেট করতে পারবেন, যাতে অলসভাবে গণনা করা যায়।ভেরিয়েন্ট লকিং : ভেরিয়েন্ট অবজেক্টগুলি এখন লক করা আছে এবং পরিবর্তনগুলি আর সম্ভব নয়।
তৈরি করা টাস্ক : বিল্ড সম্পাদনের জন্য প্রয়োজনীয়
Taskইনস্ট্যান্স তৈরি করতেVariantঅবজেক্ট এবং তাদেরPropertyমান ব্যবহার করা হয়।
AGP একটি 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 ব্যবহার করে শুধুমাত্র ঘোষণামূলক কনফিগারেশনের জন্য বিল্ড স্ক্রিপ্ট রাখা এবং যেকোনো কাস্টম ইম্পেরেটিভ লজিক buildSrc অথবা বহিরাগত প্লাগইনগুলিতে স্থানান্তর করা । আপনার প্রকল্পে প্লাগইন তৈরি করার পদ্ধতি শিখতে আপনি আমাদের Gradle recipes GitHub সংগ্রহস্থলে buildSrc নমুনাগুলিও দেখতে পারেন। প্লাগইন কোড থেকে কলব্যাক নিবন্ধনের একটি উদাহরণ এখানে দেওয়া হল:
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)
এই কলব্যাকে, আপনি বিল্ড ফাইলগুলিতে android ব্লক থেকে তথ্য পার্স করে তৈরি করা DSL অবজেক্টগুলিতে অ্যাক্সেস এবং পরিবর্তন করতে পারবেন। এই 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() এর মতো, আপনার প্রদত্ত সমস্ত মান কনফিগারেশনের সময় সমাধান করতে হবে এবং বহিরাগত ইনপুটগুলির উপর নির্ভর করবে না। beforeVariants() কলব্যাক শেষ হওয়ার পরে VariantBuilder অবজেক্টগুলি পরিবর্তন করা উচিত নয়।
androidComponents {
beforeVariants { variantBuilder ->
variantBuilder.minSdk = 23
}
}
beforeVariants() কলব্যাক ঐচ্ছিকভাবে একটি VariantSelector নেয়, যা আপনি androidComponentsExtension এ selector() পদ্ধতির মাধ্যমে পেতে পারেন। আপনি কলব্যাক ইনভোকেশনে অংশগ্রহণকারী উপাদানগুলিকে তাদের নাম, বিল্ড টাইপ বা পণ্যের স্বাদের উপর ভিত্তি করে ফিল্টার করতে এটি ব্যবহার করতে পারেন।
androidComponents {
beforeVariants(selector().withName("adfree")) { variantBuilder ->
variantBuilder.minSdk = 23
}
}
onVariants()
onVariants() কল করার সময়, AGP দ্বারা তৈরি করা সমস্ত আর্টিফ্যাক্ট ইতিমধ্যেই নির্ধারিত হয়ে গেছে তাই আপনি আর সেগুলি অক্ষম করতে পারবেন না। তবে, আপনি Variant অবজেক্টে Property attributes-এর জন্য সেট করে কাজের জন্য ব্যবহৃত কিছু মান পরিবর্তন করতে পারেন। যেহেতু AGP-এর কাজগুলি সম্পাদন করা হলেই Property মানগুলি সমাধান করা হবে, তাই আপনি নিরাপদে আপনার নিজস্ব কাস্টম টাস্ক থেকে প্রোভাইডারদের সাথে সেগুলি সংযুক্ত করতে পারেন যারা ফাইল বা নেটওয়ার্কের মতো বহিরাগত ইনপুট থেকে পড়া সহ যেকোনো প্রয়োজনীয় গণনা সম্পাদন করবে।
// 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ডিরেক্টরিতে অ্যাপ্লিকেশন কোড -
resডিরেক্টরিতে অ্যান্ড্রয়েড রিসোর্স -
resourcesডিরেক্টরিতে জাভা রিসোর্স -
assetsডিরেক্টরিতে থাকা অ্যান্ড্রয়েড অ্যাসেট
আপনি যে উৎসগুলি যোগ করতে পারেন তার সম্পূর্ণ তালিকার জন্য, উৎস API দেখুন।
এই কোড স্নিপেটে দেখানো হয়েছে কিভাবে addStaticSourceDirectory() ফাংশন ব্যবহার করে জাভা সোর্স সেটে ${variant.name} নামক একটি কাস্টম সোর্স ফোল্ডার যোগ করতে হয়। এরপর অ্যান্ড্রয়েড টুলচেইন এই ফোল্ডারটি প্রক্রিয়া করে।
onVariants { variant ->
variant.sources.java?.let { java ->
java.addStaticSourceDirectory("custom/src/kotlin/${variant.name}")
}
}
আরও বিস্তারিত জানার জন্য addJavaSource রেসিপিটি দেখুন।
এই কোড স্নিপেটটি দেখায় কিভাবে একটি কাস্টম টাস্ক থেকে তৈরি অ্যান্ড্রয়েড রিসোর্স সহ একটি ডিরেক্টরি 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-তে একটি এক্সটেনশন মেকানিজমও রয়েছে যা আপনাকে বিল্ডের সময় তৈরি মধ্যবর্তী এবং চূড়ান্ত আর্টিফ্যাক্টগুলি পড়তে বা রূপান্তর করতে দেয়। উদাহরণস্বরূপ, আপনি একটি কাস্টম Task চূড়ান্ত, মার্জ করা AndroidManifest.xml ফাইলের বিষয়বস্তু বিশ্লেষণ করতে পড়তে পারেন, অথবা আপনি আপনার কাস্টম 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() কলব্যাক থেকে পাইপলাইনে আর্টিফ্যাক্টের উপর যেকোনো সংখ্যক অপারেশন যোগ করতে পারে এবং AGP নিশ্চিত করবে যে সেগুলি সঠিকভাবে চেইন করা হয়েছে যাতে সমস্ত কাজ সঠিক সময়ে চলে এবং আর্টিফ্যাক্টগুলি সঠিকভাবে তৈরি এবং আপডেট করা হয়। এর অর্থ হল যখন কোনও অপারেশন কোনও আউটপুট যোগ, প্রতিস্থাপন বা রূপান্তর করে পরিবর্তন করে, তখন পরবর্তী অপারেশনটি ইনপুট হিসাবে এই আর্টিফ্যাক্টগুলির আপডেটেড সংস্করণ দেখতে পাবে, ইত্যাদি।
নিবন্ধন কার্যক্রমের প্রবেশ বিন্দু হল Artifacts ক্লাস। নিম্নলিখিত কোড স্নিপেটটি দেখায় কিভাবে আপনি onVariants() কলব্যাকে Variant অবজেক্টের একটি সম্পত্তি থেকে Artifacts এর একটি উদাহরণে অ্যাক্সেস পেতে পারেন।
এরপর আপনি আপনার কাস্টম TaskProvider দিয়ে একটি TaskBasedOperation অবজেক্ট (1) পেতে পারেন, এবং wiredWith* পদ্ধতি (2) ব্যবহার করে এর ইনপুট এবং আউটপুট সংযোগ করতে এটি ব্যবহার করতে পারেন।
আপনার সঠিক পদ্ধতিটি বেছে নেওয়ার প্রয়োজন হবে, আপনি যে Artifact রূপান্তর করতে চান তা দ্বারা বাস্তবায়িত কার্ডিনালিটি এবং FileSystemLocation ধরণের উপর নির্ভর করে।
এবং পরিশেষে, আপনি 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 গ্রহণ করে। TaskBasedOperation ক্লাসে অন্যান্য wiredWith* পদ্ধতি রয়েছে যা Artifact cardinality এবং FileSystemLocation ধরণের অন্যান্য সমন্বয়ের জন্য কাজ করবে।
AGP সম্প্রসারণ সম্পর্কে আরও জানতে, আমরা Gradle বিল্ড সিস্টেম ম্যানুয়াল থেকে নিম্নলিখিত বিভাগগুলি পড়ার পরামর্শ দিচ্ছি:
- কাস্টম গ্রেডল প্লাগইন তৈরি করা হচ্ছে
- গ্রেডল প্লাগইন বাস্তবায়ন
- কাস্টম গ্রেডল টাস্কের ধরণ তৈরি করা
- অলস কনফিগারেশন
- টাস্ক কনফিগারেশন এড়িয়ে যাওয়া