Афоризм
По жизни балансирую на тонкой грани между 'Береженого бог бережет' и 'Сгорел сарай — гори и хата'
Последние статьи

 • Многомодульный maven
Пример создания многомодульного maven проекта
июнь 2019
 • Maven плагин launch4j
Создание exe-файла из исполняемого jar
июнь 2019
 • Основы Contacts API
Описание структуры хранения списка контактов
май 2019
 • Синхронизаторы потока
Примеры синхронизаторов пакета java.util.concurrent.
май 2019
 • Сервисы в Android
Неявное Intent отправки Email.
апрель 2019
 • Сервисы в Android
Описание и пример создания Android сервиса.
апрель 2019
 • Вызов AlarmClock
Неявное Intent для вызова AlarmClock.
март 2019
 • Намерения Intent
Описание Intent, фильтры объектов Intent.
март 2019
 • Пример 2-х Activity
Жизненные циклы 2-х Activity android положения.
март 2019

Сервисы в Android

Сервисы (службы) в Android не имеют пользовательского интерфейса, работают в фоновом режиме и представлены классом android.app.Service. Используются сервисы в тех случаях, когда не требуется вмешательства пользователя, например, для выполнения сетевых запросов к веб-серверу, обработки информации, запуска уведомлений и т.д. Сервис может продолжать работать до тех пор, пока какой-либо компонент не остановит его, либо пока он сам себя не остановит по каким-либо условиям. Таким образом, сервисы в отличие от активностей предназначены для длительного функционирования.

Сервисы Service является компонентом приложения. Запускается сервис другим компонентом приложения, который может привязаться к сервису для взаимодействия с ним. Сервис может принимать одну их двух форм : запущенный сервис и привязанный сервис.

Запущенный сервис
Сервис является «запущенным», когда он стартует вызовом метода активности startService(). После останова/уничтожения вызывающего Service компонента приложения сервис будет функционировать в фоновом режиме в течение неограниченного времени. Обычно запущенный сервис не возвращает результатов вызывающему компоненту, и должен остановиться самостоятельно после завершения операции. Например, сервис может загружать или выгружать файл по сети.

Привязанный сервис
Сервис является «привязанным», когда он стартует вызовом метода активности bindService(). Привязанный сервис функционирует в режиме «клиент-сервер», позволяющий компонентам взаимодействовать с сервисом для отправки запросов и получения результатов. Привязанный сервис функционирует только пока к нему привязан другой компонент приложения. К сервису могут быть привязаны несколько компонентов одновременно, но когда все они «отменяют привязку», сервис уничтожается.

Пример сервиса

Рассмотрим простой пример запуска и останова сервиса. Для этого нам необходимо создать приложение с интерфейсом, включающим две кнопки : кнопку старта и кнопку останова. В примере необходимо создать класс сервиса и зарегистрировать сервис в манифесте приложения src/main/AndroidManifest.xml.

Объявление сервиса в манифесте

Чтобы объявить сервис в файле манифеста приложения необходимо добавить элемент <service> в качестве дочернего элемента секции <application> . Например :

<?xml version="1.0" encoding="utf-8"?>
<manifest 
   xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.android.test.p10service">

   <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/AppTheme">

       <service android:name=".TimeService" />

       <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>

В примере объявлен сервис "TimeService", который может быть стартован в приложении. Атрибут <android:name> является единственным обязательным атрибутом, определяющим наименование класса сервиса. Имеются другие атрибуты, которые можно включить в элемент <service> для определения свойств сервиса. Например, атрибут <android:description> включает описание сервиса, а <android:permission> — разрешения. Дополнительно можно обеспечить доступность службы только для Вашего приложения, включив атрибут <android:exported> с установленным для него значением "false". Это не позвоит другим приложениям запускать Вашу службу даже при использовании явного намерения.

Для обеспечения безопасности приложения используйте явное намерение при запуске или привязке Service и не объявляйте фильтров намерений для службы. Дополнительные сведения об объявлении сервиса в манифесте представлены в документации по описанию элемента <service>.

Листинг сервиса

