লিন্ট (lint )-এর মতো কোড ইন্সপেকশন টুল ব্যবহার করে আপনি সমস্যা খুঁজে বের করতে এবং আপনার কোড উন্নত করতে পারেন, কিন্তু ইন্সপেকশন টুলগুলোর একটি সীমাবদ্ধতা আছে। উদাহরণস্বরূপ, অ্যান্ড্রয়েড রিসোর্স আইডি স্ট্রিং, গ্রাফিক্স, রঙ এবং অন্যান্য রিসোর্স টাইপ শনাক্ত করতে একটি int ব্যবহার করে, তাই যেখানে রঙের পরিবর্তে আপনি একটি স্ট্রিং রিসোর্স উল্লেখ করেছেন, তা ইন্সপেকশন টুলগুলো বুঝতে পারে না। এই পরিস্থিতির কারণে, কোড ইন্সপেকশন ব্যবহার করা সত্ত্বেও আপনার অ্যাপটি ভুলভাবে রেন্ডার হতে পারে বা একেবারেই চলতে ব্যর্থ হতে পারে।
অ্যানোটেশন আপনাকে লিন্ট-এর মতো কোড ইন্সপেকশন টুলগুলিতে ইঙ্গিত দেওয়ার সুযোগ দেয়, যা কোডের সূক্ষ্ম সমস্যাগুলো শনাক্ত করতে সাহায্য করে। অ্যানোটেশন মেটাডেটা ট্যাগ হিসেবে যুক্ত করা হয়, যা আপনি ভেরিয়েবল, প্যারামিটার এবং রিটার্ন ভ্যালুর সাথে জুড়ে দিয়ে মেথডের রিটার্ন ভ্যালু, পাস করা প্যারামিটার, লোকাল ভেরিয়েবল এবং ফিল্ড পরীক্ষা করতে পারেন। কোড ইন্সপেকশন টুলের সাথে ব্যবহার করা হলে, অ্যানোটেশন আপনাকে নাল পয়েন্টার এক্সেপশন এবং রিসোর্স টাইপ কনফ্লিক্টের মতো সমস্যা শনাক্ত করতে সাহায্য করতে পারে।
অ্যান্ড্রয়েড জেটপ্যাক অ্যানোটেশনস লাইব্রেরির মাধ্যমে বিভিন্ন ধরনের অ্যানোটেশন সমর্থন করে। আপনি androidx.annotation প্যাকেজের মাধ্যমে এই লাইব্রেরিটি ব্যবহার করতে পারেন।
দ্রষ্টব্য: যদি কোনো মডিউলের কোনো অ্যানোটেশন প্রসেসরের উপর নির্ভরতা থাকে, তবে সেই নির্ভরতাটি যোগ করার জন্য আপনাকে অবশ্যই কোটলিনের জন্য kapt বা ksp নির্ভরতা কনফিগারেশন অথবা জাভার জন্য annotationProcessor নির্ভরতা কনফিগারেশন ব্যবহার করতে হবে।
আপনার প্রকল্পে টীকা যোগ করুন
আপনার প্রোজেক্টে অ্যানোটেশন সক্রিয় করতে, আপনার লাইব্রেরি বা অ্যাপে androidx.annotation:annotation ডিপেন্ডেন্সিটি যোগ করুন। আপনি যখন কোড ইন্সপেকশন বা lint টাস্ক চালান, তখন আপনার যোগ করা যেকোনো অ্যানোটেশন যাচাই করা হয়।
Jetpack Annotations লাইব্রেরির নির্ভরতা যোগ করুন
Jetpack Annotations লাইব্রেরিটি Google-এর Maven Repository- তে প্রকাশিত হয়েছে। আপনার প্রজেক্টে Jetpack Anotations লাইব্রেরিটি যোগ করতে, আপনার build.gradle অথবা build.gradle.kts ফাইলের dependencies ব্লকে নিম্নলিখিত লাইনটি অন্তর্ভুক্ত করুন:
কোটলিন
dependencies { implementation("androidx.annotation:annotation:1.10.0") }
গ্রুভি
dependencies { implementation 'androidx.annotation:annotation:1.10.0' }
আপনি যদি আপনার নিজস্ব লাইব্রেরি মডিউলে অ্যানোটেশন ব্যবহার করেন, তাহলে অ্যানোটেশনগুলো অ্যান্ড্রয়েড আর্কাইভ (AAR) আর্টিফ্যাক্টের অংশ হিসেবে annotations.zip ফাইলে XML ফরম্যাটে অন্তর্ভুক্ত থাকে। androidx.annotation ডিপেন্ডেন্সি যোগ করলে আপনার লাইব্রেরির পরবর্তী ব্যবহারকারীদের জন্য কোনো নতুন ডিপেন্ডেন্সি তৈরি হয় না।
দ্রষ্টব্য: আপনি যদি অন্যান্য Jetpack লাইব্রেরি ব্যবহার করেন, তাহলে আপনার androidx.annotation ডিপেন্ডেন্সিটি যোগ করার প্রয়োজন নাও হতে পারে। যেহেতু অন্যান্য অনেক Jetpack লাইব্রেরি Annotations লাইব্রেরির উপর নির্ভরশীল, তাই আপনার কাছে হয়তো ইতিমধ্যেই অ্যানোটেশনগুলো ব্যবহারের সুযোগ রয়েছে।
জেটপ্যাক রিপোজিটরিতে অন্তর্ভুক্ত অ্যানোটেশনগুলির সম্পূর্ণ তালিকার জন্য, হয় জেটপ্যাক অ্যানোটেশনস লাইব্রেরি রেফারেন্স দেখুন অথবা import androidx.annotation. স্টেটমেন্টের জন্য উপলব্ধ অপশনগুলি দেখতে অটোকমপ্লিট ফিচারটি ব্যবহার করুন।
কোড পরিদর্শন চালান
অ্যান্ড্রয়েড স্টুডিও থেকে কোড পরিদর্শন শুরু করতে, যার মধ্যে অ্যানোটেশন যাচাইকরণ এবং স্বয়ংক্রিয় লিন্ট চেকিং অন্তর্ভুক্ত, মেনু থেকে Analyze > Inspect Code নির্বাচন করুন। আপনার কোড যেখানে অ্যানোটেশনের সাথে সাংঘর্ষিক হয়, সেখানে সম্ভাব্য সমস্যা চিহ্নিত করতে এবং সম্ভাব্য সমাধানের পরামর্শ দিতে অ্যান্ড্রয়েড স্টুডিও কনফ্লিক্ট মেসেজ প্রদর্শন করে।
আপনি কমান্ড লাইন ব্যবহার করে lint টাস্ক চালানোর মাধ্যমেও অ্যানোটেশন প্রয়োগ করতে পারেন। যদিও এটি একটি কন্টিনিউয়াস ইন্টিগ্রেশন সার্ভারের সমস্যা চিহ্নিত করার জন্য উপযোগী হতে পারে, lint টাস্ক নালনেস অ্যানোটেশন (যা পরবর্তী বিভাগে বর্ণনা করা হয়েছে) প্রয়োগ করে না; শুধুমাত্র অ্যান্ড্রয়েড স্টুডিওই এটি করে থাকে। লিন্ট ইন্সপেকশন সক্রিয় করা এবং চালানোর বিষয়ে আরও তথ্যের জন্য, "লিন্ট চেকের মাধ্যমে আপনার কোডের উন্নতি" দেখুন।
যদিও অ্যানোটেশন দ্বন্দ্বের কারণে সতর্কবার্তা তৈরি হয়, এই সতর্কবার্তাগুলো আপনার অ্যাপ কম্পাইল হতে বাধা দেয় না।
শূন্যতা টীকা
জাভা কোডে ভ্যালু নাল হতে পারবে কিনা তা নিশ্চিত করতে নালনেস অ্যানোটেশন কার্যকর হতে পারে। কোটলিন কোডে এগুলোর উপযোগিতা কম, কারণ কোটলিনে বিল্ট-ইন নালিবিলিটি নিয়ম রয়েছে যা কম্পাইল টাইমে প্রয়োগ করা হয়। কোনো প্রদত্ত ভেরিয়েবল, প্যারামিটার বা রিটার্ন ভ্যালুর নাল (null) হওয়া যাচাই করতে @Nullable এবং @NonNull অ্যানোটেশন যোগ করুন। @Nullable অ্যানোটেশনটি এমন একটি ভেরিয়েবল, প্যারামিটার বা রিটার্ন ভ্যালুকে নির্দেশ করে যা নাল (null) হতে পারে। @NonNull এমন একটি ভেরিয়েবল, প্যারামিটার বা রিটার্ন ভ্যালুকে নির্দেশ করে যা নাল (null) হতে পারে না।
উদাহরণস্বরূপ, যদি @NonNull অ্যানোটেশনযুক্ত কোনো মেথডের প্যারামিটার হিসেবে null ভ্যালু ধারণকারী একটি লোকাল ভেরিয়েবল পাস করা হয়, তাহলে কোডটি বিল্ড করার সময় একটি নন-নাল কনফ্লিক্ট নির্দেশক ওয়ার্নিং তৈরি হয়। এছাড়াও, @Nullable দ্বারা চিহ্নিত কোনো মেথডের ফলাফল null কিনা তা প্রথমে পরীক্ষা না করে রেফারেন্স করার চেষ্টা করলে একটি নালনেস ওয়ার্নিং তৈরি হয়। কোনো মেথডের রিটার্ন ভ্যালুতে শুধুমাত্র তখনই @Nullable ব্যবহার করুন, যখন মেথডটির প্রতিটি ব্যবহার অবশ্যই সুস্পষ্টভাবে null-চেক করতে হবে।
নিম্নলিখিত উদাহরণটি নালিবিলিটির কার্যকারিতা প্রদর্শন করে। কোটলিন উদাহরণ কোডটি @NonNull অ্যানোটেশন ব্যবহার করে না, কারণ যখন একটি নন-নালেবল টাইপ নির্দিষ্ট করা হয়, তখন এটি স্বয়ংক্রিয়ভাবে জেনারেটেড বাইটকোডে যুক্ত হয়ে যায়। জাভা উদাহরণটি context এবং attrs প্যারামিটারগুলিতে @NonNull অ্যানোটেশন ব্যবহার করে পরীক্ষা করে যে পাস করা প্যারামিটার মানগুলি নাল নয়। এটি আরও পরীক্ষা করে যে onCreateView() মেথডটি নিজে নাল রিটার্ন করে না:
কোটলিন
... /** 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) { ... } ...
নালযোগ্যতা বিশ্লেষণ
অ্যান্ড্রয়েড স্টুডিও আপনার কোডে স্বয়ংক্রিয়ভাবে নালনেস অ্যানোটেশন অনুমান ও সন্নিবেশ করার জন্য নালিবিলিটি অ্যানালাইসিস চালানো সমর্থন করে। একটি নালিবিলিটি অ্যানালাইসিস আপনার কোডের মেথড হায়ারার্কি জুড়ে থাকা কন্ট্রাক্টগুলো স্ক্যান করে নিম্নলিখিত বিষয়গুলো শনাক্ত করে:
- এমন মেথড কল করা যা null রিটার্ন করতে পারে।
- যে মেথডগুলো null রিটার্ন করবে না।
- ফিল্ড, লোকাল ভেরিয়েবল এবং প্যারামিটারের মতো ভেরিয়েবলগুলো নাল (null) হতে পারে।
- ফিল্ড, লোকাল ভেরিয়েবল এবং প্যারামিটারের মতো ভেরিয়েবলগুলো নাল ভ্যালু ধারণ করতে পারে না।
এরপর বিশ্লেষণটি স্বয়ংক্রিয়ভাবে শনাক্তকৃত স্থানগুলিতে উপযুক্ত নাল অ্যানোটেশন সন্নিবেশ করে।
অ্যান্ড্রয়েড স্টুডিওতে নালিবিলিটি অ্যানালাইসিস (nullability analysis) চালানোর জন্য, Analyze > Infer Nullity নির্বাচন করুন। অ্যান্ড্রয়েড স্টুডিও আপনার কোডের শনাক্তকৃত স্থানগুলিতে অ্যান্ড্রয়েডের @Nullable এবং @NonNull অ্যানোটেশনগুলি যুক্ত করে। নাল অ্যানালাইসিস চালানোর পরে, যুক্ত হওয়া অ্যানোটেশনগুলি যাচাই করে নেওয়া একটি ভালো অভ্যাস।
দ্রষ্টব্য: নালনেস অ্যানোটেশন যোগ করার সময়, অটোকমপ্লিট অ্যান্ড্রয়েড নাল অ্যানোটেশনের পরিবর্তে ইন্টেলিজের @Nullable এবং @NotNull অ্যানোটেশন সাজেস্ট করতে পারে এবং সংশ্লিষ্ট লাইব্রেরি অটো-ইম্পোর্ট করতে পারে। তবে, অ্যান্ড্রয়েড স্টুডিও লিন্ট চেকার শুধুমাত্র অ্যান্ড্রয়েড নাল অ্যানোটেশনগুলোই খুঁজে থাকে। আপনার অ্যানোটেশনগুলো যাচাই করার সময়, নিশ্চিত করুন যে আপনার প্রজেক্টে অ্যান্ড্রয়েড নাল অ্যানোটেশন ব্যবহার করা হয়েছে, যাতে কোড পরিদর্শনের সময় লিন্ট চেকার আপনাকে সঠিকভাবে জানাতে পারে।
সম্পদ টীকা
রিসোর্সের ধরন যাচাই করা উপকারী হতে পারে, কারণ অ্যান্ড্রয়েডে ড্রয়েবল এবং স্ট্রিং রিসোর্সের মতো রিসোর্সগুলোর রেফারেন্স পূর্ণসংখ্যা হিসেবে পাস করা হয়।
যে কোডে প্যারামিটার হিসেবে String মতো কোনো নির্দিষ্ট ধরনের রিসোর্সকে রেফারেন্স করার কথা থাকে, সেটিকে int এর মতো প্রত্যাশিত রেফারেন্স টাইপে পাস করা হলেও, তা আসলে R.string মতো ভিন্ন ধরনের কোনো রিসোর্সকে রেফারেন্স করতে পারে।
উদাহরণস্বরূপ, কোনো রিসোর্স প্যারামিটারে R.string রেফারেন্স আছে কিনা তা পরীক্ষা করতে @StringRes অ্যানোটেশন যোগ করুন, যেমনটি এখানে দেখানো হয়েছে:
কোটলিন
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 প্যারামিটারটিতে অবশ্যই ০ থেকে ২৫৫-এর মধ্যে একটি ইন্টিজার মান থাকতে হবে:
কোটলিন
fun setAlpha(@IntRange(from = 0, to = 255) alpha: Int) { ... }
জাভা
public void setAlpha(@IntRange(from=0,to=255) int alpha) { ... }
@FloatRange অ্যানোটেশনটি পরীক্ষা করে দেখে যে, কোনো float বা double প্যারামিটারের মান ফ্লোটিং পয়েন্ট মানের একটি নির্দিষ্ট পরিসরের মধ্যে আছে কি না। নিচের উদাহরণটি নির্দেশ করে যে, alpha প্যারামিটারটির মান অবশ্যই 0.0 থেকে 1.0-এর মধ্যে একটি float হতে হবে:
কোটলিন
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 অ্যারেতে অবশ্যই অন্তত একটি উপাদান থাকতে হবে:
কোটলিন
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 পারমিশনটি থাকতে হবে:
কোটলিন
@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() মেথডের কলারের এক্সটার্নাল স্টোরেজে রিড অ্যাক্সেস এবং কপি করা ইমেজের লোকেশন মেটাডেটা উভয়টিতেই রিড অ্যাক্সেস থাকা প্রয়োজন:
কোটলিন
@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) { //... }
ইনটেন্টের অনুমতির জন্য, ইনটেন্ট অ্যাকশনের নাম নির্ধারণকারী স্ট্রিং ফিল্ডে অনুমতির প্রয়োজনীয়তাটি রাখুন:
কোটলিন
@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 অ্যানোটেশনের মধ্যে রাখুন:
কোটলিন
@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) মেথডটি, মেথডে পাস করা ইন্টেন্টের উপর একটি ইনডিরেক্ট পারমিশন ব্যবহার করে:
কোটলিন
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) ইভেন্টে ওয়ার্নিংটি তৈরি করে:
কোটলিন
@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.Read বা @RequiresPermission.Write এর পরিবর্তে @RequiresPermission ব্যবহার করতে পারেন। তবে, পরোক্ষ অনুমতির ক্ষেত্রে @RequiresPermission অ্যানোটেশনটি read বা write অনুমতির অ্যানোটেশনের সাথে একত্রে ব্যবহার করা উচিত নয়।
রিটার্ন মান টীকা
কোনো মেথডের ফলাফল বা রিটার্ন ভ্যালু আসলেই ব্যবহৃত হচ্ছে কিনা, তা যাচাই করতে @CheckResult অ্যানোটেশনটি ব্যবহার করুন। প্রতিটি নন-ভয়েড মেথডকে @CheckResult দিয়ে অ্যানোটেট করার পরিবর্তে, সম্ভাব্য বিভ্রান্তিকর মেথডগুলোর ফলাফল স্পষ্ট করার জন্য এই অ্যানোটেশনটি যোগ করুন।
উদাহরণস্বরূপ, নতুন জাভা ডেভেলপাররা প্রায়শই ভুল করে মনে করেন যে < String >.trim() মূল স্ট্রিং থেকে হোয়াইটস্পেস (whitespace) সরিয়ে দেয়। @CheckResult দিয়ে মেথডটি অ্যানোটেট করলে < String >.trim() এর সেইসব ব্যবহার চিহ্নিত করা যায়, যেখানে কলার মেথডটির রিটার্ন ভ্যালু নিয়ে কোনো কাজ করে না।
নিম্নলিখিত উদাহরণটি checkPermissions() মেথডের রিটার্ন ভ্যালুটি প্রকৃতপক্ষে রেফারেন্স করা হয়েছে কিনা তা পরীক্ষা করার জন্য মেথডটিকে অ্যানোটেট করে। এটি ডেভেলপারকে প্রতিস্থাপন হিসেবে enforcePermission() মেথডটির নামও প্রস্তাব করে:
কোটলিন
@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 অ্যানোটেশনটি ব্যবহার করুন।
নিম্নলিখিত উদাহরণটি onCreate() মেথডকে অ্যানোটেট করে, যাতে যেকোনো ওভাররাইডিং মেথড ইমপ্লিমেন্টেশন super.onCreate() কল করে:
কোটলিন
@CallSuper override fun onCreate(savedInstanceState: Bundle?) { }
জাভা
@CallSuper protected void onCreate(Bundle savedInstanceState) { }
টাইপডেফ টীকা
Typedef অ্যানোটেশনগুলো যাচাই করে দেখে যে কোনো নির্দিষ্ট প্যারামিটার, রিটার্ন ভ্যালু বা ফিল্ড কোনো নির্দিষ্ট কনস্ট্যান্ট সেটকে রেফারেন্স করে কি না। এছাড়াও, এগুলো কোড কমপ্লিশনকে অনুমোদিত কনস্ট্যান্টগুলো স্বয়ংক্রিয়ভাবে দেখানোর সুযোগ করে দেয়।
অন্যান্য ধরনের কোড রেফারেন্স যাচাই করার জন্য, @IntDef এবং @StringDef অ্যানোটেশন ব্যবহার করে পূর্ণসংখ্যা ও স্ট্রিং সেটের এনুমারেটেড অ্যানোটেশন তৈরি করুন।
Typedef অ্যানোটেশনগুলো নতুন এনুমারেটেড অ্যানোটেশন টাইপ ডিক্লেয়ার করতে @interface ব্যবহার করে। @IntDef এবং @StringDef অ্যানোটেশনগুলো, @Retention সাথে মিলে নতুন অ্যানোটেশনটিকে অ্যানোটেট করে এবং এনুমারেটেড টাইপটি ডিফাইন করার জন্য এগুলো অপরিহার্য। @Retention(RetentionPolicy.SOURCE) অ্যানোটেশনটি কম্পাইলারকে বলে দেয় যেন এনুমারেটেড অ্যানোটেশনের ডেটা .class ফাইলে স্টোর করা না হয়।
নিম্নলিখিত উদাহরণটি এমন একটি অ্যানোটেশন তৈরি করার ধাপগুলি দেখায় যা পরীক্ষা করে দেখে যে, মেথড প্যারামিটার হিসাবে প্রেরিত কোনো মান সংজ্ঞায়িত কনস্ট্যান্টগুলির মধ্যে একটিকে রেফারেন্স করে কিনা:
কোটলিন
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 অ্যানোটেশন তৈরি করে:
কোটলিন
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 access দ্বারা অনুমোদিত প্রেক্ষাপটের বাইরে থেকে, যেমন কোনো ভিন্ন কম্পাইলেশন ইউনিট থেকে, এই মেথডটিকে কল করা হলে lint একটি বার্তা প্রদর্শন করে।
কোটলিন
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) fun myMethod() { ... }
জাভা
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) void myMethod() { ... }
কোনো মেথড যে শুধুমাত্র পরীক্ষার জন্য বিদ্যমান, তা বোঝাতে আপনি @VisibleForTesting(otherwise = VisibleForTesting.NONE) নির্দিষ্ট করে দিতে পারেন। এই পদ্ধতিটি @RestrictTo(TESTS) ব্যবহারের মতোই। উভয়ই একই লিন্ট চেক সম্পাদন করে।
একটি API সীমাবদ্ধ করুন
@RestrictTo অ্যানোটেশনটি নির্দেশ করে যে, অ্যানোটেড API (প্যাকেজ, ক্লাস বা মেথড)-তে অ্যাক্সেস নিম্নরূপভাবে সীমিত:
উপশ্রেণী
শুধুমাত্র সাবক্লাসগুলোর জন্য এপিআই অ্যাক্সেস সীমাবদ্ধ করতে @RestrictTo(RestrictTo.Scope.SUBCLASSES) অ্যানোটেশনটি ব্যবহার করুন।
শুধুমাত্র যে ক্লাসগুলো অ্যানোটেড ক্লাসটিকে এক্সটেন্ড করে, তারাই এই API অ্যাক্সেস করতে পারে। জাভার ' protected মডিফায়ারটি যথেষ্ট সীমাবদ্ধ নয়, কারণ এটি একই প্যাকেজের মধ্যে থাকা সম্পর্কহীন ক্লাসগুলোকেও অ্যাক্সেসের সুযোগ দেয়। এছাড়াও, এমন কিছু ক্ষেত্র আছে যখন আপনি ভবিষ্যতের সুবিধার জন্য একটি মেথডকে public রাখতে চান, কারণ আপনি পূর্বে protected এবং ওভাররাইড করা কোনো মেথডকে কখনোই public করতে পারবেন না, কিন্তু আপনি এই ইঙ্গিত দিতে চান যে ক্লাসটি শুধুমাত্র নিজের ক্লাসের মধ্যে বা সাবক্লাস থেকে ব্যবহারের জন্য উদ্দিষ্ট।
গ্রন্থাগার
শুধুমাত্র আপনার লাইব্রেরিগুলোর জন্য এপিআই অ্যাক্সেস সীমাবদ্ধ করতে @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) অ্যানোটেশনটি ব্যবহার করুন।
শুধুমাত্র আপনার লাইব্রেরি কোডই অ্যানোটেড এপিআই অ্যাক্সেস করতে পারবে। এটি আপনাকে আপনার কোডকে ইচ্ছামতো প্যাকেজ হায়ারার্কিতে সাজানোর সুযোগ দেয় এবং একই সাথে সম্পর্কিত লাইব্রেরিগুলোর একটি গ্রুপের মধ্যে কোড শেয়ার করার সুবিধাও দেয়। এই অপশনটি সেইসব জেটপ্যাক লাইব্রেরির জন্য ইতিমধ্যেই উপলব্ধ, যেগুলোতে এমন অনেক ইমপ্লিমেন্টেশন কোড রয়েছে যা বাহ্যিক ব্যবহারের জন্য নয়, কিন্তু বিভিন্ন পরিপূরক জেটপ্যাক লাইব্রেরির মধ্যে শেয়ার করার জন্য সেটিকে public হতে হয়।
পরীক্ষা
অন্য ডেভেলপারদের আপনার টেস্টিং এপিআই অ্যাক্সেস করা থেকে বিরত রাখতে @RestrictTo(RestrictTo.Scope.TESTS) অ্যানোটেশনটি ব্যবহার করুন।
শুধুমাত্র টেস্টিং কোডই অ্যানোটেড এপিআই অ্যাক্সেস করতে পারে। এর ফলে, আপনি যে এপিআইগুলো শুধুমাত্র টেস্টিংয়ের উদ্দেশ্যে তৈরি করেছেন, সেগুলো অন্য ডেভেলপাররা ডেভেলপমেন্টের কাজে ব্যবহার করতে পারে না।