Services:可在后台长时间运行,无UI界面。html
Started:android
Services经过其余组件调用startService启动,能在后台一直运行,即便启动它的组件已经销毁。通常这种服务执行特定的操做并且没有返回值,好比经过网络下载或上传一个文件,一旦操做结束,服务须要中止本身。安全
Bound:网络
Service经过其余组件调用bindService绑定,提供一个CS架构的接口容许其余组件与Service交互、发消息、获取返回值、甚至跨进程通讯。bound service与绑定它的组件共存亡,多个组件能够绑定一个服务,当这个服务全部绑定它的组件都解绑后,服务会被销毁。多线程
Caution:Service在宿主进程的主线程运行,也就是说Service不会建立本身的线程,也不会运行在另外一个进程(除非你指定)。这就意味着,若是Service执行一些高CPU负载或阻塞界面操做的任务时,你须要建立新的线程来运行它,以下降ANR的风险。架构
(使用service仍是thread?若是你只是须要在与用户交互时,在主线程以外执行额外的任务,那么你须要建立一个新线程而不是Service。好比在activity在前台显示的时候播放音乐,你须要在onCreate里面建立线程,在onStart执行线程,在onStop里中止线程,固然也可使用AsyncTask或者HandleThread来替代线程类。)app
建立Service的子类,覆写Service生命周期中的关键回调函数,若是有必要,提供绑定Service的机制。最重要的回调函数以下:ide
onStartCommand函数
系统在其余组件调用startService启动Service时执行,以后,Service一直在后台执行。若是你实现了这个方法,那么你有责任在Service完成其工做时经过stopSelf或stopService来中止Service。(若是只是提供绑定Service,能够不用实现这个方法)oop
onBind
系统在其余组件调用bindService绑定Service时执行,在这个方法的实现中,你须要返回一个IBider接口用于clients与service交互。若是你不须要绑定,能够直接返回null
onCreate
Service第一次建立时执行,在onStartCommand和onBind以前,用于执行一次性须要初始化好的数据。
onDestroy
service销毁时执行,用于清理资源,相似线程、注册监听器,receiver等。
系统会在低内存时强制中止service。若是service绑定在一个有用户焦点的activity,那么它不多会被销毁;若是服务定义为在前台运行的,那么它永远不会被销毁。
<manifest ... > ... <application ... > <service android:name=".ExampleService" /> ... </application> </manifest>
android:name是惟一必填的属性,其余能够选填。一旦你的应用发布出去了,那么android:name永远不要再变。
为了安全性,请使用显式Intent启动或绑定服务,而不是定义filiters。若是确实容许多个服务来响应,那么请务必在Intent中经过setPackage来指定报名,以下降目标服务匹配出意外值得几率。
设置android:exported为false,能够避免其余应用启动这个服务。
Service
全部服务的基类,若是你扩展这个类,那么你可能须要建立一个新的线程,由于这个服务室在app的主线程中执行,有可能会下降activity的流畅度
IntentService
Service 的子类,经过工做线程来处理全部请求,每次处理一个。若是你的service不须要同时处理多个请求,IntentService是最佳的选择。
由于大部分服务不须要同时处理多个请求(其实是个多线程场景),IntentService是最好的推荐
IntentService工做流程以下:
实际上,你须要作的就是实现onHandleIntent,以下例子:
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) { } } } } }
若是你须要覆写其余回调,好比onCreate、onStartCommand、onDestroy,请确保要调用父类的实现,这样IntentService才能处理工做线程的生命周期。onHandleIntent和onBind是例外。
若是服务须要支持多线程(而不是经过工做队列来一一处理),那么你要扩展Service来处理每个intent。
做为对比,以下代码和上面代码功能同样。
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(); } }
这个只是模拟IntentService处理,有必要的话,你能够为每个请求建立一个线程。
onStartCommand必须返回一个整型,这个值用来描述系统如何处理这个服务,当它被异常销毁时。
若是服务执行完onStartCommand后被异常销毁,不须要从新建立服务,除非还有未处理的intents。避免服务被没必要要地启动,你的应用可以很容易地从新启动未完成的工做,选择这个。
若是服务执行完onStartCommand后被异常销毁,从新建立服务并执行onStartCommand,可是不会使用发给这个服务的最后一个intent,而是经过一个null intent来执行onStartCommand,除非还有未处理的intents。这种状况比较适合不执行命令,一直在后台运行或者等待任务的媒体播放。
若是服务执行完onStartCommand后被异常销毁,从新建立服务,用发给这个服务的最后一个intent调用onStartCommand,其余未处理的intents依次分发。这种状况适合执行的任务须要理解恢复的场景,好比下载文件。
startService –> onStartCommand
Intent intent = new Intent(this, HelloService.class); startService(intent);
startService方法当即返回。
若是service不能绑定,只能经过startService启动,并且须要发送返回值时,能够经过建立带延迟广播的PendingIntent(用getBroadcast)来启动服务,服务能用里面的广播来分发结果。
若是服务同步地处理多个请求,那么不能在处理完一个请求直接销毁,有可能其余的请求刚发过来或者还在处理中。为了不这种状况,你能够经过stopSelf(int)来确保关闭的服务就是刚处理完请求的,而不是其余正在处理的服务,整型参数惟一标识服务实例。
详见下一章节
服务一旦运行,能够经过Toast Notifications和Status Bar Notifications提醒用户。
在前台运行的服务必须提供一个状态栏的notification,来呈现运行状态,除非服务被中止或者移除,不然notification不会消失。
好比:播放音乐,在状态栏有个notification来告诉用户当前播放的歌曲,提供用户进入音乐播放器的入口
服务须要在前台运行,须要调用startForground,第一个参数是notification的惟一标示(不能为0),第一参数就是notification,好比:
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_ID, notification);
中止在前台运行,能够调用stopForeground。
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:不须要执行父类的实现。
完整的生命周期:onCreate —> onDestroy
活动的生命周期:onStartCommand/onBind —> onDestroy/onUnbind