- 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 基础
- 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收到的最后一个被调用的方法。在这里可以进行一些清除工作,例如线程、注册的监听、以及接收器等等。
<manifest...> ... <application> <service android:name=".ExampleService" /> ... </application> </manifest>
创建一个started service
- Service:这是所有Service的基类。当使用这个类时,在Service中创建一个线程来实现Service的所有工作,是非常重要的(因为之前已经提到,默认情况下,Service运行在程序的主线程中)。
- IntentService:这是Service的一个子类,它使用一个工作线程来处理所有的启动请求,每次执行一个请求。如果你不需要一个Service同时处理多个请求,这是一个最好的选择。使用这这个类时,所有需要做的,仅仅只是实现onHandleIntent(),来处理请求。
继承、扩展IntentService类
- 创建一个默认的工作线程,来处理从应用程序主线程投递到onStartCommand()的Intent。
- 创建一个队列,它每次向onHandleIntent()传递一个Intent,这样就不需要关心多线程的同步问题。
- 在所有启动请求都被处理之后,自动停止Service,这样开发人员就不需要调用stopSelf()。
- 提供了默认的onBind()实现,它返回null。
- 提供了默认的onStartCommand()实现,它将intent发送到工作队列中,然后工作队列再讲intent发送到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){
}
}
}
}
}
@Override publicint onStartCommand(Intent intent,int flags,int startId){ Toast.makeText(this,"service starting",Toast.LENGTH_SHORT).show(); returnsuper.onStartCommand(intent,flags,startId); }
继承、扩展Service类
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();
}
}
- 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
Intent intent =newIntent(this,HelloService.class); startService(intent);如果该Intent还未运行,那么系统会先调用onCreate(),然后调用onStartCommand()。
停止一个Service
创建一个Bound Service
我们知道,在创建一个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必须具备多线程能力,并且要线程安全的。
继承、扩展Binder类
- 在Service中创建一个Binder的实例:
- 包含Client可以调用的Public方法。
- 返回当前Service的实例——也包含Client可以调用的Public方法。
- 返回Service持有的其他类的的实例——也包含Client可以调用的Public方法。
- 在onBind()中返回Binder实例。
- 在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实现一个Handler——用来接收来自Client的回调。
- 这个Handler用来创建一个Messenger对象——一个Hnadler的引用。
- Messenger创建一个IBinder——由onBind()返回。
- Client使用IBinder来实例化Messenger(—一个Hnadler的引用),Client通过这个Messenger向Service发送Message对象。
- Service在它的Handler中接收每一个Message。
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
- 实现ServiceConnection:必须覆盖两个回调方法:
- onServiceConnected()——系统调用这个方法来投递IBinder(从service的onBinder()方法返回)。
- onServiceDisconnected()——当Client和Service之间的连接不是期望的丢失,例如Service崩溃,或者被杀死时,android系统调用这个方法。Client解绑定时,这个函数不会被调用。
- 调用bindService()。
- 在系统调用onServieConnected()时,就可以开始向通过调用定义的接口,呼叫Services。
- 调用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)给用户
- Toast Notification:是一种现实在当前窗口,并且过一段时间后就消失的消息。
- Status Bar Notification:是一种在状态栏提供icon的消息,用户可以选择它,以启动一种动作(例如:启动一个activity)。
运行一个前台Service
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);
管理一个服务的生命周期
- started service:当其他组件调用startService(),开始,当调用stopSelf(),或者stopService()结束,当服务停止时,系统将摧毁它。
- bound service:当其他组件调用bindService(),开始,client和service通过IBinder接口通信,当client调用unbindService()。
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
}
}

803



被折叠的 条评论
为什么被折叠?



