ANR

যখন কোনো অ্যান্ড্রয়েড অ্যাপের UI থ্রেড খুব বেশি সময় ধরে ব্লক হয়ে থাকে, তখন একটি "অ্যাপ্লিকেশন সাড়া দিচ্ছে না" (ANR) ত্রুটি দেখা দেয়। অ্যাপটি যদি ফোরগ্রাউন্ডে থাকে, তবে সিস্টেম ব্যবহারকারীকে একটি ডায়ালগ বক্স দেখায়, যেমনটি চিত্র ১-এ দেখানো হয়েছে। এই ANR ডায়ালগ বক্সটি ব্যবহারকারীকে অ্যাপটি জোর করে বন্ধ করার সুযোগ দেয়।

ব্যবহারকারীকে ANR ডায়ালগ বক্স দেখানো হয়েছে।
চিত্র ১. ব্যবহারকারীকে প্রদর্শিত ANR ডায়ালগ

ANR একটি সমস্যা, কারণ অ্যাপের প্রধান থ্রেড, যা UI আপডেট করার জন্য দায়ী, ব্যবহারকারীর ইনপুট ইভেন্টগুলি প্রসেস করতে বা আঁকতে পারে না, যার ফলে ব্যবহারকারী হতাশ হন। অ্যাপের প্রধান থ্রেড সম্পর্কে আরও তথ্যের জন্য, প্রসেস এবং থ্রেড ওভারভিউ দেখুন।

নিম্নলিখিত শর্তগুলির মধ্যে কোনো একটি ঘটলে আপনার অ্যাপের জন্য একটি ANR ট্রিগার হয়:

  • ইনপুট প্রেরণে সময়সীমা অতিক্রান্ত: যদি আপনার অ্যাপ ৫ সেকেন্ডের মধ্যে কোনো ইনপুট ইভেন্টে (যেমন কী-প্রেস বা স্ক্রিন টাচ) সাড়া না দেয়।
  • সার্ভিস সম্পাদন: যদি আপনার অ্যাপ দ্বারা ঘোষিত কোনো সার্ভিস কয়েক সেকেন্ডের মধ্যে Service.onCreate এবং Service.onStartCommand / Service.onBind সম্পাদন শেষ করতে না পারে।
  • Service.startForeground কল করা হয়নি: যদি আপনার অ্যাপ ফোরগ্রাউন্ডে একটি নতুন সার্ভিস চালু করার জন্য Context.startForegroundService ব্যবহার করে, কিন্তু সার্ভিসটি ৫ সেকেন্ডের মধ্যে startForeground কল না করে।
  • ইনটেন্টের ব্রডকাস্ট: যদি একটি BroadcastReceiver একটি নির্দিষ্ট সময়ের মধ্যে তার কার্য সম্পাদন শেষ না করে। যদি অ্যাপটি ফোরগ্রাউন্ডে কোনো কার্যকলাপ চালায়, তবে এই টাইমআউটটি ৫ সেকেন্ড।
  • JobScheduler ইন্টারঅ্যাকশন: যদি কোনো JobService JobService.onStartJob বা JobService.onStopJob থেকে কয়েক সেকেন্ডের মধ্যে রিটার্ন না করে, অথবা যদি ব্যবহারকারী-প্রবর্তিত কোনো জব শুরু হয় এবং JobService.onStartJob কল করার কয়েক সেকেন্ডের মধ্যে আপনার অ্যাপ JobService.setNotification কল না করে। Android 13 এবং তার নিচের সংস্করণের জন্য তৈরি অ্যাপগুলোর ক্ষেত্রে, ANR-গুলো সাইলেন্ট থাকে এবং অ্যাপে রিপোর্ট করা হয় না। Android 14 এবং তার উপরের সংস্করণের জন্য তৈরি অ্যাপগুলোর ক্ষেত্রে, ANR-গুলো এক্সপ্লিসিট থাকে এবং অ্যাপে রিপোর্ট করা হয়।

আপনার অ্যাপে যদি ANR দেখা দেয়, তাহলে সমস্যাটি নির্ণয় ও সমাধান করার জন্য আপনি এই ডকুমেন্টের নির্দেশিকা ব্যবহার করতে পারেন।

সমস্যাটি শনাক্ত করুন

আপনি যদি ইতিমধ্যেই আপনার অ্যাপটি প্রকাশ করে থাকেন, তাহলে আপনার অ্যাপের জন্য ANR সংক্রান্ত তথ্য দেখতে Android vitals ব্যবহার করতে পারেন। আপনি মাঠে ANR শনাক্ত করার জন্য অন্যান্য টুলও ব্যবহার করতে পারেন, কিন্তু মনে রাখবেন যে Android vitals-এর মতো নয়, 3P টুলগুলো Android 10 এবং এর নিচের সংস্করণগুলোতে ANR রিপোর্ট করতে পারে না।

অ্যান্ড্রয়েড ভাইটালস

অ্যান্ড্রয়েড ভাইটালস আপনার অ্যাপের ANR হার নিরীক্ষণ ও উন্নত করতে সাহায্য করতে পারে। অ্যান্ড্রয়েড ভাইটালস বিভিন্ন ধরনের ANR হার পরিমাপ করে:

  • ANR হার: আপনার দৈনিক সক্রিয় ব্যবহারকারীদের শতকরা হার, যারা কোনো না কোনো ধরনের ANR-এর সম্মুখীন হয়েছেন।
  • ব্যবহারকারী-অনুভূত ANR হার: আপনার দৈনিক সক্রিয় ব্যবহারকারীদের সেই শতাংশ, যারা অন্তত একটি ব্যবহারকারী-অনুভূত ANR-এর সম্মুখীন হয়েছেন। বর্তমানে শুধুমাত্র Input dispatching timed out ধরনের ANR-গুলোকেই ব্যবহারকারী-অনুভূত হিসেবে বিবেচনা করা হয়।
  • একাধিক এএনআর হার: আপনার দৈনিক সক্রিয় ব্যবহারকারীদের সেই শতাংশ, যারা কমপক্ষে দুটি এএনআর-এর সম্মুখীন হয়েছেন।

দৈনিক সক্রিয় ব্যবহারকারী হলেন এমন একজন স্বতন্ত্র ব্যবহারকারী যিনি একটি নির্দিষ্ট দিনে একটি নির্দিষ্ট ডিভাইসে, একাধিক সেশনের মাধ্যমে আপনার অ্যাপটি ব্যবহার করেন। যদি কোনো ব্যবহারকারী একটি নির্দিষ্ট দিনে একাধিক ডিভাইসে আপনার অ্যাপটি ব্যবহার করেন, তাহলে প্রতিটি ডিভাইস সেই দিনের সক্রিয় ব্যবহারকারীর সংখ্যায় অবদান রাখবে।

ব্যবহারকারীর অনুভূত ANR হার একটি অত্যন্ত গুরুত্বপূর্ণ বিষয় , কারণ এটি গুগল প্লে-তে আপনার অ্যাপের খুঁজে পাওয়ার যোগ্যতাকে প্রভাবিত করে। এটি গুরুত্বপূর্ণ কারণ এর দ্বারা গণনা করা ANR-গুলো সর্বদা তখনই ঘটে যখন ব্যবহারকারী অ্যাপটির সাথে যুক্ত থাকেন, যা সবচেয়ে বেশি বিঘ্ন ঘটায়।

প্লে এই মেট্রিকটিতে খারাপ আচরণের দুটি সীমা নির্ধারণ করেছে:

  • সামগ্রিক খারাপ আচরণের সীমা: সমস্ত ডিভাইস মডেল জুড়ে, দৈনিক সক্রিয় ব্যবহারকারীদের অন্তত ০.৪৭% ব্যবহারকারী-অনুভূত ANR-এর সম্মুখীন হন।
  • প্রতি-ডিভাইস ত্রুটিপূর্ণ আচরণের সীমা: একটি নির্দিষ্ট ডিভাইস মডেলের ক্ষেত্রে, দৈনিক ব্যবহারকারীদের কমপক্ষে ৮% একটি ব্যবহারকারী-অনুভূত ANR (অটোমেটিক নেগেটিভ রেসপন্স) অনুভব করেন।

যদি আপনার অ্যাপটি সামগ্রিক ত্রুটিপূর্ণ আচরণের সীমা অতিক্রম করে, তবে সব ডিভাইসে এটি সহজে খুঁজে পাওয়ার সম্ভাবনা কমে যাবে। যদি আপনার অ্যাপটি কিছু নির্দিষ্ট ডিভাইসে ডিভাইস-ভিত্তিক ত্রুটিপূর্ণ আচরণের সীমা অতিক্রম করে, তবে সেই ডিভাইসগুলিতে এটি সহজে খুঁজে পাওয়ার সম্ভাবনা কমে যাবে এবং আপনার স্টোর লিস্টিং-এ একটি সতর্কবার্তা দেখানো হতে পারে।

আপনার অ্যাপে অতিরিক্ত ANR দেখা দিলে Android vitals আপনাকে Play Console-এর মাধ্যমে সতর্ক করতে পারে।

গুগল প্লে কীভাবে অ্যান্ড্রয়েডের গুরুত্বপূর্ণ তথ্য সংগ্রহ করে, সে সম্পর্কে জানতে প্লে কনসোল ডকুমেন্টেশন দেখুন।

ANR নির্ণয় করুন

ANR নির্ণয় করার সময় কিছু সাধারণ লক্ষণ লক্ষ্য করা যায়:

  • অ্যাপটি প্রধান থ্রেডে ইনপুট/আউটপুট (I/O) সংক্রান্ত ধীরগতির কার্যক্রম চালাচ্ছে।
  • অ্যাপটি প্রধান থ্রেডে একটি দীর্ঘ গণনা করছে।
  • প্রধান থ্রেডটি অন্য একটি প্রসেসে একটি সিনক্রোনাস বাইন্ডার কল করছে, এবং সেই অন্য প্রসেসটি রিটার্ন করতে অনেক সময় নিচ্ছে।
  • অন্য একটি থ্রেডে চলমান একটি দীর্ঘ অপারেশনের জন্য সিনক্রোনাইজড ব্লকের অপেক্ষায় প্রধান থ্রেডটি অবরুদ্ধ হয়ে আছে।
  • প্রধান থ্রেডটি আপনার প্রসেসের মধ্যে অথবা একটি বাইন্ডার কলের মাধ্যমে অন্য একটি থ্রেডের সাথে ডেডলকে রয়েছে। প্রধান থ্রেডটি শুধু একটি দীর্ঘ অপারেশন শেষ হওয়ার জন্য অপেক্ষা করছে না, বরং এটি একটি ডেডলক পরিস্থিতিতে রয়েছে।

নিম্নলিখিত কৌশলগুলো আপনার ANR-এর কারণ নির্ণয় করতে সাহায্য করতে পারে।

স্বাস্থ্য পরিসংখ্যান

HealthStats মোট ব্যবহারকারী ও সিস্টেম সময়, সিপিইউ সময়, নেটওয়ার্ক, রেডিও স্ট্যাটস, স্ক্রিন চালু/বন্ধ সময় এবং ওয়েক আপ অ্যালার্ম ক্যাপচার করার মাধ্যমে একটি অ্যাপ্লিকেশনের স্বাস্থ্য সম্পর্কে মেট্রিক্স প্রদান করে। এটি আপনাকে সামগ্রিক সিপিইউ ব্যবহার এবং ব্যাটারি খরচ পরিমাপ করতে সাহায্য করতে পারে।

ডিবাগ

Debug আপনাকে ডেভেলপমেন্টের সময় অ্যান্ড্রয়েড অ্যাপ্লিকেশনগুলো পরীক্ষা করতে সাহায্য করে, যার মধ্যে ট্রেসিং এবং অ্যালোকেশন কাউন্ট অন্তর্ভুক্ত, যা অ্যাপের জ্যাঙ্ক এবং ল্যাগ শনাক্ত করতে সহায়ক। এছাড়াও, আপনি Debug ব্যবহার করে রানটাইম ও নেটিভ মেমরি কাউন্টার এবং মেমরি মেট্রিক্স পেতে পারেন, যা কোনো নির্দিষ্ট প্রসেসের মেমরি ফুটপ্রিন্ট শনাক্ত করতে সাহায্য করে।

অ্যাপ্লিকেশন প্রস্থান তথ্য

ApplicationExitInfo অ্যান্ড্রয়েড ১১ (এপিআই লেভেল ৩০) বা তার উচ্চতর সংস্করণে উপলব্ধ এবং এটি অ্যাপ্লিকেশন বন্ধ হওয়ার কারণ সম্পর্কে তথ্য প্রদান করে। এর মধ্যে রয়েছে এএনআর (ANR), কম মেমরি, অ্যাপ ক্র্যাশ, অতিরিক্ত সিপিইউ ব্যবহার, ব্যবহারকারীর বাধা, সিস্টেমের বাধা এবং রানটাইম পারমিশন পরিবর্তন।

কঠোর মোড

আপনার অ্যাপ ডেভেলপ করার সময় StrictMode ব্যবহার করে মেইন থ্রেডে ঘটা অনিচ্ছাকৃত I/O অপারেশনগুলো খুঁজে বের করা যায়। আপনি অ্যাপ্লিকেশন বা অ্যাক্টিভিটি লেভেলে StrictMode ব্যবহার করতে পারেন।

ব্যাকগ্রাউন্ড ANR ডায়ালগ সক্রিয় করুন

অ্যান্ড্রয়েড শুধুমাত্র তখনই সেইসব অ্যাপের জন্য ANR ডায়ালগ দেখায়, যেগুলো ব্রডকাস্ট মেসেজ প্রসেস করতে অনেক বেশি সময় নেয়, যদি ডিভাইসের ডেভেলপার অপশনে ‘Show all ANRs’ চালু করা থাকে। এই কারণে, ব্যাকগ্রাউন্ড ANR ডায়ালগগুলো সবসময় ব্যবহারকারীকে দেখানো হয় না, এমনকি যখন অ্যাপটি পারফরম্যান্স সংক্রান্ত সমস্যার সম্মুখীন হয় তখনও।

পুনর্গঠন প্রতিবন্ধকতা

রিকম্পোজিশনের প্রতিবন্ধকতাগুলো খুঁজে বের করতে অ্যান্ড্রয়েড স্টুডিও প্রোফাইলার এবং লেআউট ইন্সপেক্টর ব্যবহার করুন। আরও তথ্যের জন্য, জেটপ্যাক কম্পোজ পারফরম্যান্স দেখুন।

একটি ট্রেস ফাইল টানুন

অ্যান্ড্রয়েড যখন কোনো ANR-এর সম্মুখীন হয়, তখন এটি ট্রেস তথ্য সংরক্ষণ করে। পুরোনো OS রিলিজগুলোতে, ডিভাইসে একটিমাত্র /data/anr/traces.txt ফাইল থাকে। নতুন OS রিলিজগুলোতে, একাধিক /data/anr/anr_* ফাইল থাকে। আপনি রুট হিসেবে অ্যান্ড্রয়েড ডিবাগ ব্রিজ (adb) ব্যবহার করে ডিভাইস বা এমুলেটর থেকে ANR ট্রেস অ্যাক্সেস করতে পারেন:

adb root
adb shell ls /data/anr
adb pull /data/anr/<filename>

