Tuesday, May 29, 2012

Explain Android Service ?


Android Services
1.1 Service
A Service is a component which runs in the background, without interacting with the user. Every developer can create newServices in his application. Services support true multitasking for Android, as they can run in their own process. If you use threads in Activities their are still connected to the life-cycle of Activities and the Android system may decide to terminate them at any point in point.

1.2. Service
The Android platform provides pre-defined Services, usually exposed via a specific Manager class. Access to these services can be gained via the method getSystemService().

2. DEFINING SERVICES
2.1. Declaring own Services
You can declare your own Service to perform long running operations without user interaction or to supply functionality to other applications.
A Service needs to be declared in the AndroidManifest.xml via a <service android:name="yourclasss"> </service> and the implementing class must extend the Service class or one of its subclasses.
A Service will not automatically run in its own thread. Without the process attribute, they run the main thread of their hosting process. Therefore you should run performance intensive tasks in the background.

2.2. Running a Services in its own process
You can also specify that your Service runs in a separate process via the android:process=":process_description"attribute.
This way the service gets its own process and has its own memory. Any long running operation in the Service, e.g. a garbage collection, will not affect the user interface of your Activity
The colon prefix before the name tells Android that the Service is private to its declaring application. If the colon is not used theService would be a global process and can be used by other components.

                               
<service
        android:name="WordService"
        android:process=":my_process"
        android:icon="@drawable/icon"
        android:label="@string/service_name"
        >
</service>
                       
Running a service in its own process will not block the application in case the service performs long running operations in its main thread. But as the services runs in its own process you need to use some interprocess communication (IPC) to communicate to your service from other parts.

2.3. Intent Services
While the base class for creating a Service is the Service class you can also implement IntentService.
The IntentService is used to perform a certain task in the background. Once done, the instance of IntentService terminate itself automatically. Examples for its usage would be to download a certain resources from the Internet.
The IntentService class offers the onHandleIntent() method which will be asynchronously called by the Android system.

2.4. Starting Services
An Activity can start a Service via the startService() method and stop the service via the stopService() method. If theActivity want to interact with the Activity it can use the bindService() method of the service. This requires anServiceConnection object which allows to connect to the Service and which return a IBinder object. This IBinder object can be used by the activity to communicate with the Service.
Once a Service is started the onCreate() method is called. Afterwards the onStartCommand() method is called with the Intent data provided by the activity.
startService() also allows you to provide a flag which determines the lifecycle behavior of the services.Service.START_STICKY is used for services which are explicit started or stopped. Services started withService.START_NOT_STICKY will end automatically after the onStartCommand() method is done. A Service is started within the main thread of the application therefore all long running tasks should be performed in the background.

3. COMMUNICATING WITH SERVICES
There are several way for an Activity to communicate with an Service and vice versa.

3.1. Binding to local service
If the Service is started in the same process as the Activity, the Activity can directly bind to the service a call of thebindService() method. This method gets as a parameter a SernviceConnection. The onServiceConnected() method is called on this object once the Service is available. The Service return on its onBind() method an object of type IBinder which can be used to call to the service.
See 
Local Service Example for an example.

3.2. Binding to a service in a different process
To bind to a Service which runs in a different process you need to use Inter Process Communication (IPC) as the data needs to be send between different processes. For this you need to create a AIDL file which looks similiar to an Java Interface but ends with the .aidl file extension and is only allowed to extend other AIDL files.
If the Android Development Tools find such a file in your source folder, it will create the necessary stub classes for IPC communication for your. Still using this approach is relatively advanced and will not be covered in this tutorial.

3.3. Handler and Messenger
If the service should be communicating back to the Activity it can receive an object of type Messenger via the Intent data it receives from the Activity. If the Messenger in bound to a Handler in the Activity the Service can send objects of typeMessage to the Activity.
A Messenger is parcable, which means it can be passed to another process and you can use this object to send Messages to theHandler in the Activity.
Messenger provides also the method getBinder() which allows to pass a Messenger to the Activity. The Activity can therefore send Messages to the Service.
Another example would be the usage of . In this case Activities can send messages to the Services and receive messages as well if they register for them.

4. BROADCAST RECEIVER
4.1. Definition
A broadcast receiver is a class which extends BroadcastReceiver and which is registered as a receiver in an Android Application via the AndroidManifest.xml file(or via code).
Alternatively to the this static registration, you can also register a BroadcastReceiver dynamically via theContext.registerReceiver() method.
This class will be able to receive intents. Intents can be generated via the Context.sendBroadcast() method.
The class BroadcastReceiver defines the onReceive() method. Only during this method your BroadcastReceiver object will be valid, afterwards the Android system can recycle the BroadcastReceiver. Therefore you cannot perform any asynchronous operation in the onReceive() method.

4.2. Sending Broadcast Intents
The sendBroadcast() method allows to send Broadcast Intents. You cannot trigger system Broadcasts, the Android system will prevent this.
But you can define intent-filters for your own actions and trigger them via the sendBroadcast() method.
The following AndroidManifest.xml file show a BroadcastReceiver which is registered to a custom action.

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

    <uses-sdk android:minSdkVersion="15" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".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>

        <receiver android:name="MyReceiver" >
            <intent-filter>
                <action android:name="de.vogella.android.mybroadcast" />
            </intent-filter>
        </receiver>
    </application>

</manifest>
                        
You can trigger this event via the sendBroadcast() method.

                                       
Intent intent = new Intent();
intent.setAction("de.vogella.android.mybroadcast");
sendBroadcast(intent);
                       
4.3. Sticky Broadcast Intents
A normal broadcast Intent is not available anymore after is was send and processed by the system. If you use thesendBroadcast(Intent) method, the Intent is sticky, meaning the Intent you are sending stays around after the broadcast is complete.
You can can retrieve that data through the return value of registerReceiver(BroadcastReceiver, IntentFilter) . This works also for a null BroadcastReceiver.
In all other ways, this behaves the same as sendBroadcast(Intent).
The Android system uses sticky broadcast for certain system information. For example the battery status is send as sticky Intent and can get received at any time. The following example demonstrates that.

                               
// Register for the battery changed event
IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);

/ Intent is sticky so using null as receiver works fine
// return value contains the status
Intent batteryStatus = this.registerReceiver(null, filter);

// Are we charging / charged?
int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING
        || status == BatteryManager.BATTERY_STATUS_FULL;

boolean isFull = status == BatteryManager.BATTERY_STATUS_FULL;

// How are we charging?
int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;
                       
5. SCHEDULING OF SERVICES
5.1. Automatically starting Services via Receivers
To start Services automatically after the Android system starts you can register a BroadcastReceiver to the Androidandroid.intent.action.BOOT_COMPLETED system event. This requires theandroid.permission.RECEIVE_BOOT_COMPLETED permission.
The following AndroidManifest.xml registers a receiver for the BOOT_COMPLETED event.

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

    <uses-sdk android:minSdkVersion="10" />

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

    <application
        android:icon="@drawable/icon"
        android:label="@string/app_name" >
        <activity
            android:name=".ServiceConsumerActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <receiver android:name="MyScheduleReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
        <receiver android:name="MyStartServiceReceiver" >
        </receiver>
    </application>

</manifest>
                       
In the onReceive() method the corresponding BroadcastReceiver would then start the service.

                               
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class MyReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
                Intent service = new Intent(context, WordService.class);
                context.startService(service);
        }
}
                       
If you application is installed on the SD card, then it is not available after the android.intent.action.BOOT_COMPLETED event. Register yourself in this case for the android.intent.action.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE event.
Also note that as of Android 3.0 the user needs to have started the application at least once before your application can receiveandroid.intent.action.BOOT_COMPLETED events.

5.2. Scheduling of Services via AlarmManager
As with Activities the Android system may terminate the process of a service at any time to save resources. For this reason you cannot simple use a TimerTask in the service to ensure that it is executed on a regular basis.
The following would be incorrect, as Android may terminate your Service.

                                
public void onCreate() {
                super.onCreate();
                pollForUpdates();
        }

// WRONG, don't do this
private void pollForUpdates() {
        timer.scheduleAtFixedRate(new TimerTask() {
                @Override
                public void run() {
                        if (list.size() >= 6) {
                                list.remove(0);
                        }
                        list.add(fixedList[index++]);
                        if (index >= fixedList.length) {
                                index = 0;
                        }
                }
        }, 0, UPDATE_INTERVAL);
        Log.i(getClass().getSimpleName(), "Timer started.");
}
                       
For correct scheduling of the Service use the AlarmManager class.

6. PENDING INTENT
A PendingIntent is a token that you give to another application (e.g. Notification Manager, Alarm Manager or other 3rd party applications), which allows this other application to use the permissions of your application to execute a predefined piece of code.
To perform a broadcast via a pending intent so get a PendingIntent via PendingIntent.getBroadcast(). To perform an activity via an pending intent you receive the activity via PendingIntent.getActivity().

7 BROADCAST RECEIVER
We will define a broadcast receiver which listens to telephone state changes. If the phone receives a phone call then our receiver will be notified and log a message.
Create a new project de.vogella.android.receiver.phone. We do not need an Activity. Create the followingAndroidManifest.xml.

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

    <application
        android:icon="@drawable/icon"
        android:label="@string/app_name" >
        <receiver android:name="MyPhoneReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.PHONE_STATE" >
                </action>
            </intent-filter>
        </receiver>
    </application>

    <uses-sdk android:minSdkVersion="9" />

    <uses-permission android:name="android.permission.READ_PHONE_STATE" >
    </uses-permission>

</manifest>
               
Create the MyPhoneReceiver class.

                       
package de.vogella.android.receiver.phone;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.util.Log;

public class MyPhoneReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
                Bundle extras = intent.getExtras();
                if (extras != null) {
                        String state = extras.getString(TelephonyManager.EXTRA_STATE);
                        Log.w("DEBUG", state);
                        if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
                                String phoneNumber = extras
                                                .getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
                                Log.w("DEBUG", phoneNumber);
                        }
                }
        }
}

               
If you install your application and receive a call, e.g simulated by the DDMS perspective in Eclipse, then your receiver will be called and lot a message to the console.

8. TUTORIAL: SYSTEM SERVICES AND BROADCASTRECEIVER
In this chapter we will use the AlertManager and VibratorManager. The VibratorManager will be called by the broadcast receiver which will be called by the AlertManager.
Create a new project "de.vogella.android.alarm" with the activity "AlarmActivity". Create the following layout.

                       
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <EditText
        android:id="@+id/time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="Number of seconds"
        android:inputType="numberDecimal" >
    </EditText>

    <Button
        android:id="@+id/ok"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="startAlert"
        android:text="Start Counter" >
    </Button>

</LinearLayout>
                
Create the following broadcast receiver class. This class will get the Vibrator service.

                       
package de.vogella.android.alarm;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Vibrator;
import android.widget.Toast;

public class MyBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
                Toast.makeText(context, "Don't panik but your time is up!!!!.",
                                Toast.LENGTH_LONG).show();
                // Vibrate the mobile phone
                Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
                vibrator.vibrate(2000);
        }

}

               
Maintain this class as broadcast receiver in "AndroidManifest.xml" and allow the vibrate authorization.

                       
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="de.vogella.android.alarm" android:versionCode="1"
        android:versionName="1.0">
        <uses-sdk android:minSdkVersion="9" />

        <application android:icon="@drawable/icon" android:label="@string/app_name">
                <activity android:name=".AlarmActivity" android:label="@string/app_name">
                        <intent-filter>
                                <action android:name="android.intent.action.MAIN" />
                                <category android:name="android.intent.category.LAUNCHER" />
                        </intent-filter>
                </activity>
                <receiver android:name="MyBroadcastReceiver"></receiver>

        </application>
        <uses-permission android:name="android.permission.VIBRATE"></uses-permission>
       
</manifest>
               
Change the code of your Activity "AlarmActivity" to the following. This activity will create an Intent for the Broadcast receiver and get the AlarmManager service.

                       
package de.vogella.android.alarm;

import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

public class AlarmActivity extends Activity {
       
/** Called when the activity is first created. */

        @Override
        public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.main);
        }

        public void startAlert(View view) {
                EditText text = (EditText) findViewById(R.id.time);
                int i = Integer.parseInt(text.getText().toString());
                Intent intent = new Intent(this, MyBroadcastReceiver.class);
                PendingIntent pendingIntent = PendingIntent.getBroadcast(
                                this.getApplicationContext(), 234324243, intent, 0);
                AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
                alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()
                                + (i * 1000), pendingIntent);
                Toast.makeText(this, "Alarm set in " + i + " seconds",
                                Toast.LENGTH_LONG).show();
        }

}
               
Run your application on the device. Set your time and start the alarm. After the defined number of seconds a Toast should be displayed. Keep in mind that the vibrator alarm does not work on the Android emulator. 
9. TUTORIAL: USING INTENTSERVICE TO DOWNLOAD A FILE
The following will demonstrate how to use the IntentService class to download a file from the Internet. Once done theIntentService will use an instance of the Messenger class to inform the Activity which started the service about the location of the downloaded file.
Create a new project called "de.vogella.android.intentservice.download" with a Activity called "MainActivity".
Create a service "DownloadService" by creating the following class and the entry in "AndroidManifest.xml". Also add the permission to write to external storage and to access the Internet to the file.

                       
package de.vogella.android.intentservice.download;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;

import android.app.Activity;
import android.app.IntentService;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Message;
import android.os.Messenger;
import android.util.Log;

public class DownloadService extends IntentService {

        private int result = Activity.RESULT_CANCELED;

        public DownloadService() {
                super("DownloadService");
        }

        // Will be called asynchronously be Android
        @Override
        protected void onHandleIntent(Intent intent) {
                Uri data = intent.getData();
                String urlPath = intent.getStringExtra("urlpath");
                String fileName = data.getLastPathSegment();
                File output = new File(Environment.getExternalStorageDirectory(),
                                fileName);
                if (output.exists()) {
                        output.delete();
                }

                InputStream stream = null;
                FileOutputStream fos = null;
                try {

                        URL url = new URL(urlPath);
                        stream = url.openConnection().getInputStream();
                        InputStreamReader reader = new InputStreamReader(stream);
                        fos = new FileOutputStream(output.getPath());
                        int next = -1;
                        while ((next = reader.read()) != -1) {
                                fos.write(next);
                        }
                        // Sucessful finished
                        result = Activity.RESULT_OK;

                } catch (Exception e) {
                        e.printStackTrace();
                } finally {
                        if (stream != null) {
                                try {
                                        stream.close();
                                } catch (IOException e) {
                                        e.printStackTrace();
                                }
                        }
                        if (fos != null) {
                                try {
                                        fos.close();
                                } catch (IOException e) {
                                        e.printStackTrace();
                                }
                        }
                }

                Bundle extras = intent.getExtras();
                if (extras != null) {
                        Messenger messenger = (Messenger) extras.get("MESSENGER");
                        Message msg = Message.obtain();
                        msg.arg1 = result;
                        msg.obj = output.getAbsolutePath();
                        try {
                                messenger.send(msg);
                        } catch (android.os.RemoteException e1) {
                                Log.w(getClass().getName(), "Exception sending message", e1);
                        }

                }
        }
}

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

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

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".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>

        <service android:name="DownloadService" >
        </service>
    </application>

</manifest>
               
Change the "main.xml" layout to the following.

                       
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="Button" />

</LinearLayout>
               
Change MainActivity to the following.

                       
package de.vogella.android.intentservice.download;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity {
        private Handler handler = new Handler() {
                public void handleMessage(Message message) {
                        Object path = message.obj;
                        if (message.arg1 == RESULT_OK && path != null) {
                                Toast.makeText(MainActivity.this,
                                                "Downloaded" + path.toString(), Toast.LENGTH_LONG)
                                                .show();
                        } else {
                                Toast.makeText(MainActivity.this, "Download failed.",
                                                Toast.LENGTH_LONG).show();
                        }

                };
        };

        @Override
        public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.main);

        }

        public void onClick(View view) {
                Intent intent = new Intent(this, DownloadService.class);
                // Create a new Messenger for the communication back
                Messenger messenger = new Messenger(handler);
                intent.putExtra("MESSENGER", messenger);
                intent.setData(Uri.parse("http://www.vogella.de/index.html"));
                intent.putExtra("urlpath", "http://www.vogella.de/index.html");
                startService(intent);
        }
}
               
If you run your example and press the button, the download should be performed by the Service and once done the Activity should show a Toast with the file name.




10.DEFINE AND CONSUME YOUR OWN LOCAL SERVICE
The following chapter will demonstrate how to create and consume a service from an activity. The service will be started at boot and periodically fetch data. The service will used by an activity which bind itself to the service. The activity will allow to request the latest data from the service.
Create a new project called "de.vogella.android.ownservice.local" with a Activity called "MainActivity".
Create the LocalWordService class.

                       
package de.vogella.android.ownservice.local;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;

public class LocalWordService extends Service {
        private final IBinder mBinder = new MyBinder();
        private ArrayList<String> list = new ArrayList<String>();

        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {

                Random random = new Random();
                if (random.nextBoolean()) {
                        list.add("Linux");
                }
                if (random.nextBoolean()) {
                        list.add("Android");
                }
                if (random.nextBoolean()) {
                        list.add("iPhone");
                }
                if (random.nextBoolean()) {
                        list.add("Windows7");
                }
                if (list.size() >= 20) {
                        list.remove(0);
                }
                return Service.START_NOT_STICKY;
        }

        @Override
        public IBinder onBind(Intent arg0) {
                return mBinder;
        }

        public class MyBinder extends Binder {
                LocalWordService getService() {
                        return LocalWordService.this;
                }
        }

        public List<String> getWordList() {
                ArrayList<String> list = new ArrayList<String>();
                return list;
        }

}

                
Create the following two classes, which will be registered as BroadcastReceivers.

                       
package de.vogella.android.ownservice.local;

import java.util.Calendar;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class MyScheduleReceiver extends BroadcastReceiver {

        // Restart service every 30 seconds
        private static final long REPEAT_TIME = 1000 * 30;

        @Override
        public void onReceive(Context context, Intent intent) {
                AlarmManager service = (AlarmManager) context
                                .getSystemService(Context.ALARM_SERVICE);
                Intent i = new Intent(context, MyStartServiceReceiver.class);
                PendingIntent pending = PendingIntent.getBroadcast(context, 0, intent,
                                PendingIntent.FLAG_CANCEL_CURRENT);
                Calendar cal = Calendar.getInstance();
                // Start 30 seconds after boot completed
                cal.add(Calendar.SECOND, 30);
                //
                // Fetch every 30 seconds
                // InexactRepeating allows Android to optimize the energy consumption
                service.setInexactRepeating(AlarmManager.RTC_WAKEUP,
                                cal.getTimeInMillis(), REPEAT_TIME, pending);

                // service.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
                // REPEAT_TIME, pending);

        }
}

               
                       
package de.vogella.android.ownservice.local;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class MyStartServiceReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
                Intent service = new Intent(context, LocalWordService.class);
                context.startService(service);
        }
}
               
                       
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="de.vogella.android.ownservice.local"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="10" />

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

    <application
        android:icon="@drawable/icon"
        android:label="@string/app_name" >
        <activity
            android:name=".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>

        <service
            android:name=".LocalWordService"
            android:icon="@drawable/icon"
            android:label="@string/service_name" >
        </service>

        <receiver android:name="MyScheduleReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
        <receiver android:name="MyStartServiceReceiver" >
        </receiver>
    </application>

</manifest>
               
Change the "main.xml" layout to the following.

                       
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="showServiceData"
        android:text="Button" >
    </Button>

    <ListView
        android:id="@id/android:list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>

</LinearLayout>
               
Change your Activity to the following.

                        
package de.vogella.android.ownservice.local;

import java.util.ArrayList;
import java.util.List;

import android.app.ListActivity;
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.view.View;
import android.widget.ArrayAdapter;
import android.widget.Toast;

public class MainActivity extends ListActivity {
        private LocalWordService s;

       
/** Called when the activity is first created. */

        @Override
        public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.main);
                wordList = new ArrayList<String>();
                adapter = new ArrayAdapter<String>(this,
                                android.R.layout.simple_list_item_1, android.R.id.text1,
                                wordList);
                setListAdapter(adapter);
                doBindService();
        }

        private ServiceConnection mConnection = new ServiceConnection() {

                public void onServiceConnected(ComponentName className, IBinder binder) {
                        s = ((LocalWordService.MyBinder) binder).getService();
                        Toast.makeText(MainActivity.this, "Connected",
                                        Toast.LENGTH_SHORT).show();
                }

                public void onServiceDisconnected(ComponentName className) {
                        s = null;
                }
        };
        private ArrayAdapter<String> adapter;
        private List<String> wordList;

        void doBindService() {
                bindService(new Intent(this, LocalWordService.class), mConnection,
                                Context.BIND_AUTO_CREATE);
        }

        public void showServiceData(View view) {
                if (s != null) {

                        Toast.makeText(this, "Number of elements" + s.getWordList().size(),
                                        Toast.LENGTH_SHORT).show();
                        wordList.clear();
                        wordList.addAll(s.getWordList());
                        adapter.notifyDataSetChanged();
                }
        }
}
               
11. TUTORIAL: INTERPROCESS COMMUNICATION WITH MESSENGER
The following chapter will demonstrate how to communicate between an Activity and an Service using the Messenger andHandler class.
Create a new project called "de.vogella.android.ownservice.messenger" with an Activity called "MainActivity".
Creating the following "AndroidManifest.xml".

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

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

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".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>

        <service android:name="DownloadServiceMessenger" >
        </service>
    </application>

</manifest>
               
Create the following class

                       
package de.vogella.android.ownservice.messenger;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;

import android.app.Activity;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.StrictMode;
import android.util.Log;

public class DownloadServiceMessenger extends Service {
        public static final String FILENAME = "fileName";
        public static final String URLPATH = "urlPath";
        public static final String RESULTPATH = "urlPath";
        private int result = Activity.RESULT_CANCELED;

        // Used to receive messages from the Activity
        final Messenger inMessenger = new Messenger(new IncomingHandler());
        // Use to send message to the Activity
        private Messenger outMessenger;

        public DownloadServiceMessenger() {
                super();
                // Don't do this
                // Network Stuff will run in the main thread
                StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
                                .permitAll().build();
                StrictMode.setThreadPolicy(policy);
        }

        class IncomingHandler extends Handler {
                @Override
                public void handleMessage(Message msg) {
                        Log.e("MESSAGE", "Got message");
                        Bundle data = msg.getData();
                        String urlPath = data.getString(DownloadServiceMessenger.URLPATH);
                        String fileName = data.getString(DownloadServiceMessenger.FILENAME);
                        String outputPath = download(urlPath, fileName);

                        Message backMsg = Message.obtain();
                        backMsg.arg1 = result;
                        Bundle bundle = new Bundle();
                        bundle.putString(RESULTPATH, outputPath);
                        backMsg.setData(bundle);
                        try {
                                outMessenger.send(backMsg);
                        } catch (android.os.RemoteException e1) {
                                Log.w(getClass().getName(), "Exception sending message", e1);
                        }
                }
        }

        private String download(String urlPath, String fileName) {
                File output = new File(Environment.getExternalStorageDirectory(),
                                fileName);
                if (output.exists()) {
                        output.delete();
                }

                InputStream stream = null;
                FileOutputStream fos = null;
                try {

                        URL url = new URL(urlPath);
                        stream = url.openConnection().getInputStream();
                        InputStreamReader reader = new InputStreamReader(stream);
                        fos = new FileOutputStream(output.getPath());
                        int next = -1;
                        while ((next = reader.read()) != -1) {
                                fos.write(next);
                        }
                        // Sucessful finished
                        result = Activity.RESULT_OK;

                } catch (Exception e) {
                        e.printStackTrace();
                } finally {
                        if (stream != null) {
                                try {
                                        stream.close();
                                } catch (IOException e) {
                                        e.printStackTrace();
                                }
                        }
                        if (fos != null) {
                                try {
                                        fos.close();
                                } catch (IOException e) {
                                        e.printStackTrace();
                                }
                        }
                }
                return output.getAbsolutePath();

        }

        @Override
        public IBinder onBind(Intent intent) {
                Bundle extras = intent.getExtras();
                // Get messager from the Activity
                if (extras != null) {
                        outMessenger = (Messenger) extras.get("MESSENGER");
                }
                // Return our messenger to the Activity to get commands
                return inMessenger.getBinder();
        }
}

               
Change the "main.xml" layout to the following.

                       
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="Button" />

</LinearLayout>
                
Change MainActivity to the following.

                       
package de.vogella.android.ownservice.messenger;

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.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity {
        Messenger messenger = null;

        private Handler handler = new Handler() {
                public void handleMessage(Message message) {
                        Bundle data = message.getData();
                        if (message.arg1 == RESULT_OK && data != null) {
                                String text = data
                                                .getString(DownloadServiceMessenger.RESULTPATH);
                                Toast.makeText(MainActivity.this, text, Toast.LENGTH_LONG)
                                                .show();
                        }
                }
        };

        @Override
        public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.main);

        }

        private ServiceConnection conn = new ServiceConnection() {

                public void onServiceConnected(ComponentName className, IBinder binder) {
                        messenger = new Messenger(binder);

                }

                public void onServiceDisconnected(ComponentName className) {
                        messenger = null;
                }
        };

        protected void onResume() {
                super.onResume();
                Toast.makeText(this, "OnResume called", Toast.LENGTH_SHORT).show();
                Intent intent = null;
                intent = new Intent(this, DownloadServiceMessenger.class);
                // Create a new Messenger for the communication back
                // From the Service to the Activity
                Messenger messenger = new Messenger(handler);
                intent.putExtra("MESSENGER", messenger);

                bindService(intent, conn, Context.BIND_AUTO_CREATE);
        }

        @Override
        protected void onPause() {
                super.onPause();
                unbindService(conn);
        }

        public void onClick(View view) {
                Message msg = Message.obtain();

                try {
                        Bundle bundle = new Bundle();
                        bundle.putString(DownloadServiceMessenger.FILENAME, "index.html");
                        bundle.putString(DownloadServiceMessenger.URLPATH,
                                        "http://www.vogella.de/index.html");
                        msg.setData(bundle);
                        messenger.send(msg);
                } catch (RemoteException e) {
                        e.printStackTrace();
                }
        }
}
               
Services

Service is an application component that can perform long-running operations in the background and does not provide a user interface. Another application component can start a service and it will continue to run in the background even if the user switches to another application. Additionally, a component can bind to a service to interact with it and even perform interprocess communication (IPC). For example, a service might handle network transactions, play music, perform file I/O, or interact with a content provider, all from the background.
A service can essentially take two forms:
Started
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.
Bound
A service is "bound" when an application component binds to it by calling bindService(). A bound service offers a client-server interface that allows components to interact with the service, send requests, get results, and even do so across processes with interprocess communication (IPC). A bound service runs only as long as another application component is bound to it. Multiple components can bind to the service at once, but when all of them unbind, the service is destroyed.
Although this documentation generally discusses these two types of services separately, your service can work both ways—it can be started (to run indefinitely) and also allow binding. It's simply a matter of whether you implement a couple callback methods:onStartCommand() to allow components to start it and onBind() to allow binding.
Regardless of whether your application is started, bound, or both, any application component can use the service (even from a separate application), in the same way that any component can use an activity—by starting it with an Intent. However, you can declare the service as private, in the manifest file, and block access from other applications. This is discussed more in the section about Declaring the service in the manifest.
Caution: A service runs in the main thread of its hosting process—the service does not create its own thread and does not run in a separate process (unless you specify otherwise). This means that, if your service is going to do any CPU intensive work or blocking operations (such as MP3 playback or networking), you should create a new thread within the service to do that work. By using a separate thread, you will reduce the risk of Application Not Responding (ANR) errors and the application's main thread can remain dedicated to user interaction with your activities.
THE BASICS
Should you use a service or a thread?
A service is simply a component that can run in the background even when the user is not interacting with your application. Thus, you should create a service only if that is what you need.
If you need to perform work outside your main thread, but only while the user is interacting with your application, then you should probably instead create a new thread and not a service. For example, if you want to play some music, but only while your activity is running, you might create a thread in onCreate(), start running it in onStart(), then stop it in onStop(). Also consider usingAsyncTask or HandlerThread, instead of the traditional Thread class. See the Processes and Threading document for more information about threads.
Remember that if you do use a service, it still runs in your application's main thread by default, so you should still create a new thread within the service if it performs intensive or blocking operations.
To create a service, you must create a subclass of Service (or one of its existing subclasses). In your implementation, you need to override some callback methods that handle key aspects of the service lifecycle and provide a mechanism for components to bind to the service, if appropriate. The most important callback methods you should override are:
The system calls this method when another component, such as an activity, requests that the service be started, by callingstartService(). Once this method executes, the service is started and can run in the background indefinitely. If you implement this, it is your responsibility to stop the service when its work is done, by calling stopSelf() or stopService(). (If you only want to provide binding, you don't need to implement this method.)
The system calls this method when another component wants to bind with the service (such as to perform RPC), by callingbindService(). In your implementation of this method, you must provide an interface that clients use to communicate with the service, by returning an IBinder. You must always implement this method, but if you don't want to allow binding, then you should return null.
The system calls this method when the service is first created, to perform one-time setup procedures (before it calls eitheronStartCommand() or onBind()). If the service is already running, this method is not called.
The system calls this method when the service is no longer used and is being destroyed. Your service should implement this to clean up any resources such as threads, registered listeners, receivers, etc. This is the last call the service receives.
If a component starts the service by calling startService() (which results in a call to onStartCommand()), then the service remains running until it stops itself with stopSelf() or another component stops it by calling stopService().
If a component calls bindService() to create the service (and onStartCommand() is not called), then the service runs only as long as the component is bound to it. Once the service is unbound from all clients, the system destroys it.
The Android system will force-stop a service only when memory is low and it must recover system resources for the activity that has user focus. If the service is bound to an activity that has user focus, then it's less likely to be killed, and if the service is declared to run in the foreground (discussed later), then it will almost never be killed. Otherwise, if the service was started and is long-running, then the system will lower its position in the list of background tasks over time and the service will become highly susceptible to killing—if your service is started, then you must design it to gracefully handle restarts by the system. If the system kills your service, it restarts it as soon as resources become available again (though this also depends on the value you return from onStartCommand(), as discussed later). For more information about when the system might destroy a service, see the Processes and Threading document.
In the following sections, you'll see how you can create each type of service and how to use it from other application components.
Declaring a service in the manifest
Like activities (and other components), you must declare all services in your application's manifest file.
To declare your service, add a <service> element as a child of the <application> element. For example:
<manifest ... >
  ...
  <application ... >
      <service android:name=".ExampleService" />
      ...
  </application>
</manifest>
There are other attributes you can include in the <service> element to define properties such as permissions required to start the service and the process in which the service should run. The android:name attribute is the only required attribute—it specifies the class name of the service. Once you publish your application, you should not change this name, because if you do, you might break some functionality where explicit intents are used to reference your service (read the blog post, Things That Cannot Change).
See the <service> element reference for more information about declaring your service in the manifest.
Just like an activity, a service can define intent filters that allow other components to invoke the service using implicit intents. By declaring intent filters, components from any application installed on the user's device can potentially start your service if your service declares an intent filter that matches the intent another application passes to startService().
If you plan on using your service only locally (other applications do not use it), then you don't need to (and should not) supply any intent filters. Without any intent filters, you must start the service using an intent that explicitly names the service class. More information aboutstarting a service is discussed below.
Additionally, you can ensure that your service is private to your application only if you include the android:exported attribute and set it to "false". This is effective even if your service supplies intent filters.
For more information about creating intent filters for your service, see the Intents and Intent Filters document.
CREATING A STARTED SERVICE
TARGETING ANDROID 1.6 OR LOWER
If you're building an application for Android 1.6 or lower, you need to implement onStart(), instead of onStartCommand() (in Android 2.0, onStart() was deprecated in favor of onStartCommand()).
For more information about providing compatibility with versions of Android older than 2.0, see the onStartCommand()documentation.
A started service is one that another component starts by calling startService(), resulting in a call to the service'sonStartCommand() method.
When a service is started, it has a lifecycle that's independent of the component that started it and the service can run in the background indefinitely, even if the component that started it is destroyed. As such, the service should stop itself when its job is done by calling stopSelf(), or another component can stop it by calling stopService().
An application component such as an activity can start the service by calling startService() and passing an Intent that specifies the service and includes any data for the service to use. The service receives this Intent in the onStartCommand() method.
For instance, suppose an activity needs to save some data to an online database. The activity can start a companion service and deliver it the data to save by passing an intent to startService(). The service receives the intent in onStartCommand(), connects to the Internet and performs the database transaction. When the transaction is done, the service stops itself and it is destroyed.
Caution: A services runs in the same process as the application in which it is declared and in the main thread of that application, by default. So, if your service performs intensive or blocking operations while the user interacts with an activity from the same application, the service will slow down activity performance. To avoid impacting application performance, you should start a new thread inside the service.
Traditionally, there are two classes you can extend to create a started service:
This is the base class for all services. When you extend this class, it's important that you create a new thread in which to do all the service's work, because the service uses your application's main thread, by default, which could slow the performance of any activity your application is running.
This is a subclass of Service that uses a worker thread to handle all start requests, one at a time. This is the best option if you don't require that your service handle multiple requests simultaneously. All you need to do is implement onHandleIntent(), which receives the intent for each start request so you can do the background work.
The following sections describe how you can implement your service using either one for these classes.
Extending the IntentService class
Because most started services don't need to handle multiple requests simultaneously (which can actually be a dangerous multi-threading scenario), it's probably best if you implement your service using the IntentService class.
The IntentService does the following:
·                     Creates a default worker thread that executes all intents delivered to onStartCommand() separate from your application's main thread.
·                     Creates a work queue that passes one intent at a time to your onHandleIntent() implementation, so you never have to worry about multi-threading.
·                     Stops the service after all start requests have been handled, so you never have to call stopSelf().
·                     Provides default implementation of onBind() that returns null.
·                     Provides a default implementation of onStartCommand() that sends the intent to the work queue and then to youronHandleIntent() implementation. 
All this adds up to the fact that all you need to do is implement onHandleIntent() to do the work provided by the client. (Though, you also need to provide a small constructor for the service.)
Here's an example implementation of IntentService:
public class HelloIntentService extends IntentService {
  /**
   * A constructor is required, and must call the super IntentService(String)
   * constructor with a name for the worker thread.
   */
  public HelloIntentService() {
      super("HelloIntentService");
  }
  /**
   * The IntentService calls this method from the default worker thread with
   * the intent that started the service. When this method returns, IntentService
   * stops the service, as appropriate.
   */
  @Override
  protected void onHandleIntent(Intent intent) {
      // Normally we would do some work here, like download a file.
      // For our sample, we just sleep for 5 seconds.
      long endTime = System.currentTimeMillis() + 5*1000;
      while (System.currentTimeMillis() < endTime) {
          synchronized (this) {
              try {
                  wait(endTime - System.currentTimeMillis());
              } catch (Exception e) {
              }
          }
      }
  }
}
That's all you need: a constructor and an implementation of onHandleIntent().
If you decide to also override other callback methods, such as onCreate()onStartCommand(), or onDestroy(), be sure to call the super implementation, so that the IntentService can properly handle the life of the worker thread.
For example, onStartCommand() must return the default implementation (which is how the intent gets delivered toonHandleIntent()):
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
    return super.onStartCommand(intent,flags,startId);
}
Besides onHandleIntent(), the only method from which you don't need to call the super class is onBind() (but you only need to implement that if your service allows binding).
In the next section, you'll see how the same kind of service is implemented when extending the base Service class, which is a lot more code, but which might be appropriate if you need to handle simultaneous start requests.
Extending the Service class
As you saw in the previous section, using IntentService makes your implementation of a started service very simple. If, however, you require your service to perform multi-threading (instead of processing start requests through a work queue), then you can extend the Service class to handle each intent.
For comparison, the following example code is an implementation of the Service class that performs the exact same work as the example above using IntentService. That is, for each start request, it uses a worker thread to perform the job and processes only one request at a time.
public class HelloService extends Service {
  private Looper mServiceLooper;
  private ServiceHandler mServiceHandler;
  // Handler that receives messages from the thread
  private final class ServiceHandler extends Handler {
      public ServiceHandler(Looper looper) {
          super(looper);
      }
      @Override
      public void handleMessage(Message msg) {
          // Normally we would do some work here, like download a file.
          // For our sample, we just sleep for 5 seconds.
          long endTime = System.currentTimeMillis() + 5*1000;
          while (System.currentTimeMillis() < endTime) {
              synchronized (this) {
                  try {
                      wait(endTime - System.currentTimeMillis());
                  } catch (Exception e) {
                  }
              }
          }
          // Stop the service using the startId, so that we don't stop
          // the service in the middle of handling another job
          stopSelf(msg.arg1);
      }
  }
  @Override
  public void onCreate() {
    // Start up the thread running the service.  Note that we create a
    // separate thread because the service normally runs in the process's
    // main thread, which we don't want to block.  We also make it
    // background priority so CPU-intensive work will not disrupt our UI.
    HandlerThread thread = new HandlerThread("ServiceStartArguments",
            Process.THREAD_PRIORITY_BACKGROUND);
    thread.start();
   
    // Get the HandlerThread's Looper and use it for our Handler
    mServiceLooper = thread.getLooper();
    mServiceHandler = new ServiceHandler(mServiceLooper);
  }
  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
      Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
      // 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
  public IBinder onBind(Intent intent) {
      // We don't provide binding, so return null
      return null;
  }
 
  @Override
  public void onDestroy() {
    Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
  }
}
As you can see, it's a lot more work than using IntentService.
However, because you handle each call to onStartCommand() yourself, you can perform multiple requests simultaneously. That's not what this example does, but if that's what you want, then you can create a new thread for each request and run them right away (instead of waiting for the previous request to finish).
Notice that the onStartCommand() method must return an integer. The integer is a value that describes how the system should continue the service in the event that the system kills it (as discussed above, the default implementation for IntentService handles this for you, though you are able to modify it). The return value from onStartCommand() must be one of the following constants:
If the system kills the service after onStartCommand() returns, do not recreate the service, unless there are pending intents to deliver. This is the safest option to avoid running your service when not necessary and when your application can simply restart any unfinished jobs.
If the system kills the service after onStartCommand() returns, recreate the service and call onStartCommand(), but do notredeliver the last intent. Instead, the system calls onStartCommand() with a null intent, unless there were pending intents to start the service, in which case, those intents are delivered. This is suitable for media players (or similar services) that are not executing commands, but running indefinitely and waiting for a job.
If the system kills the service after onStartCommand() returns, recreate the service and call onStartCommand() with the last intent that was delivered to the service. Any pending intents are delivered in turn. This is suitable for services that are actively performing a job that should be immediately resumed, such as downloading a file.
For more details about these return values, see the linked reference documentation for each constant.
Starting a Service
You can start a service from an activity or other application component by passing an Intent (specifying the service to start) tostartService(). The Android system calls the service's onStartCommand() method and passes it the Intent. (You should never call onStartCommand() directly.)
For example, an activity can start the example service in the previous section (HelloSevice) using an explicit intent withstartService():
Intent intent = new Intent(this, HelloService.class);
startService(intent);
The startService() method returns immediately and the Android system calls the service's onStartCommand() method. If the service is not already running, the system first calls onCreate(), then calls onStartCommand().
If the service does not also provide binding, the intent delivered with startService() is the only mode of communication between the application component and the service. However, if you want the service to send a result back, then the client that starts the service can create a PendingIntent for a broadcast (with getBroadcast()) and deliver it to the service in the Intent that starts the service. The service can then use the broadcast to deliver a result.
Multiple requests to start the service result in multiple corresponding calls to the service's onStartCommand(). However, only one request to stop the service (with stopSelf() or stopService()) is required to stop it.
Stopping a service
A started service must manage its own lifecycle. That is, the system does not stop or destroy the service unless it must recover system memory and the service continues to run after onStartCommand() returns. So, the service must stop itself by calling stopSelf()or another component can stop it by calling stopService().
Once requested to stop with stopSelf() or stopService(), the system destroys the service as soon as possible.
However, if your service handles multiple requests to onStartCommand() concurrently, then you shouldn't stop the service when you're done processing a start request, because you might have since received a new start request (stopping at the end of the first request would terminate the second one). To avoid this problem, you can use stopSelf(int) to ensure that your request to stop the service is always based on the most recent start request. That is, when you call stopSelf(int), you pass the ID of the start request (the startId delivered to onStartCommand()) to which your stop request corresponds. Then if the service received a new start request before you were able to call stopSelf(int), then the ID will not match and the service will not stop.
Caution: It's important that your application stops its services when it's done working, to avoid wasting system resources and consuming battery power. If necessary, other components can stop the service by calling stopService(). Even if you enable binding for the service, you must always stop the service yourself if it ever received a call to onStartCommand().
For more information about the lifecycle of a service, see the section below about Managing the Lifecycle of a Service.
CREATING A BOUND SERVICE
A bound service is one that allows application components to bind to it by calling bindService() in order to create a long-standing connection (and generally does not allow components to start it by calling startService()).
You should create a bound service when you want to interact with the service from activities and other components in your application or to expose some of your application's functionality to other applications, through interprocess communication (IPC).
To create a bound service, you must implement the onBind() callback method to return an IBinder that defines the interface for communication with the service. Other application components can then call bindService() to retrieve the interface and begin calling methods on the service. The service lives only to serve the application component that is bound to it, so when there are no components bound to the service, the system destroys it (you do not need to stop a bound service in the way you must when the service is started through onStartCommand()).
To create a bound service, the first thing you must do is define the interface that specifies how a client can communicate with the service. This interface between the service and a client must be an implementation of IBinder and is what your service must return from the onBind() callback method. Once the client receives the IBinder, it can begin interacting with the service through that interface.
Multiple clients can bind to the service at once. When a client is done interacting with the service, it calls unbindService() to unbind. Once there are no clients bound to the service, the system destroys the service.
There are multiple ways to implement a bound service and the implementation is more complicated than a started service, so the bound service discussion appears in a separate document about Bound Services.
SENDING NOTIFICATIONS TO THE USER
Once running, a service can notify the user of events using Toast Notifications or Status Bar Notifications.
A toast notification is a message that appears on the surface of the current window for a moment then disappears, while a status bar notification provides an icon in the status bar with a message, which the user can select in order to take an action (such as start an activity).
Usually, a status bar notification is the best technique when some background work has completed (such as a file completed downloading) and the user can now act on it. When the user selects the notification from the expanded view, the notification can start an activity (such as to view the downloaded file).
See the Toast Notifications or Status Bar Notifications developer guides for more information.
RUNNING A SERVICE IN THE FOREGROUND
A foreground service is a service that's considered to be something the user is actively aware of and thus not a candidate for the system to kill when low on memory. A foreground service must provide a notification for the status bar, which is placed under the "Ongoing" heading, which means that the notification cannot be dismissed unless the service is either stopped or removed from the foreground.
For example, a music player that plays music from a service should be set to run in the foreground, because the user is explicitly aware of its operation. The notification in the status bar might indicate the current song and allow the user to launch an activity to interact with the music player.
To request that your service run in the foreground, call startForeground(). This method takes two parameters: an integer that uniquely identifies the notification and the Notification for the status bar. For example:
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
        System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
        getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION, notification);
To remove the service from the foreground, call stopForeground(). This method takes a boolean, indicating whether to remove the status bar notification as well. This method does not stop the service. However, if you stop the service while it's still running in the foreground, then the notification is also removed.
Note: The methods startForeground() and stopForeground() were introduced in Android 2.0 (API Level 5). In order to run your service in the foreground on older versions of the platform, you must use the previous setForeground() method—see thestartForeground() documentation for information about how to provide backward compatibility.
For more information about notifications, see Creating Status Bar Notifications.
MANAGING THE LIFECYCLE OF A SERVICE
The lifecycle of a service is much simpler than that of an activity. However, it's even more important that you pay close attention to how your service is created and destroyed, because a service can run in the background without the user being aware.
The service lifecycle—from when it's created to when it's destroyed—can follow two different paths:
·                     A started service
The service is created when another component calls startService(). The service then runs indefinitely and must stop itself by calling stopSelf(). Another component can also stop the service by calling stopService(). When the service is stopped, the system destroys it..
·                     A bound service
The service is created when another component (a client) calls bindService(). The client then communicates with the service through an IBinder interface. The client can close the connection by calling unbindService(). Multiple clients can bind to the same service and when all of them unbind, the system destroys the service. (The service does not need to stop itself.)
These two paths are not entirely separate. That is, you can bind to a service that was already started with startService(). For example, a background music service could be started by calling startService() with an Intent that identifies the music to play. Later, possibly when the user wants to exercise some control over the player or get information about the current song, an activity can bind to the service by calling bindService(). In cases like this, stopService() or stopSelf() does not actually stop the service until all clients unbind. 
Implementing the lifecycle callbacks
Like an activity, a service has lifecycle callback methods that you can implement to monitor changes in the service's state and perform work at the appropriate times. The following skeleton service demonstrates each of the lifecycle methods:

Figure 2. The service lifecycle. The diagram on the left shows the lifecycle when the service is created with startService() and the diagram on the right shows the lifecycle when the service is created with bindService().
public class ExampleService extends Service {
    int mStartMode;       // indicates how to behave if the service is killed
    IBinder mBinder;      // interface for clients that bind
    boolean mAllowRebind; // indicates whether onRebind should be used
    @Override
    public void onCreate() {
        // The service is being created
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // The service is starting, due to a call to startService()
        return mStartMode;
    }
    @Override
    public IBinder onBind(Intent intent) {
        // A client is binding to the service with bindService()
        return mBinder;
    }
    @Override
    public boolean onUnbind(Intent intent) {
        // All clients have unbound with unbindService()
        return mAllowRebind;
    }
    @Override
    public void onRebind(Intent intent) {
        // A client is binding to the service with bindService(),
        // after onUnbind() has already been called
    }
    @Override
    public void onDestroy() {
        // The service is no longer used and is being destroyed
    }
}
Note: Unlike the activity lifecycle callback methods, you are not required to call the superclass implementation of these callback methods.
By implementing these methods, you can monitor two nested loops of the service's lifecycle: 
·                     The entire lifetime of a service happens between the time onCreate() is called and the time onDestroy() returns. Like an activity, a service does its initial setup in onCreate() and releases all remaining resources in onDestroy(). For example, a music playback service could create the thread where the music will be played in onCreate(), then stop the thread in onDestroy().
The onCreate() and onDestroy() methods are called for all services, whether they're created by startService() orbindService().
·                     The active lifetime of a service begins with a call to either onStartCommand() or onBind(). Each method is handed the Intent that was passed to either startService() or bindService(), respectively.
If the service is started, the active lifetime ends the same time that the entire lifetime ends (the service is still active even after onStartCommand() returns). If the service is bound, the active lifetime ends when onUnbind() returns.
Note: Although a started service is stopped by a call to either stopSelf() or stopService(), there is not a respective callback for the service (there's no onStop() callback). So, unless the service is bound to a client, the system destroys it when the service is stopped—onDestroy() is the only callback received.
Figure 2 illustrates the typical callback methods for a service. Although the figure separates services that are created bystartService() from those created by bindService(), keep in mind that any service, no matter how it's started, can potentially allow clients to bind to it. So, a service that was initially started with onStartCommand() (by a client calling startService()) can still receive a call to onBind() (when a client calls bindService()).
For more information about creating a service that provides binding, see the Bound Services document, which includes more information about the onRebind() callback method in the section about Managing the Lifecycle of a Bound Service.


Bound Services

QUICKVIEW
·                     A bound service allows other components to bind to it, in order to interact with it and perform interprocess communication
·                     A bound service is destroyed once all clients unbind, unless the service was also started 
IN THIS DOCUMENT
·                     The Basics
·                     Creating a Bound Service
1.             Extending the Binder class
2.             Using a Messenger
·                     Binding to a Service
·                     Managing the Lifecycle of a Bound Service 
KEY CLASSES
·                     Service
·                     ServiceConnection
·                     IBinder 
SAMPLES
·                     RemoteService
·                     LocalService 
SEE ALSO
·                     Services 
A bound service is the server in a client-server interface. A bound service allows components (such as activities) to bind to the service, send requests, receive responses, and even perform interprocess communication (IPC). A bound service typically lives only while it serves another application component and does not run in the background indefinitely.
This document shows you how to create a bound service, including how to bind to the service from other application components. However, you should also refer to the Services document for additional information about services in general, such as how to deliver notifications from a service, set the service to run in the foreground, and more.
THE BASICS
A bound service is an implementation of the Service class that allows other applications to bind to it and interact with it. To provide binding for a service, you must implement the onBind() callback method. This method returns an IBinder object that defines the programming interface that clients can use to interact with the service.
Binding to a Started Service
As discussed in the Services document, you can create a service that is both started and bound. That is, the service can be started by calling startService(), which allows the service to run indefinitely, and also allow a client to bind to the service by callingbindService().
If you do allow your service to be started and bound, then when the service has been started, the system does not destroy the service when all clients unbind. Instead, you must explicitly stop the service, by calling stopSelf() or stopService().
Although you should usually implement either onBind() or onStartCommand(), it's sometimes necessary to implement both. For example, a music player might find it useful to allow its service to run indefinitely and also provide binding. This way, an activity can start the service to play some music and the music continues to play even if the user leaves the application. Then, when the user returns to the application, the activity can bind to the service to regain control of playback.
Be sure to read the section about Managing the Lifecycle of a Bound Service, for more information about the service lifecycle when adding binding to a started service.
A client can bind to the service by calling bindService(). When it does, it must provide an implementation ofServiceConnection, which monitors the connection with the service. The bindService() method returns immediately without a value, but when the Android system creates the connection between the client and service, it calls onServiceConnected() on theServiceConnection, to deliver the IBinder that the client can use to communicate with the service.
Multiple clients can connect to the service at once. However, the system calls your service's onBind() method to retrieve theIBinder only when the first client binds. The system then delivers the same IBinder to any additional clients that bind, without callingonBind() again.
When the last client unbinds from the service, the system destroys the service (unless the service was also started bystartService()).
When you implement your bound service, the most important part is defining the interface that your onBind() callback method returns. There are a few different ways you can define your service's IBinder interface and the following section discusses each technique.
CREATING A BOUND SERVICE
When creating a service that provides binding, you must provide an IBinder that provides the programming interface that clients can use to interact with the service. There are three ways you can define the interface:
If your service is private to your own application and runs in the same process as the client (which is common), you should create your interface by extending the Binder class and returning an instance of it from onBind(). The client receives the Binderand can use it to directly access public methods available in either the Binder implementation or even the Service.
This is the preferred technique when your service is merely a background worker for your own application. The only reason you would not create your interface this way is because your service is used by other applications or across separate processes.
If you need your interface to work across different processes, you can create an interface for the service with a Messenger. In this manner, the service defines a Handler that responds to different types of Message objects. This Handler is the basis for aMessenger that can then share an IBinder with the client, allowing the client to send commands to the service using Messageobjects. Additionally, the client can define a Messenger of its own so the service can send messages back.
This is the simplest way to perform interprocess communication (IPC), because the Messenger queues all requests into a single thread so that you don't have to design your service to be thread-safe.
Using AIDL
AIDL (Android Interface Definition Language) performs all the work to decompose objects into primitives that the operating system can understand and marshall them across processes to perform IPC. The previous technique, using a Messenger, is actually based on AIDL as its underlying structure. As mentioned above, the Messenger creates a queue of all the client requests in a single thread, so the service receives requests one at a time. If, however, you want your service to handle multiple requests simultaneously, then you can use AIDL directly. In this case, your service must be capable of multi-threading and be built thread-safe.
To use AIDL directly, you must create an .aidl file that defines the programming interface. The Android SDK tools use this file to generate an abstract class that implements the interface and handles IPC, which you can then extend within your service.
Note: Most applications should not use AIDL to create a bound service, because it may require multithreading capabilities and can result in a more complicated implementation. As such, AIDL is not suitable for most applications and this document does not discuss how to use it for your service. If you're certain that you need to use AIDL directly, see the AIDL document.
Extending the Binder class
If your service is used only by the local application and does not need to work across processes, then you can implement your ownBinder class that provides your client direct access to public methods in the service.
Note: This works only if the client and service are in the same application and process, which is most common. For example, this would work well for a music application that needs to bind an activity to its own service that's playing music in the background.
Here's how to set it up:
1.             In your service, create an instance of Binder that either:
·                     contains public methods that the client can call
·                     returns the current Service instance, which has public methods the client can call
·                     or, returns an instance of another class hosted by the service with public methods the client can call
2.             Return this instance of Binder from the onBind() callback method.
3.             In the client, receive the Binder from the onServiceConnected() callback method and make calls to the bound service using the methods provided. 
Note: The reason the service and client must be in the same application is so the client can cast the returned object and properly call its APIs. The service and client must also be in the same process, because this technique does not perform any marshalling across processes.
For example, here's a service that provides clients access to methods in the service through a Binder implementation:
public class LocalService extends Service {
    // Binder given to clients
    private final IBinder mBinder = new LocalBinder();
    // Random number generator
    private final Random mGenerator = new Random();
    /**
     * Class used for the client Binder.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with IPC.
     */
    public class LocalBinder extends Binder {
        LocalService getService() {
            // Return this instance of LocalService so clients can call public methods
            return LocalService.this;
        }
    }
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
    /** method for clients */
    public int getRandomNumber() {
      return mGenerator.nextInt(100);
    }
}
The LocalBinder provides the getService() method for clients to retrieve the current instance of LocalService. This allows clients to call public methods in the service. For example, clients can call getRandomNumber() from the service.
Here's an activity that binds to LocalService and calls getRandomNumber() when a button is clicked:
public class BindingActivity extends Activity {
    LocalService mService;
    boolean mBound = false;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    @Override
    protected void onStart() {
        super.onStart();
        // Bind to LocalService
        Intent intent = new Intent(this, LocalService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }
    @Override
    protected void onStop() {
        super.onStop();
        // Unbind from the service
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }
    /** Called when a button is clicked (the button in the layout file attaches to
      * this method with the android:onClick attribute) */
    public void onButtonClick(View v) {
        if (mBound) {
            // Call a method from the LocalService.
            // However, if this call were something that might hang, then this request should
            // occur in a separate thread to avoid slowing down the activity performance.
            int num = mService.getRandomNumber();
            Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
        }
    }
    /** Defines callbacks for service binding, passed to bindService() */
    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName className,
                IBinder service) {
            // We've bound to LocalService, cast the IBinder and get LocalService instance
            LocalBinder binder = (LocalBinder) service;
            mService = binder.getService();
            mBound = true;
        }
        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };
}
The above sample shows how the client binds to the service using an implementation of ServiceConnection and theonServiceConnected() callback. The next section provides more information about this process of binding to the service.
Note: The example above doesn't explicitly unbind from the service, but all clients should unbind at an appropriate time (such as when the activity pauses).
For more sample code, see the LocalService.java class and the LocalServiceActivities.java class in ApiDemos.
Using a Messenger
Compared to AIDL
When you need to perform IPC, using a Messenger for your interface is simpler than implementing it with AIDL, because Messengerqueues all calls to the service, whereas, a pure AIDL interface sends simultaneous requests to the service, which must then handle multi-threading.
For most applications, the service doesn't need to perform multi-threading, so using a Messenger allows the service to handle one call at a time. If it's important that your service be multi-threaded, then you should use AIDL to define your interface.
If you need your service to communicate with remote processes, then you can use a Messenger to provide the interface for your service. This technique allows you to perform interprocess communication (IPC) without the need to use AIDL.
Here's a summary of how to use a Messenger:
·                     The service implements a Handler that receives a callback for each call from a client.
·                     The Handler is used to create a Messenger object (which is a reference to the Handler).
·                     The Messenger creates an IBinder that the service returns to clients from onBind().
·                     Clients use the IBinder to instantiate the Messenger (that references the service's Handler), which the client uses to send Message objects to the service.
·                     The service receives each Message in its Handler—specifically, in the handleMessage() method. 
In this way, there are no "methods" for the client to call on the service. Instead, the client delivers "messages" (Message objects) that the service receives in its Handler.
Here's a simple example service that uses a Messenger interface:
public class MessengerService extends Service {
    /** Command to the service to display a message */
    static final int MSG_SAY_HELLO = 1;
    /**
     * Handler of incoming messages from clients.
     */
    class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_SAY_HELLO:
                    Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }
    /**
     * Target we publish for clients to send messages to IncomingHandler.
     */
    final Messenger mMessenger = new Messenger(new IncomingHandler());
    /**
     * When binding to the service, we return an interface to our messenger
     * for sending messages to the service.
     */
    @Override
    public IBinder onBind(Intent intent) {
        Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
        return mMessenger.getBinder();
    }
}
Notice that the handleMessage() method in the Handler is where the service receives the incoming Message and decides what to do, based on the what member.
All that a client needs to do is create a Messenger based on the IBinder returned by the service and send a message usingsend(). For example, here's a simple activity that binds to the service and delivers the MSG_SAY_HELLO message to the service:
public class ActivityMessenger extends Activity {
    /** Messenger for communicating with the service. */
    Messenger mService = null;
    /** Flag indicating whether we have called bind on the service. */
    boolean mBound;
    /**
     * Class for interacting with the main interface of the service.
     */
    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            // This is called when the connection with the service has been
            // established, giving us the object we can use to
            // interact with the service.  We are communicating with the
            // service using a Messenger, so here we get a client-side
            // representation of that from the raw IBinder object.
            mService = new Messenger(service);
            mBound = true;
        }
        public void onServiceDisconnected(ComponentName className) {
            // This is called when the connection with the service has been
            // unexpectedly disconnected -- that is, its process crashed.
            mService = null;
            mBound = false;
        }
    };
    public void sayHello(View v) {
        if (!mBound) return;
        // Create and send a message to the service, using a supported 'what' value
        Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
        try {
            mService.send(msg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    @Override
    protected void onStart() {
        super.onStart();
        // Bind to the service
        bindService(new Intent(this, MessengerService.class), mConnection,
            Context.BIND_AUTO_CREATE);
    }
    @Override
    protected void onStop() {
        super.onStop();
        // Unbind from the service
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }
}
Notice that this example does not show how the service can respond to the client. If you want the service to respond, then you need to also create a Messenger in the client. Then when the client receives the onServiceConnected() callback, it sends a Message to the service that includes the client's Messenger in the replyTo parameter of the send() method.
You can see an example of how to provide two-way messaging in the MessengerService.java (service) andMessengerServiceActivities.java (client) samples.
BINDING TO A SERVICE
Application components (clients) can bind to a service by calling bindService(). The Android system then calls the service'sonBind() method, which returns an IBinder for interacting with the service.
The binding is asynchronous. bindService() returns immediately and does not return the IBinder to the client. To receive theIBinder, the client must create an instance of ServiceConnection and pass it to bindService(). The ServiceConnectionincludes a callback method that the system calls to deliver the IBinder.
Note: Only activities, services, and content providers can bind to a service—you cannot bind to a service from a broadcast receiver.
So, to bind to a service from your client, you must: 
1.             Implement ServiceConnection.
Your implementation must override two callback methods:
The system calls this to deliver the IBinder returned by the service's onBind() method.
The Android system calls this when the connection to the service is unexpectedly lost, such as when the service has crashed or has been killed. This is not called when the client unbinds.
2.             Call bindService(), passing the ServiceConnection implementation.
3.             When the system calls your onServiceConnected() callback method, you can begin making calls to the service, using the methods defined by the interface.

4.             To disconnect from the service, call unbindService().
When your client is destroyed, it will unbind from the service, but you should always unbind when you're done interacting with the service or when your activity pauses so that the service can shutdown while its not being used. (Appropriate times to bind and unbind is discussed more below.)
For example, the following snippet connects the client to the service created above by extending the Binder class, so all it must do is cast the returned IBinder to the LocalService class and request the LocalService instance:
LocalService mService;
private ServiceConnection mConnection = new ServiceConnection() {
    // Called when the connection with the service is established
    public void onServiceConnected(ComponentName className, IBinder service) {
        // Because we have bound to an explicit
        // service that is running in our own process, we can
        // cast its IBinder to a concrete class and directly access it.
        LocalBinder binder = (LocalBinder) service;
        mService = binder.getService();
        mBound = true;
    }
    // Called when the connection with the service disconnects unexpectedly
    public void onServiceDisconnected(ComponentName className) {
        Log.e(TAG, "onServiceDisconnected");
        mBound = false;
    }
};
With this ServiceConnection, the client can bind to a service by passing this it to bindService(). For example:
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
·                     The first parameter of bindService() is an Intent that explicitly names the service to bind (thought the intent could be implicit).
·                     The second parameter is the ServiceConnection object.
·                     The third parameter is a flag indicating options for the binding. It should usually be BIND_AUTO_CREATE in order to create the service if its not already alive. Other possible values are BIND_DEBUG_UNBIND and BIND_NOT_FOREGROUND, or 0 for none. 
Additional notes
Here are some important notes about binding to a service:
·  You should always trap DeadObjectException exceptions, which are thrown when the connection has broken. This is the only exception thrown by remote methods.
·    Objects are reference counted across processes.
·    You should usually pair the binding and unbinding during matching bring-up and tear-down moments of the client's lifecycle. For example:
·    If you only need to interact with the service while your activity is visible, you should bind during onStart() and unbind during onStop().
·    If you want your activity to receive responses even while it is stopped in the background, then you can bind duringonCreate() and unbind during onDestroy(). Beware that this implies that your activity needs to use the service the entire time it's running (even in the background), so if the service is in another process, then you increase the weight of the process and it becomes more likely that the system will kill it. 
Note: You should usually not bind and unbind during your activity's onResume() and onPause(), because these callbacks occur at every lifecycle transition and you should keep the processing that occurs at these transitions to a minimum. Also, if multiple activities in your application bind to the same service and there is a transition between two of those activities, the service may be destroyed and recreated as the current activity unbinds (during pause) before the next one binds (during resume). (This activity transition for how activities coordinate their lifecycles is described in the Activitiesdocument.)
For more sample code, showing how to bind to a service, see the RemoteService.java class in ApiDemos.
Figure 1. The lifecycle for a service that is started and also allows binding.
When a service is unbound from all clients, the Android system destroys it (unless it was also started with onStartCommand()). As such, you don't have to manage the lifecycle of your service if it's purely a bound service—the Android system manages it for you based on whether it is bound to any clients.
However, if you choose to implement the onStartCommand() callback method, then you must explicitly stop the service, because the service is now considered to be started. In this case, the service runs until the service stops itself with stopSelf() or another component calls stopService(), regardless of whether it is bound to any clients.
Additionally, if your service is started and accepts binding, then when the system calls your onUnbind() method, you can optionally return true if you would like to receive a call to onRebind() the next time a client binds to the service (instead of receiving a call toonBind()). onRebind() returns void, but the client still receives the IBinder in its onServiceConnected() callback. Below, figure 1 illustrates the logic for this kind of lifecycle.
Example
ServicesDemo
package com.example;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class ServicesDemo extends Activity implements OnClickListener {
private static final String TAG = "ServicesDemo";
Button buttonStart, buttonStop;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

buttonStart = (Button) findViewById(R.id.buttonStart);
buttonStop = (Button) findViewById(R.id.buttonStop);

buttonStart.setOnClickListener(this);
buttonStop.setOnClickListener(this);
}



public void onClick(View src) {
switch (src.getId()) {
case R.id.buttonStart:
Log.d(TAG, "onClick: starting srvice");
startService(new Intent(this, MyService.class));
break;
case R.id.buttonStop:
Log.d(TAG, "onClick: stopping srvice");
stopService(new Intent(this, MyService.class));
break;
}
}
}


MyService
package com.example;

import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

public class MyService extends Service {
private static final String TAG = "MyService";
MediaPlayer player;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG).show();
Log.d(TAG, "onCreate");
player = MediaPlayer.create(this, R.raw.mai);
player.setLooping(false); // Set looping
}

@Override
public void onDestroy() {
Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
Log.d(TAG, "onDestroy");
player.stop();
}
@Override
public void onStart(Intent intent, int startid) {
Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
Log.d(TAG, "onStart");
player.start();
}
}
AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example" android:versionCode="1" android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".ServicesDemo" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:enabled="true" android:name=".MyService" />
</application>
<uses-sdk android:minSdkVersion="3" />
</manifest>


main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="Services Demo" android:gravity="center" android:textSize="20sp" android:padding="20dp"/>
<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/buttonStart" android:text="Start"></Button>
<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Stop" android:id="@+id/buttonStop"></Button>
</LinearLayout>


http://www.javabeat.net/articles/252-creating-services-in-android-1.html



No comments:

Post a Comment