Showing posts with label Services. Show all posts
Showing posts with label Services. Show all posts

Android App Development: Implementing remote Android Services with AIDL

In the last post we saw how to use Android services to do time consuming operations in the background. in this post we will see how can a client application call the methods of a service defined in another application. this is achieved through Android Interface Definition Language (AIDL).

AIDL is a java like language that enables you to define an interface that both the application defining the service and the client application implement it.

the interface defines the functions that are needed to be called in the client application.

AIDL syntax is similar to that of Java, we can use the following data types in AIDL:

primitive data types: int, long, char, boolean,….String.CharSequence.List (ArrayList,Vector,…).the AIDL file is defined as follows:
open a notepad file and paste the following code in it: package com.mina.servicedemo;// service interfaceinterface IRemoteService { //sample method String sayHello(String message);}

take care of the package name com.mina.servicedemo.
we defined a methods sayHello(String message) that returns a string.

save the file with the name IRemoteService and change it’s extension to .aidl.copy the file to the src folder of your project.once you save and build the file, Android generates an interface java file with the name IRemoteService.java in the gen folder if the project.

now we want our service to expose this interface to client applications, so we return an implementation of the service in the onBind() method of our service:

package com.mina.servicedemo;import com.mina.servicedemo.IRemoteService.Stub;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.RemoteException;import android.widget.Toast;public class DemoService extends Service {@Overridepublic IBinder onBind(Intent arg0) {return mBinder;}// implementation of the aidl interfaceprivate final IRemoteService.Stub mBinder=new Stub() {@Overridepublic String sayHello(String message) throws RemoteException {return "Hello "+message;}};}}

the last thing to do in the service is to make its exported attribute in the AndroidManifest.xml file set to true like this:

our app structure can be like this:

now to our client application where we want to invoke methods from our service. the client application is a separate application with a different package name than that where the service is defined.

the client application needs a reference to the AIDL interface defined in the original applcation, this is done through the following steps:

in the client applicatio create a package with the same package name of that the service is defined in: com.mina.servicedemo.copy the AIDL file in this package.save and build and a new file called IRemoteService.java is generated. your app structure should be like this:

and we invoke the servcice methods in our activity like this:

package com.mina.serviceclient;import com.mina.servicedemo.IRemoteService;import android.app.Activity;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.os.RemoteException;import android.util.Log;public class MainActivity extends Activity {IRemoteService mRemoteService; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Intent serviceIntent=new Intent(); serviceIntent.setClassName("com.mina.servicedemo", "com.mina.servicedemo.DemoService"); boolean ok=bindService(serviceIntent, mServiceConnection,Context.BIND_AUTO_CREATE); Log.v("ok", String.valueOf(ok)); } private ServiceConnection mServiceConnection=new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName name) {// TODO Auto-generated method stub}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {// get instance of the aidl bindermRemoteService = IRemoteService.Stub.asInterface(service);try {String message=mRemoteService.sayHello("Mina");Log.v("message", message);} catch (RemoteException e) {Log.e("RemoteException", e.toString());}}};}

and that’s was all about calling remote services with AIDL, stay tuned for another Android tutorial

More aboutAndroid App Development: Implementing remote Android Services with AIDL

Android App Development: Android Services

Android Service is used for long-running processes that do not require user interaction, such as calling a web service and parsing response. Or processes that need to be running even if the application that started the service is not on the foreground such as playing mp3 files in a music player.

we need to distinguish between A Service and a Thread or an AsyncTask: Threads or Async task perform their tasks in a background thread thus they do not block the main thread, while a service performs it’s work in the main thread. so if a service is performing an intensive task such as calling a web service, it may block the main thread until it finishes. So for intensive tasks a service should run it’s work in a background thread.

A service runs in the same process of the application and keeps running until stopped by itself, stopped by the user or killed by the system if it needs memory.

to create a service we create a class that extends android.app.Service and it would be like this:

public class DemoService extends Service {@Overridepublic IBinder onBind(Intent arg0) {// TODO Auto-generated method stubreturn null;}}

next we need to define our service in our AndroidManifest.xml file:

The service life cycle has the following events

onCreate(): called when the service is created.onStart(): Called when the service starts by a call to startService(Intent intent).onDestroy(): Called as the service is terminates.

A service can be called from an activity in two ways:

By calling startService(Intent intent).By binding to the service through an Binder object.

to start a service from an activity using this method, we create an intent and start the service like this:

Intent intent=new Intent(this,DemoService.class);startService(intent);

the startService(intent) method causes the onStart() method of the service to be called, so the service can execute it’s work like this:

public class DemoService extends Service {@Overridepublic IBinder onBind(Intent arg0) {// TODO Auto-generated method stubreturn null;}@Overridepublic void onStart(Intent intent, int startId) {super.onStart(intent, startId);doSomething();}public void doSomething(){// do some work}}

the service will keep running until it stops itself via stop stopSelf() after finishing work:

@Overridepublic void onStart(Intent intent, int startId) {super.onStart(intent, startId);doSomething();stopSelf();}

or it can be stopped from the activity via stopService(Intent intent).

As the service runs in the same process of the application the service has only one instance (singleton) instance running. you may want to keep reference to this instance to perform periodical tasks or to call the service methods themselves.

to make the service bind-able we extends Binder class and return an instance of it in the service’s onBind(Intent intent) method:

public class DemoService extends Service {private final IBinder binder = new LocalBinder();@Overridepublic IBinder onBind(Intent arg0) {return binder;}public class LocalBinder extends Binder {DemoService getService() { return DemoService.this; } }@Overridepublic void onStart(Intent intent, int startId) {super.onStart(intent, startId);doSomething();stopSelf();}public void doSomething(){// do something}}

then we bind the service from our activity by first creating a ServiceConnection object to handle the service connection/disconnection then binding to the service by an intent like this:

public class MainActivity extends Activity {DemoService mService; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } ServiceConnection serviceConn=new ServiceConnection() { /** * service unbound, release from memory **/@Overridepublic void onServiceDisconnected(ComponentName name) {mService=null;} /** * service is bound, start it's work **/@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mService=((LocalBinder)service).getService();mService.doSomething();}}; @Override protected void onResume() { super.onResume(); // bind to the service by an intent Intent intent=new Intent(this,DemoService.class); // AUTO CREATE: creates the service and gives it an importance so that it won't be killed // unless any process bound to it (our activity in this case) is killed to bindService(intent, serviceConn, Context.BIND_AUTO_CREATE); } @Override protected void onDestroy() { super.onDestroy(); / unbind the service whena ctivity is destroyed unbindService(serviceConn); }}

notice that we unbind the service in the activity’s onDestroy() method to disconnect from the service and stop it from executing any further

and that’s was all about Android services, stay tuned for another Android tutorial.

More aboutAndroid App Development: Android Services