Статьи

Руководство по обслуживанию Android

В этом посте мы хотим поговорить о службе Android . Это ключевой компонент в разработке приложения для Android. В отличие от Activity, служба в Android работает в фоновом режиме, у них нет интерфейса и жизненный цикл сильно отличается от Activity. Используя Сервис, мы можем реализовать некоторую фоновую операцию, например, мы можем предположить, что хотим загрузить веб-страницу с удаленного сервера. Используя Сервис, мы можем реализовать многозадачность в Android.

Обзор услуг

Мы уже знаем, что активность Android может быть запущена, остановлена, уничтожена, если системные ресурсы становятся слишком низкими и, возможно, могут быть воссозданы, Служба предназначена для продления срока службы. Службу в Android можно запустить из Активности, из Приемника вещания и других служб.

Мы должны заметить, что используя Сервис, мы не создаем автоматически новые потоки, поэтому, если мы реализуем простую логику внутри нашего Сервиса, которая не требует длительной обработки, нам не нужно запускать отдельный поток, но если мы Мы должны реализовать сложную логику, с длительной обработкой, мы должны позаботиться о создании нового потока, в противном случае служба запускается в основном потоке, и это может вызвать проблему ANR.

В Android Сервис используется по двум основным причинам:

  • Реализовать многозадачность
  • Включить межпроцессное взаимодействие (IPC)

Типичным примером первого случая является приложение, которое требуется для загрузки данных с удаленного сервера, в этом случае у нас может быть Activity, которая взаимодействует с пользователем и запускает службу, которая выполняет работу в фоновом режиме, в то время как пользователь может использовать приложение и возможно, когда служба заканчивается, отправляет сообщение пользователю.

Во втором случае мы хотим «поделиться» некоторыми общими функциями, чтобы разные приложения могли их повторно использовать. Например, мы можем предположить, что у нас есть служба, которая отправляет электронную почту, и мы хотим использовать эту службу для нескольких приложений, чтобы нам не приходилось переписывать один и тот же код. В этом случае мы можем использовать IPC, чтобы служба предоставляла «удаленный» интерфейс, который может вызываться другим приложением.

В этом посте мы рассмотрим первый случай, в данном случае у нас есть локальный сервис, локальный означает, что сервис можно увидеть только внутри нашего apk.

Базовый сервис

Теперь мы знаем больше о Сервисе, мы хотим его создать. В Android для создания Сервиса мы должны расширить класс Сервиса .

1
2
3
4
5
6
7
8
public class TestService extends Service {
 
    @Override
    public IBinder onBind(Intent arg0) {       
        return null;
    }
 
}

Как мы видим, мы должны реализовать только один метод с именем onBind. В нашем случае мы используем локальный сервис, поэтому этот метод должен возвращать ноль. Как мы упоминали ранее, у Сервиса есть свой жизненный цикл, и мы можем переопределить некоторые методы обратного вызова, чтобы мы могли обрабатывать его различные состояния:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class TestService extends Service {
 
    @Override
    public void onCreate() {       
        super.onCreate();
    }
 
    @Override
    public void onDestroy() {       
        super.onDestroy();
    }
 
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {       
        return super.onStartCommand(intent, flags, startId);
    }
 
    @Override
    public IBinder onBind(Intent arg0) {       
        return null;
    }
 
}

Первый метод onCreate вызывается только один раз, когда Сервис должен быть создан. Если служба уже запущена, этот метод вызываться не будет. Мы не называем это напрямую, но именно ОС вызывает это.

OnStartCommand является наиболее важным методом, потому что он вызывается, когда нам требуется запустить Сервис. В этом методе мы передаем Намерение во время запуска Сервиса, таким образом мы можем обмениваться некоторой информацией со Сервисом. В этом методе мы реализуем нашу логику, которая может выполняться непосредственно внутри этого метода, если это не требует больших затрат времени, в противном случае мы можем создать поток. Как видите, этот метод требует, чтобы мы возвращали Integer как результат. Это целое число представляет, как служба должна обрабатываться ОС:

  • START_STICKY : Используя это возвращаемое значение, если ОС убивает нашу Службу, она будет воссоздана, но Намерение, отправленное в Службу, не будет доставлено. Таким образом, Сервис всегда работает
  • START_NOT_STICKY : Если SO убивает Сервис, он не будет воссоздавать его, пока клиент явно не вызовет команду onStart.
  • START_REDELIVER_INTENT : аналогично START_STICKY, и в этом случае Намерение будет доставлено в службу.

OnDestroy — это метод, вызываемый ОС, когда Служба будет уничтожена.

После того, как у нас есть класс обслуживания, мы должны объявить его в Manifest.xml, чтобы мы могли его использовать:

1
2
<service android:name=".TestService"
         android:enabled="true"/>

Запуск и остановка сервиса

Как мы знаем, служба должна быть запущена и в конечном итоге остановлена, чтобы она могла выполнить свою задачу. Мы можем предположить, что начать это с действия, и мы могли бы передать службе некоторую информацию, используя Intent. Мы можем предположить, что в нашей Деятельности есть две кнопки: одна для запуска и одна для остановки Службы:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
btnStart.setOnClickListener(new View.OnClickListener() {
 
    @Override
    public void onClick(View v) {
        Intent i = new Intent(MainActivity.this, TestService.class);
        i.putExtra("name", "SurvivingwithAndroid");       
        MainActivity.this.startService(i);       
    }
});
 
btnStop.setOnClickListener(new View.OnClickListener() {
 
    @Override
    public void onClick(View v) {
        Intent i = new Intent(MainActivity.this, TestService.class);
        MainActivity.this.stopService(i);
    }
});

В приведенном выше коде в строке 5 мы создаем Intent, передавая имя класса, которое обрабатывает наш Сервис, более того, мы устанавливаем некоторые параметры, такие как name, а затем запускаем Сервис в строке 7. Таким же образом, в строке 17 мы останавливаем сервис ,

android_service [4]

Нажав на кнопку Пуск, мы попадаем в журнал:

android_service_start_log [5]

Мы можем заметить, что метод onCreate вызывается, потому что мы запускаем службу впервые, если мы снова нажимаем кнопку запуска, ОС не вызывает метод onCreate. Когда мы нажимаем кнопку «Стоп», ОС уничтожает сервис.

IntentService

Как мы упоминали ранее, служба запускается в основном потоке, поэтому мы должны быть очень осторожны, когда реализуем некоторую логику в этом сервисе. Мы должны учитывать, что если эта логика является блокирующей операцией или требуется много времени для завершения, может возникнуть проблема ANR. В этом случае мы должны переместить нашу логику в отдельный поток, то есть мы должны создать поток в методе onStartCommand и запустить его.

Есть еще один класс, называемый IntentService, полученный из Service и упрощающий нашу жизнь. Этот класс полезен, когда нам не нужно обрабатывать несколько запросов одновременно. Этот класс создает рабочий поток для обработки разных запросов. Этот класс выполняет эту операцию:

  • создать отдельный поток для обработки запроса
  • создать очередь запросов и передать один Intent за раз
  • создать реализацию onStartCommand по умолчанию
  • остановить службу, когда все запросы обработаны

Если мы хотим создать IntentService, мы должны расширить класс IntentService вместо Service:

01
02
03
04
05
06
07
08
09
10
11
12
public class TestIntentService extends IntentService {
 
    public TestIntentService() {
        super("TestIntentService");       
    }
 
    @Override
    protected void onHandleIntent(Intent intent) {
 
    }
 
}

В этом случае у нас есть только один метод для реализации, называемый onHandleIntent . Здесь мы реализуем логику без заботы, если эта операция требует много времени или нет, потому что этот метод вызывается в отдельном потоке.

Запуск сервиса автоматически

Много раз мы хотим запускать наш сервис автоматически, например, во время загрузки. Мы знаем, что для запуска Сервиса нам нужен компонент для его запуска. Как мы можем сделать это? Ну, мы могли бы использовать широковещательный приемник, который запускает наш сервис. Например, если мы хотим запустить его во время загрузки смартфона, мы сначала создаем приемник Broadcast, который прослушивает это событие, а затем запускает службу.

1
2
3
4
5
6
7
8
9
public class BootBroadcast extends BroadcastReceiver {
 
    @Override
    public void onReceive(Context ctx, Intent intent) {       
        ctx.startService(new Intent(ctx, TestService.class));
 
    }
 
}

и в Manifest.xml

1
2
3
4
5
<receiver android:name=".BootBroadcast">   
    <intent-filter >
        <action android:name="android.intent.action.BOOT_COMPLETED"/>               
    </intent-filter>
</receiver>

Ссылка: руководство по обслуживанию Android от нашего партнера JCG Франческо Аццолы в блоге Surviving w / Android .