هرگاه برنامه ای در پس زمینه اجرا شود، برخی از منابع محدود دستگاه مانند RAM را مصرف می کند. این می تواند منجر به اختلال در تجربه کاربری شود، به خصوص اگر کاربر از یک برنامه فشرده منابع مانند بازی کردن یا تماشای ویدیو استفاده کند. برای بهبود تجربه کاربر، Android 8.0 (سطح API 26) محدودیتهایی را در مورد کارهایی که برنامهها میتوانند هنگام اجرا در پسزمینه انجام دهند، اعمال میکند. این سند تغییرات سیستم عامل و نحوه به روز رسانی برنامه خود را توضیح می دهد تا تحت محدودیت های جدید به خوبی کار کند.
نمای کلی
بسیاری از برنامه ها و سرویس های اندرویدی می توانند به طور همزمان اجرا شوند. به عنوان مثال، کاربر میتواند در حال انجام یک بازی در یک پنجره در حالی که در حال مرور وب در پنجره دیگر است، و از برنامه سوم برای پخش موسیقی استفاده کند. هرچه تعداد برنامهها به طور همزمان بیشتر باشد، بار بیشتری روی سیستم قرار میگیرد. اگر برنامهها یا سرویسهای اضافی در پسزمینه اجرا میشوند، بارهای اضافی روی سیستم وارد میشود که میتواند منجر به تجربه کاربری ضعیف شود. به عنوان مثال، برنامه موسیقی ممکن است به طور ناگهانی خاموش شود.
برای کاهش احتمال بروز این مشکلات، اندروید 8.0 محدودیتهایی را در مورد کارهایی که برنامهها میتوانند انجام دهند در حالی که کاربران مستقیماً با آنها در تعامل نیستند، ایجاد میکند. برنامه ها به دو صورت محدود می شوند:
محدودیتهای خدمات پسزمینه : در حالی که یک برنامه غیرفعال است، محدودیتهایی برای استفاده آن از خدمات پسزمینه وجود دارد. این در مورد خدمات پیش زمینه که بیشتر برای کاربر قابل توجه است صدق نمی کند.
محدودیتهای پخش : با استثناهای محدود، برنامهها نمیتوانند از مانیفست خود برای ثبت نام برای پخشهای ضمنی استفاده کنند. آنها هنوز هم میتوانند در زمان اجرا برای این پخشها ثبت نام کنند و میتوانند از مانیفست برای ثبتنام برای پخشهای صریح و پخشهایی که بهطور خاص در برنامه خود هدفگذاری شدهاند استفاده کنند.
در بیشتر موارد، برنامهها میتوانند با استفاده از JobScheduler
JobScheduler این محدودیتها را برطرف کنند. این رویکرد به یک برنامه اجازه میدهد تا زمانی که برنامه به طور فعال اجرا نمیشود، ترتیبی دهد که کار را انجام دهد، اما همچنان به سیستم اجازه میدهد تا این کارها را طوری برنامهریزی کند که بر تجربه کاربر تأثیری نداشته باشد. Android 8.0 چندین پیشرفت را برای JobScheduler
ارائه میکند که جایگزینی سرویسها و گیرندههای پخش با کارهای زمانبندی شده را آسانتر میکند. برای اطلاعات بیشتر، به بهبودهای JobScheduler مراجعه کنید.
محدودیت های خدمات پس زمینه
سرویسهایی که در پسزمینه اجرا میشوند میتوانند منابع دستگاه را مصرف کنند و به طور بالقوه منجر به تجربه کاربری بدتر شوند. برای کاهش این مشکل، سیستم تعدادی محدودیت در خدمات اعمال می کند.
این سیستم بین برنامه های پیش زمینه و پس زمینه تمایز قائل می شود. (تعریف پسزمینه برای اهداف محدودیتهای سرویس متفاوت از تعریفی است که مدیریت حافظه استفاده میکند؛ یک برنامه ممکن است در پسزمینه مربوط به مدیریت حافظه باشد، اما در پیشزمینه مربوط به توانایی آن برای راهاندازی خدمات است.) اگر هر یک از موارد زیر درست باشد، در پیش زمینه در نظر گرفته می شود:
- این یک فعالیت قابل مشاهده است، خواه فعالیت شروع شده باشد یا متوقف شود.
- سرویس پیش زمینه دارد.
- یکی دیگر از برنامه های پیش زمینه یا با اتصال به یکی از سرویس های آن یا با استفاده از یکی از ارائه دهندگان محتوای آن به برنامه متصل می شود. به عنوان مثال، اگر برنامه دیگری به آن متصل شود، برنامه در پیش زمینه است:
- IME
- سرویس کاغذ دیواری
- شنونده اعلان
- سرویس صوتی یا متنی
اگر هیچ یک از این شرایط درست نباشد، برنامه در پسزمینه در نظر گرفته میشود.
در حالی که یک برنامه در پیش زمینه است، می تواند خدمات پیش زمینه و پس زمینه را آزادانه ایجاد و اجرا کند. هنگامی که یک برنامه به پسزمینه میرود، یک پنجره چند دقیقهای دارد که در آن همچنان مجاز به ایجاد و استفاده از خدمات است. در انتهای آن پنجره، برنامه غیرفعال در نظر گرفته می شود. در این زمان، سیستم خدمات پسزمینه برنامه را متوقف میکند، درست مثل اینکه برنامه متدهای Service.stopSelf()
را فراخوانی کرده باشد.
تحت شرایط خاص، یک برنامه پسزمینه برای چند دقیقه در فهرست مجاز موقت قرار میگیرد. در حالی که یک برنامه در لیست مجاز است، میتواند خدمات را بدون محدودیت راهاندازی کند و خدمات پسزمینه آن مجاز به اجرا هستند. یک برنامه زمانی در لیست مجاز قرار می گیرد که وظیفه ای را انجام می دهد که برای کاربر قابل مشاهده است، مانند:
- مدیریت یک پیام با اولویت بالا Firebase Cloud Messaging (FCM) .
- دریافت پخش، مانند پیام SMS/MMS.
- اجرای
PendingIntent
از یک اعلان. - راه اندازی
VpnService
قبل از اینکه برنامه VPN خود را در پیش زمینه معرفی کند.
در بسیاری از موارد، برنامه شما میتواند خدمات پسزمینه را با JobScheduler
جایگزین کند. برای مثال، CoolPhotoApp باید بررسی کند که آیا کاربر عکسهای به اشتراک گذاشته شده از دوستان خود را دریافت کرده است، حتی اگر برنامه در پیشزمینه اجرا نشود. پیش از این، برنامه از یک سرویس پسزمینه استفاده میکرد که با فضای ذخیرهسازی ابری برنامه بررسی میشد. برای انتقال به Android 8.0 (سطح API 26)، توسعهدهنده سرویس پسزمینه را با یک کار زمانبندی شده جایگزین میکند، که به صورت دورهای راهاندازی میشود، سرور را پرس و جو میکند، سپس خارج میشود.
قبل از اندروید 8.0، روش معمول برای ایجاد یک سرویس پیشزمینه، ایجاد یک سرویس پسزمینه و سپس تبلیغ آن سرویس در پیشزمینه بود. با اندروید 8.0، یک عارضه وجود دارد. سیستم به یک برنامه پسزمینه اجازه ایجاد سرویس پسزمینه را نمیدهد. به همین دلیل، اندروید 8.0 متد جدید startForegroundService()
را برای راه اندازی یک سرویس جدید در پیش زمینه معرفی می کند. پس از اینکه سیستم سرویس را ایجاد کرد، برنامه پنج ثانیه فرصت دارد تا روش [ startForeground()
](/reference/android/app/Service#startForeground(int, android.app.Notification) سرویس را فراخوانی کند تا کاربر سرویس جدید را نشان دهد. اعلان قابل مشاهده اگر برنامه startForeground()
را در محدوده زمانی فراخوانی نکند ، سیستم سرویس را متوقف می کند و برنامه را ANR اعلام می کند.
محدودیت های پخش
اگر برنامه ای برای دریافت پخش ها ثبت نام کند، گیرنده برنامه هر بار که پخش ارسال می شود، منابع را مصرف می کند. اگر تعداد زیادی برنامه برای دریافت پخش بر اساس رویدادهای سیستم ثبت نام کنند، می تواند مشکلاتی ایجاد کند. یک رویداد سیستمی که پخش را راهاندازی میکند میتواند باعث شود همه آن برنامهها منابع را بهسرعت مصرف کنند و تجربه کاربر را مختل کند. برای کاهش این مشکل، Android 7.0 (سطح API 24) محدودیت هایی را بر روی پخش اعمال کرد، همانطور که در Background Optimization توضیح داده شد. اندروید 8.0 (سطح API 26) این محدودیت ها را سخت تر می کند.
- برنامههایی که Android 8.0 یا بالاتر را هدف قرار میدهند، دیگر نمیتوانند گیرندههای پخش را برای پخش ضمنی در مانیفست خود ثبت کنند، مگر اینکه پخش به طور خاص به آن برنامه محدود شود. پخش ضمنی پخشی است که جزء خاصی را در یک برنامه هدف قرار نمی دهد. برای مثال،
ACTION_PACKAGE_REPLACED
برای همه شنوندگان ثبتشده در همه برنامهها ارسال میشود و به آنها اطلاع میدهد که برخی از بستههای دستگاه جایگزین شده است. از آنجایی که پخش به صورت ضمنی است، به گیرندههای ثبتشده در مانیفست در برنامههایی که Android 8.0 یا بالاتر را هدف قرار میدهند، تحویل داده نمیشود.ACTION_MY_PACKAGE_REPLACED
نیز یک پخش ضمنی است، اما از آنجایی که فقط به برنامهای ارسال میشود که بسته آن جایگزین شده است، به گیرندههای ثبتشده در مانیفست تحویل داده میشود. - برنامه ها می توانند به ثبت نام برای پخش صریح در مانیفست خود ادامه دهند.
- برنامهها میتوانند از
Context.registerReceiver()
در زمان اجرا برای ثبت یک گیرنده برای هر پخش، اعم از ضمنی یا صریح استفاده کنند. - پخشهایی که به مجوز امضا نیاز دارند از این محدودیت مستثنی هستند، زیرا این پخشها فقط به برنامههایی ارسال میشوند که با گواهینامه مشابه امضا شدهاند، نه به همه برنامههای موجود در دستگاه.
در بسیاری از موارد، برنامههایی که قبلاً برای پخش ضمنی ثبت نام کردهاند، میتوانند با استفاده از JobScheduler
کارکرد مشابهی داشته باشند. به عنوان مثال، یک برنامه عکس اجتماعی ممکن است نیاز به پاکسازی دادههای خود هر از گاهی داشته باشد و ترجیح میدهد زمانی که دستگاه به شارژر متصل است این کار را انجام دهد. قبلاً، برنامه یک گیرنده برای ACTION_POWER_CONNECTED
در مانیفست خود ثبت کرده بود. وقتی برنامه آن پخش را دریافت کرد، بررسی می کرد که آیا پاکسازی لازم است یا خیر. برای انتقال به Android 8.0 یا بالاتر، برنامه آن گیرنده را از مانیفست خود حذف می کند. در عوض، برنامه یک کار پاکسازی را برنامهریزی میکند که وقتی دستگاه بیحرکت است و در حال شارژ است اجرا میشود.
راهنمای مهاجرت
بهطور پیشفرض، این تغییرات فقط بر برنامههایی تأثیر میگذارد که Android 8.0 (سطح API 26) یا بالاتر را هدف قرار میدهند. با این حال، کاربران میتوانند این محدودیتها را برای هر برنامهای از صفحه تنظیمات فعال کنند، حتی اگر برنامه سطح API کمتر از 26 را هدف قرار دهد. ممکن است لازم باشد برنامه خود را برای مطابقت با محدودیتهای جدید بهروزرسانی کنید.
بررسی کنید تا ببینید برنامه شما چگونه از خدمات استفاده می کند. اگر برنامه شما به سرویسهایی متکی است که در پسزمینه اجرا میشوند، باید آنها را جایگزین کنید. راه حل های ممکن عبارتند از:
- اگر برنامه شما نیاز به ایجاد سرویس پیش زمینه دارد در حالی که برنامه در پس زمینه است، به جای startService
startForegroundService()
startService()
استفاده کنید. - اگر سرویس توسط کاربر قابل توجه است، آن را به یک سرویس پیش زمینه تبدیل کنید. به عنوان مثال، سرویسی که صدا را پخش می کند باید همیشه یک سرویس پیش زمینه باشد. سرویس را با استفاده از متد
startForegroundService()
به جایstartService()
ایجاد کنید. - راهی برای کپی کردن عملکرد سرویس با یک کار برنامه ریزی شده پیدا کنید. اگر سرویس کاری را انجام نمی دهد که بلافاصله برای کاربر قابل توجه باشد، به طور کلی باید بتوانید به جای آن از یک کار برنامه ریزی شده استفاده کنید.
- از FCM برای بیدار کردن انتخابی برنامه خود در هنگام وقوع رویدادهای شبکه، به جای نظرسنجی در پس زمینه استفاده کنید.
- کار پس زمینه را تا زمانی که برنامه به طور طبیعی در پیش زمینه قرار گیرد به تعویق بیندازید.
گیرنده های پخش تعریف شده در مانیفست برنامه خود را مرور کنید. اگر مانیفست شما گیرنده ای را برای پخش ضمنی آسیب دیده اعلام کرد، باید آن را جایگزین کنید. راه حل های ممکن عبارتند از:
- گیرنده را در زمان اجرا با فراخوانی
Context.registerReceiver()
ایجاد کنید، به جای اینکه گیرنده را در مانیفست اعلام کنید. - از یک کار برنامه ریزی شده برای بررسی شرایطی استفاده کنید که باعث پخش ضمنی می شود.