عیب یابی سرویس های پیش زمینه

این صفحه برخی از دلایل متداول خرابی سرویس‌های پیش‌زمینه را مورد بحث قرار می‌دهد و به شما کمک می‌کند تشخیص دهید که چه چیزی باعث این مشکل شده است.

این سند در مورد مسائل زیر بحث می کند:

قبل از اینکه عیب یابی کنید

تغییرات اخیر در خدمات پیش زمینه را بررسی کنید

اگر از خدمات پیش زمینه به طور نادرست استفاده شود، می تواند تأثیرات منفی بر عملکرد دستگاه و عمر باتری داشته باشد. به همین دلیل، نسخه های پلتفرم اندروید اغلب تغییراتی را در رفتار خدمات پیش زمینه ایجاد می کنند تا این اثرات بد را محدود کنند.

اگر با خدمات پیش زمینه مشکل دارید، باید تغییرات اسناد خدمات پیش زمینه را بررسی کنید و ببینید آیا تغییرات اخیری وجود دارد که می تواند مشکلات شما را توضیح دهد. بررسی تغییرات در این شرایط به ویژه مهم است:

  • کد سرویس پیش زمینه که قبلاً کار می کرد اکنون ناموفق است
  • شما به تازگی آزمایش را روی یک نسخه پلتفرم جدید شروع کرده اید، یا سطح API مورد نظر برنامه خود را تغییر داده اید

علاوه بر این، اگر دستگاه خود را روی پیش‌نمایش برنامه‌نویس پلتفرم آزمایش می‌کنید، مطمئن شوید که جدیدترین نسخه اسناد پیش‌نمایش توسعه‌دهنده را بررسی کنید.

خطاهای برنامه پاسخ نمی دهد (ANR).

تحت شرایط خاصی، انتظار می‌رود که یک برنامه سرویس پیش‌زمینه خود را خاموش کند. اگر برنامه سرویس را متوقف نکند، سیستم سرویس را متوقف می کند و خطای Application Not Responding (ANR) را ایجاد می کند.

سرویس کوتاه مدت بیش از حد طولانی است که باعث ANR می شود

خدمات پیش زمینه ای که از نوع سرویس کوتاه استفاده می کنند باید به سرعت و در عرض حدود سه دقیقه تکمیل شوند. هنگامی که زمان تمام می شود، سیستم متد Service.onTimeout(int,int) سرویس را فراخوانی می کند. این سرویس چند ثانیه فرصت دارد تا stopSelf() فراخوانی کند. اگر سرویس به خودی خود متوقف نشود، سیستم خطای Application Not Responsing را ایجاد می کند.

تشخیص :

اگر ANR ناشی از عدم توقف سرویس پیش زمینه باشد، سیستم یک استثنا داخلی ایجاد می کند. با بررسی Logcat می‌توانید تأیید کنید که این مشکل بوده است. در این مورد، گزارش شامل پیام زیر است:

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type FOREGROUND_SERVICE_TYPE_SHORT_SERVICE did not stop within its timeout:
[component name]"

رفع :

مطمئن شوید که تمام سرویس‌های پیش‌زمینه با زمان محدود کار خود را به پایان می‌رسانند و stopForeground(int) در محدوده زمانی سیستم فراخوانی می‌کنند.

از خدمات پیش زمینه خود بخواهید Service.onTimeout(int,int) را پیاده سازی کنند. مطمئن شوید که پیاده سازی آن متد فوراً stopSelf() را فراخوانی می کند.

استثناهای خدمات پیش زمینه

این بخش چندین مشکل خدمات پیش زمینه را توضیح می دهد که می تواند باعث شود سیستم یک استثنا ایجاد کند. اگر برنامه استثنا را نپذیرد، کاربر یک گفتگو می بیند که به او می گوید برنامه متوقف شده است.

در برخی موارد، سیستم یک استثنا داخلی ایجاد می کند. شما نمی توانید آن استثناها را بگیرید، اما می توانید به Logcat نگاه کنید تا ببینید چه استثنایی ایجاد شده است.

