Sunday, 15 June 2014

Android Intent Service



Intent Service Overview


Android provides two types of services started and bound. A started service is started by the system when its client (ex- Activity) call startService method from its own content. The started service once started, will run forever until it is self stopped by calling stopSelf method or client stop it by calling stopService method. A bound service is created by the system when a client call bindService instead of the startService method. The bound service will run only till the client is bound to it. It will not run forever like started service.


Started service can be implemented by either extending IntentService class or by extending Service class. IntentService class provide a very simple way to create a service. The started service is locally available only, meaning that the client must be in the same process in which service is. This is not accessible by the remote client.


These services are best suited for a single request from the client. For example service like sending a file from android client to a web server. The client application activity component will call the IntentService service to perform the network operation to send the file. Here sending a file a service which activity use it for sending.


In this post, we will learn how to create a IntentService based started service through a live example. The custom service class need to extends the IntentService class. You have to override the onHandleIntent method of the class. If the service is performing a time consuming task or some network operation then, you have to create a separate thread over which these operation will be performed. It will degrade the user experience for time consuming tasks.


Implement Started Service by Extending IntentService class


Public class MyStartedService extends IntentService {
..
..
@Override
protected void onHandleIntent (Intent intent) {
..
..
}
}





Define your service in the manifest.xml
It is required to define your service in the manifest so that other component can use it. It is done statically here. You can register dynamically through program also.


<application android:icon="@drawable/icon" android:label="@string/app_name"
       android:theme="@android:style/Theme.Holo.Light">
       <service android:name=".MyDownloadService"/>
       <activity android:name=".IntentServiceActivity"
           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>


Some insight into Intentservice
A service is started by another component of Android (like Activity) by invoking startService() method. Intent Service Creates a Handler thread thread in the background which processes Intent command. It creates a work queue that passes one intent at a time to your onHandleIntent() implementation, so you never have to worry about multi-threading. The system stops the service after all start requests have been handled, so you never have to call stopSelf(). it provides default implementation of onBind() that returns null. It provides a default implementation of onStartCommand() that sends the intent to the work queue and then to your onHandleIntent() implementation.


Below diagram shows the flows of interaction between the IntentService and its client (Activity). I hope this will help you in understanding the service in a better way. The service depicted below is a download service which is used by the activity.



An Example


The sample example contains a button which starts the service on clicking and the service display a webpage whose URL is entered in the edit text box. Service also return a string which is used to update the text vies of main UI thread.




MainActivity.java


package pp.myintentservice;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;


public class MainActivity extends Activity {

           Button serviceButton;
           TextView tv;  
           WebView wv;
          
           Intent serviceIntent;
           MyDownloadServiceReceiver breciever;          
          
           @Override
           protected void onCreate(Bundle savedInstanceState) {
                       super.onCreate(savedInstanceState);
                       setContentView(R.layout.activity_main);
                      
                       tv=(TextView)findViewById(R.id.textView2);                     
                       serviceButton = (Button)findViewById(R.id.button1);
                       wv=(WebView)findViewById(R.id.webView1);

                       IntentFilter intentFilter = new IntentFilter("DownloadService");
                       intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
                       breciever = new MyDownloadServiceReceiver();
                       registerReceiver(breciever, intentFilter);
                      
                       serviceIntent=newIntent(getApplicationContext(), MyDownloadIntentService.class);                                                                   
                       serviceButton.setOnClickListener(new View.OnClickListener() {                               
                                                                      
                                   @Override
                                   public void onClick(View arg0) {        
                                              
                                               EditText selection=(EditText)findViewById(R.id.editText1);
                                               String url=selection.getText().toString();                                           
                                               System.out.println("Entered URL is..."+url);
                                               serviceIntent.putExtra("REQUEST", url);
                                               startService(serviceIntent);
                                   }
                       });
                      
           }



           class MyDownloadServiceReceiver extends BroadcastReceiver{             

                       @Override
                       public void onReceive(Context context, Intent intent) {
                                   // TODO Auto-generated method stub
                                   String rep=intent.getStringExtra("RESPONSE");                            
                                   tv.setText(rep);
                                  
                                   String web=intent.getStringExtra("WEB");
                       //          wv.getSettings().setJavaScriptEnabled(true);
                                   wv.getSettings().getMinimumFontSize();
                                   try {
               wv.loadData(URLEncoder.encode(web,"utf-8").replaceAll("\\+"," "),
                                   "text/html", "UTF-8");
           } catch (UnsupportedEncodingException e) {
               e.printStackTrace();
           }
                       }
           }
}



MyDownloadIntentService.java


package pp.myintentservice;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.IntentService;
import android.content.Intent;
import android.util.Log;

public class MyDownloadIntentService extends IntentService {
          
           public MyDownloadIntentService() {
                       super("PP");
                       // TODO Auto-generated constructor stub
           }

           @Override
           protected void onHandleIntent(Intent intent) {
                       // TODO Auto-generated method stub                       
                       String url=intent.getStringExtra("REQUEST");                  
                       System.out.println("Requested URL is: "+url);                     
                       String reply= "Hi From Service !!!";
                                                                                              
                       try{
                       HttpClient httpclient = new DefaultHttpClient();
                       String responseMessage="";                            
                       HttpGet httpGet = new HttpGet(url);
       HttpResponse response = httpclient.execute(httpGet);
       StatusLine statusLine = response.getStatusLine();
      
       if(statusLine.getStatusCode() == HttpStatus.SC_OK){
           ByteArrayOutputStream out = new ByteArrayOutputStream();
           response.getEntity().writeTo(out);
           out.close();
           responseMessage = out.toString();
          
           Intent bIntent = new Intent ("DownloadService");
                                   bIntent.addCategory(Intent.CATEGORY_DEFAULT);
                                   bIntent.putExtra("RESPONSE", reply);                              
                                   bIntent.putExtra("WEB", responseMessage);                                                           
                                   sendBroadcast(bIntent);
       }

       else{
           //Closes the connection.
           Log.w("HTTP1:",statusLine.getReasonPhrase());
           response.getEntity().getContent().close();
           throw new IOException(statusLine.getReasonPhrase());
       }

   } catch (Exception e) {
     
   }                                                                             
           }         
}


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.myintentservice.MainActivity"
   tools:ignore="MergeRootFrame" >

   <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:layout_marginTop="10dp"
       android:text="Intent Service Test"
       android:textAppearance="?android:attr/textAppearanceLarge" />

   <FrameLayout
       android:id="@+id/iml"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_below="@+id/textView2"
       android:layout_centerHorizontal="true"
       android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
         android:layout_alignParentBottom="true"
       android:layout_marginTop="18dp" >

       <WebView
           android:id="@+id/webView1"
           android:layout_width="match_parent"
           android:layout_height="match_parent" />

   </FrameLayout>

   <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_below="@+id/textView1"
       android:ems="10"
       android:hint="Enter URL"
       android:inputType="textWebEditText" />

   <Button
       android:id="@+id/button1"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_alignParentLeft="true"
       android:layout_alignParentRight="true"
       android:layout_below="@+id/editText1"
       android:text="Start Service" />

   <TextView
       android:id="@+id/textView2"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_alignParentLeft="true"
       android:layout_alignParentRight="true"
       android:layout_below="@+id/button1"
       android:text="Wait for service Reply"
       android:textAppearance="?android:attr/textAppearanceLarge" />

</RelativeLayout>


AndroidManifest.xml


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="pp.myintentservice"
   android:versionCode="1"
   android:versionName="1.0" >

   <uses-sdk
       android:minSdkVersion="15"
       android:targetSdkVersion="19" />
   <uses-permission android:name="android.permission.INTERNET"/>

   <application
       android:allowBackup="true"
       android:icon="@drawable/ic_launcher"
       android:label="@string/app_name"
       android:theme="@style/AppTheme" >
       <service android:name="pp.myintentservice.MyDownloadIntentService"/>
       <activity
           android:name="pp.myintentservice.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>

No comments:

Post a Comment