سرویس های پیش زمینه
یک سرویس های پیش زمینه عملیاتی را انجام می دهند که برای کاربر قابل توجه است.
سرویسهای پیش زمینه یک نوتیفیکیشن وضعیت را نشان می دهد، به طوری که کاربران به طور کامل آگاه میشوند که برنامه شما در حال انجام یک کار در پیش زمینه است و منابع سیستم را مصرف می کند. نوتیفیکیشن را نمی توان رد کرد مگر اینکه سرویس متوقف شود یا از پیش زمینه حذف شود. دستگاههایی که دارای Android 12 (سطح API 31) یا بالاتر هستند، تجربه سادهای را برای خدمات پیشزمینه کوتاهمدت ارائه میکنند. در این دستگاهها، سیستم قبل از نمایش اعلان مربوط برای یک سرویس پیشزمینه، 10 ثانیه منتظر میماند. چند استثنا وجود دارد؛ چندین نوع از سرویس ها همیشه یک اعلان را بلافاصله نمایش می دهند.
استفاده از سرویس پیش زمینه
نمونه هایی از برنامه هایی که از سرویس های پیش زمینه استفاده می کنند عبارتند از:
- یک برنامه پخش کننده موسیقی که موسیقی را در یک سرویس پیش زمینه پخش می کند. اعلان ممکن است آهنگ فعلی در حال پخش را نشان دهد.
- یک برنامه تناسب اندام که پس از دریافت مجوز از کاربر، دویدن کاربر را در یک سرویس پیش زمینه ثبت می کند. اعلان ممکن است مسافتی را که کاربر در طول جلسه تناسب اندام فعلی طی کرده است را نشان دهد.
شما فقط زمانی باید از سرویس پیش زمینه استفاده کنید که برنامه شما نیاز به انجام کاری دارد که توسط کاربر قابل توجه باشد، حتی زمانی که کاربر مستقیماً با برنامه تعامل ندارد. اگر عملکرد آنقدر کم اهمیت است که میخواهید از یک اعلان با حداقل اولویت استفاده کنید، بهتر است به جای سرویس پیش زمینه از یک سرویس پسزمینه استفاده کنید.
این مقاله مجوز لازم برای استفاده از سرویس پیشزمینه، نحوه راهاندازی سرویس پیشزمینه و حذف آن از پسزمینه، نحوه مرتبط کردن موارد استفاده خاص با انواع سرویسهای پیشزمینه، و محدودیتهای دسترسی که هنگام راهاندازی یک سرویس پیشزمینه اعمال میشود برای برنامه هایی که در پس زمینه اجرا می شود, را توضیح میدهد.
سرویس های که بلافاصله اعلان را نشان می دهند
اگر یک سرویس پیشزمینه حداقل یکی از ویژگیهای زیر را داشته باشد، سیستم اعلان مربوطه را بلافاصله پس از شروع سرویس نشان میدهد، حتی در دستگاههایی که Android 12 یا بالاتر دارند:
- اجرای سرویس با یک اعلان همراه است که شامل دکمههای برای انجام عملیات هایی است.
- نوع یک سرویس foregroundservicetype از نوع پخش رسانه، مدیا پروژکتور یا تماس تلفنی باشد.
- این سرویس یک مورد استفاده که مربوط به تماسهای تلفنی، پیمایش یا پخش رسانه، همانطور که در ویژگی دسته اعلان تعریف شده است، ارائه کند.
- در حین اجرا این سرویس با ارسال FOREGROUND_SERVICE_IMMEDIATE به متد setForegroundServiceBehavior() هنگام تنظیم اعلان، از تغییر رفتار انصراف داده باشد.
درخواست مجوز سرویس پیش زمینه
برنامههایی که Android 9 (سطح API 28) یا بالاتر را هدف قرار میدهند و از سرویس پیشزمینه استفاده میکنند، باید مجوز FOREGROUND_SERVICE را درخواست کنند، همانطور که در قطعه کد زیر نشان داده شده است. این یک مجوز عادی است، بنابراین سیستم به طور خودکار آن را به برنامه درخواست کننده اعطا می کند.
<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...> <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> <application ...> ... </application> </manifest>
توجه: اگر برنامهای که سطح API 28 یا بالاتر را هدف قرار میدهد، بدون درخواست مجوز FOREGROUND_SERVICE، اقدام به ایجاد یک سرویس پیشزمینه کند، سیستم یک SecurityException ایجاد میکند.
شروع یک Foreground سرویس
قبل از اینکه از سیستم درخواست کنید تا یک سرویس را به عنوان سرویس پیش زمینه اجرا کند، خود سرویس را راه اندازی کنید:
Context context = getApplicationContext(); Intent intent = new Intent(...); //در این intent باید سرویس مد نظر را مشخص کنید context.startForegroundService(intent);
در داخل سرویس، معمولاً در متد onStartCommand()، می توانید درخواست کنید که سرویس شما در پیش زمینه اجرا شود. برای این کار متد startForeground() را فراخوانی کنید. این متد دو پارامتر دارد: یک عدد صحیح مثبت که به طور منحصر به فرد اعلان را در نوار وضعیت شناسایی می کند و خود شی Notification.
توجه: اعلان نوار وضعیت باید از اولویت PRIORITY_LOW یا بالاتر استفاده کند. اگر برنامه شما سعی کند از اعلانی استفاده کند که اولویت کمتری دارد، سیستم پیامی را به کشوی اعلان اضافه می کند و کاربر را از استفاده برنامه از سرویس پیش زمینه آگاه می کند.
نمونه مثال :
Intent notificationIntent = new Intent(this, ExampleActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); Notification notification = new Notification.Builder(this, CHANNEL_DEFAULT_IMPORTANCE) .setContentTitle(getText(R.string.notification_title)) .setContentText(getText(R.string.notification_message)) .setSmallIcon(R.drawable.icon) .setContentIntent(pendingIntent) .setTicker(getText(R.string.ticker_text)) .build(); // Notification ID نباید 0 باشد. startForeground(ONGOING_NOTIFICATION_ID, notification);
محدودیت ها در شروع سرویس
برنامههایی که Android 12 (سطح API 31) یا بالاتر را هدف قرار میدهند، نمیتوانند سرویس پیشزمینه را هنگام اجرا در پسزمینه راهاندازی کنند، بهجز چند مورد خاص. اگر برنامه ای سعی کند یک سرویس پیش زمینه را در حالی که برنامه در پس زمینه اجرا می شود راه اندازی کند و سرویس پیش زمینه یکی از موارد استثنایی را برآورده نکند، سیستم یک ForegroundServiceStartNotAllowedException را ایجاد می کند.
توجه: اگر یکی از برنامهها متد Context.startForegroundService() را برای راهاندازی یک سرویس پیشزمینه که متعلق به برنامه دیگری است را فراخوانی کند، این محدودیتها فقط در صورتی اعمال میشوند که هر دو برنامه Android 12 یا بالاتر را هدف قرار داده باشند.
بررسی توانایی اجرای سرویس در برنامه
برای درک بهتر زمانی که برنامه شما سعی میکند سرویس پیشزمینه را در حین اجرا در پسزمینه راهاندازی کند، میتوانید اعلانهایی را فعال کنید که هر بار که این رفتار رخ میدهد ظاهر میشوند. برای انجام این کار، دستور ADB زیر را در ماشین توسعه متصل به دستگاه تست یا شبیه ساز خود اجرا کنید:
adb shell device_config put activity_manager \ default_fgs_starts_restriction_notification_enabled true
گذر از محدودیت های شروع پس زمینه
در شرایط زیر، برنامه شما میتواند سرویس پیشزمینه را حتی زمانی که برنامه شما در پسزمینه اجرا میشود راهاندازی کند:
- اگر برنامه شما از یک حالت قابل مشاهده برای کاربر، مانند یک اکتیویتی، انتقال یابد.
- میتوانید یک اکتیویتی را از پسزمینه شروع کند، به جز در مواردی که برنامه دارای یک اکتیویتی در حال فعالیت باشد.
- برنامه شما با استفاده از Firebase Cloud Messaging پیامی با اولویت بالا دریافت می کند.
توجه: هنگامی که برنامه شما در سطل مکرر یا سطل محدودتر قرار دارد، پیامهای FCM با اولویت بالا ممکن است به اولویت عادی کاهش یابد. اگر اولویت پیام کاهش یابد، برنامه شما نمیتواند سرویس پیشزمینه را راهاندازی کند. برای بررسی اولویت پیام FCM که برنامه شما دریافت می کند، با فراخوانی متد getPriority() از اولویت آن آگاه شوید.
- کاربر اقدامی را روی یک عنصر رابط کاربری مربوط به برنامه شما انجام می دهد. برای مثال، ممکن است با یک حباب، اعلان، ویجت یا اکتیویتی تعامل داشته باشند.
- فرا خواندن یک زنگ دقیق برای تکمیل عملی که کاربر درخواست می کند.
- متد ورودی فعلی دستگاه برنامه شما باشد.
- دریافت رویدادی در برنامه شما که مربوط به geofencing یا انتقال تشخیص اکتیویتی است.
- پس از راهاندازی مجدد دستگاه و دریافت broadcast مربوط به intent های ACTION_BOOT_COMPLETED، ACTION_LOCKED_BOOT_COMPLETED یا ACTION_MY_PACKAGE_REPLACED.
- برنامه شما broadcast مربوط به intent های ACTION_TIMEZONE_CHANGED، ACTION_TIME_CHANGED یا ACTION_LOCALE_CHANGED را در کلاس broadcast دریافت میکند.
- برنامه شما پخش بلوتوثی دریافت می کند که به مجوزهای BLUETOOTH_CONNECT یا BLUETOOTH_SCAN نیاز دارد.
- برنامههایی با نقشها یا مجوزهای سیستمی خاص، مانند مالکان دستگاه و مالکان نمایه.
- برنامه شما از مدیر دستگاه همراه استفاده می کند و مجوز REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND یا REQUEST_COMPANION_RUN_IN_BACKGROUND را اعلام می کند. در صورت امکان، از REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND استفاده کنید.
- کاربر بهینه سازی باتری را برای برنامه شما خاموش می کند. میتوانید با ارسال آنها به صفحه اطلاعات برنامه در تنظیمات سیستم، به کاربران کمک کنید این گزینه را پیدا کنند. برای انجام این کار، یک intent را فراخوانی کنید که حاوی کنش intent ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS است.
حذف یک سرویس از پیش زمینه
برای حذف سرویس از پیش زمینه متد stopForeground() را فراخوانی کنید. این متد یک Boolean می گیرد که نشان می دهد اعلان نوار وضعیت نیز حذف شود یا خیر. توجه داشته باشید که سرویس به کار خود ادامه می دهد. اگر سرویس را در حالی که در پیش زمینه در حال اجرا است متوقف کنید، اعلان آن حذف می شود.
اعلام انواع سرویس های پیش زمینه
اگر برنامه شما Android 10 (سطح API 29) یا بالاتر را هدف قرار میدهد و به اطلاعات موقعیت مکانی در یک سرویس پیشزمینه دسترسی دارد، نوع سرویس پیشزمینه مکان را به عنوان ویژگی مؤلفه <service> خود اعلام کنید. اگر برنامه شما Android 11 (سطح API 30) یا بالاتر را هدف قرار میدهد و به دوربین یا میکروفون در سرویس پیشزمینه دسترسی دارد، انواع سرویس پیشزمینه دوربین یا میکروفون را به ترتیب بهعنوان ویژگیهای مؤلفه <service> خود اعلام کنید.
توجه: اگرچه افزودن نوع سرویس پیشزمینه به سرویس پیشزمینه امکان دسترسی به مکان، دوربین یا میکروفون را میدهد، اما این سرویس پیشزمینه همچنان تحت تأثیر محدودیتهای دسترسی معرفیشده در اندروید 11 قرار دارد.
بهطور پیشفرض، وقتی در زمان اجرا, متد ()startForeground را فراخوانی میکنید، سیستم اجازه دسترسی به هر یک از انواع سرویسهایی را که در مانیفست برنامه اعلام میکنید، میدهد. همانطور که در قطعه کد های زیر نشان داده شده است، میتوانید دسترسی به زیرمجموعهای از انواع سرویس اعلامشده را محدود کنید.
مثال با استفاده از موقعیت مکانی و دوربین
اگر یک سرویس پیش زمینه در برنامه شما نیاز به دسترسی به موقعیت مکانی و دوربین دستگاه دارد، سرویس را همانطور که در قطعه زیر نشان داده شده است، اعلام کنید:
فایل AndroidManifest.xml :
<manifest> ... <service ... android:foregroundServiceType="location|camera" /> </manifest>
در زمان اجرا، اگر سرویس پیش زمینه فقط نیاز به دسترسی به زیرمجموعه ای از انواع اعلام شده در مانیفست داشته باشد، می توانید دسترسی سرویس را با استفاده از منطق موجود در قطعه کد زیر محدود کنید:
درون کلاس سرویس مورد نظر :
Notification notification = ...; Service.startForeground(notification, FOREGROUND_SERVICE_TYPE_LOCATION);
مثال استفاده از مکان، دوربین و میکروفون در سرویس
اگر یک سرویس پیش زمینه نیاز به دسترسی به مکان، دوربین و میکروفون دارد، سرویس را همانطور که در قطعه زیر نشان داده شده است، اعلام کنید:
فایل AndroidManifest.xml :
<manifest> ... <service ... android:foregroundServiceType="location|camera|microphone" /> </manifest>
در زمان اجرا، اگر سرویس پیش زمینه فقط نیاز به دسترسی به زیرمجموعه ای از انواع اعلام شده در مانیفست داشته باشد، می توانید دسترسی سرویس را با استفاده از منطق موجود در قطعه کد زیر محدود کنید:
درون کلاس سرویس مورد نظر :
Notification notification = ...; Service.startForeground(notification, FOREGROUND_SERVICE_TYPE_LOCATION | FOREGROUND_SERVICE_TYPE_CAMERA);
اضافه کردن انواع سرویس پیش زمینه کارگر Work Manager
اگر برنامه شما از Work Manager استفاده میکند و کارگر طولانیمدتی دارد که نیاز به دسترسی به موقعیت مکانی، دوربین یا میکروفون را دارد، مراحل اضافه کردن یک نوع سرویس پیشزمینه به یک کارگر طولانیمدت را دنبال کنید و انواع سرویس پیشزمینه اضافی یا جایگزین را که کارگر شما استفاده می کند, مشخص کنید. می توانید از انواع سرویس پیش زمینه زیر انتخاب کنید:
- FOREGROUND_SERVICE_TYPE_LOCATION
- FOREGROUND_SERVICE_TYPE_CAMERA
- FOREGROUND_SERVICE_TYPE_MICROPHONE
دسترسی محدود به مکان، دوربین و میکروفون
برای کمک به محافظت از حریم خصوصی کاربر، Android 11 (سطح API 30) محدودیتهایی را برای زمانی که یک سرویس پیشزمینه میتواند به مکان، دوربین یا میکروفون دستگاه دسترسی داشته باشد، معرفی میکند. هنگامی که برنامه شما یک سرویس پیش زمینه را در حالی که برنامه در پس زمینه اجرا می شود راه اندازی می کند، سرویس پیش زمینه دارای محدودیت های زیر است:
- تا زمانی که کاربر مجوز ACCESS_BACKGROUND_LOCATION را به برنامه شما اعطا نکرده باشد، سرویس پیش زمینه نمی تواند به مکان دسترسی پیدا کند.
- سرویس پیش زمینه نمی تواند به میکروفون یا دوربین دسترسی پیدا کند.
گذر از محدودیت ها
در برخی شرایط، حتی اگر یک سرویس پیشزمینه در حالی که برنامه در پسزمینه اجرا میشود، راهاندازی شود، همچنان میتواند به اطلاعات موقعیت مکانی، دوربین و میکروفون دسترسی داشته باشد، در حالی که برنامه در پیشزمینه اجرا میشود (“هنگام استفاده”). در همین شرایط، اگر یک سرویس از نوع موقعیت مکانی توسط برنامهای راهاندازی شود که دارای مجوز ACCESS_BACKGROUND_LOCATION است، این سرویس میتواند همیشه به اطلاعات مکان دسترسی داشته باشد، حتی زمانی که برنامه در پسزمینه اجرا میشود.
لیست زیر شامل این موقعیت ها است:
- اگر توسط یک جزء سیستم راه اندازی شود.
- سرویس با تعامل با ویجت های برنامه شروع شود.
- هنگام تعامل با یک اعلان شروع شود.
- به عنوان یک PendingIntent شروع شود که از یک برنامه قابل مشاهده و متفاوت ارسال می شود.
- توسط برنامه ای راه اندازی شود که یک کنترل کننده خط مشی دستگاه است که در حالت مالک دستگاه اجرا می شود.
- سرویس توسط اپلیکیشنی راه اندازی شود که VoiceInteractionService را ارائه می دهد.
- توسط برنامه ای سرویس راه اندازی شود که دارای مجوز ممتاز START_ACTIVITIES_FROM_BACKGROUND است.
تعیین کنید کدام سرویس ها در برنامه شما تحت تأثیر قرار می گیرند
هنگام آزمایش برنامه خود، سرویس پیش زمینه آن را اجرا کنید. اگر سرویس در حال اجرا بشد اما دسترسی به مکان، میکروفون و دوربین را محدود کرده باشد، پیام زیر در Logcat ظاهر میشود:
Foreground service started from background can not have \ location/camera/microphone access: service SERVICE_NAME