首页 > 代码库 > 2.App Components-Services

2.App Components-Services

1.Services

  A Service is an application component that can perform long-running operations in the background and does not provide a user interface.

  A service can essentially take two forms:

    <1>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.

    <2>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.

  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.

 

2. The Basic

  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:

    <1>onStartCommand()

      The system calls this method when another component, such as an activity, requests that the service be started, by calling

        startService(). 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().

    <2>onBind()

      The system calls this method when another component wants to bind with the service (such as to perform RPC), by calling

        bindService(). 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,

    <3>onCreate()

    <4>onDestroy()

  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.

 

3. Declaring a service in the manifest

  Like activities (and other components), you must declare all services in your application‘s manifest file.

  To ensure your app is secure, always use an explicit intent when starting or binding your Service and do not declare intent filters for

    the service.

 

4. Creating a started Service

  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,

  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.

  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:

  <1>IntentService

    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.

//IntentServiceTestpackage com.example.intentservicedemo;import android.app.IntentService;import android.content.Intent;public class IntentServiceTest extends IntentService {        /**       * A constructor is required, and must call the super IntentService(String)       * constructor with a name for the worker thread.       */    public IntentServiceTest() {  //be sure to use empty constructor!!!!!        super("IntentServiceTest");    }        /**       * 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.                String action = intent.getExtras().getString("param");          if (action.equals("oper1")) {              System.out.println("Operation1");          }else if (action.equals("oper2")) {              System.out.println("Operation2");          }                    try {              Thread.sleep(2000);          } catch (InterruptedException e) {              e.printStackTrace();          }      }}
//Mainactivitypackage com.example.intentservicedemo;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.view.Menu;import android.view.MenuItem;public class MainActivity extends Activity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);              //可以启动多次,每启动一次,就会新建一个work thread,但IntentService的实例始终只有一个          //Operation 1          Intent startServiceIntent = new Intent("com.test.intentservice");          Bundle bundle = new Bundle();          bundle.putString("param", "oper1");          startServiceIntent.putExtras(bundle);          startService(startServiceIntent);                    //Operation 2          Intent startServiceIntent2 = new Intent("com.test.intentservice");          Bundle bundle2 = new Bundle();          bundle2.putString("param", "oper2");          startServiceIntent2.putExtras(bundle2);          startService(startServiceIntent2);      }}
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.intentservicedemo"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk        android:minSdkVersion="16"        android:targetSdkVersion="18" />    <application        android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme" >        <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=".IntentServiceTest">              <intent-filter >                  <action android:name="com.test.intentservice"/>              </intent-filter>          </service>      </application></manifest>

  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.)

  

  <2>Services

    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.

    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.

//MainActivitypackage mirror.android.servicetest;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.view.Menu;import android.view.MenuItem;public class MainActivity extends Activity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);                startService(new Intent("servicetest"));    }}
//ServiceTestpackage mirror.android.servicetest;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.util.Log;public class ServiceTest extends Service {    @Override    public IBinder onBind(Intent intent) {        // We don‘t provide binding, so return null        return null;    }    @Override    public void onDestroy() {        super.onDestroy();    }    @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.        super.onCreate();                Log.d("Service_Test","started");        try {              Thread.sleep(20000);          } catch (InterruptedException e) {              e.printStackTrace();          }          Log.d("Service_Test","Sleep ends");    }}
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="mirror.android.servicetest"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk        android:minSdkVersion="16"        android:targetSdkVersion="18" />    <application        android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme" >        <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=".ServiceTest">            <intent-filter >                <action android:name="servicetest"/>            </intent-filter>        </service>    </application></manifest>

  The appliction will be blocked, and will be warned "The appliction will do too much work ....", because we need to create a new thread,!!!!!!

 

5. Starting a Service

  You can start a service from an activity or other application component by passing an Intent (specifying the service to start) to startService().

    The Android system calls the service‘s onStartCommand() method and passes it the Intent. (You should never call onStartCommand() directly.)

  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.

 

6. Stopping a service

  the service must stop itself by calling stopSelf() or another component can stop it by calling stopService().

  It‘s important that your application stops its services when it‘s done working, to avoid wasting system resources and consuming battery

    power.

  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.

 

7. Sending Notifications to the user

  A service can notify user of events using Toast Notifications or Status Bar Notification

 

8. Managing the lifecycle of a service

  

  

  

2.App Components-Services