استثنا داخلی: مدت زمان بیش از حد مجاز است

این سیستم محدودیتی را برای مدت زمان اجرای خدمات پیش زمینه همگام سازی داده و پردازش رسانه در زمانی که برنامه در پس زمینه است، اعمال می کند . اگر سرویس از حد مجاز فراتر رفت، سیستم روش Service.onTimeout(int,int) سرویس را فراخوانی می کند. این سرویس چند ثانیه فرصت دارد تا stopSelf() فراخوانی کند. اگر سرویس به خودی خود متوقف نشود، سیستم یک استثنا داخلی ایجاد می کند که باعث از کار افتادن برنامه می شود.

تشخیص :

اگر علت بیش از مهلت زمانی باشد، Logcat پیام زیر را شامل می شود:

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type [service type] did not stop within its timeout: [component name]"

رفع :

مطمئن شوید که تمام سرویس‌های پیش‌زمینه با زمان محدود کار خود را به پایان می‌رسانند و stopForeground(int) در محدوده زمانی سیستم فراخوانی می‌کنند.

از سرویس های پیش زمینه خود بخواهید Service.onTimeout(int,int) را پیاده سازی کنند. مطمئن شوید که پیاده سازی آن متد فوراً stopSelf() را فراخوانی می کند.

استثنا داخلی: ForegroundServiceDidNotStartInTimeException

هنگامی که یک سرویس را با فراخوانی context.startForegroundService() راه اندازی می کنید، آن سرویس چند ثانیه فرصت دارد تا با فراخوانی ServiceCompat.startForeground() خود را به یک سرویس پیش زمینه ارتقا دهد. اگر سرویس این کار را انجام ندهد، سیستم خطای ANR را راه‌اندازی می‌کند.

تشخیص :

اگر سرویس پیش‌زمینه به موقع شروع نشود، برنامه از کار می‌افتد و باعث می‌شود کاربر گفتگوی برنامه متوقف شده را ببیند. در این حالت می توانید پیام زیر را در Logcat پیدا کنید:

android.app.RemoteServiceException$ForegroundServiceDidNotStartInTimeException:
Context.startForegroundService() did not then call Service.startForeground()

رفع :

مطمئن شوید که تمام سرویس‌های پیش‌زمینه تازه ایجاد شده، ServiceCompat.startForeground() در عرض چند ثانیه فراخوانی می‌کنند.

ForegroundServiceStartNotAllowedException

خطا :

سیستم ForegroundServiceStartNotAllowedException را پرتاب می کند.

علت :

این معمولاً به دلیل راه‌اندازی یک سرویس پیش‌زمینه از پس‌زمینه در زمانی که معافیت معتبری وجود ندارد، ایجاد می‌شود.

با شروع Android 12 (سطح API 31)، برنامه‌ها مجاز به راه‌اندازی سرویس‌های پیش‌زمینه در حالی که برنامه در پس‌زمینه در حال اجرا است ، با چند معافیت خاص ، ندارند. اگر بخواهید یک سرویس پیش‌زمینه را از پس‌زمینه راه‌اندازی کنید و الزامات یکی از معافیت‌ها را برآورده نکنید، سیستم ForegroundServiceStartNotAllowedException را پرتاب می‌کند. اگر شرایط معافیت را نداشته باشید، سیستم نیز این کار را انجام می دهد.

برای مثال، یک برنامه ممکن است دکمه‌ای داشته باشد که کاربر می‌تواند روی آن کلیک کند، که باعث می‌شود برنامه مقداری پردازش را انجام دهد و سپس یک سرویس پیش‌زمینه را راه‌اندازی کند. در این حالت، این خطر وجود دارد که کاربر روی دکمه کلیک کرده و بلافاصله برنامه را در پس زمینه قرار دهد. در این مورد، برنامه سعی می کند سرویس را از پس زمینه راه اندازی کند. اگر برنامه یکی از معافیت‌های مشخص‌شده را برآورده نکند، سیستم یک ForegroundServiceStartNotAllowedException پرتاب می‌کند.

علاوه بر این، برخی از معافیت ها محدودیت زمانی کوتاهی دارند. به عنوان مثال، اگر برنامه شما یک سرویس پیش زمینه را در پاسخ به یک پیام FCM با اولویت بالا راه اندازی کند، یک معافیت مختصر وجود دارد. اگر سرویس را با سرعت کافی راه اندازی نکنید، یک ForegroundServiceStartNotAllowedException دریافت می کنید.

معافیت های خاص گاهی اوقات با نسخه های جدید اندروید محدودتر می شوند. اگر نسخه Android مورد نظر برنامه شما را تغییر داده اید، تغییرات اسناد خدمات پیش زمینه را بررسی کنید و تأیید کنید که برنامه شما همچنان یکی از معافیت های مجاز را دارد.

رفع :

گردش کار برنامه خود را تغییر دهید تا زمانی که برنامه در پس‌زمینه است، نیازی به راه‌اندازی سرویس‌های پیش‌زمینه نباشد، یا تأیید کنید که برنامه شما یکی از معافیت‌ها را دارد.

می توانید از اجزای چرخه حیات مانند LiveData برای مدیریت چرخه عمر برنامه خود استفاده کنید تا ناخواسته سعی نکنید یک سرویس پیش زمینه را از پس زمینه راه اندازی کنید.

Security Exception

خطا :

سیستم SecurityException پرتاب می کند.

علت :

برنامه شما سعی کرد بدون داشتن مجوزهای لازم، یک سرویس پیش زمینه راه اندازی کند.

  • اگر برنامه‌ای Android 9 (سطح API 28) یا بالاتر را هدف قرار می‌دهد، باید مجوز FOREGROUND_SERVICE برای راه‌اندازی یک سرویس پیش‌زمینه را داشته باشد.
  • اگر برنامه‌ای اندروید 14 (سطح API 34) یا بالاتر را هدف قرار می‌دهد، باید همه پیش‌نیازهای نوع سرویس پیش‌زمینه خود را برآورده کند. این پیش نیازها در اسناد انواع خدمات پیش زمینه به تفصیل آمده است. به ویژه از الزامات زیر آگاه باشید:
    • چندین نوع سرویس پیش زمینه به مجوزهای زمان اجرا خاصی نیاز دارند. به عنوان مثال، یک سرویس پیش زمینه پیام از راه دور باید مجوز FOREGROUND_SERVICE_REMOTE_MESSAGING را داشته باشد.
  • در چندین مورد، محدودیت‌های اضافی در حین استفاده برای مجوزهای مورد نیاز برخی از انواع خدمات پیش‌زمینه وجود دارد. این مجوزها فقط زمانی که برنامه در پیش زمینه است ( با چند استثنا خاص ) به برنامه اعطا می شود. این بدان معنی است که حتی اگر برنامه شما یکی از این مجوزها را درخواست کرده باشد و به آنها اعطا شده باشد، اگر برنامه سعی کند سرویس پیش زمینه را در حالی که برنامه در پس زمینه است راه اندازی کند، سیستم یک SecurityException ایجاد می کند حتی اگر برنامه برای شروع یک سرویس پیش زمینه از پس زمینه معافیت داشته باشد. برای اطلاعات بیشتر، به محدودیت‌های راه‌اندازی سرویس‌های پیش‌زمینه که به مجوزهای حین استفاده نیاز دارند مراجعه کنید.
    • اگر مجوزهای لازم را درخواست کرده باشید، اما قبل از تأیید اعطای مجوزهای لازم، سرویس پیش زمینه را شروع کنید، ممکن است یک SecurityException دریافت کنید.

رفع :

قبل از راه‌اندازی سرویس پیش‌زمینه، تمام مجوزهای سرویس پیش‌زمینه مناسب را درخواست کنید و تأیید کنید که سایر پیش‌نیازهای زمان اجرا را برآورده کرده‌اید.