আপনি কোনো ফিজিক্যাল ডিভাইস থেকে বাগ রিপোর্ট ক্যাপচার করতে পারেন, হয় ডিভাইসটির ‘Take bug report’ ডেভেলপার অপশন ব্যবহার করে অথবা আপনার ডেভেলপমেন্ট মেশিনের adb bugreport ’ কমান্ড ব্যবহার করে। আরও তথ্যের জন্য, ‘Capture and read bug reports’ দেখুন।

সমস্যাগুলো সমাধান করুন

সমস্যাটি শনাক্ত করার পর, সাধারণভাবে দেখা যায় এমন সমস্যাগুলো সমাধান করতে আপনি এই বিভাগের পরামর্শগুলো ব্যবহার করতে পারেন।

প্রধান থ্রেডে ধীরগতির কোড

আপনার কোডের সেই জায়গাগুলো চিহ্নিত করুন যেখানে অ্যাপের প্রধান থ্রেড ৫ সেকেন্ডের বেশি সময় ধরে ব্যস্ত থাকে। আপনার অ্যাপে সন্দেহজনক ব্যবহারের ক্ষেত্রগুলো সন্ধান করুন এবং ANR-টি পুনরায় তৈরি করার চেষ্টা করুন।

একটি সাধারণ সমস্যা হলো কম্পোজেবলের ঠিক ভেতরে একটি দীর্ঘ সময় ধরে চলা টাস্ক:

@Composable
fun BadList(rawStrings: List<String>) {
    // Math or sorting inside the composable runs on EVERY recomposition pass!
    val heavilyProcessedList = rawStrings
        .filter { it.isNotBlank() }
        .map { it.uppercase().reversed() }
        .map { it.computationallyHeavyFunction() }
.sortedBy { it.length }
    LazyColumn { items(sortedList) { Text(it) } }
}

// Modern Compose-first fix
@Composable
fun GoodList(viewModel: MyViewModel = viewModel()) {
    val uiState by viewModel.uiState.collectAsStateWithLifecycle()

    // UI simply renders state; no heavy processing allowed here
    LazyColumn { items(uiState.sortedData) { Text(it) } }
}

প্রধান থ্রেডে I/O

মেইন থ্রেডে I/O অপারেশন চালানো হলো মেইন থ্রেডে ধীরগতির অপারেশনের একটি সাধারণ কারণ, যা ANR ঘটাতে পারে। Compose-এ, ডেভেলপাররা প্রায়শই প্রাথমিক অবস্থা নির্ধারণ করার চেষ্টা করার সময় ভুলবশত ডিস্ক রিড (যেমন SharedPreferences বা ডাটাবেস কল) চালু করে ফেলেন।

দীর্ঘ সময় ধরে চলা I/O অপারেশনগুলো UI লেয়ার থেকে দূরে সম্পাদন করুন। একটি ViewModelwithContext(Dispatchers.IO) ব্যবহার করুন অথবা, আরও ভালো হয়, ডেটা লেয়ারে একটি Repository ব্যবহার করুন।

অচলাবস্থা

যখন কোনো থ্রেড তার প্রয়োজনীয় রিসোর্স অন্য একটি থ্রেডের দখলে থাকার কারণে অপেক্ষারত অবস্থায় প্রবেশ করে, তখন ডেডলক ঘটে। এই অন্য থ্রেডটিও প্রথম থ্রেডটির দখলে থাকা একটি রিসোর্সের জন্য অপেক্ষা করে। অ্যাপের প্রধান থ্রেড এই পরিস্থিতিতে থাকলে ANR (অ্যাক্টিভ নাম্বার রেসপন্স) ঘটার সম্ভাবনা থাকে।

কম্পিউটার বিজ্ঞানে ডেডলক একটি বহুল আলোচিত বিষয়, এবং ডেডলক এড়ানোর জন্য ব্যবহারযোগ্য ডেডলক প্রতিরোধক অ্যালগরিদমও রয়েছে।

