Android Start/Stop Service from Activity Example using HandlerThread
On this page, we will walk through Android start and stop Service from Activity using HandlerThread. Service runs in background and does not interact with user interface. The use of service is to run long operation like downloading content. If starting application switches to another application, still our service is running in background. Normally service does not return result to starting application. Service can be started and stopped from Activity using startService(intent) and stopService(intent) respectively by passing Intent. Service starts a new thread to run in background. Android provides HandlerThread class to start a thread with Looper. In our example we will provide a demo to start and stop service from Activity and service will log a message after every second while running in background.
android.app.Service
android.app.Service runs the long running process in background. Service does not interact to user. It will run in background even if the user switches to another application. While using Service we need to override methods. Some of them are as follows.
onCreate() : System calls it when service is first created. We can use it to initialize values for process.
onStartCommand(Intent intent, int flags, int startId) : System calls it when service is started explicitly. For every service start call, it is called.
onBind(Intent): It is used for inter process communication(IPC). It returns null if clients can not bind to service.
onDestroy(): System calls it when service is completed or stopped. We can use it for resource cleanup purpose.
Service can stop itself by calling methods as follows.
stopSelf(): On calling it, Service is stopped if it is running.
stopSelfResult(int startId): Stops the service for the most recent start id.
Find some constants which are returned from onStartCommand(Intent, int, int) .
START_STICKY : It starts the onStartCommand if killed while stating.
START_NOT_STICKY : If service is killed while starting, it does not restart until explicitly service is started.
START_REDELIVER_INTENT : If service is killed while starting, it will schedule to restart with latest intent.
To use service we need to configure it in AndroidManifest.xml within application tag.
<service android:name=".MyService"/>
Start/Stop Service from Activity
To start and stop service from Activity , we need to create Intent first for our Service . To start the service, call startService(intent) and to stop the service, call stopService(intent) .
Intent intent = new Intent(MainActivity.this, MyService.class); startService(intent); stopService(intent);
HandlerThread
android.os.HandlerThread creates a new thread with Looper which is used to create handler class. It extends java.lang.Thread . To start it we need to call start() method. This class provides getLooper() which returns Looper of that thread.
Complete Example
package com.concretepage; import android.app.Service; import android.content.Intent; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.Process; import android.util.Log; import android.widget.Toast; public class MyService extends Service < private static final String TAG = "MyService"; private boolean isRunning = false; private Looper looper; private MyServiceHandler myServiceHandler; @Override public void onCreate() < HandlerThread handlerthread = new HandlerThread("MyThread", Process.THREAD_PRIORITY_BACKGROUND); handlerthread.start(); looper = handlerthread.getLooper(); myServiceHandler = new MyServiceHandler(looper); isRunning = true; >@Override public int onStartCommand(Intent intent, int flags, int startId) < Message msg = myServiceHandler.obtainMessage(); msg.arg1 = startId; myServiceHandler.sendMessage(msg); Toast.makeText(this, "MyService Started.", Toast.LENGTH_SHORT).show(); //If service is killed while starting, it restarts. return START_STICKY; >@Override public IBinder onBind(Intent intent) < return null; >@Override public void onDestroy() < isRunning = false; Toast.makeText(this, "MyService Completed or Stopped.", Toast.LENGTH_SHORT).show(); >private final class MyServiceHandler extends Handler < public MyServiceHandler(Looper looper) < super(looper); >@Override public void handleMessage(Message msg) < synchronized (this) < for (int i = 0; i < 10; i++) < try < Log.i(TAG, "MyService running. "); Thread.sleep(1000); >catch (Exception e) < Log.i(TAG, e.getMessage()); >if(!isRunning) < break; >> > //stops the service for the start id. stopSelfResult(msg.arg1); > > >
package com.concretepage; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; public class MainActivity extends Activity < @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.main); OnClickListener listener = new OnClickListener() < public void onClick(View view) < Intent intent = new Intent(MainActivity.this, MyService.class); switch (view.getId()) < case R.id.service_start: //starts service for the given Intent startService(intent); break; case R.id.service_stop: //stops service for the given Intent stopService(intent); break; >> >; findViewById(R.id.service_start).setOnClickListener(listener); findViewById(R.id.service_stop).setOnClickListener(listener); > >
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#C98C00" tools:context=".MainActivity"> <Button android:id="@+id/service_start" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/btn_start" /> <Button android:id="@+id/service_stop" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/btn_stop" /> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.concretepage" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="11"/> <application android:allowBackup ="false" android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".MainActivity"> <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>
Output
07-14 15:13:25.070: I/MyService(756): MyService running. 07-14 15:13:26.080: I/MyService(756): MyService running. 07-14 15:13:27.110: I/MyService(756): MyService running. 07-14 15:13:28.110: I/MyService(756): MyService running. ------------------------------------------------------- -------------------------------------------------------
Урок 92. Service. Простой пример
Для начала надо определиться, как по-русски называть Service. Общепринятый перевод – служба. Наиболее популярный пример – службы в Windows. Но для системы Android мне привычнее использовать слово сервис. Его я и буду использовать в своих уроках для обозначения Service.
И еще один момент надо сразу прояснить. Service прописывается в манифесте рядом с Activity, и получается, что приложение (Application) содержит в себе и Activity и сервис. Предлагаю для упрощения изложения материала под словом приложение понимать все таки только Activity, которые можно запустить и увидеть на экране. Т.е. то, что мы раньше и называли приложением. А сервис считать отдельной от приложения вещью. А если надо будет обозначить приложение, как контейнер для Activity и сервиса, буду использовать слово Application.
Т.е. приложение – это набор Activity, сервис – Service. Приложение + сервис = Application. Как то так.
Итак, сервис – это некая задача, которая работает в фоне и не использует UI. Запускать и останавливать сервис можно из приложений и других сервисов. Также можно подключиться к уже работающему сервису и взаимодействовать с ним.
В качестве примера можно рассмотреть алгоритм почтовой программы. Она состоит из приложения и сервиса. Сервис работает в фоне и периодически проверяет наличие новой почты, скачивает ее и выводит уведомления. А когда вы запускаете приложение, оно отображает вам эти загруженные сервисом письма. Также приложение может подключиться к сервису и поменять в нем, например, период проверки почты или совсем закрыть сервис, если постоянная проверка почты больше не нужна.
Т.е. сервис нужен, чтобы ваша задача продолжала работать, даже когда приложение закрыто. В ближайших уроках мы разберемся, какие способы взаимодействия существуют между приложением и сервисом. В этом же уроке создадим простейший сервис, который будет выводить что-нибудь в лог. А приложение будет запускать и останавливать сервис.
Project name: P0921_ServiceSimple
Build Target: Android 2.3.3
Application name: ServiceSimple
Package name: ru.startandroid.develop.p0921servicesimple
Create Activity: MainActivity
Добавим в strings.xml строки:
Start service Stop service
Две кнопки – для запуска и остановки сервиса. И ProgressBar.
Рядом с MainActivity создайте класс MyService, наследующий android.app.Service
Содержимое MyService.java:
package ru.startandroid.develop.p0921servicesimple; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; public class MyService extends Service < final String LOG_TAG = "myLogs"; public void onCreate() < super.onCreate(); Log.d(LOG_TAG, "onCreate"); >public int onStartCommand(Intent intent, int flags, int startId) < Log.d(LOG_TAG, "onStartCommand"); someTask(); return super.onStartCommand(intent, flags, startId); >public void onDestroy() < super.onDestroy(); Log.d(LOG_TAG, "onDestroy"); >public IBinder onBind(Intent intent) < Log.d(LOG_TAG, "onBind"); return null; >void someTask() < >>
У сервиса так же, как и у Activity есть методы onCreate и onDestroy – которые срабатывают при создании и уничтожении сервиса.
Метод onStartCommand – срабатывает, когда сервис запущен методом startService. В нем мы запускаем наш метод someTask, который пока пуст. У onStartCommand на вход и на выход идут параметры, мы их пока не используем.
Метод onBind нам пока не интересен. Но реализовать его мы обязаны, возвращаем null.
someTask – здесь будем кодить работу для сервиса
Сервис, как и новые, создаваемые Activity необходимо прописать в манифесте. Делается это полностью аналогично. Жмете Add, выбираете Service. И в поле Name выбираете MyService.
package ru.startandroid.develop.p0921servicesimple; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; public class MainActivity extends Activity < final String LOG_TAG = "myLogs"; public void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.main); >public void onClickStart(View v) < startService(new Intent(this, MyService.class)); >public void onClickStop(View v) < stopService(new Intent(this, MyService.class)); >>
Здесь у нас два метода, которые срабатывают при нажатии на кнопки Start service и Stop service. В них мы соответственно запускаем или останавливаем сервис методами startService и stopService. На вход передаем Intent, указывающий на сервис. Это очень похоже на то, как мы вызываем Activity методом startActivity.
Давайте все сохраним и запустим приложение.
Нажмем Start service и смотрим лог:
onCreate
onStartCommand
Выполнился метод onCreate – сервис создался, и onStartCommand – сервис выполняет содержимое метода onStartCommand.
Если мы теперь еще раз нажмем Start service:
Сервис уже создан, onCreate не вызывается, выполняется только метод onStartCommand.
Убедимся, что сервис не зависит от приложения. Жмем Start service.
onCreate
onStartCommand
Сервис запущен. Закрываем приложение кнопкой Назад. В логах тишина, onDestroy в сервисе не выполнился, сервис продолжает жить. Ему все равно, работает приложение, его запустившее или не работает.
Долгим удержанием клавиши Домой выведем список последних приложений
снова откроем наше приложение и нажмем Stop service. В логах:
Теперь попробуем выполнять что-нибудь осмысленное в onStartCommand. Перепишем метод someTask в MyService.java:
Перепишем метод someTask:
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Compose, Kotlin, RxJava, Dagger, Тестирование, Performance
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня