Android Started Service Concept and Example
Android Service Types
Started ServiceAndroid Service Types
- Started Service (Unbound)
- Bound Service
- By extending Intent Service class
- By extending Service
Android provides multiple API to create a Service within same or different address space than their clients. Started Service is used within the same Application which implements it i.e. inside same address space.
A service is "started" when an application component (such as an activity) starts it by calling startService(). Once started, a service can run in the background indefinitely, even if the component that started it is destroyed. Usually, a started service performs a single operation and does not return a result to the caller. For example, it might download or upload a file over the network. When the operation is done, the service should stop itself.
What Service needs ?
- Extends Service
- Handler and write its handleMessage()
- Looper : For multiple requests to be queued
- Override onCreate()
- No need to override onBind()
Extends the Service
public class MyStartedService extends Service { …. }
|
Required Field Variables
public class MyStartedService extends Service {
MyServiceHandler mHandler;
Looper looper;
…. }
|
Implement The Handler for the Service
private final class MyServiceHandler extends Handler {
public MyServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
// Service will do the necessary jobs using the Message
// you can stop the service here
stopSelf(msg.arg1);
}
}
|
Override onCreate() of Service Class
@Override
public void onCreate() {
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
looper = thread.getLooper();
mHandler = new ServiceHandler(mServiceLooper);
}
|
Override onStartCommand() of Service Class
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// For each start request, send a message to start a job and deliver the
// start ID so we know which request we're stopping when we finish the job
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
// If we get killed, after returning from here, restart
return START_STICKY;
}
|
Override onBind(): No need to override it because service is not Bound
@Override
public IBinder onBind(Intent intent) {
// We don't provide binding, so return null
return null;
}
|
What Client needs
- Start the Service
Intent intent = new Intent(this, HelloService.class);
startService(intent);
|
- Stop the Service
Once requested to stop with stopSelf() or stopService(), the system destroys the service as soon as possible.
A live example
In the sample example UI Activity class sends a request to "started service " and service gives back the reply to the client which is displayed inside the edit text area.
MyStartedService.java
package pp.startedservice;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.widget.Toast;
public class MyStartedService extends Service {
private Looper serviceLooper;
private ServiceHandler serviceHandler;
private class ServiceHandler extends Handler{
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
String req=msg.getData().getString("REQ");
String dis ="Service: "+req;
// Toast.makeText(getApplicationContext(), dis,Toast.LENGTH_SHORT).show();
Intent bIntent = new Intent ("STARTED_SERVICE");
bIntent.addCategory(Intent.CATEGORY_DEFAULT);
bIntent.putExtra("RESPONSE", dis);
sendBroadcast(bIntent);
// Service stop itself after serving
// stopSelf(msg.arg1);
}
}
@Override
public void onCreate() {
// New thread other than UI....
HandlerThread thread = new HandlerThread("ServiceStartArguments", 7);
thread.start();
serviceLooper = thread.getLooper();
serviceHandler = new ServiceHandler(serviceLooper);
// Toast.makeText(this, "Service is created",Toast.LENGTH_SHORT).show();
};
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
// Not required if Service is " Started One"
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId){
String req = intent.getExtras().getString("REQUEST");
Bundle data=new Bundle();
data.putString("REQ", req);
Message msg = serviceHandler.obtainMessage();
msg.arg1 = startId;
msg.setData(data);
serviceHandler.sendMessage(msg);
Toast.makeText(this, "Service is started"+"\nREQUEST is : "+req,Toast.LENGTH_SHORT).show();
return START_STICKY;
}
public void onDestroy(){
Toast.makeText(this, "Service is Destroyed",Toast.LENGTH_SHORT).show();
}
}
|
MainActivity.java
package pp.startedservice;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.widget.Toast;
public class MyStartedService extends Service {
private Looper serviceLooper;
private ServiceHandler serviceHandler;
private class ServiceHandler extends Handler{
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
String req=msg.getData().getString("REQ");
String dis ="Service: "+req;
// Toast.makeText(getApplicationContext(), dis,Toast.LENGTH_SHORT).show();
Intent bIntent = new Intent ("STARTED_SERVICE");
bIntent.addCategory(Intent.CATEGORY_DEFAULT);
bIntent.putExtra("RESPONSE", dis);
sendBroadcast(bIntent);
// Service stop itself after serving
// stopSelf(msg.arg1);
}
}
@Override
public void onCreate() {
// New thread other than UI....
HandlerThread thread = new HandlerThread("ServiceStartArguments", 7);
thread.start();
serviceLooper = thread.getLooper();
serviceHandler = new ServiceHandler(serviceLooper);
// Toast.makeText(this, "Service is created",Toast.LENGTH_SHORT).show();
};
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
// Not required if Service is " Started One"
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId){
String req = intent.getExtras().getString("REQUEST");
Bundle data=new Bundle();
data.putString("REQ", req);
Message msg = serviceHandler.obtainMessage();
msg.arg1 = startId;
msg.setData(data);
serviceHandler.sendMessage(msg);
Toast.makeText(this, "Service is started"+"\nREQUEST is : "+req,Toast.LENGTH_SHORT).show();
return START_STICKY;
}
public void onDestroy(){
Toast.makeText(this, "Service is Destroyed",Toast.LENGTH_SHORT).show();
}
}
|
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="pp.messengerservice.MainActivity"
tools:ignore="MergeRootFrame"
android:background="#000000" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="Started Service Test"
android:textColor="#ff0000"
android:textSize="25sp" />
<RelativeLayout
android:id="@+id/control"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginBottom="44dp" >
<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginTop="28dp"
android:onClick="sayHello"
android:text="Start Service"
android:textSize="25sp" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_below="@+id/button1"
android:layout_marginTop="20dp"
android:text="Stop Service"
android:textSize="25sp" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/reqrep"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_below="@+id/textView1"
android:layout_marginTop="62dp" >
<EditText
android:id="@+id/editText2"
android:layout_width="wrap_content"
android:layout_height="35dp"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_below="@+id/editText1"
android:layout_margin="5dp"
android:background="#f0fcf2"
android:ems="10"
android:hint="Response from Server !"
android:textColor="#ff0000" >
<requestFocus />
</EditText>
<EditText
android:id="@+id/editText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_margin="3dp"
android:ems="10"
android:hint="Request Message !" />
</RelativeLayout>
</RelativeLayout>
|
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="pp.startedservice"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<service android:name="pp.startedservice.MyStartedService"/>
<activity
android:name="pp.startedservice.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
|