Global Exception Handler — ایک مرکزی طریقہ کار جو غیر پروسیس شدہ مستثنیات کو پکڑتا ہے اور موبائل ایپ کے کریش کو روکتا ہے۔ Apple Developer، 2024 کے مطابق، صحیح استثنی ہینڈلنگ کریش کی تعداد کو 40–60% تک کم کرتی ہے اور صارف کے تجربے کو بہتر بناتی ہے۔ اس طرح کے ہینڈلر کے بغیر، بیک گراؤنڈ تھریڈ میں کوئی بھی غیر پروسیس شدہ استثنی فوری طور پر ایپ کو بند کر دیتا ہے۔
اہم نکات
Global Exception Handler — ایک مرکزی طریقہ کار ہے جو ان مستثنیات کو پکڑتا ہے جو ایپ کے انفرادی فنکشنز یا ماڈیولز کی سطح پر پروسیس نہیں کی گئیں۔ موبائل ڈویلپمنٹ کے سیاق و سباق میں، ایسا ہینڈلر عمل کے غیر معمولی خاتمے سے پہلے دفاع کی آخری لائن کے طور پر کام کرتا ہے۔
iOS اور Android عالمی ہینڈلر سیٹ کرنے کے لیے بلٹ ان APIs فراہم کرتے ہیں۔ Apple Objective-C ماحول کے لیے NSSetUncaughtExceptionHandler استعمال کرتا ہے، جبکہ Google Java/Kotlin میں Thread.setDefaultUncaughtExceptionHandler فراہم کرتا ہے۔ دونوں طریقہ کار ان مستثنیات کو پکڑتے ہیں جو ایپ کے تمام تھریڈز پر try-catch ڈھانچے کے ذریعے نہیں پکڑی گئیں۔
Crashlytics (Google، 2024) کے مطابق، تقریباً 25% کریش بیک گراؤنڈ تھریڈز میں غیر پروسیس شدہ مستثنیات کی وجہ سے ہوتے ہیں — ایک ایسا شعبہ جہاں Global Exception Handler خاص طور پر اہم ہے۔ ڈویلپرز اکثر UI تھریڈ پر توجہ مرکوز کرتے ہیں، غیر متزامن کارروائیوں کو بھول جاتے ہیں۔
عالمی ہینڈلر کا استعمال مقامی خرابی ہینڈلنگ کو تبدیل نہیں کرتا بلکہ اس کی تکمیل کرتا ہے۔ بنیادی کام استثنی کے لمحے ایپ کی حالت کے بارے میں زیادہ سے زیادہ معلومات محفوظ کرنا اور صحیح طریقے سے ختم کرنا ہے۔
کام کرنے کا طریقہ کار Global Exception Handler آپریٹنگ سسٹم سگنلز یا رن ٹائم مستثنیات کو روکنے پر مبنی ہے۔ جب کوڈ ایک استثنی پھینکتا ہے جو کسی try-catch بلاک کے ذریعے نہیں پکڑی جاتی، تو کنٹرول پہلے سے رجسٹرڈ ہینڈلر کو منتقل کر دیا جاتا ہے۔
iOS پر، ہینڈلر NSSetUncaughtExceptionHandler کے ذریعے رجسٹر ہوتا ہے اور مکمل اسٹیک ٹریس کے ساتھ ایک NSException آبجیکٹ وصول کرتا ہے۔ Android پر، Thread.setDefaultUncaughtExceptionHandler استعمال ہوتا ہے، جو Thread اور Throwable قبول کرتا ہے — استثنی کی قسم، پیغام اور کال اسٹیک تک رسائی فراہم کرتا ہے۔
کریش ڈیٹا وصول کرنے کے بعد، ہینڈلر تین لازمی اقدامات کرتا ہے: مقامی اسٹوریج میں لاگ لکھنا، Crashlytics یا Sentry کو رپورٹ بھیجنا، اور ایپ کو صحیح طریقے سے ختم کرنا۔ Apple WWDC 2023 کے مطابق، ہینڈلر کے عملدرآمد کا وقت 5 سیکنڈ تک محدود ہے — اس کے بعد سسٹم زبردستی عمل ختم کر دیتا ہے۔
iOS 13 سے شروع ہونے والی Swift ایپلیکیشنز کے لیے، Signals API متعارف کرائی گئی ہے، جو نہ صرف مستثنیات بلکہ آپریٹنگ سسٹم سگنلز — SIGABRT، SIGSEGV اور SIGBUS — کو بھی ہینڈل کرتی ہے، ہینڈلر کی کوریج کو نچلی سطح کی میموری غلطیوں تک بڑھاتی ہے۔
نفاذ iOS پر عالمی ہینڈلر کے لیے NSSetUncaughtExceptionHandler کے ذریعے C-فنکشن سیٹ کرنا ضروری ہے۔ ہینڈلر ایک غیر پروسیس شدہ استثنی کے لمحے ہم وقت سازی سے کال کیا جاتا ہے اور مکمل خرابی کا سیاق و سباق وصول کرتا ہے۔
void handleUncaughtException(NSException exception) {
NSDictionary userInfo = [exception userInfo];
NSArray stackTrace = [exception callStackSymbols];
NSString reason = [exception reason];
// کریش لاگ کو مقامی فائل میں محفوظ کریں
NSString logPath = [NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
[exceptionLog writeToFile:logPath atomically:YES];
}
int main(int argc, char argv[]) {
NSSetUncaughtExceptionHandler(&handleUncaughtException);
return UIApplicationMain(argc, argv, nil, nil);
}
iOS نفاذ کی ایک اہم خصوصیت: ہینڈلر صرف Objective-C مستثنیات کو پکڑتا ہے۔ throw-catch طریقہ کار استعمال کرنے والی Swift غلطیاں اس ہینڈلر تک نہیں پہنچتیں — ان کے لیے Swift Error Handling کے ذریعے علیحدہ ہینڈلنگ ضروری ہے۔ iOS 14 سے شروع کرتے ہوئے، Apple زیادہ سے زیادہ کوریج کے لیے NSSetUncaughtExceptionHandler کو Signals API کے ساتھ ملانے کی سفارش کرتا ہے۔
Apple Technical Note TN2151 کے مطابق، ہینڈلر کال کرنے کے بعد، ایپ کو 5 سیکنڈ کے اندر ختم ہو جانا چاہیے۔ ہینڈلر سے واپس آنے کے بعد عملدرآمد جاری رکھنے کی کوئی بھی کوشش غیر متعینہ رویے اور دوبارہ کریش کا باعث بنتی ہے۔
Android Thread.setDefaultUncaughtExceptionHandler کے ذریعے عالمی استثنی ہینڈلنگ کے لیے زیادہ لچکدار طریقہ کار فراہم کرتا ہے۔ ہینڈلر اس تھریڈ کا حوالہ وصول کرتا ہے جہاں استثنی ہوئی اور خود Throwable آبجیکٹ وصول کرتا ہے۔
class GlobalExceptionHandler : Thread.UncaughtExceptionHandler {
override fun uncaughtException(thread: Thread, throwable: Throwable) {
// کریش لاگ کو فائل میں محفوظ کریں
val stackTrace = throwable.stackTraceToString()
val crashLog = "CRASH: ${thread.name}\n${stackTrace}"
val file = File(context.cacheDir, "crash_log.txt")
file.writeText(crashLog)
// Crashlytics کو بھیجیں
FirebaseCrashlytics.getInstance()
.recordException(throwable)
// عمل ختم کریں
android.os.Process.killProcess(
android.os.Process.myPid()
)
}
}
// Application.onCreate میں سیٹ اپ
class App : Application() {
override fun onCreate() {
super.onCreate()
Thread.setDefaultUncaughtExceptionHandler(
GlobalExceptionHandler()
)
}
}
Android نفاذ کا ایک اہم فرق: ہر تھریڈ کا اپنا ہینڈلر ہوتا ہے، اور setDefaultUncaughtExceptionHandler ان تمام تھریڈز کے لیے ہینڈلر سیٹ کرتا ہے جن کے پاس انفرادی ہینڈلر تفویض نہیں ہے۔ یہ عالمی کوریج کو یقینی بناتا ہے — UI تھریڈ سے لے کر بیک گراؤنڈ AsyncTask اور کوروٹینز تک۔
Android 12+ پر، ایک حد ہے: uncaughtException کال کرنے کے بعد، ایپ کو 100 ملی سیکنڈ کے اندر ختم ہو جانا چاہیے۔ اگر ہینڈلر طویل عرصے تک چلنے والی کارروائیاں کرتا ہے، تو سسٹم لاگ لکھے جانے سے پہلے عمل کو ختم کر سکتا ہے۔ کریش رپورٹس بھیجنے کے لیے بیک گراؤنڈ سروس استعمال کرنے کی سفارش کی جاتی ہے۔
پہلا اصول — غیر پروسیس شدہ استثنی کے بعد ایپ کے آپریشن کو بحال کرنے کی کوشش نہ کریں۔ کریش کے بعد ایپ کی حالت غیر متعینہ ہوتی ہے، اور عملدرآمد جاری رکھنا صارف کے ڈیٹا کو نقصان پہنچا سکتا ہے۔
وقت کی حد — Global Exception Handler کی اہم تکنیکی رکاوٹ۔ iOS پر یہ 5 سیکنڈ ہے، Android پر — 100 ملی سیکنڈ۔ ہینڈلر کے اندر، صرف کم سے کم ڈیٹا سیٹ محفوظ کیا جانا چاہیے: استثنی کی قسم، کال اسٹیک اور چند اہم متغیرات کی حالت۔
نیٹ ورک کی درخواستیں بھیجنا، ڈیٹا بیس میں لکھنا اور پیچیدہ سیریلائزیشن کو مؤخر طریقہ کار میں منتقل کیا جانا چاہیے — مثال کے طور پر، لاگ کو فائل میں محفوظ کریں اور اگلی ایپ لانچ پر بھیجیں۔
کریش رپورٹنگ سروسز — Firebase Crashlytics، Sentry، Bugsnag — اپنا عالمی ہینڈلر سیٹ کرتی ہیں۔ اگر کوئی ڈویلپر اوپر ایک حسب ضرورت ہینڈلر سیٹ کرتا ہے، تو انہیں اپنی کارروائیوں کے بعد کریش رپورٹنگ سسٹم کو کنٹرول دینا ہوگا۔ Android پر ہینڈلر کمپوزیشن استعمال ہوتی ہے: اپنی منطق چلائیں، پھر پچھلے ہینڈلر کو کال کریں۔
Firebase Crashlytics کے لیے، حسب ضرورت Thread.setDefaultUncaughtExceptionHandler بالکل نہ سیٹ کرنے کی سفارش کی جاتی ہے — Crashlytics SDK ابتدا میں خود بخود یہ کرتا ہے۔
صارف کا سیاق و سباق — معیاری کال اسٹیک کے علاوہ، ایپ ورژن، OS ورژن، دستیاب میموری کا سائز اور کریش سے پہلے کا اپ ٹائم لاگ کرنا مفید ہے۔ یہ ڈیٹا مسئلہ کی تولید اور حل کے لیے انتہائی اہم ہے۔
iOS پر، NSSetUncaughtExceptionHandler کو نہ صرف لکھنے کے لیے بلکہ NSUserDefaults میں synchronize پرچم کے ساتھ عارضی ڈیٹا اسٹوریج کے لیے بھی استعمال کیا جا سکتا ہے — یہ فوری عمل ختم ہونے پر بھی استحکام کو یقینی بناتا ہے۔
لازمی جانچ — Global Exception Handler کو CI/CD کے ہر مرحلے پر جانچا جانا چاہیے۔ iOS پر، @throw NSException کے ذریعے ٹیسٹ استثنی شروع کی جا سکتی ہے، Android پر — throw RuntimeException() کے ذریعے۔ تصدیق کریں کہ ہینڈلر کال ہوا، لاگ محفوظ ہوا اور ایپ صحیح طریقے سے ختم ہوئی۔
Google I/O 2023 کے مطابق، پروڈکشن میں 30% سے زیادہ کریش ان آلات پر ہوتے ہیں جن کی ڈویلپر نے جانچ نہیں کی — مختلف Android ورژن، حسب ضرورت فرم ویئر، محدود میموری۔
پہلی اور سب سے عام غلطی — استثنی کو ہینڈل کرنے کے بعد ایپ کا عملدرآمد جاری رکھنے کی کوشش کرنا۔ uncaughtException کال کرنے کے بعد، ایپ غیر مستحکم حالت میں ہوتی ہے، اور مزید کوئی بھی کارروائی سیڑھی نما غلطیاں اور ڈیٹا کی خرابی کا سبب بن سکتی ہے۔
دوسری غلطی — ہینڈلر کے اندر طویل عرصے تک چلنے والی کارروائیاں انجام دینا۔ نیٹ ورک کی درخواستیں، بڑی فائلیں لکھنا یا پیچیدہ حسابات عمل کے زبردستی ختم ہونے سے پہلے مکمل نہیں ہوتے۔ Apple Technical Q&A QA1468 کے مطابق، ہینڈلر کے اندر HTTP درخواست بھیجنے کی کوشش کھوئی ہوئی کریش رپورٹس کی سب سے بڑی وجہ ہے۔
تیسری غلطی — بیک گراؤنڈ تھریڈز کو نظر انداز کرنا۔ صرف مین تھریڈ کے لیے سیٹ کردہ Global Exception Handler کوروٹینز، DispatchQueue، AsyncTask یا RxJava میں کریش سے تحفظ نہیں دیتا۔ Android پر، ہر تھریڈ کا اپنا ہینڈلر ہونا چاہیے — اور setDefaultUncaughtExceptionHandler صرف ان تھریڈز کے لیے یہ حل کرتا ہے جن کے پاس انفرادی ہینڈلر نہیں ہے۔
چوتھی غلطی — OS سگنلز کے لیے فال بیک کی کمی۔ iOS پر NSSetUncaughtExceptionHandler SIGABRT، SIGSEGV اور SIGBUS کو نہیں پکڑتا۔ ان سگنلز کے لیے sigaction API کے ذریعے علیحدہ ہینڈلر سیٹ اپ ضروری ہے۔ ڈویلپرز کو اس کے بارے میں تب پتہ چلتا ہے جب ایپ بغیر کسی کریش رپورٹ کے کریش ہو جاتی ہے۔
پانچویں غلطی — خفیہ ڈیٹا لاگ کرنا۔ کریش لاگ میں ای میلز، توثیقی ٹوکنز یا صارفین کا ذاتی ڈیٹا آ سکتا ہے۔ یہ GDPR اور Apple App Store جائزہ رہنما خطوط کی خلاف ورزی کرتا ہے۔ ریجیکس یا اجازت یافتہ فیلڈز کی وائٹ لسٹ کے ذریعے منتقل کردہ ڈیٹا کو ہمیشہ فلٹر کریں۔
اکثر پوچھے گئے سوالات
نہیں — Global Exception Handler کو کال کرنے کے بعد، ایپ کی حالت غیر متعینہ ہوتی ہے۔ عملدرآمد جاری رکھنے کی کوئی بھی کوشش ڈیٹا کی خرابی کا سبب بن سکتی ہے۔ واحد درست اقدام کریش لاگ محفوظ کرنا اور عمل ختم کرنا ہے۔
سبھی نہیں — iOS پر، NSSetUncaughtExceptionHandler صرف Objective-C مستثنیات کو پکڑتا ہے۔ Swift غلطیاں اور OS سگنلز (SIGSEGV، SIGABRT) علیحدہ ہینڈلرز کی ضرورت رکھتے ہیں۔ Android پر، Thread.setDefaultUncaughtExceptionHandler تمام RuntimeExceptions کو پکڑتا ہے لیکن JNI کے ذریعے نیٹو کوڈ کی غلطیوں کو نہیں پکڑتا۔
اپنا ہینڈلر سیٹ کرنے سے پہلے Thread.getDefaultUncaughtExceptionHandler() کے ذریعے پچھلے ہینڈلر کا حوالہ محفوظ کریں۔ اپنے ہینڈلر کے آخر میں، previousHandler.uncaughtException(thread, throwable) کال کریں — یہ یقینی بناتا ہے کہ Crashlytics یا Sentry اپنا ڈیٹا وصول کریں۔
نیٹو کوڈ کے لیے، sigaction() کے ذریعے سگنل ہینڈلنگ ضروری ہے — SIGSEGV، SIGABRT، SIGBUS۔ Android پر آپ Google Breakpad یا Crashpad استعمال کر سکتے ہیں۔ iOS ورژن 13 سے شروع کرتے ہوئے، mach مستثنیات کو ہینڈل کرنے کے لیے Signals API دستیاب ہے۔
نہیں — ہینڈلر سیٹ کرنا صرف استثنی ہونے کے لمحے کو متاثر کرتا ہے۔ عام ایپ آپریشن میں، کوئی اوور ہیڈ نہیں ہے۔ واحد خطرہ میموری لیک ہے اگر ہینڈلر Activity یا Context کا حوالہ رکھتا ہے، کوڑا کرکٹ جمع کرنے سے روکتا ہے۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں