Android Start/Stop Service from Activity Example using HandlerThread
July 14, 2015
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 fromActivity
, 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
MyService.java
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); } } }
MainActivity.java
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); } }
main.xml
<?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>
AndroidManifest.xml
<?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... ------------------------------------------------------- -------------------------------------------------------