فرایندهای پسزمینهای میتوانند مصرف حافظه و باتری را افزایش دهند. برای مثال، همهفرستی غیرصریح ممکن است فرایندهای پسزمینهای زیادی را که برای گوش دادن به آن ثبت شدهاند شروع کند، حتی اگر آن فرایندها کار زیادی انجام ندهند. این امر میتواند تأثیر قابلتوجهی بر عملکرد دستگاه و تجربه کاربری داشته باشد.
برای جلوگیری از محدودیتهای سیستم، مطمئن شوید از میانای برنامهسازی کاربردی مناسب برای تکلیف پسزمینهتان استفاده میکنید. سند نمای کلی تکالیف پسزمینه به شما کمک میکند API مناسب را برای نیازهایتان انتخاب کنید.
محدودیتهای شروعشده توسط کاربر
اگر برنامهای برخیاز رفتارهای بد شرحدادهشده در معیارهای کلیدی Android را نشان دهد، سیستم از کاربر میخواهد دسترسی آن برنامه به منابع سیستم را محدود کند.
اگر سیستم متوجه شود که برنامهای بیشازحد از منابع استفاده میکند، به کاربر اطلاع میدهد و به او امکان میدهد کنشهای برنامه را محدود کند. رفتارهایی که میتواند باعث نمایش این اعلان شود عبارتاند از:
- قفلهای بیداری مفرط: ۱ قفل بیداری جزئی برای یک ساعت وقتی صفحهنمایش خاموش است نگه داشته شده است
- سرویسهای پسزمینه بیشازحد: اگر برنامه سطوح میانای برنامهسازی کاربردی پایینتر از ۲۶ را هدف قرار دهد و سرویسهای پسزمینه بیشازحد داشته باشد
محدودیتهای دقیق اعمالشده توسط سازنده دستگاه تعیین میشود. برای مثال، در نسخههای ساخت AOSP، برنامههای محدودشده نمیتوانند کارها را اجرا کنند، زنگهای ساعت را فعال کنند، یا از شبکه استفاده کنند، مگراینکه برنامه در پیشزمینه باشد.
محدودیتهای دریافت همهفرستیهای فعالیت شبکه
اگر برنامهها برای دریافت همهفرستی CONNECTIVITY_ACTION در مانیفست خود ثبتنام کنند، آن را دریافت نمیکنند و فرایندهایی که به این همهفرستی وابسته هستند شروع نخواهند شد. این امر میتواند برای برنامههایی که میخواهند تغییرات شبکه را گوش دهند یا فعالیتهای شبکه انبوه را هنگام اتصال دستگاه به شبکه نامحدود انجام دهند، مشکل ایجاد کند. درحالحاضر چندین راهحل برای دور زدن این محدودیت در چارچوب Android وجود دارد، اما انتخاب راهحل مناسب به آنچه میخواهید برنامهتان انجام دهد بستگی دارد.
زمانبندی کار در اتصالهای نامحدود
هنگام ساختن WorkRequest، NetworkType.UNMETERED Constraint اضافه کنید.
fun scheduleWork(context: Context) { val workManager = WorkManager.getInstance(context) val workRequest = OneTimeWorkRequestBuilder<MyWorker>() .setConstraints( Constraints.Builder() .setRequiredNetworkType(NetworkType.UNMETERED) .build() ) .build() workManager.enqueue(workRequest) }
وقتی شرایط کارتان برآورده شد، برنامهتان فراخوانی برگشتی دریافت میکند تا
روش doWork() را در کلاس Worker مشخصشده اجرا کند.
نظارت بر اتصال شبکه درحین اجرای برنامه
برنامههایی که درحال اجرا هستند همچنان میتوانند با BroadcastReceiver ثبتشده به CONNECTIVITY_CHANGE گوش دهند. بااینحال، ConnectivityManager API
روش قویتری برای درخواست تماس برگشتی فقط درصورت برآورده شدن شرایط شبکه مشخصشده ارائه میدهد.
اشیاء NetworkRequest پارامترهای فراخوانی شبکه را ازنظر NetworkCapabilities تعریف میکنند. اشیاء NetworkRequest را
با کلاس NetworkRequest.Builder ایجاد میکنید. registerNetworkCallback
سپس شیء NetworkRequest را به سیستم ارسال میکند. وقتی شرایط شبکه برآورده شود، برنامه یک فراخوانی برگشتی برای اجرای روش onAvailable() تعریفشده در کلاس ConnectivityManager.NetworkCallback خود دریافت میکند.
برنامه تا زمانی که از آن خارج نشوید یا unregisterNetworkCallback() را فراخوانی نکند، به دریافت تماسهای برگشتی ادامه میدهد.
محدودیتهای دریافت همهفرستیهای تصویری و ویدیویی
برنامهها نمیتوانند همهفرستیهای ACTION_NEW_PICTURE یا ACTION_NEW_VIDEO را ارسال یا دریافت کنند. این محدودیت به کاهش تأثیرات بر عملکرد و تجربه کاربری کمک میکند، بهویژه زمانی که چندین برنامه باید برای پردازش تصویر یا ویدیو جدید فعال شوند.
تعیین اینکه کدام مراجع محتوا باعث شروع کار شدهاند
WorkerParameters به برنامه شما اجازه میدهد اطلاعات مفیدی درباره اینکه کدام
مراجع محتوا و URIها کار را راهاندازی کردهاند دریافت کند:
List<Uri> getTriggeredContentUris()
فهرستی از URIهایی را که کار را راهاندازی کردهاند برمیگرداند. اگر هیچ URI باعث راهاندازی کار نشده باشد (برای مثال، کار بهدلیل مهلت یا دلیل دیگری راهاندازی شده باشد) یا تعداد URIهای تغییریافته بیشتر از ۵۰ باشد، این مورد خالی است.
List<String> getTriggeredContentAuthorities()
فهرست رشتهای از مراجع محتوا را که کار را راهاندازی کردهاند برمیگرداند. اگر
فهرست برگرداندهشده خالی نیست، از getTriggeredContentUris() برای بازیابی
جزئیات شناسه منبع یکسان تغییریافته استفاده کنید.
کد نمونه زیر روش CoroutineWorker.doWork() را لغو میکند
و مراجع محتوا و URIهایی را که کار را راهاندازی کردهاند ثبت میکند:
class MyWorker( appContext: Context, private val params: WorkerParameters ) : CoroutineWorker(appContext, params) { override suspend fun doWork(): Result { StringBuilder().apply { append("Media content has changed:\n") params.triggeredContentAuthorities .takeIf { it.isNotEmpty() } ?.let { authorities -> append("Authorities: ${authorities.joinToString(", ")}\n") append(params.triggeredContentUris.joinToString("\n")) } ?: append("(No content)") Log.i(TAG, toString()) } return Result.success() } }
آزمایش برنامه تحت محدودیتهای سیستم
بهینهسازی برنامهها برای اجرا در دستگاههای با حافظه کم، یا در شرایط حافظه کم، میتواند عملکرد و تجربه کاربری را بهبود بخشد. حذف وابستگیها به سرویسهای پسزمینهای و گیرندههای همهفرستی غیرصریح ثبتشده در مانیفست میتواند به اجرای بهتر برنامهتان در چنین دستگاههایی کمک کند. توصیه میشود برنامهتان را طوری بهینهسازی کنید که بدون استفاده از این فرایندهای پسزمینهای اجرا شود.
برخیاز فرمانهای اضافی پل اشکالزدایی Android (ADB) میتواند به شما کمک کند رفتار برنامه را با غیرفعال کردن آن فرایندهای پسزمینهای آزمایش کنید:
برای شبیهسازی شرایطی که همهفرستیهای غیرصریح و سرویسهای پسزمینهای دردسترس نیستند، فرمان زیر را وارد کنید:
$ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND ignoreبرای فعال کردن مجدد همهفرستیهای غیرصریح و سرویسهای پسزمینهای، فرمان زیر را وارد کنید:
$ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND allow
بهینهسازی بیشتر برنامه
برای روشهای خوب دیگر برای بهینهسازی رفتار کارهای پسزمینه، سند بهینهسازی مصرف باتری برای میاناهای برنامهسازی کاربردی زمانبندی کار را ببینید.