Коротко про сервіси Android
Сервіси являють собою особливу організацію програми. На відміну від activity вони не вимагають наявності візуального інтерфейсу. Сервіси дають змогу виконувати довготривалі завдання без втручання користувача.
Усі сервіси успадковуються від класу Service і проходять такі етапи життєвого циклу:
Метод onCreate(): викликається під час створення сервісуМетод onStartCommand(): викликається при отриманні сервісом команди, відправленої за допомогою методуstartService()Метод onBind(): викликається при закріпленні клієнта за сервісом за допомогою методуbindService()- Метод
onDestroy(): викликається при завершенні роботи сервісу
Створимо найпростіший додаток із сервісом. Наш сервіс буде відтворювати музичний файл. І спочатку додамо в проєкт у каталог res папку raw. Для цього натиснемо правою кнопкою миші на каталог res і в контекстному меню виберемо пункт New -> Android Resource Directory.

Далі вкажемо як тип папки - raw:

І помістимо в цю папку (res/raw) який-небудь mp3-файл.
Потім додамо новий клас сервісу. Назвемо його MediaService. У підсумку вийде наступний проєкт:
Для відтворення аудіо-файлу визначимо в класі MediaService такий код:
package com.example.soundserviceapp;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
public class MediaService extends Service {
MediaPlayer ambientMediaPlayer;
@Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onCreate(){
ambientMediaPlayer=MediaPlayer.create(this, R.raw.music);
ambientMediaPlayer.setLooping(true);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId){
ambientMediaPlayer.start();
return START_STICKY;
}
@Override
public void onDestroy() {
ambientMediaPlayer.stop();
}
}
Для відтворення музичного файлу сервіс використовуватиме компонент MediaPlayer.
У сервісі перевизначаються всі чотири методи життєвого циклу. Але по суті метод onBind() не має жодної реалізації.
У методі onCreate() ініціалізується медіа-програвач за допомогою музичного ресурсу, який додано в папку res/raw.
У методі onStartCommand() починається відтворення.
Метод onStartCommand() може повертати одне зі значень, яке передбачає різну поведінку в разі, якщо процес сервісу був несподівано завершений системою:
START_STICKY: у цьому разі сервіс знову повертається до запущеного стану, так, начебто якби знову був би викликаний метод onStartCommand() без передання в цей метод об'єкта IntentSTART_REDELIVER_INTENT: у цьому разі сервіс знову повертається до запущеного стану, так, начебто якби знову було б викликано метод onStartCommand() з передачею в цей метод об'єкта IntentSTART_NOT_STICKY: сервіс залишається в зупиненому положенні
Метод onDestroy() завершує відтворення.
Щоб керувати сервісом, змінимо activity. Спочатку додамо у файл activity_main.xml кілька кнопок для керування сервісом:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/start"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Старт"
android:onClick="click"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/stop"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/stop"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Стоп"
android:onClick="click"
app:layout_constraintLeft_toRightOf="@id/start"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
І змінимо код MainActivity:
package com.example.soundserviceapp;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void click(View v) {
Intent i=new Intent(this, MediaService.class);
if (v.getId()==R.id.start) {
startService(i);
}
else {
stopService(i);
}
}
}
Для запуску сервісу використовується об'єкт Intent:
Intent i=new Intent(this, MediaService.class);
Для запуску сервісу в класі Activity визначено метод startService(), у який передається об'єкт Intent. Цей метод надсилатиме команду сервісу і викликатиме його метод onStartCommand(), а також вказуватиме системі, що сервіс має продовжувати працювати доти, доки не буде викликано метод stopService().
Метод stopService() також визначений у класі Activity і приймає об'єкт Intent. Він зупиняє роботу сервісу, викликаючи його метод onDestroy()
І наприкінці нам треба зареєструвати сервіс у файлі маніфесту:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.soundserviceapp">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.SoundServiceApp">
<service
android:name=".MediaService"
android:enabled="true"
android:exported="true" >
</service>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Реєстрація сервісу проводиться у вузлі application за допомогою додавання елемента <service>. У ньому визначається атрибут android:name, який зберігає назву класу сервісу. І крім того може приймати ще низку атрибутів:
android:enabled: якщо має значення"true", то сервіс може створюватися системою. Значення за замовчуванням -"true".android:exported: вказує, чи можуть компоненти інших додатків звертатися до сервісу. Якщо має значення"true", то можуть, якщо має значення"false", то ні.android:icon: значок сервісу, являє собою посилання на ресурсdrawableandroid:isolatedProcess: якщо має значенняtrue, то сервіс може бути запущений як спеціальний процес, ізольований від решти системи.android:label: назва сервісу, яка відображається користувачевіandroid:permission: набір дозволів, які має застосовувати додаток для запуску сервісуandroid:process: назва процесу, в якому запущено сервіс. Як правило, має ту саму назву, що й пакет застосунку.
Запустимо додаток і натиснемо на кнопку запуску сервісу:
