সংযোগ হারানো — মোবাইল অ্যাপে সবচেয়ে সাধারণ এবং বিরক্তিকর ঘটনাগুলির একটি। ব্যবহারকারী ডেটা অ্যাক্সেস হারায়, অপারেশন বাধাগ্রস্ত হয়, অ্যাপ জমে যায় বা ক্র্যাশ হয়। Google Android Developer Blog-এর মতে, 70% ব্যবহারকারী অ্যাপ ডিলিট করে দেন যদি এটি দুবার ক্র্যাশ বা জমে যায়। আসুন সংযোগ হারানোর কারণ এবং দোষ-সহনশীল যোগাযোগ তৈরির উপায়গুলি বুঝি।
মূল বিষয়
সংযোগ বিচ্ছিন্ন হওয়া — একটি ব্যবহারকারী শব্দ যা সেই পরিস্থিতি বর্ণনা করে যখন অ্যাপ সার্ভারের সাথে সংযোগ হারায়, কর্মে সাড়া দেওয়া বন্ধ করে দেয় বা ত্রুটির সাথে শেষ হয়। প্রযুক্তিগতভাবে এটি হতে পারে: নেটওয়ার্ক ত্রুটি (টাইমআউট, DNS ব্যর্থতা), ANR (UI থ্রেড জমে যাওয়া), ক্র্যাশ (অনারোধিত ব্যতিক্রম) বা রেস কন্ডিশন।
ব্যবহারকারীর দৃষ্টিকোণ থেকে, এই সমস্ত পরিস্থিতি একই রকম দেখায়: অ্যাপ কাজ করা বন্ধ করে দেয়। ডেভেলপারদের জন্য পার্থক্য নির্ণয় এবং সমাধানের পদ্ধতিতে। নেটওয়ার্ক ত্রুটিগুলি রিট্রি মেকানিজম দিয়ে সমাধান করা হয়, ANR UI থ্রেড থেকে অপারেশন সরিয়ে, ক্র্যাশ ব্যতিক্রম হ্যান্ডলিং দিয়ে।
Crittercism (বর্তমানে Apteligent)-এর মতে, গড়ে একটি মোবাইল অ্যাপ প্রতিটি ক্র্যাশের সাথে 1-2% ব্যবহারকারী হারায়। 1 মিলিয়ন ব্যবহারকারীর অ্যাপের জন্য, এর অর্থ প্রতি একটি বাগে 10-20 হাজার হারানো ইনস্টল। এটি বিশেষ করে আর্থিক এবং চিকিৎসা খাতের অ্যাপগুলির জন্য গুরুত্বপূর্ণ।
অস্থির নেটওয়ার্ক — মোবাইল ডিভাইসগুলি constantly Wi-Fi এবং মোবাইল নেটওয়ার্কের মধ্যে সুইচ করে, কভারেজ ছাড়া এলাকায় (মেট্রো, লিফট, বেসমেন্ট) প্রবেশ করে। প্রতিটি সুইচ অস্থায়ী সংযোগ হারানোর কারণ হয় যা অ্যাপকে সঠিকভাবে পরিচালনা করতে হবে।
টাইমআউট — যদি সার্ভার নির্ধারিত টাইমআউটের (সাধারণত 10-30 সেকেন্ড) মধ্যে সাড়া না দেয়, তাহলে ক্লায়েন্ট SocketTimeoutException ছোঁড়ে। প্রতিক্রিয়া ছাড়া দীর্ঘ টাইমআউট ব্যবহারকারী দ্বারা জমে যাওয়া হিসেবে ধরা হয়। 15 সেকেন্ডের বেশি টাইমআউট না সেট করার সুপারিশ করা হয়।
val client = OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.retryOnConnectionFailure(true)
.build()
রেস কন্ডিশন — ঘটে যখন একাধিক থ্রেড সিঙ্ক্রোনাইজেশন ছাড়া একই সাথে একই ডেটা পড়ে এবং লেখে। উদাহরণস্বরূপ, নেটওয়ার্ক থেকে ক্যাশ আপডেট করার সমান্তরালে UI থ্রেডে ক্যাশ থেকে ডেটা লোড করা পুরানো বা ভুল ডেটা প্রদর্শন করতে পারে।
Offline-first — একটি আর্কিটেকচারাল প্যাটার্ন যেখানে স্থানীয় স্টোরেজ (Room, CoreData) সত্যের একমাত্র উৎস। নেটওয়ার্ক ব্যাকগ্রাউন্ডে ডেটা সিঙ্ক্রোনাইজেশনের জন্য ব্যবহৃত হয়। ব্যবহারকারী নেটওয়ার্ক সংযোগ ছাড়াই সর্বদা স্থানীয় ক্যাশ থেকে হালনাগাদ ডেটা দেখেন।
রিপজিটরি প্যাটার্ন — ডেটার জন্য একক প্রবেশ বিন্দু যা সিদ্ধান্ত নেয় নেটওয়ার্ক থেকে বা ক্যাশ থেকে ডেটা নেওয়া হবে কিনা। রিপজিটরি ViewModel এবং UI থেকে ডেটা উৎসকে বিমূর্ত করে। নেটওয়ার্ক ত্রুটিতে, রিপজিটরি স্বয়ংক্রিয়ভাবে স্থানীয় উৎসে সুইচ করে।
class UserRepository(
private val api: UserApi,
private val dao: UserDao
) {
suspend fun getUsers(): Result<List<User>> {
return try {
val remote = api.fetchUsers()
dao.insertAll(remote)
Result.success(remote)
} catch (e: IOException) {
val cached = dao.getAll()
if (cached.isNotEmpty()) {
Result.success(cached) // return cache on network error
} else {
Result.failure(e)
}
}
}
}
সার্কিট ব্রেকার — একটি প্যাটার্ন যা সার্ভারকে অনুপলব্ধ থাকাকালীন অনুরোধের বন্য থেকে রক্ষা করে। পরপর N ত্রুটির পরে, সার্কিট ব্রেকার খোলে, এবং সমস্ত অনুরোধ সংযোগের চেষ্টা না করেই তাত্ক্ষণিকভাবে ত্রুটি ফেরত দেয়। নির্দিষ্ট টাইমআউটের পরে, সার্কিট ব্রেকার পরীক্ষার অনুরোধের জন্য অর্ধ-খোলা অবস্থায় যায়।
এক্সপোনেনশিয়াল ব্যাকঅফ — একটি মানক রিট্রি মেকানিজম। প্রথম ব্যর্থতার পরে, 1 সেকেন্ড অপেক্ষা করুন; দ্বিতীয়টির পরে, 2 সেকেন্ড; তারপর 4, 8, 16। সার্ভার এবং ব্যাটারি ওভারলোড না করতে সর্বাধিক পুনরায় চেষ্টার সংখ্যা (সাধারণত 3-5) সীমিত করুন।
ব্যবহারকারীর প্রতিক্রিয়া — নেটওয়ার্ক ত্রুটিতে, একটি স্পষ্ট বার্তা দেখান: “কোনো সংযোগ নেই”, “সার্ভার সাময়িকভাবে অনুপলব্ধ”, “আপনার ইন্টারনেট পরীক্ষা করুন”। Snackbar বা Inline State View ব্যবহার করুন। কখনই ব্যবহারকারীকে প্রযুক্তিগত ত্রুটি (HTTP 500, SocketException) দেখাবেন না।
ConnectivityManager — নেটওয়ার্ক পর্যবেক্ষণের জন্য Android API। অ্যাপকে পরিবর্তনে প্রতিক্রিয়া জানাতে দিন: সংযোগ হারালে প্লেসহোল্ডার দেখান, পুনরুদ্ধারে স্বয়ংক্রিয়ভাবে ডেটা রিফ্রেশ করুন। iOS-এ Network ফ্রেমওয়ার্ক থেকে NWPathMonitor ব্যবহার করুন।
class NetworkMonitor(private val context: Context) {
private val manager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
fun isOnline(): Boolean {
val network = manager.activeNetwork ?: return false
val caps = manager.getNetworkCapabilities(network) ?: return false
return caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
}
}
Crashlytics (Firebase) — মোবাইল অ্যাপের জন্য একটি মানক ক্র্যাশ-রিপোর্টিং টুল। এটি সমস্ত অনারোধিত ব্যতিক্রমের স্ট্যাকট্রেস, OS সংস্করণ, ডিভাইস মডেল এবং ক্র্যাশ সময় সংগ্রহ করে। এটি ত্রুটিগুলি গ্রুপ করতে এবং ফিক্সের জন্য দায়ী ব্যক্তি নিয়োগ করতে দেয়।
Sentry — পারফরম্যান্স মনিটরিং সমর্থন সহ Crashlytics-এর একটি বিকল্প। এটি নির্দিষ্ট লেনদেন (যেমন “ব্যবহারকারী অনুমোদন”) ট্রেস করতে এবং কোন ধাপে ত্রুটি ঘটেছে তা দেখতে দেয়। পারফরম্যান্স ট্রেসিং নেটওয়ার্ক টাইমআউটকে অ্যাপ লজিকে বাগ থেকে আলাদা করতে সাহায্য করে।
Timber — Android-এর জন্য একটি লগিং লাইব্রেরি যা ক্লাস অনুযায়ী স্বয়ংক্রিয়ভাবে ট্যাগ যোগ করে। ডিবাগ বিল্ডে, সমস্ত নেটওয়ার্ক অনুরোধ এবং প্রতিক্রিয়া লগ করুন। রিলিজ বিল্ডে, শুধুমাত্র Crashlytics.setCustomLog-এর মাধ্যমে ত্রুটি এবং সতর্কতা লগ করুন।
| টুল | ধরন | কখন ব্যবহার করবেন |
|---|---|---|
| Crashlytics | ক্র্যাশ রিপোর্টিং | সর্বদা রিলিজে — স্বয়ংক্রিয় ক্র্যাশ সংগ্রহ |
| Sentry | ক্র্যাশ + পারফরম্যান্স | যখন নির্দিষ্ট ব্যবহারকারী পরিস্থিতি প্রোফাইল করতে হবে |
| Timber | লগিং | ডিবাগ: সম্পূর্ণ লগিং; রিলিজ: শুধুমাত্র ত্রুটি |
| HTTP Toolkit | নেটওয়ার্ক ডিবাগ | স্থানীয় HTTP ট্রাফিক ইন্টারসেপশন এবং বিশ্লেষণ |
Firebase Summit 2023-এর মতে, যে অ্যাপগুলি Crashlytics + Performance Monitoring বাস্তবায়ন করেছে, তারা গুরুত্বপূর্ণ বাগ সনাক্ত এবং ঠিক করার গড় সময় 3 দিন থেকে 4 ঘন্টায় কমিয়েছে। সক্রিয় ব্যবহারকারীদের 0.1% এর বেশি ফ্রিকোয়েন্সি সহ প্রতিটি ক্র্যাশের জন্য সতর্কতা সেট করার সুপারিশ করা হয়।
প্রায়শই জিজ্ঞাসিত প্রশ্ন
যদি ক্র্যাশ Crashlytics-এ না ধরা পড়ে, তাহলে নেটিভ ক্র্যাশ (SIGSEGV, SIGABRT) পরীক্ষা করুন — এগুলি Java/Kotlin ব্যতিক্রম হ্যান্ডলার দ্বারা পরিচালিত হয় না। Android-এ, এটি JNI থেকে নেটিভ মেমরি লিক হতে পারে; iOS-এ, EXC_BAD_ACCESS। নেটিভ ক্র্যাশ স্ট্যাকট্রেস সংগ্রহের জন্য Breakpad (Android) বা PLCrashReporter (iOS) ব্যবহার করুন।
Network Link Conditioner ব্যবহার করুন (iOS-এ বিল্ট-ইন; Android-এর জন্য Facebook Network Connection Class বা Developer Options > Network > Select network type ব্যবহার করুন)। 500-3000 ms বিলম্ব এবং 5-30% প্যাকেট লস সেট করুন। নেটওয়ার্ক লেটেন্সি এবং ডিসকানেকশন সিমুলেট করতে Charles Proxy বা mitmproxy-ও ব্যবহার করতে পারেন।
ANR ঘটে যখন UI থ্রেড 5 সেকেন্ডের বেশি ব্লক থাকে। নেটওয়ার্ক অনুরোধ ব্যাকগ্রাউন্ড থ্রেডে সম্পাদন করা উচিত: coroutine (viewModelScope.launch(Dispatchers.IO)), RxJava (subscribeOn(Schedulers.io)), বা সিঙ্ক্রোনাইজেশনের জন্য WorkManager। HTTP ক্লায়েন্টে সর্বদা টাইমআউট সেট করুন — টাইমআউটের অনুপস্থিতি স্থায়ী ব্লকিং হতে পারে।
রেস কন্ডিশন — এমন একটি পরিস্থিতি যেখানে অপারেশনের ফলাফল থ্রেড সম্পাদনের ক্রমের উপর নির্ভর করে। উদাহরণস্বরূপ, ব্যবহারকারী দ্রুত “পাঠান” বাটন দুবার চাপে, এবং অনুরোধ দুবার পাঠানো হয়। সমাধান: Mutex, সিঙ্গেল-থ্রেডেড এক্সিকিউটর বা স্টেট মেশিন ব্যবহার করুন (প্রথম ক্লিকের পরে বাটন নিষ্ক্রিয় করুন)। Kotlin-এ, coroutine থেকে Mutex বা @Synchronized অ্যানোটেশন ব্যবহার করুন।
মোবাইল অ্যাপের জন্য Chaos Engineering প্রয়োগ করুন: অপারেশনের সময় নেটওয়ার্ক সংযোগ বিচ্ছিন্ন করুন, উচ্চ বিলম্ব সিমুলেট করুন, Wi-Fi এবং মোবাইল নেটওয়ার্কের মধ্যে সুইচ করুন, সিস্টেমের মাধ্যমে প্রক্রিয়া বন্ধ করুন। টুল: Facebook Network Connection Class, Charles Proxy, iOS Network Link Conditioner। CI/CD-তে, AndroidTest Orchestrator-এর মাধ্যমে বিভিন্ন নেটওয়ার্ক অবস্থার সাথে UI পরীক্ষা যোগ করুন।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন