service基础
来源:互联网 发布:百度统计数据导出 php 编辑:程序博客网 时间:2024/06/13 04:55
作为android四大组件之一,Services主要用作后台的、耗时操作。它没有UI。应用程序的其他组件可以启动Service,此时Service 即会在后台持续运行,即使用户切换到了其他应用程序,service也依旧运行。此外,组件可以绑定一个Service,一般和它进行交换,甚至实现进程间通信(IPC)。一般:网络传输、播放音乐、执行文件I/O,或者和内容提供者(content provider)交互,都可以放到Service中到后台来执行。
我们知道,在创建一个Bound Service时,必须一个IBinder接口以供Client和Service交互、通信。有三种方式可以用来定义这样的一个接口: 将一个Service从前台运行中移除,只需要调用stopForeground()。这个方法,有个boolean参数,表示是否也从状态栏移除通知。这个方法,并不停止service。然而,如果你停止了一个正在前台运行的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的方法。
这种方式须遵循以下步骤:
- 在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能够和远端进程通信,可以是哟一个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:
- 实现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)给用户
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);
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 }}
- Service基础
- service基础
- Service基础
- Service基础
- service基础
- Service基础
- Service基础
- Service基础
- Service基础
- service基础
- Service基础
- web service 基础
- XML Web Service 基础
- XML Web Service 基础
- XML Web Service 基础
- XML Web Service 基础
- XML Web Service 基础
- XML Web Service 基础
- Java程序员应该知道的10个Eclipse调试技巧
- 使用RegularExpressionValidator验证
- 一边掉眼泪,一边用文字诉说_伤感日志
- 织梦 去掉html代码的截取字符方法
- 数据结构——孤独的运货员
- service基础
- mybatis配置文件解释标签坑爹
- Htmlayout之table模仿CGridCtrl开源控件,实现完美编辑
- 苹果iOS开发者账号过期临时解决办法
- 棉子丶mm的伤感独特空间日志发布:我笑了,在那个萧瑟的秋季
- <c:when> <c:otherwise> <c:choose> 嵌套 遍历 jstl
- $.ajax的一些总结
- 进程和线程的区别和联系
- 央视炮轰信用卡全额罚息:透支11万5年后还44万
原创粉丝点击
热门IT博客
热门问题
老师的惩罚
人脸识别
我在镇武司摸鱼那些年
重生之率土为王
我在大康的咸鱼生活
盘龙之生命进化
天生仙种
凡人之先天五行
春回大明朝
姑娘不必设防,我是瞎子
锦城教务网
锦城在线
锦城学院
御锦城
锦城花时
锦城公园
万锦城
御锦城11期
锦城四少
西安御锦城
经开万锦城
华置西锦城
御锦城近况
天下锦城
泰华锦城
川大锦城
未来锦城
正荣润锦城
十里锦城
东华锦城
俪锦城二期
新锦城
上东锦城a区
盛恒御锦城
锦城邻里
汇锦城房价
御锦城房价
汇锦城二期
中南御锦城
御锦城四期
御锦城别墅
御锦城五期
御锦城地址
锦城小区
四川大学锦城学院
四川大学锦城
四川大学锦城学院教务网
四川大学锦城学院学工网
锦城丝管日纷纷
成都锦城公园
四川锦城学院