Tuesday 1 July 2014

Android Started Service by extending Service

Android Started Service Concept and Example

Android Service Types
  • Started Service (Unbound)
  • Bound Service
For Android Service Concepts go to this blog. To get over Bound Services visit the link.
Started Service
  • By extending Intent Service class
  • By extending Service



In this post I am going to explain about Started Service by extending Service Class.


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>