lint-এর মতো কোড ইন্সপেকশন টুল ব্যবহার করে আপনি সমস্যা খুঁজে পেতে এবং কোড উন্নত করতে পারেন, তবে ইন্সপেকশন টুল শুধুমাত্র অনুমান করতে পারে। Android রিসোর্স আইডি,
যেমন, স্ট্রিং, গ্রাফিক্স, রঙ এবং অন্যান্য রিসোর্সের ধরন শনাক্ত করতে int ব্যবহার করুন, যাতে আপনি যেখানে রঙ নির্দিষ্ট করা উচিত সেখানে স্ট্রিং রিসোর্স নির্দিষ্ট করলে,
ইন্সপেকশন টুল তা বলতে পারে না। এই পরিস্থিতির অর্থ হল, আপনার অ্যাপ ভুলভাবে রেন্ডার করতে পারে বা একেবারেই রান নাও করতে পারে,
এমনকি আপনি কোড ইন্সপেকশন ব্যবহার করলেও।
অ্যানোটেশন আপনাকে কোড ইন্সপেকশন টুল, যেমন লিন্ট-এ ইঙ্গিত প্রদান করতে দেয়, যাতে এই ধরনের আরও সূক্ষ্ম কোড সমস্যা শনাক্ত করতে সাহায্য করা যায়। অ্যানোটেশন মেটাডেটা ট্যাগ হিসেবে যোগ করা হয় যা আপনি ভেরিয়েবল, প্যারামিটার ও রিটার্ন ভ্যালুর সাথে অ্যাটাচ করেন যাতে মেথড রিটার্ন ভ্যালু, পাস করা প্যারামিটার, লোকাল ভেরিয়েবল ও ফিল্ড চেক করা যায়। কোড ইন্সপেকশন টুলের সাথে ব্যবহার করা হলে, অ্যানোটেশন আপনাকে কোনও পয়েন্টার এক্সেপশন নেই এবং রিসোর্স টাইপ কনফ্লিক্টের মতো সমস্যা শনাক্ত করতে সাহায্য করতে পারে।
Jetpack Annotations Library-এর মাধ্যমে
Android বিভিন্ন ধরনের অ্যানোটেশন সাপোর্ট করে।
আপনি
androidx.annotation
প্যাকেজের মাধ্যমে লাইব্রেরি অ্যাক্সেস করতে পারবেন।
মনে রাখবেন: কোনও মডিউল যদি অ্যানোটেশন প্রসেসরের উপর নির্ভরশীল হয়,
তাহলে সেই নির্ভরতা যোগ করার জন্য আপনাকে Kotlin-এর ক্ষেত্রে kapt বা ksp ডিপেন্ডেন্সি কনফিগারেশন
অথবা Java-এর ক্ষেত্রে annotationProcessor ডিপেন্ডেন্সি কনফিগারেশন ব্যবহার করতে হবে।
আপনার প্রোজেক্টে অ্যানোটেশন যোগ করুন
আপনার প্রোজেক্টে অ্যানোটেশন চালু করতে, আপনার লাইব্রেরি বা অ্যাপে androidx.annotation:annotation
ডিপেন্ডেন্সি যোগ করুন। আপনি কোনও কোড ইন্সপেকশন বা lint টাস্ক রান করার সময় আপনার যোগ করা যেকোনও অ্যানোটেশন চেক করা হয়।
Jetpack Annotations লাইব্রেরি ডিপেন্ডেন্সি যোগ করা
Jetpack Annotations লাইব্রেরি
Google-এর Maven রিপোজিটরিতে প্রকাশ করা হয়েছে।
আপনার প্রোজেক্টে Jetpack Anotations লাইব্রেরি যোগ করতে, আপনার build.gradle বা
build.gradle.kts ফাইলের dependencies ব্লকে নিম্নলিখিত লাইনটি
যোগ করুন:
Kotlin
dependencies { implementation("androidx.annotation:annotation:1.11.0") }
গ্ৰুভি
dependencies { implementation 'androidx.annotation:annotation:1.11.0' }
আপনি নিজের লাইব্রেরি মডিউলে অ্যানোটেশন ব্যবহার করলে, অ্যানোটেশনগুলি annotations.zip ফাইলে XML ফর্ম্যাটে Android Archive (AAR) আর্টিফ্যাক্টের অংশ হিসেবে অন্তর্ভুক্ত করা হয়। androidx.annotation ডিপেন্ডেন্সি যোগ করলে, আপনার লাইব্রেরির কোনও ডাউনস্ট্রিম ব্যবহারকারীর জন্য ডিপেন্ডেন্সি যোগ হয় না।
মনে রাখবেন: আপনি অন্য Jetpack লাইব্রেরি ব্যবহার করলে,
আপনাকে হয়ত androidx.annotation ডিপেন্ডেন্সি যোগ করতে হবে না। অন্যান্য অনেক Jetpack লাইব্রেরি Annotations লাইব্রেরির উপর নির্ভর করে, তাই আপনার কাছে আগে থেকেই
annotations-এর অ্যাক্সেস থাকতে পারে।
Jetpack রিপোজিটরিতে অন্তর্ভুক্ত অ্যানোটেশনের সম্পূর্ণ তালিকা পেতে, হয়
Jetpack অ্যানোটেশন লাইব্রেরি
রেফারেন্স দেখুন অথবা import androidx.annotation. স্টেটমেন্টের জন্য উপলভ্য বিকল্পগুলি দেখতে অটোকমপ্লিট ফিচার ব্যবহার করুন।
কোড ইন্সপেকশন রান করুন
Android Studio থেকে কোড ইন্সপেকশন শুরু করতে, যার মধ্যে অ্যানোটেশন যাচাই করা এবং অটোমেটিক লিন্ট চেকিং অন্তর্ভুক্ত, মেনু থেকে বিশ্লেষণ করুন > কোড ইন্সপেক্ট করুন বিকল্প বেছে নিন। Android Studio সম্ভাব্য সমস্যা ফ্ল্যাগ করার জন্য কনফ্লিক্ট মেসেজ দেখায়, যেখানে আপনার কোড অ্যানোটেশনের সাথে কনফ্লিক্ট করে এবং সম্ভাব্য সমাধান সাজেস্ট করে।
এছাড়াও, আপনি কমান্ড লাইন ব্যবহার করে
lint টাস্ক রান করার মাধ্যমে অ্যানোটেশন এনফোর্স করতে পারবেন। যদিও এটি কন্টিনিউয়াস ইন্টিগ্রেশন সার্ভারের সাথে সমস্যা ফ্ল্যাগ করার জন্য উপযোগী হতে পারে, lint টাস্ক নালনেস অ্যানোটেশন (নিম্নলিখিত বিভাগে বর্ণিত) এনফোর্স করে না;
শুধুমাত্র Android Studio এটি করে। লিন্ট
ইন্সপেকশন চালু করা ও রান করার ব্যাপারে আরও তথ্যের জন্য, লিন্ট
চেকের মাধ্যমে আপনার কোড উন্নত করা দেখুন।
অ্যানোটেশন সংক্রান্ত দ্বন্দ্বের কারণে সতর্কতা দেখানো হলেও, এই সতর্কতা আপনার অ্যাপকে কম্পাইল করা থেকে আটকায় না।
নালনেস অ্যানোটেশন
ভ্যালু ফাঁকা হতে পারে কিনা তা এনফোর্স করার জন্য জাভা কোডে ফাঁকা অ্যানোটেশন উপযোগী হতে পারে। Kotlin কোডে এগুলি কম উপযোগী, কারণ Kotlin-এ বিল্ট-ইন নালিবিলিটি নিয়ম আছে যা কম্পাইল করার সময় প্রয়োগ করা হয়।প্রদত্ত ভেরিয়েবল, প্যারামিটার বা রিটার্ন ভ্যালু নাল কিনা তা চেক করতে
@Nullable এবং
@NonNull অ্যানোটেশন
যোগ করুন। @Nullable
অ্যানোটেশন এমন একটি ভেরিয়েবল, প্যারামিটার বা রিটার্ন ভ্যালু নির্দেশ করে যা শূন্য হতে পারে।
@NonNull এমন একটি ভেরিয়েবল, প্যারামিটার বা রিটার্ন ভ্যালু নির্দেশ করে যা শূন্য হতে পারে না।
যেমন, নাল ভ্যালু আছে এমন কোনও লোকাল ভেরিয়েবল যদি @NonNull অ্যানোটেশন অ্যাটাচ করা আছে এমন কোনও মেথডে প্যারামিটার হিসেবে পাস করা হয়, তাহলে কোড তৈরি করার সময় নন-নাল কনফ্লিক্ট সংক্রান্ত একটি সতর্কতা দেখানো হয়। এছাড়াও, @Nullable দ্বারা চিহ্নিত কোনও মেথডের ফলাফল নাল কিনা তা প্রথমে চেক না করেই
ফলাফল রেফারেন্স করার চেষ্টা করলে
নালনেস সংক্রান্ত সতর্কতা জেনারেট হয়। কোনও মেথডের রিটার্ন ভ্যালুতে শুধুমাত্র @Nullable ব্যবহার করুন
যদি মেথডের প্রতিটি ব্যবহার স্পষ্টভাবে নাল-চেক করা হয়।
নিম্নলিখিত উদাহরণে নালেবিলিটি কীভাবে কাজ করে তা দেখানো হয়েছে। Kotlin-এর উদাহরণ কোড @NonNull অ্যানোটেশন ব্যবহার করে না কারণ
নন-নালেবেল টাইপ নির্দিষ্ট করা হলে
এটি অটোমেটিক জেনারেট করা বাইটকোডে যোগ করা হয়। Java-এর উদাহরণে context ও attrs প্যারামিটারে @NonNull অ্যানোটেশন ব্যবহার করা হয় যাতে পাস করা প্যারামিটারের ভ্যালু
নাল কিনা তা চেক করা যায়। এটি আরও চেক করে যে onCreateView() মেথডটি নিজে থেকে null রিটার্ন করে না:
Kotlin
... /** Annotation not used because of the safe-call operator(?)**/ override fun onCreateView( name: String?, context: Context, attrs: AttributeSet ): View? { ... } ...
জাভা
import androidx.annotation.NonNull; ... /** Add support for inflating the <fragment> tag. **/ @NonNull @Override public View onCreateView(String name, @NonNull Context context, @NonNull AttributeSet attrs) { ... } ...
নালেবিলিটি বিশ্লেষণ
Android Studio-তে নালেবিলিটি বিশ্লেষণ রান করার সুবিধা আছে, যার মাধ্যমে আপনার কোডে অটোমেটিক নালনেস অ্যানোটেশন অনুমান ও যোগ করা যায়। নালেবিলিটি বিশ্লেষণ আপনার কোডের মেথড হায়ারার্কি জুড়ে কন্ট্র্যাক্ট স্ক্যান করে এগুলি শনাক্ত করে:
- নাল রিটার্ন করতে পারে এমন কলিং পদ্ধতি।
- পদ্ধতি যা শূন্য ফেরত দেবে না।
- ভেরিয়েবল, যেমন ফিল্ড, লোকাল ভেরিয়েবল এবং প্যারামিটার, যা ফাঁকা থাকতে পারে।
- ভেরিয়েবল, যেমন ফিল্ড, লোকাল ভেরিয়েবল এবং প্যারামিটার, যেগুলি নাল ভ্যালু হোল্ড করতে পারে না।
বিশ্লেষণটি তখন শনাক্ত করা লোকেশনে উপযুক্ত নাল অ্যানোটেশন অটোমেটিক যোগ করে।
Android Studio-তে নালেবিলিটি বিশ্লেষণ রান করতে, বিশ্লেষণ করুন >
নালিটি অনুমান করুন বিকল্প বেছে নিন। Android Studio আপনার কোডের শনাক্ত করা লোকেশনে Android @Nullable এবং @NonNull অ্যানোটেশন
যোগ করে। নাল অ্যানালিসিস চালানোর পরে, ইনজেক্ট করা অ্যানোটেশন যাচাই করা একটি ভালো অভ্যাস।
মনে রাখবেন: নালনেস অ্যানোটেশন যোগ করার সময়, 'অটোমেটিক সম্পূর্ণ করুন' ফিচার
Android নাল অ্যানোটেশনের পরিবর্তে IntelliJ
@Nullable এবং
@NotNull অ্যানোটেশন সাজেস্ট করতে পারে
এবং সংশ্লিষ্ট লাইব্রেরি অটোমেটিক ইমপোর্ট করতে পারে। তবে, Android Studio
লিন্ট চেকার শুধু Android নাল অ্যানোটেশন খোঁজে। আপনার অ্যানোটেশন যাচাই করার সময়, আপনার প্রোজেক্টে Android null অ্যানোটেশন ব্যবহার করা হয়েছে কিনা তা কনফার্ম করুন যাতে
কোড চেক করার সময় লিন্ট চেকার আপনাকে সঠিকভাবে বিজ্ঞপ্তি পাঠাতে পারে।
রিসোর্স অ্যানোটেশন
রিসোর্সের ধরন যাচাই করা উপযোগী হতে পারে কারণ Android-এ রিসোর্সের রেফারেন্স, যেমন drawable এবং string রিসোর্স, পূর্ণসংখ্যা হিসেবে পাস করা হয়।
যে কোড কোনও প্যারামিটারকে নির্দিষ্ট ধরনের রিসোর্স রেফারেন্স করার প্রত্যাশা করে, যেমন String,
সেটি int-এর প্রত্যাশিত রেফারেন্সের ধরন পাস করতে পারে, কিন্তু আসলে অন্য ধরনের রিসোর্স রেফারেন্স করে, যেমন R.string রিসোর্স।
যেমন, কোনও রিসোর্স প্যারামিটারে R.string রেফারেন্স আছে কিনা তা চেক করতে
@StringRes অ্যানোটেশন যোগ করুন, যেমন এখানে দেখানো হয়েছে:
Kotlin
abstract fun setTitle(@StringRes resId: Int)
জাভা
public abstract void setTitle(@StringRes int resId)
কোড ইন্সপেকশন চলাকালীন, প্যারামিটারে R.string রেফারেন্স পাস না করা হলে,
অ্যানোটেশন একটি সতর্কতা জেনারেট করে।
অন্যান্য রিসোর্স টাইপের জন্য অ্যানোটেশন, যেমন @DrawableRes, @DimenRes, @ColorRes এবং @InterpolatorRes, একই অ্যানোটেশন ফর্ম্যাট ব্যবহার করে যোগ করা যেতে পারে এবং কোড ইন্সপেকশনের সময় রান করা যেতে পারে।
আপনার প্যারামিটার
একাধিক রিসোর্স টাইপ সাপোর্ট করলে, আপনি প্রদত্ত প্যারামিটারে
একাধিক রিসোর্স টাইপ অ্যানোটেশন যোগ করতে পারবেন। অ্যানোটেট করা প্যারামিটার যে কোনও ধরনের R রিসোর্স হতে পারে তা বোঝাতে
@AnyRes ব্যবহার করুন।
যদিও আপনি @ColorRes ব্যবহার করে উল্লেখ করতে পারেন যে একটি
প্যারামিটার একটি কালার রিসোর্স হওয়া উচিত, একটি কালার ইন্টিজার (RRGGBB বা
AARRGGBB ফর্ম্যাটে) কালার রিসোর্স হিসাবে স্বীকৃত নয়। পরিবর্তে, @ColorInt অ্যানোটেশন ব্যবহার করে
নির্দেশ করুন যে প্যারামিটারটি অবশ্যই একটি কালার ইন্টিজার হতে হবে। বিল্ড টুল ভুল কোড ফ্ল্যাগ করবে যা
অ্যানোটেট করা পদ্ধতিতে কালার ইন্টিজারের পরিবর্তে android.R.color.black-এর মতো
কালার রিসোর্স আইডি পাস করে।
থ্রেড অ্যানোটেশন
থ্রেড অ্যানোটেশন চেক করে দেখে যে কোনও পদ্ধতি নির্দিষ্ট ধরনের থ্রেড থেকে কল করা হয়েছে কিনা। নিম্নলিখিত থ্রেড অ্যানোটেশন কাজ করে:
বিল্ড টুল @MainThread এবং
@UiThread অ্যানোটেশনকে ইন্টারচেঞ্জেবল হিসেবে বিবেচনা করে, তাই আপনি @MainThread পদ্ধতি থেকে @UiThread
পদ্ধতি এবং এর উল্টোটাও কল করতে পারবেন। তবে, UI থ্রেড মূল থ্রেডের থেকে আলাদা হতে পারে, যদি সিস্টেম অ্যাপের একাধিক ভিউ
আলাদা থ্রেডে থাকে। তাই, অ্যাপের ভিউ হায়ারার্কির সাথে যুক্ত পদ্ধতিগুলি @UiThread দিয়ে অ্যানোটেট করা উচিত এবং অ্যাপের লাইফসাইকেলের সাথে যুক্ত পদ্ধতিগুলি শুধুমাত্র @MainThread দিয়ে অ্যানোটেট করা উচিত।
কোনও ক্লাসের সব মেথড যদি একই থ্রেডিংয়ের প্রয়োজনীয়তা শেয়ার করে, তাহলে আপনি ক্লাসে একটি থ্রেড অ্যানোটেশন যোগ করতে পারেন। এর মাধ্যমে আপনি যাচাই করতে পারবেন যে ক্লাসের সব মেথড একই ধরনের থ্রেড থেকে কল করা হয়েছে।
থ্রেড অ্যানোটেশনের একটি সাধারণ ব্যবহার হল,
@WorkerThread-এর সাথে অ্যানোটেট করা পদ্ধতি বা ক্লাস শুধুমাত্র উপযুক্ত ব্যাকগ্রাউন্ড থ্রেড থেকে কল করা হয়েছে কিনা তা যাচাই করা।
ভ্যালু কনস্ট্রেন্ট অ্যানোটেশন
পাস করা প্যারামিটারের ভ্যালু যাচাই করতে
@IntRange,
@FloatRange এবং
@Size অ্যানোটেশন ব্যবহার করুন। @IntRange এবং @FloatRange
উভয়ই সবচেয়ে বেশি উপযোগী হয় যখন এমন প্যারামিটারে প্রয়োগ করা হয় যেখানে ব্যবহারকারীদের রেঞ্জ ভুল হওয়ার সম্ভাবনা থাকে।
@IntRange অ্যানোটেশন যাচাই করে যে কোনও ইন্টিজার বা লং প্যারামিটারের
ভ্যালু নির্দিষ্ট রেঞ্জের মধ্যে আছে কিনা। নিচের উদাহরণ থেকে বোঝা যায় যে alpha
প্যারামিটারে অবশ্যই ০ থেকে ২৫৫-এর মধ্যে কোনও পূর্ণসংখ্যা থাকতে হবে:
Kotlin
fun setAlpha(@IntRange(from = 0, to = 255) alpha: Int) { ... }
জাভা
public void setAlpha(@IntRange(from=0,to=255) int alpha) { ... }
@FloatRange অ্যানোটেশন চেক করে যে ফ্লোট বা ডবল প্যারামিটার ভ্যালু
ফ্লোটিং পয়েন্ট ভ্যালুর নির্দিষ্ট রেঞ্জের মধ্যে আছে কিনা। নিচের উদাহরণ থেকে বোঝা যায় যে
alpha প্যারামিটারে অবশ্যই ০.০ থেকে ১.০ পর্যন্ত ফ্লোট ভ্যালু থাকতে হবে:
Kotlin
fun setAlpha(@FloatRange(from = 0.0, to = 1.0) alpha: Float) {...}
জাভা
public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {...}
@Size অ্যানোটেশন কোনও কালেকশন বা অ্যারের সাইজ অথবা স্ট্রিংয়ের দৈর্ঘ্য চেক করে। @Size অ্যানোটেশন ব্যবহার করে নিম্নলিখিত কোয়ালিটি
যাচাই করা যেতে পারে:
- ন্যূনতম সাইজ, যেমন
@Size(min=2) - সর্বাধিক সাইজ, যেমন
@Size(max=2) - সঠিক সাইজ, যেমন
@Size(2) - এমন একটি সংখ্যা যার গুণিতক হিসেবে সাইজটি হতে হবে, যেমন
@Size(multiple=2)
যেমন, @Size(min=1)
চেক করে যে কোনও কালেকশন খালি আছে কিনা এবং @Size(3)
যাচাই করে যে কোনও অ্যারেতে ঠিক তিনটি ভ্যালু আছে কিনা।
নিচের উদাহরণ থেকে বোঝা যায় যে
location অ্যারেতে অন্তত একটি এলিমেন্ট থাকতে হবে:
Kotlin
fun getLocation(button: View, @Size(min=1) location: IntArray) { button.getLocationOnScreen(location) }
জাভা
void getLocation(View button, @Size(min=1) int[] location) { button.getLocationOnScreen(location); }
অনুমতি সংক্রান্ত অ্যানোটেশন
কোনও মেথডের কলারের অনুমতি যাচাই করতে @RequiresPermission
অ্যানোটেশন ব্যবহার করুন। বৈধ অনুমতির তালিকা থেকে
একটি অনুমতি চেক করতে, anyOf অ্যাট্রিবিউট ব্যবহার করুন। এক সেট অনুমতি চেক করতে, allOf অ্যাট্রিবিউট ব্যবহার করুন। নিম্নলিখিত উদাহরণটি
setWallpaper() পদ্ধতিকে অ্যানোটেট করে যাতে বোঝা যায় যে পদ্ধতির কলারের কাছে অবশ্যই
permission.SET_WALLPAPERS অনুমতি থাকতে হবে:
Kotlin
@RequiresPermission(Manifest.permission.SET_WALLPAPER) @Throws(IOException::class) abstract fun setWallpaper(bitmap: Bitmap)
জাভা
@RequiresPermission(Manifest.permission.SET_WALLPAPER) public abstract void setWallpaper(Bitmap bitmap) throws IOException;
নিম্নলিখিত উদাহরণের ক্ষেত্রে copyImageFile() মেথডের কলারের কাছে
এক্সটার্নাল স্টোরেজে রিড অ্যাক্সেস এবং কপি করা ছবিতে লোকেশন মেটাডেটায়
রিড অ্যাক্সেস, দুটিই থাকতে হবে:
Kotlin
@RequiresPermission(allOf = [ Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.ACCESS_MEDIA_LOCATION ]) fun copyImageFile(dest: String, source: String) { ... }
জাভা
@RequiresPermission(allOf = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.ACCESS_MEDIA_LOCATION}) public static final void copyImageFile(String dest, String source) { //... }
ইনটেন্টের ক্ষেত্রে অনুমতির জন্য, স্ট্রিং ফিল্ডে অনুমতির প্রয়োজনীয়তা উল্লেখ করুন যা ইনটেন্ট অ্যাকশনের নাম সংজ্ঞায়িত করে:
Kotlin
@RequiresPermission(android.Manifest.permission.BLUETOOTH) const val ACTION_REQUEST_DISCOVERABLE = "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE"
জাভা
@RequiresPermission(android.Manifest.permission.BLUETOOTH) public static final String ACTION_REQUEST_DISCOVERABLE = "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
কন্টেন্ট প্রোভাইডারের ক্ষেত্রে অনুমতি দেওয়ার জন্য, যেগুলির রিড ও রাইট অ্যাক্সেসের জন্য আলাদা আলাদা অনুমতি প্রয়োজন,
সেগুলির ক্ষেত্রে প্রতিটি অনুমতির প্রয়োজনীয়তা @RequiresPermission.Read
বা @RequiresPermission.Write
অ্যানোটেশনে র্যাপ করুন:
Kotlin
@RequiresPermission.Read(RequiresPermission(READ_HISTORY_BOOKMARKS)) @RequiresPermission.Write(RequiresPermission(WRITE_HISTORY_BOOKMARKS)) val BOOKMARKS_URI = Uri.parse("content://browser/bookmarks")
জাভা
@RequiresPermission.Read(@RequiresPermission(READ_HISTORY_BOOKMARKS)) @RequiresPermission.Write(@RequiresPermission(WRITE_HISTORY_BOOKMARKS)) public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks");
পরোক্ষ অনুমতি
কোনও মেথডের প্যারামিটারে দেওয়া নির্দিষ্ট ভ্যালুর উপর অনুমতি নির্ভর করলে, নির্দিষ্ট অনুমতি তালিকাভুক্ত না করে
@RequiresPermission প্যারামিটারেই ব্যবহার করুন।
যেমন, startActivity(Intent)
পদ্ধতিটি পদ্ধতিতে পাস করা ইনটেন্টের উপর একটি পরোক্ষ অনুমতি ব্যবহার করে:
Kotlin
abstract fun startActivity(@RequiresPermission intent: Intent, bundle: Bundle?)
জাভা
public abstract void startActivity(@RequiresPermission Intent intent, @Nullable Bundle)
আপনি পরোক্ষ অনুমতি ব্যবহার করলে, বিল্ড টুল ডেটা ফ্লো বিশ্লেষণ করে দেখে যে পদ্ধতিতে পাস করা আর্গুমেন্টে কোনও @RequiresPermission অ্যানোটেশন আছে কিনা। তারপর তারা
পদ্ধতিতেই প্যারামিটার থেকে আগে থেকে থাকা যেকোনও অ্যানোটেশন এনফোর্স করে। startActivity(Intent) উদাহরণে, Intent ক্লাসে অ্যানোটেশন, startActivity(Intent)-এর ভুল ব্যবহারের ফলে সতর্কতা দেখায়,
যখন উপযুক্ত অনুমতি ছাড়া কোনও ইনটেন্ট পদ্ধতিতে পাস করা হয়,
যেমনটি চিত্র ১-এ দেখানো হয়েছে।
ছবি ১. startActivity(Intent) পদ্ধতিতে পরোক্ষ অনুমতি অ্যানোটেশন থেকে
সতর্কতা তৈরি হয়েছে।
বিল্ড টুল Intent ক্লাসে সংশ্লিষ্ট ইনটেন্ট অ্যাকশনের নামের অ্যানোটেশন থেকে
startActivity(Intent)-এ সতর্কতা তৈরি করে:
Kotlin
@RequiresPermission(Manifest.permission.CALL_PHONE) const val ACTION_CALL = "android.intent.action.CALL"
জাভা
@RequiresPermission(Manifest.permission.CALL_PHONE) public static final String ACTION_CALL = "android.intent.action.CALL";
প্রয়োজন হলে, কোনও পদ্ধতির প্যারামিটার অ্যানোটেট করার সময় আপনি @RequiresPermission-এর পরিবর্তে
@RequiresPermission.Read বা @RequiresPermission.Write ব্যবহার করতে পারেন। তবে, পরোক্ষ অনুমতির জন্য @RequiresPermission-কে
রিড বা রাইট অনুমতির অ্যানোটেশনের সাথে ব্যবহার করা উচিত নয়।
রিটার্ন ভ্যালু অ্যানোটেশন
কোনও পদ্ধতির ফলাফল বা রিটার্ন ভ্যালু আসলে ব্যবহার করা হয়েছে কিনা তা যাচাই করতে
@CheckResult অ্যানোটেশন ব্যবহার করুন। প্রতিটি নন-ভয়েড পদ্ধতি @CheckResult দিয়ে অ্যানোটেট করার পরিবর্তে, সম্ভাব্য বিভ্রান্তিকর পদ্ধতির ফলাফল স্পষ্ট করতে অ্যানোটেশন যোগ করুন।
যেমন, নতুন Java ডেভেলপাররা প্রায়শই ভুল করে ভাবেন যে
<String>.trim() আসল স্ট্রিং থেকে হোয়াইটস্পেস সরিয়ে দেয়। @CheckResult-এর সাথে
পদ্ধতিটি অ্যানোটেট করা হলে <String>.trim()-এর ব্যবহার ফ্ল্যাগ করে
যেখানে কলার পদ্ধতির রিটার্ন ভ্যালু নিয়ে কিছু করে না।
নিম্নলিখিত উদাহরণটি checkPermissions()
পদ্ধতিকে অ্যানোটেট করে যাতে পদ্ধতির রিটার্ন ভ্যালু
আসলে রেফারেন্স করা হয়েছে কিনা তা চেক করা যায়। এছাড়াও, এটি enforcePermission()
পদ্ধতিকে এমন একটি পদ্ধতি হিসেবে উল্লেখ করে যা ডেভেলপারকে বিকল্প হিসেবে সাজেস্ট করা যেতে পারে:
Kotlin
@CheckResult(suggest = "#enforcePermission(String,int,int,String)") abstract fun checkPermission(permission: String, pid: Int, uid: Int): Int
জাভা
@CheckResult(suggest="#enforcePermission(String,int,int,String)") public abstract int checkPermission(@NonNull String permission, int pid, int uid);
CallSuper অ্যানোটেশন
ওভাররাইডিং মেথড যাতে মেথডের সুপার ইমপ্লিমেন্টেশনকে কল করে তা যাচাই করতে
@CallSuper অ্যানোটেশন ব্যবহার করুন।
নিম্নলিখিত
উদাহরণটি onCreate() পদ্ধতিকে অ্যানোটেট করে যাতে নিশ্চিত করা যায় যে যেকোনও ওভাররাইডিং পদ্ধতি
বাস্তবায়ন super.onCreate()-কে কল করে:
Kotlin
@CallSuper override fun onCreate(savedInstanceState: Bundle?) { }
জাভা
@CallSuper protected void onCreate(Bundle savedInstanceState) { }
Typedef অ্যানোটেশন
Typedef অ্যানোটেশন চেক করে যে কোনও নির্দিষ্ট প্যারামিটার, রিটার্ন ভ্যালু বা ফিল্ড কোনও নির্দিষ্ট সেট অফ কনস্ট্যান্টকে রেফার করে কিনা। এছাড়াও, এগুলি কোড সম্পূর্ণ করার সুবিধা চালু করে যাতে অনুমোদিত কনস্ট্যান্ট অটোমেটিক অফার করা যায়।
অন্যান্য ধরনের কোড রেফারেন্স যাচাই করতে, পূর্ণসংখ্যা এবং স্ট্রিং সেটের সংখ্যাযুক্ত অ্যানোটেশন তৈরি করতে @IntDef এবং
@StringDef
অ্যানোটেশন ব্যবহার করুন।
Typedef অ্যানোটেশন নতুন গণনা করা অ্যানোটেশনের ধরন ঘোষণা করতে @interface ব্যবহার করে।
@IntDef এবং @StringDef অ্যানোটেশন, @Retention-এর সাথে, নতুন অ্যানোটেশনকে অ্যানোটেট করে এবং এনিউমেরেটেড টাইপকে সংজ্ঞায়িত করার জন্য প্রয়োজনীয়। @Retention(RetentionPolicy.SOURCE) অ্যানোটেশন কম্পাইলারকে বলে
.class ফাইলে এনিউমেরেটেড অ্যানোটেশন ডেটা স্টোর না করতে।
নিম্নলিখিত উদাহরণে দেখানো হয়েছে যে কীভাবে একটি অ্যানোটেশন তৈরি করতে হয় যা চেক করে যে মেথড প্যারামিটার হিসেবে পাস করা ভ্যালু নির্দিষ্ট করা কনস্ট্যান্টের মধ্যে কোনও একটিকে রেফারেন্স করে কিনা:
Kotlin
import androidx.annotation.IntDef //... // Define the list of accepted constants and declare the NavigationMode annotation. @Retention(AnnotationRetention.SOURCE) @IntDef(NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS) annotation class NavigationMode // Declare the constants. const val NAVIGATION_MODE_STANDARD = 0 const val NAVIGATION_MODE_LIST = 1 const val NAVIGATION_MODE_TABS = 2 abstract class ActionBar { // Decorate the target methods with the annotation. // Attach the annotation. @get:NavigationMode @setparam:NavigationMode abstract var navigationMode: Int }
জাভা
import androidx.annotation.IntDef; //... public abstract class ActionBar { //... // Define the list of accepted constants and declare the NavigationMode annotation. @Retention(RetentionPolicy.SOURCE) @IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS}) public @interface NavigationMode {} // Declare the constants. public static final int NAVIGATION_MODE_STANDARD = 0; public static final int NAVIGATION_MODE_LIST = 1; public static final int NAVIGATION_MODE_TABS = 2; // Decorate the target methods with the annotation. @NavigationMode public abstract int getNavigationMode(); // Attach the annotation. public abstract void setNavigationMode(@NavigationMode int mode); }
আপনি এই কোড তৈরি করার সময়, mode প্যারামিটার যদি নির্দিষ্ট করা ধ্রুবকগুলির (NAVIGATION_MODE_STANDARD,
NAVIGATION_MODE_LIST, বা NAVIGATION_MODE_TABS) কোনও একটিকে রেফার না করে, তাহলে একটি সতর্কতা জেনারেট করা হয়।
@IntDef এবং @IntRange একত্রিত করে দেখান যে একটি
ইন্টিজার হয় প্রদত্ত ধ্রুবকের সেট অথবা একটি রেঞ্জের মধ্যে থাকা ভ্যালু হতে পারে।
ফ্ল্যাগের সাথে কনস্ট্যান্ট একত্রিত করার সুবিধা চালু করুন
ব্যবহারকারীরা যদি অনুমোদিত কনস্ট্যান্টকে কোনও ফ্ল্যাগের (যেমন |,
&, ^ ইত্যাদি) সাথে একত্রিত করতে পারেন, তাহলে কোনও প্যারামিটার বা রিটার্ন ভ্যালু সঠিক প্যাটার্নকে রেফারেন্স করছে কিনা তা চেক করার জন্য আপনি flag অ্যাট্রিবিউট সহ একটি অ্যানোটেশন সংজ্ঞায়িত করতে পারেন।
নিম্নলিখিত উদাহরণটি সঠিক DISPLAY_ কনস্ট্যান্টের তালিকা সহ
DisplayOptions অ্যানোটেশন তৈরি করে:
Kotlin
import androidx.annotation.IntDef ... @IntDef(flag = true, value = [ DISPLAY_USE_LOGO, DISPLAY_SHOW_HOME, DISPLAY_HOME_AS_UP, DISPLAY_SHOW_TITLE, DISPLAY_SHOW_CUSTOM ]) @Retention(AnnotationRetention.SOURCE) annotation class DisplayOptions ...
জাভা
import androidx.annotation.IntDef; ... @IntDef(flag=true, value={ DISPLAY_USE_LOGO, DISPLAY_SHOW_HOME, DISPLAY_HOME_AS_UP, DISPLAY_SHOW_TITLE, DISPLAY_SHOW_CUSTOM }) @Retention(RetentionPolicy.SOURCE) public @interface DisplayOptions {} ...
আপনি যখন অ্যানোটেশন ফ্ল্যাগ সহ কোড তৈরি করেন, তখন ডেকোরেটেড প্যারামিটার বা রিটার্ন ভ্যালু কোনও সঠিক প্যাটার্ন রেফারেন্স না করলে, একটি সতর্কতা তৈরি হয়।
অ্যানোটেশন রাখুন
@Keep
অ্যানোটেশন নিশ্চিত করে যে বিল্ড টাইমে কোড ছোট করার সময় অ্যানোটেট করা ক্লাস বা পদ্ধতি
সরানো হবে না। এই অ্যানোটেশন সাধারণত
মেথড ও ক্লাসে যোগ করা হয় যা রিফ্লেকশনের মাধ্যমে অ্যাক্সেস করা হয় যাতে কম্পাইলার
কোডটিকে অব্যবহৃত হিসেবে বিবেচনা না করে।
সতর্কতা: আপনি @Keep ব্যবহার করে যেসব ক্লাস ও পদ্ধতি অ্যানোটেট করেন,
সেগুলি সবসময় আপনার অ্যাপের APK-তে দেখা যায়, এমনকি আপনি যদি কখনও
আপনার অ্যাপের লজিকে এইসব ক্লাস ও পদ্ধতি রেফারেন্স না করেন, তাহলেও।
আপনার অ্যাপের সাইজ ছোট রাখতে, আপনার অ্যাপে প্রতিটি @Keep অ্যানোটেশন
সংরক্ষণ করা প্রয়োজন কিনা তা বিবেচনা করুন। আপনি যদি কোনও অ্যানোটেটেড ক্লাস বা পদ্ধতি অ্যাক্সেস করতে
রিফ্লেকশন ব্যবহার করেন, তাহলে আপনার ProGuard নিয়মে একটি
-if শর্ত ব্যবহার করুন, যা রিফ্লেকশন কল করে এমন ক্লাস নির্দিষ্ট করে।
আপনার কোড কীভাবে ছোট করবেন এবং কোন কোড সরানো যাবে না তা নির্দিষ্ট করবেন সেই সম্পর্কে আরও তথ্যের জন্য, আপনার অ্যাপ সঙ্কুচিত, অস্পষ্ট এবং অপ্টিমাইজ করুন দেখুন।
কোড দৃশ্যমানতা অ্যানোটেশন
মেথড, ক্লাস, ফিল্ড বা প্যাকেজের মতো কোডের নির্দিষ্ট অংশের দৃশ্যমানতা বোঝাতে নিম্নলিখিত অ্যানোটেশন ব্যবহার করুন।
টেস্টিংয়ের জন্য কোড দৃশ্যমান করুন
@VisibleForTesting
অ্যানোটেশন থেকে বোঝা যায় যে অ্যানোটেট করা পদ্ধতিটি সাধারণত প্রয়োজনীয়তার চেয়ে বেশি দৃশ্যমান যাতে পদ্ধতিটি
পরীক্ষা করা যায়। এই অ্যানোটেশনে একটি ঐচ্ছিক otherwise আর্গুমেন্ট আছে যা আপনাকে
পরীক্ষার জন্য দৃশ্যমান করার প্রয়োজন না হলে পদ্ধতির দৃশ্যমানতা কী হবে তা নির্ধারণ করতে
দেয়। Lint, otherwise আর্গুমেন্ট ব্যবহার করে কাঙ্খিত দৃশ্যমানতা এনফোর্স করে।
নিচের উদাহরণে, myMethod() সাধারণত private, কিন্তু এটি
পরীক্ষার জন্য package-private। VisibleForTesting.PRIVATE
ডেজিগনেশনের সাথে, এই পদ্ধতিটি private অ্যাক্সেসের মাধ্যমে অনুমোদিত প্রসঙ্গের বাইরে থেকে কল করা হলে,
যেমন একটি ভিন্ন কম্পাইলেশন ইউনিট থেকে, লিন্ট একটি মেসেজ দেখায়।
Kotlin
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) fun myMethod() { ... }
জাভা
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) void myMethod() { ... }
এছাড়াও, আপনি @VisibleForTesting(otherwise = VisibleForTesting.NONE)
উল্লেখ করে জানাতে পারেন যে কোনও পদ্ধতি শুধুমাত্র পরীক্ষার জন্য উপলভ্য। এই ফর্মটি
@RestrictTo(TESTS) ব্যবহার করার মতোই। দুটিই একই লিন্ট চেক করে।
API-তে বিধিনিষেধ আরোপ করা
@RestrictTo
অ্যানোটেশন থেকে বোঝা যায় যে অ্যানোটেট করা API (প্যাকেজ, ক্লাস বা পদ্ধতি) অ্যাক্সেস করার সুবিধা সীমিত,
যেমন:
সাবক্লাস
শুধু সাবক্লাসে API অ্যাক্সেস সীমাবদ্ধ করতে
অ্যানোটেশন ফর্ম @RestrictTo(RestrictTo.Scope.SUBCLASSES) ব্যবহার করুন।
শুধুমাত্র যেসব ক্লাস অ্যানোটেট করা ক্লাসকে এক্সটেন্ড করে, সেগুলিই এই API অ্যাক্সেস করতে পারে। Java
protected মডিফায়ার যথেষ্ট সীমাবদ্ধ নয়, কারণ এটি একই প্যাকেজের মধ্যে
অসম্পর্কিত ক্লাস থেকে অ্যাক্সেসের অনুমতি দেয়। এছাড়াও, এমন কিছু পরিস্থিতি আছে যেখানে আপনি ভবিষ্যতে নমনীয়তার জন্য একটি
মেথড public ছেড়ে দিতে চান, কারণ আপনি কখনই আগে থেকে
protected এবং ওভাররাইড করা মেথড public তৈরি করতে পারবেন না, তবে আপনি একটি
ইঙ্গিত দিতে চান যে ক্লাসটি শুধুমাত্র ক্লাসের মধ্যে বা সাবক্লাস থেকে ব্যবহারের জন্য তৈরি করা হয়েছে।
লাইব্রেরি
শুধু আপনার লাইব্রেরিতে API অ্যাক্সেস সীমাবদ্ধ করতে
অ্যানোটেশন ফর্ম @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) ব্যবহার করুন।
শুধুমাত্র আপনার লাইব্রেরি কোড অ্যানোটেট করা API অ্যাক্সেস করতে পারবে। এটি আপনাকে শুধু আপনার কোডকে আপনার পছন্দমতো প্যাকেজ হায়ারার্কিতে
সাজাতে দেয় না, বরং সম্পর্কিত লাইব্রেরির একটি গ্রুপের মধ্যে
কোড শেয়ার করতেও দেয়। এই বিকল্পটি Jetpack লাইব্রেরিতে আগে থেকেই উপলভ্য আছে,
যেখানে অনেক ইমপ্লিমেন্টেশন কোড আছে যা এক্সটার্নাল ব্যবহারের জন্য নয়, তবে
বিভিন্ন পরিপূরক Jetpack লাইব্রেরিতে শেয়ার করার জন্য এটি public হতে হবে।
পরীক্ষা করা
অন্যান্য ডেভেলপারদের আপনার টেস্টিং API অ্যাক্সেস করা থেকে আটকাতে
অ্যানোটেশন ফর্ম @RestrictTo(RestrictTo.Scope.TESTS) ব্যবহার করুন।
শুধুমাত্র টেস্টিং কোড অ্যানোটেট করা API অ্যাক্সেস করতে পারে। এটি অন্যান্য ডেভেলপারদের ডেভেলপমেন্টের জন্য API ব্যবহার করা থেকে বিরত রাখে যা আপনি শুধুমাত্র পরীক্ষার উদ্দেশ্যে ব্যবহার করতে চান।