আরও তথ্যের জন্য, উইকিপিডিয়ায় ডেডলক এবং ডেডলক প্রতিরোধ অ্যালগরিদম দেখুন।

Kotlin এবং Compose ব্যবহার করার সময়, UI থ্রেডকে ফ্রিজ করার পরিবর্তে এক্সিকিউশন কনটেক্সটকে সাসপেন্ড করে থ্রেড ব্লকিং প্রতিরোধ করতে আপনি প্রিমিটিভ লকের বদলে নন-ব্লকিং কো-রুটিন মিউটেক্স ( Mutex.withLock ) ব্যবহার করতে পারেন। উদাহরণস্বরূপ:

import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock

// Modern non-blocking concurrency state architecture
class SecureDataRepository {
    private val mutex = Mutex()

    suspend fun safeUIAccess() {
        // If locked, the main thread suspends seamlessly, preventing an ANR
        mutex.withLock {
            performSafeOperation()
        }
    }
}

ধীরগতির সম্প্রচার রিসিভার

অ্যাপগুলো ব্রডকাস্ট রিসিভারের মাধ্যমে ব্রডকাস্ট মেসেজে সাড়া দিতে পারে, যেমন এয়ারপ্লেন মোড চালু বা বন্ধ করা কিংবা কানেক্টিভিটি স্ট্যাটাসের পরিবর্তন। যখন কোনো অ্যাপ ব্রডকাস্ট মেসেজটি প্রসেস করতে অতিরিক্ত সময় নেয়, তখন একটি ANR ঘটে।

নিম্নলিখিত ক্ষেত্রে ANR ঘটে থাকে:

  • একটি ব্রডকাস্ট রিসিভার যথেষ্ট পরিমাণ সময়ের মধ্যে তার onReceive মেথডটির সম্পাদন সম্পন্ন করতে পারেনি।
  • একটি ব্রডকাস্ট রিসিভার goAsync কল করে এবং PendingResult অবজেক্টের উপর finish কল করতে ব্যর্থ হয়।

আপনার অ্যাপের BroadcastReceiver এর onReceive মেথডে শুধুমাত্র ছোটখাটো অপারেশন করা উচিত। তবে, যদি কোনো ব্রডকাস্ট মেসেজের ফলে আপনার অ্যাপের আরও জটিল প্রক্রিয়াকরণের প্রয়োজন হয়, তাহলে কাজটি একটি ViewModel এ (Kotlin coroutines, scopes, এবং dispatchers-এর শক্তি ব্যবহার করে) স্থানান্তর করা উচিত, যদি কাজটি সম্পন্ন হতে সর্বোচ্চ কয়েক সেকেন্ড সময় লাগার সম্ভাবনা থাকে; অথবা যেকোনো ধরনের স্টেট হোল্ডারে; কিংবা কয়েক সেকেন্ডের বেশি সময় লাগার সম্ভাবনা থাকলে WorkManager এ স্থানান্তর করা যেতে পারে।

গেমঅ্যাক্টিভিটি

C বা C++ এ লেখা গেম এবং অ্যাপের কেস স্টাডিতে দেখা গেছে যে GameActivity লাইব্রেরি ANR-এর হার কমিয়েছে। আপনি যদি আপনার বিদ্যমান নেটিভ অ্যাক্টিভিটিকে GameActivity দিয়ে প্রতিস্থাপন করেন, তবে আপনি UI থ্রেড ব্লকিং কমাতে এবং কিছু ANR ঘটা প্রতিরোধ করতে পারবেন।

ANR সম্পর্কে আরও তথ্যের জন্য, “আপনার অ্যাপকে রেসপন্সিভ রাখুন” দেখুন। থ্রেড সম্পর্কে আরও তথ্যের জন্য, “থ্রেডিংয়ের মাধ্যমে উন্নত পারফরম্যান্স” দেখুন।

অতিরিক্ত সম্পদ

বিষয়বস্তু দেখুন

{% হুবহু %} {% endverbatim %} {% হুবহু %} {% endverbatim %}