service基础

来源:互联网 发布:百度统计数据导出 php 编辑:程序博客网 时间:2024/06/13 04:55
作为android四大组件之一,Services主要用作后台的、耗时操作。它没有UI。应用程序的其他组件可以启动Service,此时Service 即会在后台持续运行,即使用户切换到了其他应用程序,service也依旧运行。此外,组件可以绑定一个Service,一般和它进行交换,甚至实现进程间通信(IPC)。一般:网络传输、播放音乐、执行文件I/O,或者和内容提供者(content provider)交互,都可以放到Service中到后台来执行。
    之前已经提到,Service可以被启动,也可以被绑定。不难理解,Service的两种形式:started Service和bound Service。
  • started:这是一种被应用的组件以调用startService()方法的方式启动的Service。这种Service,被启动后,就开始独立运行,即便当初启动它的组件被摧毁了,也依旧工作。通常,一个started Service执行单独的、不需向调用者返回结果的操作。当操作完成以后,服务应该结束自己。例如,通过网络上传、下载一个文件。
  • bound:这是一种被应用的组件以调用bindService()方法的方式启动的service。这种Service,提供一种Client-Server的接口,来允许组件和Service进行交互:发送请求、获取结果,甚至以这种方式实现夸进程的IPC。bound Service的生命周期依赖于绑定它的组件,和绑定它的组件的生命周期一致。当绑定它的组件的生命周期结束时,bound Service的生命周期也结束。bound Service可以被多个组件绑定,此时,只有多有和它绑定的组件和它unbind之后,这个Service才被摧毁。
  • 混合模式:一个Service可以同时是started、bound模式,Service支持同时是started、bound的方式。
    看上去Service和Thread很像,那么什么时候使用Service,什么时候使用Thread?一般,如果不需要和用户交互也需要执行的任务可以选择使用Service,如果任务只在用户交互驱动时,才工作的,而又不想在main线程中执行,可以选择使用Thread。
    不管是哪种模式的Service,任何一个应用的组件都可以以一种相同的方式使用一个Service,——以Intent来启动。当然,也可以在manifest中声明为私有,阻止来自其他程序的访问。
 

service 基础

    为了创建一个Service,必须创建一个继承自Service或者它的子类的类。在实现中,需要重载一些回调方法来处理Service生命周期的关键环节,以及为组件绑定该Service提供一种合适的机制。下面是一些在创建的类中,需要实现的最重要的回调方法:
  • onStartCommand(): 其他组件调用startService()来启动一个Service时,系统会调用这个回调函数,该函数执行过后,Service就已经被启动了,并且开始在后独立运行。如果你实现了这个函数,那么就必须由你来停止Service,要么调用stopSelt(),要么调用stopService()。也就是说,如果Service只是向提供绑定服务,那么就不需要实现这个方法。让其使用系统默认的实现。
  • onBind(): 其他组件调用bindService()来绑定一个Service时,系统会调用这个回调函数。在实现这个方法(onBind())时,必须提供一个可供Client和Service通信的接口,该接口通过返回一个IBinde来传递。如果不允许service被绑定,那么这里返回null, 否则必须实现这个接口。
  • onCreate(): 系统在Service第一次被创建的时候调用该方法,它是再onStartCommand()和onBind()方法之前被调用的。如果这个Service已经在运行了,那么这个函数不会被调用。
  • onDestroy():系统在一个Service不再被使用,并且准备摧毁的时候调用该方法,它是Service收到的最后一个被调用的方法。在这里可以进行一些清除工作,例如线程、注册的监听、以及接收器等等。
 
    一个被startService()方法启动的Service,它将会一直运行,直到自己调用了stopSelf(),或者其他组件调用了stopService()。
    一个被bindService()犯法启动的Service,它的生命周期和绑定在它上面的组件一样。一旦所有绑定其的client都解绑定了,系统就会摧毁这个Service。
 
    android系统只有在内存不足时,并且必须为拥有焦点的activity回收资源时,强制停止一个Service。如果一个service绑定到了一个拥有焦点的activity上,那么它被杀死的几率比普通的更低。而如果一个Service被声明为在前台运行,那它几乎不可能被杀死。然而如果,一个仅仅只是长期运行的long-running Service,系统将它的位置设置地比后台任务低好几倍,并且这种Service很容易被杀死,你必须优雅地设计这种Service,以便处理其被系统重新启动的情况。
 
    要使用一个service, 首先需要类似activity那样在manifest中声明service。如:
    
