আপনার অ্যাপ্লিকেশনে নেটওয়ার্ক ক্রিয়াকলাপ সম্পাদন করতে, আপনার ম্যানিফেস্টে নিম্নলিখিত অনুমতিগুলি অন্তর্ভুক্ত করতে হবে:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
নিরাপদ নেটওয়ার্ক যোগাযোগের জন্য সর্বোত্তম অনুশীলন
আপনার অ্যাপে নেটওয়ার্কিং কার্যকারিতা যোগ করার আগে, আপনাকে নিশ্চিত করতে হবে যে নেটওয়ার্কের মাধ্যমে ট্রান্সমিট করার সময় আপনার অ্যাপের মধ্যে থাকা ডেটা এবং তথ্য নিরাপদ থাকে। এটি করার জন্য, এই নেটওয়ার্কিং সুরক্ষার সেরা অনুশীলনগুলি অনুসরণ করুন:
- নেটওয়ার্কের মাধ্যমে আপনার দ্বারা প্রেরিত সংবেদনশীল বা ব্যক্তিগত ব্যবহারকারীর তথ্যের পরিমাণ কমিয়ে আনুন।
- আপনার অ্যাপ থেকে সমস্ত নেটওয়ার্ক ট্র্যাফিক SSL এর মাধ্যমে পাঠান।
- একটি নেটওয়ার্ক সুরক্ষা কনফিগারেশন তৈরি করার কথা বিবেচনা করুন, যা আপনার অ্যাপকে কাস্টম সার্টিফিকেট কর্তৃপক্ষ (CAs) বিশ্বাস করতে দেয় অথবা নিরাপদ যোগাযোগের জন্য এটি বিশ্বাস করে এমন সিস্টেম CAs-এর সেটকে সীমাবদ্ধ করতে দেয়।
নিরাপদ নেটওয়ার্কিং নীতিগুলি কীভাবে প্রয়োগ করবেন সে সম্পর্কে আরও তথ্যের জন্য, নেটওয়ার্কিং সুরক্ষা টিপস দেখুন।
একটি HTTP ক্লায়েন্ট নির্বাচন করুন
বেশিরভাগ নেটওয়ার্ক-সংযুক্ত অ্যাপ ডেটা প্রেরণ এবং গ্রহণের জন্য HTTP ব্যবহার করে। অ্যান্ড্রয়েড প্ল্যাটফর্মে HttpsURLConnection ক্লায়েন্ট অন্তর্ভুক্ত রয়েছে, যা TLS, স্ট্রিমিং আপলোড এবং ডাউনলোড, কনফিগারযোগ্য টাইমআউট, IPv6 এবং সংযোগ পুলিং সমর্থন করে।
নেটওয়ার্কিং কার্যক্রমের জন্য উচ্চ-স্তরের API অফার করে এমন তৃতীয়-পক্ষের লাইব্রেরিগুলিও উপলব্ধ। এগুলি বিভিন্ন সুবিধাজনক বৈশিষ্ট্যগুলিকে সমর্থন করে, যেমন অনুরোধ সংস্থাগুলির সিরিয়ালাইজেশন এবং প্রতিক্রিয়া সংস্থাগুলির ডিসিরিয়ালাইজেশন।
- রেট্রোফিট : স্কয়ার থেকে JVM-এর জন্য একটি টাইপ-সেফ HTTP ক্লায়েন্ট, যা OkHttp-এর উপরে তৈরি। রেট্রোফিট আপনাকে ঘোষণামূলকভাবে একটি ক্লায়েন্ট ইন্টারফেস তৈরি করতে দেয় এবং বেশ কয়েকটি সিরিয়ালাইজেশন লাইব্রেরির জন্য সমর্থন করে।
- Ktor : JetBrains এর একটি HTTP ক্লায়েন্ট, সম্পূর্ণরূপে Kotlin এর জন্য তৈরি এবং coroutine দ্বারা চালিত। Ktor বিভিন্ন ইঞ্জিন, সিরিয়ালাইজার এবং প্ল্যাটফর্ম সমর্থন করে।
DNS কোয়েরিগুলি সমাধান করুন
অ্যান্ড্রয়েড ১০ (এপিআই লেভেল ২৯) এবং উচ্চতর ভার্সন চালিত ডিভাইসগুলিতে ক্লিয়ারটেক্সট লুকআপ এবং ডিএনএস-ওভার-টিএলএস মোড উভয়ের মাধ্যমে বিশেষায়িত ডিএনএস লুকআপের জন্য অন্তর্নির্মিত সমর্থন রয়েছে। DnsResolver এপিআই জেনেরিক, অ্যাসিঙ্ক্রোনাস রেজোলিউশন প্রদান করে, যা আপনাকে SRV , NAPTR এবং অন্যান্য রেকর্ড প্রকারগুলি অনুসন্ধান করতে দেয়। প্রতিক্রিয়া বিশ্লেষণ করার কাজটি অ্যাপের উপর ছেড়ে দেওয়া হয়।
অ্যান্ড্রয়েড ৯ (এপিআই লেভেল ২৮) এবং তার নিচের ভার্সনে চালিত ডিভাইসগুলিতে, প্ল্যাটফর্ম ডিএনএস রেজলভার শুধুমাত্র A এবং AAAA রেকর্ড সমর্থন করে। এটি আপনাকে নামের সাথে যুক্ত আইপি ঠিকানাগুলি দেখতে দেয় তবে অন্য কোনও রেকর্ড ধরণের সমর্থন করে না।
NDK-ভিত্তিক অ্যাপগুলির জন্য, android_res_nsend দেখুন।
একটি সংগ্রহস্থলের সাহায্যে নেটওয়ার্ক ক্রিয়াকলাপগুলিকে অন্তর্ভুক্ত করুন
নেটওয়ার্ক অপারেশন সম্পাদনের প্রক্রিয়া সহজ করতে এবং আপনার অ্যাপের বিভিন্ন অংশে কোডের ডুপ্লিকেশন কমাতে, আপনি রিপোজিটরি ডিজাইন প্যাটার্ন ব্যবহার করতে পারেন। রিপোজিটরি হল এমন একটি ক্লাস যা ডেটা অপারেশন পরিচালনা করে এবং কিছু নির্দিষ্ট ডেটা বা রিসোর্সের উপর একটি পরিষ্কার API বিমূর্ততা প্রদান করে।
আপনি রেট্রোফিট ব্যবহার করে এমন একটি ইন্টারফেস ঘোষণা করতে পারেন যা HTTP পদ্ধতি, URL, আর্গুমেন্ট এবং নেটওয়ার্ক ক্রিয়াকলাপের জন্য প্রতিক্রিয়ার ধরণ নির্দিষ্ট করে, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে:
কোটলিন
interface UserService { @GET("/users/{id}") suspend fun getUser(@Path("id") id: String): User }
জাভা
public interface UserService { @GET("/user/{id}") Call<User> getUserById(@Path("id") String id); }
একটি রিপোজিটরি ক্লাসের মধ্যে, ফাংশনগুলি নেটওয়ার্ক ক্রিয়াকলাপগুলিকে এনক্যাপসুলেট করতে পারে এবং তাদের ফলাফল প্রকাশ করতে পারে। এই এনক্যাপসুলেশন নিশ্চিত করে যে রিপোজিটরি কলকারী উপাদানগুলিকে ডেটা কীভাবে সংরক্ষণ করা হয় তা জানার প্রয়োজন নেই। ডেটা কীভাবে সংরক্ষণ করা হয় তার ভবিষ্যতের যেকোনো পরিবর্তনগুলি রিপোজিটরি ক্লাসেও আলাদা করা হয়। উদাহরণস্বরূপ, আপনার কাছে API এন্ডপয়েন্টগুলিতে আপডেটের মতো একটি দূরবর্তী পরিবর্তন থাকতে পারে, অথবা আপনি স্থানীয় ক্যাশিং বাস্তবায়ন করতে চাইতে পারেন।
কোটলিন
class UserRepository constructor( private val userService: UserService ) { suspend fun getUserById(id: String): User { return userService.getUser(id) } }
জাভা
class UserRepository { private UserService userService; public UserRepository( UserService userService ) { this.userService = userService; } public Call<User> getUserById(String id) { return userService.getUser(id); } }
একটি প্রতিক্রিয়াহীন UI তৈরি এড়াতে, প্রধান থ্রেডে নেটওয়ার্ক অপারেশন করবেন না। ডিফল্টরূপে, Android আপনাকে প্রধান UI থ্রেড ছাড়া অন্য কোনও থ্রেডে নেটওয়ার্ক অপারেশন করতে বাধ্য করে। যদি আপনি প্রধান থ্রেডে নেটওয়ার্ক অপারেশন করার চেষ্টা করেন, তাহলে একটি NetworkOnMainThreadException থ্রো করা হয়।
পূর্ববর্তী কোড উদাহরণে, নেটওয়ার্ক অপারেশনটি আসলে ট্রিগার করা হয় না। UserRepository এর কলারকে অবশ্যই coroutines ব্যবহার করে অথবা enqueue() ফাংশন ব্যবহার করে থ্রেডিং বাস্তবায়ন করতে হবে। আরও তথ্যের জন্য, codelab দেখুন Get data from the internet , যা Kotlin coroutines ব্যবহার করে থ্রেডিং বাস্তবায়নের পদ্ধতি প্রদর্শন করে।
কনফিগারেশন পরিবর্তনগুলি টিকিয়ে রাখুন
যখন কোনও কনফিগারেশন পরিবর্তন ঘটে, যেমন স্ক্রিন রোটেশন, তখন আপনার টুকরো বা কার্যকলাপ ধ্বংস হয়ে যায় এবং পুনরায় তৈরি করা হয়। আপনার টুকরো কার্যকলাপের জন্য ইনস্ট্যান্স অবস্থায় সংরক্ষিত না থাকা যেকোনো ডেটা, যা কেবলমাত্র অল্প পরিমাণে ডেটা ধারণ করতে পারে, হারিয়ে যায়। যদি এটি ঘটে, তাহলে আপনাকে আবার আপনার নেটওয়ার্ক অনুরোধ করতে হতে পারে।
কনফিগারেশন পরিবর্তনের ফলে আপনার ডেটা টিকে থাকতে আপনি একটি ViewModel ব্যবহার করতে পারেন। ViewModel কম্পোনেন্টটি জীবনচক্র-সচেতনভাবে UI-সম্পর্কিত ডেটা সংরক্ষণ এবং পরিচালনা করার জন্য ডিজাইন করা হয়েছে। পূর্ববর্তী UserRepository ব্যবহার করে, ViewModel প্রয়োজনীয় নেটওয়ার্ক অনুরোধ করতে পারে এবং LiveData ব্যবহার করে আপনার খণ্ড বা কার্যকলাপে ফলাফল প্রদান করতে পারে:
কোটলিন
class MainViewModel constructor( savedStateHandle: SavedStateHandle, userRepository: UserRepository ) : ViewModel() { private val userId: String = savedStateHandle["uid"] ?: throw IllegalArgumentException("Missing user ID") private val _user = MutableLiveData<User>() val user = _user as LiveData<User> init { viewModelScope.launch { try { // Calling the repository is safe as it moves execution off // the main thread val user = userRepository.getUserById(userId) _user.value = user } catch (error: Exception) { // Show error message to user } } } }
জাভা
class MainViewModel extends ViewModel { private final MutableLiveData<User> _user = new MutableLiveData<>(); LiveData<User> user = (LiveData<User>) _user; public MainViewModel( SavedStateHandle savedStateHandle, UserRepository userRepository ) { String userId = savedStateHandle.get("uid"); Call<User> userCall = userRepository.getUserById(userId); userCall.enqueue(new Callback<User>() { @Override public void onResponse(Call<User> call, Response<User> response) { if (response.isSuccessful()) { _user.setValue(response.body()); } } @Override public void onFailure(Call<User> call, Throwable t) { // Show error message to user } }); } }
সম্পর্কিত নির্দেশিকা পড়ুন
এই বিষয় সম্পর্কে আরও জানতে, নিম্নলিখিত সম্পর্কিত নির্দেশিকাগুলি দেখুন:
- নেটওয়ার্ক ব্যাটারির খরচ কমানো: ওভারভিউ
- নিয়মিত আপডেটের প্রভাব কমিয়ে আনুন
- ওয়েব-ভিত্তিক কন্টেন্ট
- প্রয়োগের মৌলিক বিষয়সমূহ
- অ্যাপ আর্কিটেকচারের নির্দেশিকা