Службы Android
Служба — это компонент, который работает в фоновом режиме для выполнения длительных задач, не требующих взаимодействия с пользователем. Она может продолжать работу, даже если приложение уничтожено. По сути, служба имеет два состояния —
| State | Описание |
|---|---|
| Запущена | Когда компонент Android-приложения, например, activity, запускает службу с помощью startService(), служба находится в состоянии «Запущена». После запуска служба может работать в фоновом режиме неограниченно долго, даже если компонент, который её запустил, уничтожен. |
| Привязана | Когда компонент Android-приложения привязывается к службе с помощью bindService(), служба находится в состоянии «Привязана». Служба в состоянии «Привязана» предоставляет интерфейс клиент-сервер, который позволяет компонентам взаимодействовать со службой, например, отправлять запросы, получать результаты и даже выполнять межпроцессное взаимодействие через IPC. |
Службы имеют методы жизненного цикла, которые позволяют отслеживать изменения состояния службы и выполнять работу на соответствующих этапах. Левая диаграмма ниже показывает жизненный цикл службы, созданной через startService(), а правая диаграмма показывает жизненный цикл, когда служба создана через bindService():
Чтобы создать службу, вам нужно создать класс Java, который расширяет базовый класс Service или один из его известных подклассов. Базовый класс Service определяет различные callback-методы и большинство важных методов. Вам не нужно реализовывать все callback-методы. Однако всё ещё очень важно понимать их все. Реализация этих callback-методов гарантирует, что ваше приложение ведёт себя так, как ожидают пользователи.
| Обратный вызов | Описание |
|---|---|
| onStartCommand() | Когда другие компоненты (например, activity) запрашивают запуск службы, вызывая startService(), система вызывает этот метод. Если вы реализуете этот метод, вы несёте ответственность за остановку службы, когда её работа завершена, используя stopSelf() или stopService(). |
| onBind | Когда другие компоненты хотят привязаться к службе с помощью bindService(), система вызывает этот метод. Если вы реализуете этот метод, вам нужно вернуть объект IBinder, чтобы предоставить интерфейс, который клиенты могут использовать для связи со службой. Вы должны реализовать этот метод; если вы не хотите разрешать привязку, просто верните null. |
| onUnbind() | Когда клиент отключается от всех интерфейсов, опубликованных службой, система вызывает этот метод. |
| onRebind() | Когда новый клиент подключается к службе, после того как он ранее был уведомлен об отключении через onUnbind(Intent), система вызывает этот метод. |
| onCreate() | Когда служба впервые создается через onStartCommand() и onBind(), система вызывает этот метод. Этот вызов используется для выполнения однократной настройки. |
| onDestroy() | Когда служба больше не используется или уничтожается, система вызывает этот метод. Ваша служба должна реализовать этот метод, чтобы очистить все ресурсы, такие как потоки, зарегистрированные слушатели, приемники и т.д. |
Следующая основная служба демонстрирует жизненный цикл каждого метода -
package com.example.androidservices;
import android.app.Service;
import android.os.IBinder;
import android.content.Intent;
import android.os.Bundle;
public class HelloService extends Service {
/** 标识服务如果被杀死之后的行为 */
int mStartMode;
/** 绑定的客户端接口 */
IBinder mBinder;
/** 标识是否可以使用onRebind */
boolean mAllowRebind;
/** 当服务被创建时调用. */
@Override
public void onCreate() {
}
/** 调用startService()启动服务时回调 */
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return mStartMode;
}
/** 通过bindService()绑定到服务的客户端 */
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/** 通过unbindService()解除所有客户端绑定时调用 */
@Override
public boolean onUnbind(Intent intent) {
return mAllowRebind;
}
/** 通过bindService()将客户端绑定到服务时调用*/
@Override
public void onRebind(Intent intent) {
}
/** 服务不再有用且将要被销毁时调用 */
@Override
public void onDestroy() {
}
}
Пример
Этот пример покажет вам, как создать свою собственную службу Android с помощью простых шагов. Следуйте приведенным ниже шагам, чтобы изменить приложение Android, созданное ранее в главе примера Hello World:
| Шаг | Описание |
|---|---|
| 1 | Используйте Android Studio IDE для создания приложения Android с именем androidservices в пакете com.example.androidservices. Аналогично главе примера Hello World. |
| 2 | Измените файл основной активности MainActivity.java, чтобы добавить методы startService() и stopService(). |
| 3 | Создайте новый файл Java MyService.java в пакете com.example.androidservices. Этот файл будет реализовывать методы, связанные со службой Android. |
| 4 | Используйте тег <service.../> в файле AndroidManifest.xml, чтобы определить сервис. Приложение может иметь один или несколько сервисов без каких-либо ограничений. |
| 5 | Измените макет по умолчанию в файле res/layout/activity_main.xml, добавив две кнопки в линейном макете. |
| 6 | Не изменяйте никакие константы в файле res/values/strings.xml. Android Studio обработает строковые значения. |
| 7 | Запустите эмулятор Android, чтобы запустить приложение и проверить результаты изменений, внесённых в приложение. |
Ниже приведено изменённое содержимое файла главной активности src/com.example.androidservices/MainActivity.java. Этот файл содержит все основные методы жизненного цикла. Мы добавили методы startService() и stopService() для запуска и остановки сервиса.
package com.example.androidservices;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.content.Intent;
import android.view.View;
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
// Method to start the service
public void startService(View view) {
startService(new Intent(getBaseContext(), MyService.class));
}
// Method to stop the service
public void stopService(View view) {
stopService(new Intent(getBaseContext(), MyService.class));
}
}
Ниже приведено содержимое src/com.example.androidservices/MyService.java. Этот файл может реализовывать один или несколько методов, связанных с сервисом, в зависимости от требований. Для начинающих мы реализуем только onStartCommand() и onDestroy() -
package com.example.androidservices;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
public class MyService extends Service {
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
Toast.makeText(this, "服务已经启动", Toast.LENGTH_LONG).show();
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "服务已经停止", Toast.LENGTH_LONG).show();
}
}
Далее мы изменим файл AndroidManifest.xml. Здесь мы добавляем тег <service.../>, чтобы включить наш сервис:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidservices"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk
android:minSdkVersion="13"
android:targetSdkVersion="22" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service android:name=".MyService" />
</application>
</manifest>
Ниже приведено содержимое файла res/layout/activity_main.xml, который содержит две кнопки:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Android 服务实例"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:textSize="30dp" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="www.example.com"
android:textColor="#ff87ff09"
android:textSize="30dp"
android:layout_above="@+id/imageButton"
android:layout_centerHorizontal="true"
android:layout_marginBottom="40dp" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageButton"
android:src="@drawable/ic_launcher.html"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button2"
android:text="启动服务"
android:onClick="startService"
android:layout_below="@+id/imageButton"
android:layout_centerHorizontal="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="停止服务"
android:id="@+id/button"
android:onClick="stopService"
android:layout_below="@+id/button2"
android:layout_alignLeft="@+id/button2"
android:layout_alignStart="@+id/button2"
android:layout_alignRight="@+id/button2"
android:layout_alignEnd="@+id/button2" />
</RelativeLayout>
Ниже приведено содержимое res/values/strings.xml, определяющее две новые константы:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Android Services</string>
<string name="title_activity_main">MainActivity</string>
<string name="menu_settings">Settings</string>
<string name="action_settings">Settings</string>
</resources>
Давайте запустим только что изменённое приложение My Application. Я предполагаю, что вы уже создали AVD при настройке среды. Откройте файл активности в вашем проекте и нажмите
значок, чтобы запустить приложение в Android Studio. Android Studio устанавливает приложение на AVD и запускает его. Если всё пройдёт хорошо, в окне эмулятора отобразится следующее:

Теперь нажмите кнопку «Start Service», чтобы запустить сервис. Это выполнит написанный нами метод onStartCommand(), и в нижней части эмулятора появится сообщение «Service started», как показано ниже:

Нажмите кнопку «Stop Service» внизу, чтобы остановить сервис.
Другие расширения