ہر موبائل ڈویلپر آخر کار ایک ہی دیوار سے ٹکرا جاتا ہے۔ اس کا مطلب ہے کہ جب کوئی صارف اسے دیکھے گا تو آپ کی ایپ بالکل کام کرے گی۔
لیکن جیسے ہی میں ہوم بٹن دباتا ہوں، سب کچھ رک جاتا ہے۔ ایک مطابقت پذیری جو پس منظر میں مکمل ہونی چاہیے تھی وہ نہیں چلی۔ ایک نوٹیفکیشن جو چلنا چاہیے تھا وہ نہیں چلا۔ فائل اپ لوڈز جو اس وقت شروع ہوئے جب صارف ایپ میں تھا اس وقت خود بخود ناکام ہو گیا جب اس نے ایپس کو تبدیل کیا۔
موبائل پر پس منظر پر عمل درآمد موبائل انجینئرنگ کے پورے شعبے میں سب سے زیادہ غلط فہمی والے موضوعات میں سے ایک ہے۔ زیادہ تر ڈویلپرز اسے ایک سادہ مسئلہ سمجھتے ہیں۔ بس اپنے کوڈ کو پس منظر میں چلاتے رہیں۔ پلیٹ فارم اس کا علاج وسائل کے انتظام کے مسئلے کی طرح کرتا ہے جو بیٹری کی زندگی، کارکردگی اور آلے کی مجموعی صحت کو براہ راست متاثر کرتا ہے۔
یہ سمجھنا کہ iOS اور Android واقعی پس منظر کے کاموں کے بارے میں کیسے سوچتے ہیں، اور Flutter دونوں کے ساتھ کیسے کام کرتا ہے، وہی چیز ہے جو پلیٹ فارم سے لڑنے والے انجینئرز کو اس کا استعمال کرنے والوں سے الگ کرتی ہے۔
یہ مضمون صرف اسی سے خطاب کرتا ہے۔ آپ دونوں پلیٹ فارمز کے بنیادی میکانزم کو سمجھیں گے، فلٹر پیکجز جو ان کو جوڑتے ہیں، اور ہر نقطہ نظر پر کہاں پہنچنا ہے۔
انڈیکس
شرطیں
یہ مضمون موبائل انجینئرز کے لیے لکھا گیا ہے جو iOS، Android، یا Flutter پر پروڈکشن ایپلی کیشنز بنانے یا اسے برقرار رکھتے ہیں۔ پڑھنے سے پہلے، آپ کو درج ذیل سے واقف ہونا چاہئے:
-
موبائل ایپ کا بنیادی لائف سائیکل: کیا ہوتا ہے جب کوئی ایپ پیش منظر، پس منظر، اور موقوف حالتوں کے درمیان حرکت کرتی ہے
-
موبائل ڈویلپمنٹ کے عمومی تصورات: کسی بھی پلیٹ فارم یا فریم ورک پر ایک یا زیادہ موبائل ایپلیکیشنز کو جاری یا برقرار رکھا جاتا ہے۔
-
موبائل ایپلیکیشنز کو کسی بھی فریم ورک میں لکھیں: مقامی iOS، مقامی Android، Flutter، React Native، یا کوئی دوسرا موبائل ڈیولپمنٹ اسٹیک۔
-
آپ کی پسند کی پروگرامنگ زبان میں ملٹی تھریڈنگ اور ہم آہنگی: یہ سمجھنا کہ ایک زبان ان کاموں کو کیسے ہینڈل کرتی ہے جو مرکزی تھریڈ سے باہر چلتے ہیں اس مضمون میں شامل ہر چیز کی بنیاد ہے۔
اگر آپ موبائل ڈیولپمنٹ میں نئے ہیں یا آپ نے کبھی دھاگوں اور ہم آہنگی کے بارے میں نہیں سوچا ہے، تو پہلے بنیادی باتوں سے شروع کریں اور جب آپ پروڈکشن کی سطح کے پس منظر کے کاموں کے بارے میں سوچنے کے لیے تیار ہوں تو اس مضمون پر واپس جائیں۔
پس منظر پر عمل درآمد کیوں مشکل ہے۔
جب کوئی ایپ پیش منظر میں ہوتی ہے، تو پلیٹ فارم CPU، نیٹ ورک اور میموری تک بطور ڈیفالٹ مکمل رسائی فراہم کرتا ہے۔ صارفین آپ کی ایپ کو فعال طور پر دیکھ رہے ہیں۔ بیٹری ختم ہونے کی توقع ہے۔ وسائل کا استعمال جائز ہے۔
جس لمحے کوئی ایپ بیک گراؤنڈ میں جاتی ہے، کیلکولس مکمل طور پر بدل جاتا ہے۔ آپ کے آلے پر ممکنہ طور پر درجنوں ایپس انسٹال ہیں۔ اگر یہ سب پس منظر میں آزادانہ طور پر چلتے ہیں، تو آپ کی بیٹری چند گھنٹوں میں ختم ہو جائے گی۔ سی پی یو مسلسل فعال ہے۔ یادیں بھری ہوں گی۔ آلہ گرم اور سست ہو جاتا ہے۔
آئی او ایس اور اینڈرائیڈ دونوں نے ابتدائی فیصلہ کیا کہ پس منظر میں چلنا ایک استحقاق تھا، حق نہیں۔ ایپس کو یہ بتا کر پس منظر میں چلنے کی اجازت حاصل کرنی چاہیے کہ انہیں کس چیز کی ضرورت ہے اور کیوں۔ پلیٹ فارم پھر فیصلہ کرتا ہے کہ اس تک رسائی کیسے، کب، اور کب تک دی جائے۔
iOS اور Android نے اس مسئلے سے مختلف طریقے سے رابطہ کیا ہے، لیکن وقت کے ساتھ ساتھ پلیٹ فارم کے زیر کنٹرول اعلامیہ، درجہ بندی، اور پس منظر کے محدود کاموں کے ایک ہی ماڈل پر اکٹھا ہو گئے ہیں۔
پس منظر میں پھڑپھڑانا کس طرح چلتا ہے۔
آئی او ایس اور اینڈرائیڈ کو الگ الگ دیکھنے سے پہلے، آپ کو اس بات کی بنیادی باتوں کو سمجھنا ہوگا کہ فلٹر کیسے کام کرتا ہے۔
فلٹر ایک ہی ڈیفالٹ تنہائی میں ڈارٹ کوڈ چلاتا ہے۔ یہ تنہائی پلیٹ فارم کے مرکزی دھاگے سے جڑی ہوئی ہے۔ یہ UI، کاروباری منطق، سب کچھ ہینڈل کرتا ہے۔ جب ایپ بیک گراؤنڈ میں جاتی ہے تو اس ڈیفالٹ آئسولیشن کو کسی بھی وقت معطل کیا جا سکتا ہے۔
جب فلٹر کو پس منظر کے کام انجام دینے کی ضرورت ہوتی ہے، تو پلیٹ فارم پہلے سے طے شدہ تنہائی کو بیدار نہیں کرتا ہے۔ پس منظر پر عمل درآمد کے لیے خاص طور پر الگ تھلگ الگ، آزاد ڈارٹ کو بیدار کرتا ہے۔ یہ پس منظر کی تنہائی پہلے سے طے شدہ تنہائی سے مکمل طور پر الگ تھلگ چلتی ہے۔
عملی طور پر اس کا کیا مطلب ہے:
پس منظر کی تنہائی کو ویجیٹ ٹری تک رسائی حاصل نہیں ہے۔ آپ سیٹ اسٹیٹ کو کال نہیں کر سکتے، UI کو اپ ڈیٹ نہیں کر سکتے، وجیٹس یا BuildContext استعمال نہیں کر سکتے۔ یہ خالص ڈارٹ ایگزیکیوشن ہے جس میں UI پرت نہیں ہے۔
پس منظر کی تنہائی پہلے سے طے شدہ تنہائی کے ساتھ میموری کا اشتراک نہیں کرتی ہے۔ پس منظر میں درکار تمام ڈیٹا کو ڈسک (مشترکہ ترجیحات، مقامی ڈیٹا بیس، فائلز) پر برقرار رکھا جانا چاہیے اور پس منظر کی تنہائی سے آزادانہ طور پر پڑھنا چاہیے۔
پس منظر کی تنہائی ایک اعلیٰ سطحی فنکشن یا ایک جامد طریقہ ہونا چاہیے۔ یہ ایک گمنام فنکشن یا کلاس مثال کے طور پر ایک طریقہ نہیں ہوسکتا ہے۔ ایپ کو بیدار کرتے وقت پلیٹ فارم کو اس فنکشن کو نام سے کال کرنے کے قابل ہونا چاہیے۔
اس کو سمجھنے سے فلٹر میں پس منظر کے کاموں کے بارے میں آپ کے سوچنے کا انداز بدل جائے گا۔ ایپ مسلسل نہیں چل رہی ہے۔ پلیٹ فارم ڈارٹ کوڈ کا ایک علیحدہ حصہ رجسٹر کر رہا ہے جسے اس کے اپنے الگ تھلگ ماحول میں اپنے شیڈول کے مطابق کال کیا جا سکتا ہے۔
iOS پس منظر پر عملدرآمد
ایپس پر iOS کا اثر
iOS ریاستوں کے واضح طور پر بیان کردہ سیٹ کے ذریعے ایپس کا نظم کرتا ہے۔
جب صارف ہوم بٹن دباتا ہے تو ایپ پیش منظر سے پس منظر میں چلی جاتی ہے۔ آپ جس کام کو انجام دے رہے ہیں اسے مکمل کرنے کے لیے iOS آپ کو وقت کی ایک بہت ہی مختصر ونڈو دیتا ہے، عام طور پر 5 سے 10 سیکنڈز۔ اس کے بعد، ایپ کو روک دیا جائے گا۔ معطل کا مطلب ہے کہ میموری مکمل طور پر منجمد ہے۔ ڈارٹ کوڈ نہیں چلتا ہے۔ نیٹ ورک کی درخواستیں باہر نہیں جا رہی ہیں۔ ایپ RAM میں ہے لیکن بطور ڈیفالٹ موقوف ہے۔
اگر اسے میموری کی ضرورت ہو تو iOS کسی بھی وقت منجمد ایپس کو ختم کر سکتا ہے۔ جب صارف ایپ پر واپس آتا ہے، iOS یا تو ایپ کو معطل حالت (تیز) سے دوبارہ شروع کرتا ہے یا اسے شروع سے دوبارہ شروع کرتا ہے (آہستہ)۔ صارفین نوٹس نہیں لیں گے کہ آیا ایپ معطل ہونے کے دوران ختم ہو گئی ہے۔ ایپ کو عام طور پر دوبارہ چلنا چاہیے۔
iOS میں پس منظر میں کوئی معنی خیز کام کرنے کے لیے، آپ کو ایک ارادے کا اعلان کرنے کی ضرورت ہے۔ iOS میں مخصوص پس منظر کی خصوصیات کی فہرست ہے، لہذا ایپس کو بالکل وہی خصوصیات کی درخواست کرنی چاہیے جن کی انہیں ضرورت ہے۔ ایپل ایپ اسٹور جمع کرانے کے دوران ان اعلانات کا جائزہ لیتا ہے۔
BGTaskScheduler
BGTaskScheduler بیک گراؤنڈ ٹاسک شیڈولنگ کے لیے ایک جدید iOS API ہے۔ iOS 13 میں متعارف کرایا گیا، اس نے ایک پرانے اور کم مستحکم انداز کی جگہ لے لی۔ یہ دو قسم کے کام پیش کرتا ہے:
BGAppRefreshTask مختصر، متواتر پس منظر کے کاموں کے لیے ہے۔ اس کے بارے میں سوچیں کہ iOS مختصر طور پر آپ کی ایپ کو نئے مواد کی جانچ کرنے اور اس کی حیثیت کو اپ ڈیٹ کرنے کے لیے بیدار کر رہا ہے۔ اس میں تقریباً 30 سیکنڈ لگتے ہیں۔ iOS اس بات کا تعین کرتا ہے کہ آپ کے استعمال کے نمونوں کی بنیاد پر کوئی کارروائی کب چلانی ہے۔ اگر کوئی صارف روزانہ صبح 8 بجے ایپ کو کھولتا ہے، تو iOS یہ سیکھتا ہے اور صبح 8 بجے سے پہلے ایک ریفریش ٹاسک چلاتا ہے تاکہ یہ یقینی بنایا جا سکے کہ مواد کے آنے پر تیار ہے۔
BGPprocessingTask طویل اور بھاری کاموں کے لیے ہے۔ ڈیٹا بیس کو منتقل کریں، بڑی فائلوں پر کارروائی کریں، یا ایم ایل ماڈلز کو اپ ڈیٹ کریں۔ اس میں کچھ منٹ لگ سکتے ہیں۔ یہ کارروائیاں صرف اس وقت چلیں گی جب آپ کا آلہ مثالی طور پر وائی فائی سے منسلک ہوگا۔ آپ کو مزید وقت مل سکتا ہے، لیکن اس بات کی کوئی گارنٹی نہیں ہے کہ کام اصل میں کب چلے گا۔
iOS کے نافذ کردہ قوانین سخت ہیں۔
آپ کو Info.plist میں ٹاسک شناخت کنندہ کا اعلان کرنا ہوگا۔ BGTaskSchedulerPermittedIdentifiers ایپ بھیجنے سے پہلے۔ اگر شناخت کنندہ کا اعلان نہیں کیا جاتا ہے تو، آپریشن کو عمل میں نہیں لایا جائے گا، قطع نظر اس کے کہ کوڈ کیا کرتا ہے۔
پہلے آپ کو ٹاسک ہینڈلر کو رجسٹر کرنے کی ضرورت ہے۔ applicationDidFinishLaunching مکمل یہ پھڑپھڑانے کے شروع ہونے سے پہلے ہوتا ہے۔ ورک مینیجر پیکیج اسے خود بخود ہینڈل کرتا ہے، لیکن یہ سمجھنا ضروری ہے کہ کیوں۔
تمام آپریشنز کو بلایا جانا چاہیے۔ setTaskCompleted جب یہ ختم ہو جائے۔ اگر آپ اسے کال نہیں کرتے ہیں، تو iOS اس کام کو ناکام کے طور پر نشان زد کردے گا اور مستقبل کے کاموں کو شیڈول کرنے سے ہچکچاتا ہے۔
آپ کو ہمیشہ ایک میعاد ختم ہونے والا ہینڈلر ترتیب دینا چاہئے۔ اگر iOS کسی ٹاسک کو جلد ختم کرنے کا فیصلہ کرتا ہے، تو یہ سب سے پہلے میعاد ختم ہونے والے ہینڈلر کو کال کرے گا کہ وہ کلین اپ کرے، اسٹیٹ کو محفوظ کرے، اور ٹاسک کو نامکمل کے طور پر نشان زد کرے، جس سے آپ کو ری شیڈول کرنے کے لیے ایک مختصر ونڈو ملے گی۔
iOS پس منظر موڈ
BGTaskScheduler کے علاوہ، iOS میں مخصوص ایپ کیٹیگریز کے لیے مخصوص بیک گراؤنڈ موڈز بھی ہیں۔ ان کا اعلان Info.plist میں کیا جاتا ہے اور بہت ہی مخصوص مقاصد کے لیے مستقل پس منظر پر عمل درآمد کو فعال کرتے ہیں۔
آڈیو چلتے وقت آڈیو اور ایئر پلے ایپس کو چلتے رہتے ہیں۔ صارفین لاک اسکرین پر فی الحال چل رہے کنٹرولز کو دیکھ سکتے ہیں۔ صوتی رہنمائی والی پوڈ کاسٹ ایپس، میوزک ایپس، اور نیویگیشن ایپس اسے استعمال کرتی ہیں۔ iOS اس موڈ کو استعمال کرنے میں نرمی رکھتا ہے کیونکہ یہ واضح ہے کہ صارف آڈیو چلانا جاری رکھنا چاہتا ہے۔
مقام کی تازہ کارییں پس منظر میں رہتے ہوئے بھی مسلسل GPS تک رسائی کی اجازت دیتی ہیں۔ دو سطحیں ہیں: اہم مقام کی تبدیلیاں سیل ٹاور ڈیٹا کا استعمال کرتی ہیں اور بیٹری کے موافق ہوتی ہیں۔ آگ لگتی ہے جب آلہ نمایاں طور پر تقریباً 500 میٹر حرکت کرتا ہے۔ مقام کی مسلسل اپ ڈیٹس درست GPS فراہم کرتی ہیں لیکن بیٹری ختم کردیتی ہیں۔ ایپل جائزوں کے دوران مقام کے پس منظر کے موڈ کی جانچ پڑتال کرتا ہے۔ آپ کو ایک حقیقی صارف کا سامنا کرنے والی وجہ کی ضرورت ہے۔
پس منظر کی بازیافت ایک میراثی طریقہ کار ہے جہاں iOS وقتاً فوقتاً آپ کی ایپ کو مواد کی بازیافت کے لیے مختصر وقت کے لیے جگاتا ہے۔ BGAppRefreshTask کے برعکس، یہ پرانے API کا استعمال کرتا ہے۔ زیادہ تر نئی ایپس BGTaskScheduler کو ترجیح دیتی ہیں۔
دور دراز کی اطلاع content-available جھنڈا سرور کو ایک مختصر پس منظر ویک اپ کو متحرک کرنے کی اجازت دیتا ہے۔ جب سرور خاموش پش نوٹیفکیشن بھیجتا ہے، iOS اس پر کارروائی کرنے کے لیے ایپ کو بیدار کرتا ہے۔ یہ ان ایپس کی تعداد ہے جو مسلسل پولنگ کے بغیر موجودہ حالت کو برقرار رکھتی ہیں۔
iOS حقیقت
iOS کے پس منظر میں چلنا بنیادی طور پر اعتماد کے بارے میں ہے۔ Apple آپ کی ایپ کے پس منظر کے وقت پر بھروسہ کرتا ہے اگر آپ اپنی ضرورت کا اعلان کرتے ہیں، اسے اس کے اعلان کردہ مقصد کے لیے استعمال کرتے ہیں، اور وقت کی حدود کی پابندی کرتے ہیں۔
اگر وقت کی حد سے تجاوز کیا جاتا ہے تو، iOS ایپ کو ختم کردے گا۔ اگر آپ بیک گراؤنڈ موڈ کی درخواست کرتے ہیں جس کی آپ کو درحقیقت ضرورت نہیں ہے، تو App Store Review اس پر پرچم لگائے گا۔ پس منظر کے مقام کی معلومات کو ایسے مقاصد کے لیے استعمال کرنا جو آپ کے لیے واضح نہیں ہیں، اس کے نتیجے میں مسترد ہو سکتے ہیں۔
واچ ڈاگ ٹائمر حقیقی ہیں۔ iOS پس منظر کے کاموں کو فعال طور پر مانیٹر کرتا ہے۔ وہ کام جو بہت لمبے عرصے تک چلتے ہیں، بہت زیادہ CPU استعمال کرتے ہیں، یا غیر متوقع طور پر برتاؤ کرتے ہیں انہیں ختم کر دیا جاتا ہے۔ بیک گراؤنڈ ٹاسکس کو تیز، گہرا، اور سسٹم کے وسائل کا احترام کرنے کے لیے بنائیں۔
android پس منظر پر عمل درآمد
اینڈرائیڈ ایپس کو کیسے متاثر کرتا ہے۔
Android ایک درجہ بندی کے ذریعے عمل کی ترجیحات کا نظم کرتا ہے۔ پیش منظر ایپس کو سب سے زیادہ ترجیح حاصل ہے۔ چلنے والی خدمات والی ایپس کو زیادہ ترجیح حاصل ہوگی۔ پس منظر کی ایپس کی ترجیح کم ہے۔ خالی عمل اور ایپس جن میں فعال اجزاء نہیں ہیں سب سے کم ترجیح رکھتے ہیں۔
جب سسٹم کو میموری کی ضرورت ہوتی ہے، تو یہ سب سے کم سے شروع کرتے ہوئے ترجیحی ترتیب میں عمل کو ختم کر دیتا ہے۔ بیک گراؤنڈ ایپس کو کسی بھی وقت ختم کیا جا سکتا ہے۔ پیش منظر کی خدمات والی ایپس کو ختم کرنا زیادہ مشکل ہے۔ فعال پیش منظر والے ایپس فطری طور پر سسٹم کے ذریعہ نہیں مارے جاتے ہیں۔
اینڈرائیڈ تاریخی طور پر iOS کے مقابلے میں زیادہ نرم رہا ہے۔ ابتدائی اینڈرائیڈ نے ایپس کو پس منظر میں خدمات کو غیر معینہ مدت تک چلانے کی اجازت دی۔ اس آزادی کا غلط استعمال کیا گیا ہے۔ ایپ چلتی رہی یہاں تک کہ اگر صارف نے کئی ہفتوں تک اس کے ساتھ بات چیت نہ کی ہو۔ بیٹری کی زندگی کم ہو رہی تھی اور اینڈرائیڈ کو جواب دینا پڑا۔
Android 8.0 Oreo کے ساتھ شروع کرتے ہوئے، گوگل نے پس منظر کی خدمات کو محدود کرنا شروع کر دیا۔ کوئی ایپ اس وقت تک پس منظر کی خدمات شروع نہیں کر سکتی جب تک کہ ایپ خود پیش منظر میں نہ ہو۔ ہر بعد کے اینڈرائیڈ ورژن نے ان پابندیوں کو مزید سخت کیا۔ Android iOS کے اعلان کردہ، محدود پس منظر کے ٹاسک ماڈل میں تبدیل ہو رہا ہے۔
پیش منظر کی خدمت
پیش منظر کی خدمات اینڈرائیڈ پر پس منظر پر عمل درآمد کی سب سے قابل اعتماد شکل ہیں۔ اسے مسلسل چلنا چاہیے اور مسلسل اطلاعات کو ظاہر کرنا چاہیے۔ رپورٹنگ کی ضرورت ہے۔ یہ اینڈرائیڈ کا صارف کو یہ بتانے کا طریقہ ہے کہ کچھ فعال طور پر ہو رہا ہے۔ صارفین تفصیلات دیکھنے کے لیے اسے دیکھ اور بڑھا سکتے ہیں اور اگر چاہیں تو اسے روک سکتے ہیں۔
میوزک پلیئر یہ بتانے کے لیے پلے بیک کنٹرولز کا استعمال کرتا ہے کہ فی الحال کون سا ٹریک چل رہا ہے۔ نیویگیشن ایپ آپ کی آمد کے متوقع وقت کے ساتھ آپ کا موجودہ راستہ دکھاتی ہے۔ فائل اپ لوڈ ایپ ایک پروگریس بار دکھاتی ہے۔ فٹنس ایپ گزرے ہوئے وقت اور موجودہ اعدادوشمار دکھاتی ہے۔
اینڈرائیڈ 14 نے پیش منظر کی سروس کی قسم متعارف کرائی ہے۔ اب ہمیں یہ اعلان کرنے کی ضرورت ہے کہ ہم کس قسم کی پیش منظر خدمت چلا رہے ہیں۔ میڈیا پلے بیک، لوکیشن، ڈیٹا سنک، کیمرہ، مائیکروفون، فون کال، ریموٹ میسجنگ، شارٹ سروس، ہیلتھ اور سسٹم مستثنیٰ قسمیں ہیں۔ یہ جان بوجھ کر iOS ماڈل کی طرف ہے جس میں Android ایک اعلان کردہ زمرہ ہے۔
پیش منظر کی خدمت اس وقت صحیح انتخاب ہوتی ہے جب صارف توقع کرتا ہے کہ کچھ سرگرمی سے ہو گا۔ موسیقی بجانا دریافت کرنا۔ فائل اپ لوڈ ہو رہی ہے۔ کوئی بھی چیز جس میں جاری سرگرمی ہے جسے صارف نے شروع کیا ہے اور اسے جاری رکھنے کی توقع ہے۔
ورک مینیجر
ورک مینجر موخر اور ضمانت شدہ پس منظر کے کاموں کے لیے گوگل کا تجویز کردہ حل ہے۔ ان اہم خصوصیات کو سمجھنا ضروری ہے جو ان کی وضاحت کرتی ہیں۔
گارنٹی کا مطلب یہ ہے کہ کام آخر کار چلے گا۔ یہاں تک کہ اگر ایپ مر جاتی ہے، صارف آلہ کو دوبارہ شروع کرتا ہے، یا سسٹم عمل کو ختم کر دیتا ہے، ورک مینجر مقامی ڈیٹا بیس میں آپریشن کو برقرار رکھتا ہے اور اگر حالات اجازت دیتے ہیں تو دوبارہ کوشش کرتے ہیں۔ یہ بنیادی طور پر پس منظر کی خدمات سے مختلف ہے، جو ایپ کے ختم ہونے پر غائب ہو جاتی ہیں۔
ڈیفر ایبل کا مطلب ہے کہ جب کام چلتا ہے تو آپ بالکل کنٹرول نہیں کر سکتے۔ ایک بار جب آپ رکاوٹوں کی وضاحت کرتے ہیں، ورک مینیجر ان رکاوٹوں کے پورا ہونے کا انتظار کرتا ہے۔ رکاوٹوں میں نیٹ ورک کنیکٹیویٹی کی ضرورت، ڈیوائس چارجنگ کی ضرورت، یا بیٹری کا ختم نہ ہونا شامل ہو سکتا ہے۔ ورک مینجر ان رکاوٹوں کے اندر بہترین وقت کا انتخاب کرتا ہے۔
متواتر کاموں کے لیے کم از کم وقفہ 15 منٹ ہے۔ یہ پلیٹ فارم کے ذریعے نافذ کیا جاتا ہے، ورک مینجر نہیں۔ بیٹری کے غلط استعمال کو روکنے کے لیے اینڈرائیڈ ایپس کو اس سے زیادہ کاموں کو شیڈول کرنے کی اجازت نہیں دیتا ہے۔
اندرونی طور پر، WorkManager جدید Android میں JobScheduler استعمال کرتا ہے۔ پسماندہ مطابقت اور رکاوٹ سے نمٹنے کی پیچیدگیوں کا نظم کریں۔
ورک مینجر ڈیٹا کو سرور کے ساتھ ہم آہنگ کرنے، لاگز یا تجزیات کو اپ لوڈ کرنے، ڈاؤن لوڈ کی گئی فائلوں پر کارروائی کرنے، پرانے کیش آئٹمز کو صاف کرنے، تھمب نیلز بنانے، یا قطار میں لگے پیغامات بھیجنے کے لیے ایک اچھا انتخاب ہے۔
ورک مینجر ان کاموں کے لیے ایک برا انتخاب ہے جنہیں فوری طور پر، عین وقت پر، یا مسلسل چلانے کی ضرورت ہے۔
سلیپ موڈ اور ایپ اسٹینڈ بائی
سلیپ موڈ اس وقت چالو ہوتا ہے جب ڈیوائس ان پلگ ہو، سٹیشنری ہو، یا اسکرین طویل مدت کے لیے بند ہو۔ سلیپ موڈ میں، Android نیٹ ورک تک رسائی کو روکتا ہے، ورک مینجر کے کاموں کو ملتوی کرتا ہے، ویک لاک کو نظر انداز کرتا ہے، اور الارم کو ملتوی کرتا ہے۔ جب آلہ واضح طور پر استعمال میں نہ ہو تو سسٹم بیٹری بچانے کے لیے اس حالت میں داخل ہوتا ہے۔
نظام وقتاً فوقتاً دیکھ بھال کی کھڑکیوں کے دوران Doze کو بند کر دیتا ہے، جس سے موخر کاموں کو چل سکتا ہے۔ آپ کا آلہ جتنی دیر تک سوتا رہے گا، یہ ونڈوز اتنی ہی کم ہوتی جائیں گی۔
صرف اعلی ترجیحی فائربیس کلاؤڈ پیغام رسانی کی اطلاعات کو ختم کیا جا سکتا ہے۔ یہی وجہ ہے کہ سرور پر بیک گراؤنڈ ریفریش چلنا اتنا طاقتور ہے۔ سرور ایک اعلی ترجیحی FCM پیغام بھیجتا ہے، اور Android اس پر کارروائی کرنے کے لیے ایپ کو نیند سے بھی بیدار کرتا ہے۔
ایپ اسٹینڈ بائی بکٹس اس بنیاد پر ایپس کی درجہ بندی کرتی ہیں کہ صارف نے حال ہی میں ان کے ساتھ کتنی بار تعامل کیا ہے۔ بالٹیاں ایکٹو، ورکنگ سیٹ، بار بار، نایاب، اور محدود ہیں۔ ایپ جس بالٹی سے تعلق رکھتی ہے اس کے پس منظر کے کام کی مقدار کو براہ راست متاثر کرتی ہے۔
ایکٹو کا مطلب ہے کہ صارف نے ایپ کو حال ہی میں استعمال کیا ہے۔ مکمل پس منظر پر عمل درآمد کی اجازت ہے۔
ورکنگ سیٹ کا مطلب ہے کہ صارف ایپ کو باقاعدگی سے استعمال کرتا ہے۔ پس منظر کے کام کتنی بار چلتے ہیں اس پر کچھ حدود ہیں۔
بار بار استعمال کا مطلب یہ ہے کہ صارفین ایپ کو اکثر استعمال کرتے ہیں، لیکن ہر روز نہیں۔ مزید پابندیاں۔
کبھی کبھار کا مطلب یہ ہے کہ صارفین شاذ و نادر ہی ایپ استعمال کرتے ہیں۔ اہم حدود ہیں۔ ورک مینیجر کی کارروائیوں میں کافی تاخیر ہوتی ہے۔
محدود کا مطلب ہے کہ ایپ کو خراب رویے کے لیے نشان زد کیا گیا ہے یا شاذ و نادر ہی استعمال کیا جاتا ہے۔ پس منظر کے کام بہت محدود ہیں۔ صارف یا سسٹم نے مؤثر طریقے سے ایپ میں ایک اطلاع ظاہر کی ہے۔
اگر کوئی ایپ کسی نایاب یا محدود بالٹی میں شامل ہے، تو پس منظر کی مطابقت پذیری غیر مستحکم ہو جاتی ہے۔ اس سے بچنے کا طریقہ آسان ہے۔ یہ ایپس بنانے کے بارے میں ہے جو لوگ درحقیقت مستقل بنیادوں پر استعمال کرتے ہیں۔
پھڑپھڑاہٹ کا نفاذ
اب دیکھتے ہیں کہ فلٹر انجینئرز اوپر دیے گئے بنیادی میکانزم کا استعمال کرتے ہوئے پس منظر کے کاموں کو کیسے نافذ کرتے ہیں۔
ترتیب دینا: پروجیکٹ کا ڈھانچہ
فلٹر کے پس منظر کے کاموں کے لیے ڈارٹ کوڈ اور بنیادی پلیٹ فارم کے درمیان ہم آہنگی کی ضرورت ہوتی ہے۔ پیکیج اس میں سے زیادہ تر کو ہینڈل کرتا ہے، لیکن ترتیب کے ایسے اقدامات ہیں جنہیں iOS اور اینڈرائیڈ دونوں طرف سے مکمل کرنے کی ضرورت ہے تاکہ اصل میں کام کیا جا سکے۔
workmanager
ورک مینیجر پیکیج فلٹر میں موخر ہونے والے پس منظر کے کاموں کا سب سے مقبول حل ہے۔ Android WorkManager اور iOS BGTaskScheduler کو لپیٹتا ہے۔
انحصار شامل کریں۔
dependencies:
workmanager: ^0.5.2
اینڈرائیڈ کو انحصار سے آگے کسی اضافی کنفیگریشن کی ضرورت نہیں ہے۔ WorkManager AndroidX کا حصہ ہے اور تمام جدید Android آلات پر دستیاب ہے۔
iOS پر، ٹاسک شناخت کنندہ کو Info.plist میں شامل کریں۔
BGTaskSchedulerPermittedIdentifiers
com.yourapp.syncTask
com.yourapp.cleanupTask
یہ Xcode میں بیک گراؤنڈ موڈ کی فعالیت کو بھی شامل کرتا ہے اور بیک گراؤنڈ فیچنگ اور بیک گراؤنڈ پروسیسنگ کو قابل بناتا ہے۔
بیک گراؤنڈ کال بیکس اعلیٰ سطح کے فنکشنز ہونے چاہئیں۔ یہ کسی کلاس کے اندر نہیں ہو سکتا۔
@pragma('vm:entry-point')
void callbackDispatcher() {
Workmanager().executeTask((taskName, inputData) async {
switch (taskName) {
case 'syncUserData':
await syncUserData(inputData);
break;
case 'cleanupOldFiles':
await cleanupOldFiles();
break;
default:
print('Unknown task: $taskName');
}
return Future.value(true);
});
}
کہ @pragma('vm:entry-point') تبصرے اہم ہیں۔ اس خصوصیت کے بغیر، ڈارٹ ٹری شیکر اسے ریلیز کی تعمیر کے دوران ہٹا سکتا ہے کیونکہ ایسا لگتا ہے کہ اسے ڈارٹ کوڈ میں نہیں بلایا گیا ہے۔ پلیٹ فارم ڈارٹ کے بجائے نام سے پکارتا ہے، لہذا ٹری شیکر حوالہ کا پتہ نہیں لگا سکتا۔
واپسی کے راستے میں true ٹاسک ورک مینجر کو مطلع کرتا ہے کہ ٹاسک کامیاب تھا۔ واپسی کے راستے میں false یہ آپ کو بتاتا ہے کہ آپریشن ناکام ہو گیا ہے اور آپ کو دوبارہ کوشش کرنی چاہیے۔
مین فنکشن سے ورک مینیجر کو شروع کریں۔
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Workmanager().initialize(
callbackDispatcher,
isInDebugMode: kDebugMode,
);
runApp(const MyApp());
}
isInDebugMode: true شیڈولنگ اور چلانے کے کاموں کے بارے میں تفصیلی معلومات ریکارڈ کرتا ہے۔ پیداوار میں اس خصوصیت کو بند کریں۔
ایک وقتی کام کو رجسٹر کریں:
Future scheduleDataSync() async {
await Workmanager().registerOneOffTask(
'syncUserData',
'syncUserData',
initialDelay: const Duration(minutes: 5),
constraints: Constraints(
networkType: NetworkType.connected,
requiresBatteryNotLow: true,
),
inputData: {
'userId': currentUser.id,
'syncType': 'full',
},
);
}
کام ایک بار چلتا ہے، کم از کم 5 منٹ کی تاخیر کے ساتھ، اور صرف اس صورت میں جب آلہ نیٹ ورک سے منسلک ہو اور بیٹری کم نہ ہو۔ ان پٹ ڈیٹا کا نقشہ کال بیک کو منتقل کیا جاتا ہے اور inputData پیرامیٹر executeTask.
باقاعدہ کاموں کو رجسٹر کریں:
Future schedulePeriodicSync() async {
await Workmanager().registerPeriodicTask(
'periodicSync',
'syncUserData',
frequency: const Duration(hours: 1),
constraints: Constraints(
networkType: NetworkType.connected,
),
);
}
پلیٹ فارم پر نافذ ہونے والی کم از کم تعدد 15 منٹ ہے۔ اگر آپ ایک چھوٹا وقفہ مقرر کرتے ہیں، تو اسے 15 منٹ تک گول کر دیا جائے گا۔ iOS پر، BGTaskScheduler اصل وقت کو کنٹرول کر سکتا ہے اور ڈیوائس کے حالات کی بنیاد پر ٹاسک کی تعدد کو کم کر سکتا ہے۔
کام منسوخ کریں:
// cancel one specific task
await Workmanager().cancelByUniqueName('periodicSync');
// cancel all registered tasks
await Workmanager().cancelAll();
flutter_background_service
ورک مینیجر پیکج موخر ہونے والے کاموں کے لیے موزوں ہے، لیکن بعض اوقات آپ کو ایسی خصوصیات کی ضرورت ہوتی ہے جو مسلسل چلتی رہیں، جیسے کہ ہیلتھ مانیٹر، ریئل ٹائم ڈیٹا اکٹھا کرنے والے، یا مستقل رابطے۔
اس کو حاصل کرنے کے لیے، flutter_Background_service ایک طویل عرصے سے چلنے والی سروس بناتی ہے۔ اینڈرائیڈ پر، یہ ایک پیش منظر کی خدمت بن جاتی ہے جو مستقل اطلاعات فراہم کرتی ہے۔ iOS پس منظر کے طریقوں کا مجموعہ استعمال کرتا ہے۔
انحصار شامل کریں۔
dependencies:
flutter_background_service: ^5.0.5
flutter_local_notifications: ^17.0.0
بیک گراؤنڈ سروس انٹری پوائنٹ بھی ایک اعلیٰ سطحی فنکشن ہونا چاہیے۔
@pragma('vm:entry-point')
void onStart(ServiceInstance service) async {
DartPluginRegistrant.ensureInitialized();
if (service is AndroidServiceInstance) {
service.on('setAsForeground').listen((event) {
service.setAsForegroundService();
});
service.on('setAsBackground').listen((event) {
service.setAsBackgroundService();
});
}
service.on('stopService').listen((event) {
service.stopSelf();
});
// your actual background work runs here
Timer.periodic(const Duration(seconds: 30), (timer) async {
if (service is AndroidServiceInstance) {
if (await service.isForegroundService()) {
service.setForegroundNotificationInfo(
title: 'App is running',
content: 'Last sync: ${DateTime.now()}',
);
}
}
// do the actual work
await performBackgroundSync();
// send data to the main isolate if needed
service.invoke('update', {
'lastSync': DateTime.now().toIso8601String(),
});
});
}
سروس شروع کریں۔
Future initializeBackgroundService() async {
final service = FlutterBackgroundService();
const AndroidNotificationChannel channel = AndroidNotificationChannel(
'background_service',
'Background Service',
description: 'This channel is used for the background service notification',
importance: Importance.low,
);
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
await service.configure(
androidConfiguration: AndroidConfiguration(
onStart: onStart,
autoStart: true,
isForegroundMode: true,
notificationChannelId: 'background_service',
initialNotificationTitle: 'App Running',
initialNotificationContent: 'Background sync active',
foregroundServiceNotificationId: 888,
),
iosConfiguration: IosConfiguration(
autoStart: true,
onForeground: onStart,
onBackground: onIosBackground,
),
);
await service.startService();
}
پس منظر کی خدمات اور UI کے درمیان مواصلت:
// in your widget, listen for updates from the background service
class HomeScreen extends StatefulWidget {
@override
State createState() => _HomeScreenState();
}
class _HomeScreenState extends State {
String lastSync="Never";
@override
void initState() {
super.initState();
FlutterBackgroundService().on('update').listen((event) {
setState(() {
lastSync = event?['lastSync'] ?? 'Unknown';
});
});
}
void stopService() {
FlutterBackgroundService().invoke('stopService');
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Text('Last sync: $lastSync'),
ElevatedButton(
onPressed: stopService,
child: const Text('Stop Background Service'),
),
],
),
);
}
}
کہ invoke اور on یہ طریقہ پس منظر کی تنہائی اور بنیادی تنہائی کے درمیان دو طرفہ مواصلاتی چینل بناتا ہے۔ بیک گراؤنڈ سروس ڈیٹا پر مشتمل ایونٹ کو کال کرتی ہے۔ UI ان واقعات کو سنتا ہے اور اسی کے مطابق اپ ڈیٹ کرتا ہے۔
background_fetch
سادہ متواتر پس منظر کے کاموں کے لیے جن کے لیے Workmanager کے مکمل پابندی والے نظام کی ضرورت ہوتی ہے، background_fetch ایک کلینر API فراہم کرتا ہے۔
dependencies:
background_fetch: ^1.2.1
void main() {
runApp(const MyApp());
BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask);
}
@pragma('vm:entry-point')
void backgroundFetchHeadlessTask(HeadlessTask task) async {
String taskId = task.taskId;
bool isTimeout = task.timeout;
if (isTimeout) {
BackgroundFetch.finish(taskId);
return;
}
await performQuickSync();
BackgroundFetch.finish(taskId);
}
ترتیب اور آغاز:
Future configureBackgroundFetch() async {
await BackgroundFetch.configure(
BackgroundFetchConfig(
minimumFetchInterval: 15,
stopOnTerminate: false,
enableHeadless: true,
requiresBatteryNotLow: false,
requiresCharging: false,
requiresStorageNotLow: false,
requiresDeviceIdle: false,
requiredNetworkType: NetworkType.ANY,
),
(taskId) async {
await performQuickSync();
BackgroundFetch.finish(taskId);
},
(taskId) async {
// timeout handler
BackgroundFetch.finish(taskId);
},
);
}
کال کرنا BackgroundFetch.finish(taskId) درکار ہے۔ iOS پر، ایک ناکام شٹ ڈاؤن کال پلیٹ فارم کو اشارہ کرتی ہے کہ کام صحیح طریقے سے مکمل نہیں ہوا، جو مستقبل کے شیڈولنگ کو متاثر کرے گا۔ اینڈرائیڈ ورک مینیجر کو مطلع کرتا ہے کہ کام مکمل ہو گیا ہے۔
قرنطینہ کے درمیان ڈیٹا رکھیں
پس منظر کی تنہائی اور پہلے سے طے شدہ تنہائی میموری کا اشتراک نہیں کرتی ہے، لہذا ڈیٹا کو ڈسک پر رہنا چاہیے۔
سب سے عام نقطہ نظر سادہ کلیدی قدر والے ڈیٹا کے لیے مشترکہ ترجیحات اور مقامی ڈیٹا بیس جیسے کہ sqflite یا سٹرکچرڈ ڈیٹا کے لیے isar ہیں۔
// writing from background isolate
@pragma('vm:entry-point')
void callbackDispatcher() {
Workmanager().executeTask((taskName, inputData) async {
final prefs = await SharedPreferences.getInstance();
// fetch new data
final newData = await fetchFromServer();
// persist for main isolate to read
await prefs.setString('lastSyncData', jsonEncode(newData));
await prefs.setString('lastSyncTime', DateTime.now().toIso8601String());
return Future.value(true);
});
}
// reading in main isolate when app comes to foreground
class HomeScreen extends StatefulWidget {
@override
State createState() => _HomeScreenState();
}
class _HomeScreenState extends State {
@override
void initState() {
super.initState();
loadLastSyncedData();
}
Future loadLastSyncedData() async {
final prefs = await SharedPreferences.getInstance();
final data = prefs.getString('lastSyncData');
final syncTime = prefs.getString('lastSyncTime');
if (data != null) {
setState(() {
// update your state with the synced data
});
}
}
}
فیصلہ سازی کا فریم ورک
اپنے پس منظر کے کام کی ضروریات پر غور کرتے وقت، یہ فیصلہ کرنے کا طریقہ یہ ہے کہ کس نقطہ نظر سے رجوع کرنا ہے:
کیا صارف کسی سرگرمی کو انجام دینے کی توقع رکھتا ہے جیسے موسیقی بجانا، نیویگیشن کرنا، یا فائل اپ لوڈ کرنا؟ flutter_Background_service کے ذریعے پیش منظر کی سروس استعمال کریں۔ مسلسل اطلاعات صرف ایک ضرورت نہیں ہیں۔ وہ ایسی چیز ہیں جو براہ راست صارف کو بتاتی ہے کہ ایپ کیا کر رہی ہے۔
کام آخرکار کرنے کی ضرورت ہے، لیکن ضروری نہیں کہ ابھی ہو؟ ڈیٹا سنکرونائزیشن، لاگ اپ لوڈ، فائل پروسیسنگ، کیش کلیننگ وغیرہ۔ پھر ورک مینجر استعمال کریں۔ ٹاسک پر عمل درآمد کو یقینی بناتا ہے، رکاوٹوں کا احترام کرتا ہے، اور ایپ کے دوبارہ شروع ہونے اور ڈیوائس کے ریبوٹس پر برقرار رہتا ہے۔
سرور کو متحرک کرنے والے سگنل پر کچھ کرنے کی ضرورت ہے؟ خودکار، اعلی ترجیحی اطلاعات کے ساتھ Firebase کلاؤڈ پیغام رسانی کا استعمال کریں۔ سرور ایک سگنل بھیجتا ہے، iOS اور Android ایپ کو جگاتے ہیں، اور پس منظر کی تنہائی کام کی دیکھ بھال کرتی ہے۔ اس سے اینڈرائیڈ کا سلیپ موڈ ٹوٹ جاتا ہے اور iOS کے سائلنٹ پش میکانزم کے ساتھ کام کرتا ہے۔
کیا کم سے کم رکاوٹوں کے ساتھ ایک سادہ سائیکلیکل شیڈول پر کام کیا جانا چاہئے؟ اگر ورک مینیجر کا مکمل رکاوٹ کا نظام آپ کی ضرورت سے زیادہ ہے تو، آسان API کے لیے background_fetch استعمال کریں۔
کیا آپ کا کام درست وقت کی ضرورت ہے؟ اس پر دوبارہ غور کریں کہ کیا واقعی اس کے پس منظر میں ہونے کی ضرورت ہے۔ اگر صارف نے 3 PM کے لیے نوٹیفکیشن مقرر کیا ہے، تو مقامی اطلاع درست طریقہ ہے۔ نوٹیفیکیشن عین وقت پر فائر ہوتے ہیں، قطع نظر اس سے کہ ایپ پس منظر میں ہے یا نہیں۔
ایک نوٹ خاص طور پر iOS کے حوالے سے: پھڑپھڑانے والے پیکجز ایپل کی حدود میں کام نہیں کر سکتے۔ جب آپ BGAppRefreshTask کو رجسٹر کرتے ہیں، تو iOS فیصلہ کرتا ہے کہ اسے کب چلانا ہے۔ جب آپ WorkManager پر پابندیاں لگاتے ہیں، تو Android اس بات کا تعین کرتا ہے کہ رکاوٹیں کب پوری ہوں گی۔ پلیٹ فارم کنٹرول میں ہے۔ آپ کا کام واضح طور پر اس بات کا اعلان کرنا ہے کہ آپ کو کیا ضرورت ہے، جب پلیٹ فارم فراہم کرے تو ونڈوز کو صحیح طریقے سے ہینڈل کریں، اور جب بیک گراؤنڈ ٹاسک توقع سے زیادہ تاخیر سے چلیں تو اپنی ایپ کو لچکدار بنائے۔
نتیجہ
موبائل پر بیک گراؤنڈ ایگزیکیوشن فلٹر کا مسئلہ یا ڈارٹ کا مسئلہ نہیں ہے۔ یہ ایک پلیٹ فارم کا مسئلہ ہے جس کے اوپر فلٹر بیٹھتا ہے۔
iOS ڈیزائن کے لحاظ سے محدود ہے۔ مطلوبہ پس منظر کے کاموں کے مخصوص زمروں کا اعلان کریں۔ ایپل جانچتا ہے کہ آیا استعمال کا معاملہ جائز ہے۔ ایک بار منظور ہونے کے بعد، پلیٹ فارم ایک کنٹرول شدہ، وقت کے لیے محدود ونڈو فراہم کرتا ہے۔ اگر اس ونڈو سے تجاوز کیا جاتا ہے، تو سسٹم کام کو ختم کر دیتا ہے۔
اینڈروئیڈ نے اجازت کے ساتھ شروع کیا اور ہر بڑے ورژن کے ساتھ زیادہ پابندی والا بن جاتا ہے۔ پیش منظر کی خدمات بصری اطلاعات کے ساتھ قابل اعتماد مسلسل عملدرآمد فراہم کرتی ہیں۔ ورک مینجر رکاوٹوں کے ذریعے سست عملدرآمد کی ضمانت دیتا ہے۔ ڈوز موڈ اور ایپ اسٹینڈ بائی بالٹی ڈیوائس کی حالت اور صارف کے رویے کی بنیاد پر ہر چیز کو محدود کرتی ہے۔
فلٹر ان پیکجوں کے ذریعے دونوں کو جوڑتا ہے جو مقامی APIs سے نقشہ بناتا ہے۔ ورک مینیجر دونوں پلیٹ فارمز پر موخر کاموں کو سنبھالتا ہے۔ flutter_Background_service جاری آپریشنز کو پیش منظر کی اطلاعات کے ذریعے ہینڈل کرتی ہے۔ background_fetch ایک کلینر API کے ساتھ سادہ متواتر کاموں کو ہینڈل کرتا ہے۔
انجینئرز جو موبائل بیک گراؤنڈ ٹاسک میں کامیاب ہوتے ہیں وہ ہوتے ہیں جو سمجھتے ہیں کہ پلیٹ فارم اصل میں کیا کرتا ہے اور ان رکاوٹوں کو ذہن میں رکھتے ہوئے ڈیزائن کرتے ہیں۔ وہ پلیٹ فارم سے نہیں لڑتے۔ ایک ایسا نظام بنائیں جو اس کی ضرورت کا اعلان کرے، دی گئی کھڑکیوں کو سنبھالے، الگ تھلگ حدود میں مناسب طریقے سے حالت کو برقرار رکھے، اور پس منظر کے کاموں میں تاخیر یا ملتوی ہونے پر لچکدار ہو۔
دراصل موبائل پر بیک گراؤنڈ ٹاسک اس طرح انجام پاتے ہیں۔
مقامی اور ہائبرڈ موبائل انجینئرنگ کے پس منظر کے عمل کو سمجھنا اور ایپ لائف سائیکل کی نٹی-گریٹی آپ کو مخصوص کاموں کو انجام دینے کے لیے درکار ٹاسک ہینڈلرز کا انتخاب کرتے وقت باخبر تعمیراتی فیصلے کرنے میں مدد کرے گی۔
کوڈنگ کا مزہ لیں !!