Рассмотрим пример сервиса TimeService, включенный в манифест приложения (см. выше). Класс TimeService наследует свойства сервиса Service и включает методы onCreate и onDestroy, которые срабатывают при создании и уничтожении сервиса. Метод onStartCommand вызывается системой при старте сервиса из активности методом startService. В этом методе обратимся к serviceTask и запустим отдельный поток Thread, который периодически будет выводить сообщения в консоль и Logcat. Метод onStartCommand получает от системы определенные параметры, которые не используются в этом примере. Метод onBind реализовывать не будем и вернем null.

package com.android.test.p10service;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

import java.util.concurrent.TimeUnit;

public class TimeService extends Service
{
    private  String   TAG_LOG = "SERVICE";
    private  boolean  STOP    = false;

    public void onCreate() {
        super.onCreate();
        Log.d(TAG_LOG, "TimeService.onCreate");
    }

    public int onStartCommand(Intent intent, int flags,
                                             int startId) {
        Log.d(TAG_LOG, "TimeService.onStartCommand");
        serviceTask();
        return super.onStartCommand(intent, flags, startId);
    }

    public void onDestroy() {
        super.onDestroy();
        STOP = true;
        Log.d(TAG_LOG, "TimeService.onDestroy");
    }

    public IBinder onBind(Intent intent) {
        Log.d(TAG_LOG, "TimeService.onBind");
        return null;
    }

    void serviceTask()
    {
        new Thread(new Runnable() {
            public void run() {
                int i = 1;
                do {
                    Log.d(TAG_LOG, "i = " + i++);
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                         e.printStackTrace();
                    }
                    Log.d(TAG_LOG, "STOP = " + STOP + ", " + 
                                  (!STOP || (i >= 25)));
                } while (!STOP || (i >= 25));
                stopSelf();
            }
        }).start();
    }
}

Описание интерфейса

При описании интерфейса используем шаблон типа LinearLayout с двумя кнопками. Заголовки кнопок внесем в файл res/values/strings.xml.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">
    <Button
        android:id="@+id/btnStart"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onClickStart"
        android:text="@string/start">
    </Button>
    <Button
        android:id="@+id/btnStop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onClickStop"
        android:text="@string/stop">
    </Button>
</LinearLayout>

Код активности

В активности MainActivity переопределим методы onStart, onResume, onPause, onStop, onDestroy, в которых в консоль будут выводится сообщения с тегом "SERVICE". К кнопкам интерфейса подключим методы старта и останова сервиса.

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends Activity
{
    final String TAG = "SERVICE";

    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btn = (Button) findViewById(R.id.btnStart);
        btn.setOnClickListener(new Button.OnClickListener(){
            public void onClick(View v) {
                startService(new Intent(MainActivity.this, 
                                        TimeService.class));
            }
        });
        btn = (Button) findViewById(R.id.btnStop);
        btn.setOnClickListener(new Button.OnClickListener(){
            public void onClick(View v) {
                stopService(new Intent(MainActivity.this,
                                       TimeService.class));
            }
        });
        Log.d(TAG, "MainActivity.onCreate");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.d(TAG, "MainActivity.onStart");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "MainActivity.onResume");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "MainActivity.onPause");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG, "MainActivity.onStop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "MainActivity.onDestroy");
    }
}

Старт примера

Ниже представлен результат вывода сообщений примера в консоль. Как видно из результатов вывода сообщений на 5-ой секунде приложение было остановлено, а сервис продолжил свою работу. На 10-ой секунде приложение возобновило свою работу, и через 3 секунды сервис был остановлен.


D/SERVICE: MainActivity.onCreate
D/SERVICE: MainActivity.onStart
D/SERVICE: MainActivity.onResume

D/SERVICE: TimeService.onCreate
D/SERVICE: TimeService.onStartCommand
D/SERVICE: i = 1
D/SERVICE: i = 2
D/SERVICE: i = 3
D/SERVICE: i = 4

D/SERVICE: MainActivity.onPause
D/SERVICE: MainActivity.onStop

D/SERVICE: i = 5
D/SERVICE: i = 6
D/SERVICE: i = 7
D/SERVICE: i = 8
D/SERVICE: i = 9

D/SERVICE: MainActivity.onStart
D/SERVICE: MainActivity.onResume

D/SERVICE: i = 10
D/SERVICE: i = 11
D/SERVICE: i = 12
D/SERVICE: TimeService.onDestroy

 

Связанные страницы

Layout интерфейса Android приложения
Жизненные циклы двух Activity
Объект намерения Intent
Отладка приложения, Logcat

  Рейтинг@Mail.ru