<manifest...>        ...        <application>            <service android:name=".ExampleService" />            ...        </application></manifest>
    如果不希望被其他应用使用,则只须不声明 intent filter.如何这么做,那只能显示地调用Service类名。此外,可以设置android:exported,为false,来设置Service为你的应用所私有的。

创建一个started service

    started service是一个由其它组件通过调用startService()方法启动的Service,并且这种方式将导致系统调用onStartCommand()方法(如果目标机是1.6或者1.6以前的话,则要以onStart()。2.0以后onStart()被废弃)。
    其它组件通过Intent指定Service,并且包含一些供Service使用的数据。Service通过onStartCommand()接收Intent。
    由于started Service的生命周期独立于启动它的组件,所以在其任务完成时,需要调用stopself()或者其它组件调用stopService()。
    需要注意的是,Service是运行在声明它的应用程序的进程中,并且默认运行在主线程中。所以如果Service执行一些密集的、阻塞型的操作,它将会是activity和用户的交互变慢,为了避免影响应用程序的性能,应该在Service中启动一个新的线程。
 
    有两个类可以用来扩展、继承以创建一个新的Service:
  • Service:这是所有Service的基类。当使用这个类时,在Service中创建一个线程来实现Service的所有工作,是非常重要的(因为之前已经提到,默认情况下,Service运行在程序的主线程中)。
  • IntentService:这是Service的一个子类,它使用一个工作线程来处理所有的启动请求,每次执行一个请求。如果你不需要一个Service同时处理多个请求,这是一个最好的选择。使用这这个类时,所有需要做的,仅仅只是实现onHandleIntent(),来处理请求。

继承、扩展IntentService类

    IntentService做了以下工作:
  • 创建一个默认的工作线程,来处理从应用程序主线程投递到onStartCommand()的Intent。
  • 创建一个队列,它每次向onHandleIntent()传递一个Intent,这样就不需要关心多线程的同步问题。
  • 在所有启动请求都被处理之后,自动停止Service,这样开发人员就不需要调用stopSelf()。
  • 提供了默认的onBind()实现,它返回null。
  • 提供了默认的onStartCommand()实现,它将intent发送到工作队列中,然后工作队列再讲intent发送到onHandleIntent()。
    以上所有都表明,开发人员只需要实现onHandleIntent()方法,例如:
publicclassHelloIntentServiceextendsIntentService{  /**    * A constructor is required, and must call the super IntentService(String)   * constructor with a name for the worker thread.   */  publicHelloIntentService(){      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  protectedvoid 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){              }          }      }  }}
    例中所有需要开发者做的就是,实现Service的构造函数和onHandleIntent()。
    如果你决定要覆盖其他的回调函数,那么要保证调用超类的中的实现。例如onStartCommand()必须返回默认的实现:
@Overridepublicint onStartCommand(Intent intent,int flags,int startId){    Toast.makeText(this,"service starting",Toast.LENGTH_SHORT).show();    returnsuper.onStartCommand(intent,flags,startId);}

继承、扩展Service类

    当需要Service实现多线程并发的请求时,应该从Service类扩展,来处理每一个Intent。例如:
publicclassHelloServiceextendsService{  privateLooper mServiceLooper;  privateServiceHandler mServiceHandler;  // Handler that receives messages from the thread  privatefinalclassServiceHandlerextendsHandler{      publicServiceHandler(Looper looper){          super(looper);      }      @Override      publicvoid 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  publicvoid 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 =newHandlerThread("ServiceStartArguments",            Process.THREAD_PRIORITY_BACKGROUND);    thread.start();        // Get the HandlerThread's Looper and use it for our Handler     mServiceLooper = thread.getLooper();    mServiceHandler =newServiceHandler(mServiceLooper);  }  @Override  publicint 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  publicIBinder onBind(Intent intent){      // We don't provide binding, so return null      return null;  }    @Override  publicvoid onDestroy(){    Toast.makeText(this,"service done",Toast.LENGTH_SHORT).show();   }}
    这个例子中,为每一个启动请求,都启动一个工作线程来完成这项共工作,每次只处理一个请求。由于开发者实现了onStartCommand(),所以可以并发的执行多个请求。如果有需求,可以为每个请求启动一个线程,然后使它们正确地运行。
 
    onStartCommand()必须返回一个整数,这个整数,告诉系统,如何继续这个Service,当系统杀死这个Service的时候。onStartCommand()的返回值,必须是以下几个:
  • START_NOT_STICKY,如果系统在onStartCommand()之后杀死了Service,除非有待投递的Intent,否则不要在重新创建Service。这是一个安全的选项,使得 能够避免在不需要的时候运行Service,并且能够简单地重启那些未完成的工作。
  • START_STICKY,重启Service,并且重新调用onStartCommand(),但是不要再次投送最后一个Intent。取而代之的是,系统调用onStartCommand(),并且,除非Service中还有其它待投递的Intent,否则向它传递null Intent。这种情形适合Media players——未在执行命令的,并且无限期的运行、等待工作的媒体播放器。
  • START_REDELIVER_INTENT,重新创建Service,并且传递最近的一个Intent。其它待投递的Intent有序的跟着被投递。这种情形适合那些积极的执行那种必须马上恢复工作的Service,例如下载文件。

启动一个Service

    activity或者应用程序的其他组件,可以通过向startSerive()传递一个Intent来启动一个Service,系统调用Service的回调函数onStartCommand(),并且向其传递这个Intent。例如:
Intent intent =newIntent(this,HelloService.class);startService(intent);
    如果该Intent还未运行,那么系统会先调用onCreate(),然后调用onStartCommand()。
    如果Service不提供绑定。通过startService()投递Intent是应用组件和Service唯一的通信方式。然而,如果你希望Service发回结果,那么启动该Service的Client可以为广播(getBroadcast())创建一个待定的Intent(PendingIntent),并且随Intent一起通过startService()投递,然后Service可以使用这个广播来返回结果。
    多个请求要启动Service,导致了系统对应地调用onStartCommand(),然而,想要停止一个Service,只需要一个请求(stopSelf()或者stopService())。

停止一个Service

    一个Started的Service,必须自己管理生命周期,因为,除非系统为了回收内存,否则不会停止或者摧毁这样的Service,并且即便因为回收内存而摧毁了这样的Service,也会在onStartCommand()返回后继续运行。所以必须调用stopSelf()或者被其他组件调用stopService(),来终止一个Service。
    一旦调用了stopSelf()或者stopService(),系统将在尽可能快的时间里终止Service。
    然而,如果你的Service正在处理多个请求,那么就不能终止请求,因为有可能接收到了多个启动请求(在第一个请求的结尾结束,可能导致终止第二个请求)。为了避免这种情况,可以使用stopSelf(int),来保证停止Service的请求是基于最近的请求。这是因为,当调用stopSelf(int)时,你传递了对应的要停止的请求的启动请求的ID(statedID被投递到onStartCommand()),然后如果在你调用stopSelf(int)之前收到了一个新的请求,那么这两个ID将不会匹配,此时Service就不会被停止。
 

创建一个Bound Service

    一个Bound Service允许应用程序的其它组件调用bindService(),以创建一个长期的存在的连接(并且一般不允许组件通过调用startService()来启动它)。
    当你需要同过IPC让应用程序的组件(activity和其它组件)和Service进行交互的时候,或者想要将应用中的一些功能暴露给其它应用程序的时候,应该创建一个bound service。为了创建Bound Service,必须实现onBind()回调方法,它返回一个IBinder——它定义了和Service交互的接口。其它应用的组件可以调用bindService()来接收这个接口,并且开始调用在Service上的方法。这种Service只在应用程序的组件绑定它的时候才存活。所以当没有组件和Service绑定的时候,系统将摧毁这个Service。
    为了创建一个Bound Service,必须首先定义指定Client和Service如何交互、通信的接口。Client和Service直接的接口必须是一个IBinder,也就是Service中onBind()回调必须要返回的IBinder。Client接收到IBinder之后,就可以和Service交互了。
    有多个Client可以绑定到一个Service上,Client调用unbindService()来解绑定,如之前提到过的,一点一个Service没有Client绑定到它上面时,系统将会摧毁它。
    
    我们知道,在创建一个Bound Service时,必须一个IBinder接口以供Client和Service交互、通信。有三种方式可以用来定义这样的一个接口:
  • 扩展Binder类(Extending the Binder class):如果Service是你的程序所私有的,并且和Client允许在同一个进程中,你应该通过扩展Binder类来创建接口,并且从onBinde()返回它的实例。Client接收到以后,通过它直接访问Binder中、或者Service中的Public方法。当服务是你的程序私有的时候,这是首选的一项技术。不能以这个方式创建接口的唯一理由是,Service要被其他程序所用,或者需要跨进程使用。
  • 使用一个Messenger(Using a Messenger):如果需要接口能够在跨进程间使用,可以以一个Messenger创建接口,这种方式,Service定义一个Handler来响应各种不同的Message对象。这个Handler是Messager和Client共享一个IBinder的基础,它允许Client使用Message对象向Service发送命令。并且Client也可以定义一个Messenger,这样Service可以向Client发送Messages。这是一种简单的IPC,因为Messenger队列要求是个单线程的,这样就不许要为线程安全而设计Service。
  • 使用AIDL(Using AID):AIDL(ANDROID INTERFACE DEFINITION LANGUAGE)执行所有工作——将对象分解成系统能理解的原语,并且使它们能够跨进程执行。使用Messenger的方式,实际是就是基于AIDL的。和Messenger方式不同的是,Messenger方式,在一个单独的线程中创建所有请求的队列,所以这样的Service每次只能接收一个请求。而如果需要Service并发地处理请求,那就可以直接使用AIDL来实现,此时,Service必须具备多线程能力,并且要线程安全的。
    为了能够直接使用AIDL,必须创建一个.adil文件,它定义了程序的接口。android sdk tool用这个文件来生成抽象类——实现interface和处理IPC,然后在Service中继承、扩展它。
 

继承、扩展Binder类

    如果Service只在本地程序工作,并且不考虑跨进程,那么就可以通过这种继承、扩展Binder类来实现,它使Client直接访问Service中Public的方法。
    这种方式须遵循以下步骤:
  1. 在Service中创建一个Binder的实例:
    • 包含Client可以调用的Public方法。
    • 返回当前Service的实例——也包含Client可以调用的Public方法。
    • 返回Service持有的其他类的的实例——也包含Client可以调用的Public方法。
  2. 在onBind()中返回Binder实例。
  3. 在Client侧,从onServiceConnected()回调方法中接收这个Binder,并且使用Binder包含的Service提供的方法。
publicclassLocalServiceextendsService{    // Binder given to clients    privatefinalIBinder mBinder =newLocalBinder();    // Random number generator    privatefinalRandom mGenerator =newRandom();    /**     * 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.     */    publicclassLocalBinderextendsBinder{        LocalService getService(){            // Return this instance of LocalService so clients can call public methods            returnLocalService.this;        }    }    @Override    publicIBinder onBind(Intent intent){        return mBinder;    }    /** method for clients */    publicint getRandomNumber(){      return mGenerator.nextInt(100);    }}publicclassBindingActivityextendsActivity{    LocalService mService;    boolean mBound =false;    @Override    protectedvoid onCreate(Bundle savedInstanceState){        super.onCreate(savedInstanceState);        setContentView(R.layout.main);    }    @Override    protectedvoid onStart(){        super.onStart();        // Bind to LocalService        Intent intent =newIntent(this,LocalService.class);        bindService(intent, mConnection,Context.BIND_AUTO_CREATE);    }    @Override    protectedvoid 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) */    publicvoid 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() */    privateServiceConnection mConnection =newServiceConnection(){        @Override        publicvoid 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        publicvoid onServiceDisconnected(ComponentName arg0){            mBound =false;        }    };}

使用一个Messenger

    如果需要Service能够和远端进程通信,可以是哟一个Messenger提供Service的接口,这项技术允许执行IPC,而不需要用AIDL。
  • Service实现一个Handler——用来接收来自Client的回调。
  • 这个Handler用来创建一个Messenger对象——一个Hnadler的引用。
  • Messenger创建一个IBinder——由onBind()返回。
  • Client使用IBinder来实例化Messenger(—一个Hnadler的引用),Client通过这个Messenger向Service发送Message对象。
  • Service在它的Handler中接收每一个Message。
    这种方式,Client以向Service投递消息替代调用Service的Public方法。
publicclassMessengerServiceextendsService{    /** Command to the service to display a message */    staticfinalint MSG_SAY_HELLO =1;    /**     * Handler of incoming messages from clients.     */    classIncomingHandlerextendsHandler{        @Override        publicvoid 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.     */    finalMessenger mMessenger =newMessenger(newIncomingHandler());    /**     * When binding to the service, we return an interface to our messenger     * for sending messages to the service.     */    @Override    publicIBinder onBind(Intent intent){        Toast.makeText(getApplicationContext(),"binding",Toast.LENGTH_SHORT).show();        return mMessenger.getBinder();    }} publicclassActivityMessengerextendsActivity{    /** 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.     */    privateServiceConnection mConnection =newServiceConnection(){        publicvoid 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 =newMessenger(service);            mBound =true;        }        publicvoid 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;        }    };    publicvoid 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    protectedvoid onCreate(Bundle savedInstanceState){        super.onCreate(savedInstanceState);        setContentView(R.layout.main);    }    @Override    protectedvoid onStart(){        super.onStart();        // Bind to the service        bindService(newIntent(this,MessengerService.class), mConnection,            Context.BIND_AUTO_CREATE);    }    @Override    protectedvoid onStop(){        super.onStop();        // Unbind from the service        if(mBound){            unbindService(mConnection);            mBound =false;        }    }}

绑定到一个Service

    应用程序的通过bindService()绑定到一个Service。Android系统调用Service的onBind(),它返回IBinder,以便Client和Service交互。
    注意:只有activities、services和content providers可以绑定到一个Service,不能从broadcast receiver绑定一个service。
 
    从Client绑定一个Service:
  1.     实现ServiceConnection:必须覆盖两个回调方法:
    • onServiceConnected()——系统调用这个方法来投递IBinder(从service的onBinder()方法返回)。
    • onServiceDisconnected()——当Client和Service之间的连接不是期望的丢失,例如Service崩溃,或者被杀死时,android系统调用这个方法。Client解绑定时,这个函数不会被调用。
  2. 调用bindService()。
  3. 在系统调用onServieConnected()时,就可以开始向通过调用定义的接口,呼叫Services。
  4. 调用unbindService()来断开Service。当Client被摧毁时,它会和Service解绑定。但是在和服务完成交互时、或者你的activity pause时,你必须解绑定,这样Service在不被使用才能被关闭。
    例子:
LocalService mService;privateServiceConnection mConnection =newServiceConnection(){    // Called when the connection with the service is established    publicvoid 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    publicvoid onServiceDisconnected(ComponentName className){        Log.e(TAG,"onServiceDisconnected");        mBound =false;    }}; Intent intent =newIntent(this,LocalService.class);bindService(intent, mConnection,Context.BIND_AUTO_CREATE);

绑定一个Service时所需要注意的:

  • 必须处理DeadObjectException异常。
  • Object是夸进程的引用计数
  • 在Client生命周期中——启动、停止,成对的使用绑定和解绑定。
    • 如果只是在Activity可见时才和Service交互,那么应该在onStart()时绑定,onStop()时解绑定。
    • 如果想要Activity即使在后台运行,stop状态,也要和Service交互,那么就应该在onCreate()时绑定,onDestroy()时解绑定。需要注意的是。这种情形,在Activity的整个生命周期中都要使用Service,此时如果Service是运行在其他进程中,那么你就加重了该进程,并且它也变得更容易被系统杀死。
    • 一般不要在onResume()和onPause()中进行绑定和解绑定。
 

Bound Service的生命周期

发送通知(Notification)给用户

    Service可以通过Toast Notification或者Status Bar Notification通知用户。
  • Toast Notification:是一种现实在当前窗口,并且过一段时间后就消失的消息。
  • Status Bar Notification:是一种在状态栏提供icon的消息,用户可以选择它,以启动一种动作(例如:启动一个activity)。
    详见《开发指南》用户接口中的通知章节。

运行一个前台Service

    一个前台运行的Service,是一个用户知道的,当系统内存不足时,并不会选择杀死这样的Service来回收内存。一个前台Service必须提供一个status bar的通知,它被放在Ongoing头下——表示不能被dismissed,除非这个服务停止了或者被从前台服务移除了。
    例如,一个音乐播放器,从一个Service播放音乐,需要被设置成前台运行,因为用户明显地知道它的操作。status bar中可能代表着当前的歌曲,并且允许用户启动一个activity来和播放器交互。
    调用startForegound()来使你的Service运行在前台。这个方法有两个参数,一个整数代表通知的唯一的ID,一个是status bar的通知:
Notification notification =newNotification(R.drawable.icon, getText(R.string.ticker_text),        System.currentTimeMillis());Intent notificationIntent =newIntent(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);
    将一个Service从前台运行中移除,只需要调用stopForeground()。这个方法,有个boolean参数,表示是否也从状态栏移除通知。这个方法,并不停止service。然而,如果你停止了一个正在前台运行的service,那么它通知也将被移除。
 
    android 2.0 之后才能使用上述两个接口,如果在更早的版本,那需要使用setFroeground()。
 

管理一个服务的生命周期

    Service的生命周期有两种方式:
  • started service:当其他组件调用startService(),开始,当调用stopSelf(),或者stopService()结束,当服务停止时,系统将摧毁它。
  • bound service:当其他组件调用bindService(),开始,client和service通过IBinder接口通信,当client调用unbindService()。
    这两种模式,并不是完全独立的,因为一个已经started 的Service可以被bind。当这种情形出现时,一个stopSelf()、stopService()并不能时Service停止,只有Client也调用了unbind()之后,Service才被停止。
publicclassExampleServiceextendsService{    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    publicvoidonCreate(){        // The service is being created    }    @Override    publicintonStartCommand(Intent intent,int flags,int startId){        // The service is starting, due to a call to startService()        returnmStartMode;    }    @Override    publicIBinderonBind(Intent intent){        // A client is binding to the service with bindService()        returnmBinder;    }    @Override    publicbooleanonUnbind(Intent intent){        // All clients have unbound with unbindService()        returnmAllowRebind;    }    @Override    publicvoidonRebind(Intent intent){        // A client is binding to the service with bindService(),        // after onUnbind() has already been called    }    @Override    publicvoidonDestroy(){        // The service is no longer used and is being destroyed    }}