## 一、官方文檔
**Class Overview**
*A Service is an application component representing either an application’s desire to perform a longer-running operation while not interacting with the user or to supply functionality for other applications to use. Each service class must have a corresponding declaration in its package’s AndroidManifest.xml. Services can be started with Context.startService() and Context.bindService().*
**服務是一種應用程序組件代表應用程序的意圖,而不是與用戶或其他應用程序使用電源的功能執行更長的運行操作。每個服務類必須有一個相應的服務聲明在其AndroidManifest.xml。啟動服務的方法有startservice(), bindservice()。后面會有具體事例測試這兩種方法的使用。**
*Note that services, like other application objects, run in the main thread of their hosting process. This means that, if your service is going to do any CPU intensive (such as MP3 playback) or blocking (such as networking) operations, it should spawn its own thread in which to do that work. More information on this can be found in Application Fundamentals: Processes and Threads. The IntentService class is available as a standard implementation of Service that has its own thread where it schedules its work to be done.*
**注意,服務是運行在他們的主進程的主線程。這意味著,如果你的服務是要做任何CPU消耗大的操作(如MP3播放)或阻塞(如網絡)的操作,它會以它自己的線程去做這項工作。關于這方面的更多信息可以在應用基礎:進程和線程。intentservice類可以作為一個標準的服務實現,可以調度自己的線程去工作。**
**What is a Service?**
*Most confusion about the Service class actually revolves around what it is not:*
- *A Service is not a separate process. The Service object itself does not imply it is running in its own process; unless otherwise specified, it runs in the same process as the application it is part of.*
- *A Service is not a thread. It is not a means itself to do work off of the main thread (to avoid Application Not Responding errors).*
**這里要說的是我們不僅要知道service是什么,還要知道它不是什么.**
- **服務不是一個單獨的進程。服務對象本身并不意味著它是在它自己的進程中運行;除非另有規定,它運行在同一進程中的應用就是它的一部分。**
-
**服務不是一個線程。這并不意味著主線程去完成相應工作(避免應用程序無響應的錯誤)**。
**Thus a Service itself is actually very simple, providing two main features:**
-
*A facility for the application to tell the system about something it wants to be doing in the background (even when the user is not directly interacting with the application). This corresponds to calls to Context.startService(), which ask the system to schedule work for the service, to be run until the service or someone else explicitly stop it.*
- *A facility for an application to expose some of its functionality to other applications. This corresponds to calls to Context.bindService(), which allows a long-standing connection to be made to the service in order to interact with it.*
- **用于告訴系統什么要在后臺運行(即用戶不直接與應用程序交互),調用Context.startService() 啟動服務,這要求系統來管理該服務,該服務會一直運行到知道明確停止它為止,即stopService()。**
-
**一個應用程序提供它的一些功能給其他的應用。可以調用Context.bindService()來綁定服務,它允許一個長期的連接是為了服務與它進行交互。(操作中會獲得service的binder對象,通過binder來調用相關的服務)**
*When a Service component is actually created, for either of these reasons, all that the system actually does is instantiate the component and call its onCreate() and any other appropriate callbacks on the main thread. It is up to the Service to implement these with the appropriate behavior, such as creating a secondary thread in which it does its work.*
*Note that because Service itself is so simple, you can make your interaction with it as simple or complicated as you want: from treating it as a local Java object that you make direct method calls on (as illustrated by Local Service Sample), to providing a full remoteable interface using AIDL.*
**當一個服務組件被創造時,系統都會調用它的oncreate()和主線程的任何其他適當的回調。它是由服務來實現這些與適當的行為,如創建一個輔助線程來完成它的工作。**
**值得注意的是,由于服務本身那么簡單,你可以用service與其他應用或其他組件實現一些或簡單或復雜的交互:比如要為本地Java對象你直接調用方法,也可以調用AIDL接口進行進程間操作。**
**Service Lifecycle 服務的生命周期**
*There are two reasons that a service can be run by the system. If someone calls Context.startService() then the system will retrieve the service (creating it and calling its onCreate() method if needed) and then call its onStartCommand(Intent, int, int) method with the arguments supplied by the client. The service will at this point continue running until Context.stopService() or stopSelf() is called. Note that multiple calls to Context.startService() do not nest (though they do result in multiple corresponding calls to onStartCommand()), so no matter how many times it is started a service will be stopped once Context.stopService() or stopSelf() is called; however, services can use their stopSelf(int) method to ensure the service is not stopped until started intents have been processed.*
**有兩個理由可以說明服務可以被系統運行。如果有人Context.startService()來啟動服務。然后系統會檢索服務(創造它,如果需要調用它的oncreate()方法)然后調用onStartCommand(Intent, int, int) 方法。然后該服務將一直運行,直到stopservice()或stopself()被調用。請注意,當服務啟動后,再調用Context.startService() 方法時,(onstartcommand()會被調用oncreate()方法不會再次被調用,也就是說服務只會被創建一次,然調用stopservice()或stopself()會停止服務;然而,服務可以用stopSelf(int)來保證服務直到成功打開意圖之后才停止。**
*For started services, there are two additional major modes of operation they can decide to run in, depending on the value they return from onStartCommand(): START_STICKY is used for services that are explicitly started and stopped as needed, while START_NOT_STICKY or START_REDELIVER_INTENT are used for services that should only remain running while processing any commands sent to them.*
**為啟動的服務,有兩個主要的操作模式,他們可以決定運行,取決于他們的回報onstartcommand()價值:start_sticky用于顯式啟動和停止所需要的服務,而start_not_sticky或start_redeliver_intent用于服務,應運行在處理任何命令發送給他們。**
*Clients can also use Context.bindService() to obtain a persistent connection to a service. This likewise creates the service if it is not already running (calling onCreate() while doing so), but does not call onStartCommand(). The client will receive the IBinder object that the service returns from its onBind(Intent) method, allowing the client to then make calls back to the service. The service will remain running as long as the connection is established (whether or not the client retains a reference on the service’s IBinder). Usually the IBinder returned is for a complex interface that has been written in aidl.*
**客戶端也可以使用Context.bindService() 獲得持久連接到服務。這同樣造成服務如果它沒有運行(雖然這樣叫oncreate()),但不調用onstartcommand()。客戶端將從onBind(Intent)方法得到IBinder對象,讓綁定者可以調用相關服務。該服務被創建后將和綁定者保持連接(不管客戶端是否仍保留服務的IBinder)。通常返回的是一個復雜的接口,這個已經在AIDL中實現。**
*A service can be both started and have connections bound to it. In such a case, the system will keep the service running as long as either it is started or there are one or more connections to it with the Context.BIND_AUTO_CREATE flag. Once neither of these situations hold, the service’s onDestroy() method is called and the service is effectively terminated. All cleanup (stopping threads, unregistering receivers) should be complete upon returning from onDestroy().*
**對于一個服務的綁定者,服務既可以被開啟,也可以被連接。在這種情況下,系統會保持服務的運行只要是開始或有一個或多個連接到它的context.bind_auto_create標識。一旦這些情況都存在,服務的ondestroy()方法被調用后,服務才會有效終止。這樣,所有的清理(停止線程,注銷接收器)等方法都可以卸載ondestroy()中。**
**Process Lifecycle 進程周期**
*The Android system will attempt to keep the process hosting a service around as long as the service has been started or has clients bound to it. When running low on memory and needing to kill existing processes, the priority of a process hosting the service will be the higher of the following possibilities:*
**Android系統會試圖讓進程托管服務當這個服務被開啟或被綁定時。在低內存的時候需要殺死現有的進程,一個托管了服務將的進程優先級更高:**
*If the service is currently executing code in its onCreate(), onStartCommand(), or onDestroy() methods, then the hosting process will be a foreground process to ensure this code can execute without being killed.*
**如果服務是目前正在執行oncreate()、onstartcommand()或ondestroy()方法,然后宿主進程將變成前臺進程以確保這些方法能被執行而不被殺死。**
*If the service has been started, then its hosting process is considered to be less important than any processes that are currently visible to the user on-screen, but more important than any process not visible. Because only a few processes are generally visible to the user, this means that the service should not be killed except in extreme low memory conditions.*
**如果此服務已被啟動,任何可見進程都比它的宿主進程更重要,但比那些不可見的進程都要重要。因為只有很少的進程是可見進程,這表明服務應該不會在極端低內存情況下被殺死。**
*If there are clients bound to the service, then the service’s hosting process is never less important than the most important client. That is, if one of its clients is visible to the user, then the service itself is considered to be visible.*
**如果有客戶端綁定到服務,那么服務的宿主進程比這些重要的客戶端還重要。也就是說,如果綁定它的一個客戶端是用戶可見的,那么服務本身是可見的。**
*A started service can use the startForeground(int, Notification) API to put the service in a foreground state, where the system considers it to be something the user is actively aware of and thus not a candidate for killing when low on memory. (It is still theoretically possible for the service to be killed under extreme memory pressure from the current foreground application, but in practice this should not be a concern.)*
**一個啟動的服務可以使用startForeground(int, Notification) API把服務設置為前臺狀態,系統認為是用戶的主動意識,所以在內存不足時,該服務并不是被殺候選人。(這仍然是理論上可能的,在內存極端不足時,即便是前臺service也有可能被殺。)**
*Note this means that most of the time your service is running, it may be killed by the system if it is under heavy memory pressure. If this happens, the system will later try to restart the service. An important consequence of this is that if you implement onStartCommand() to schedule work to be done asynchronously or in another thread, then you may want to use START_FLAG_REDELIVERY to have the system re-deliver an Intent for you so that it does not get lost if your service is killed while processing it.*
**注意,大部分時間你的服務一直在運行,在內存壓力非常大的時候它也會被殺死。如果發生這種情況,系統將嘗試重新啟動服務。這是一個重要的結果,如果你實現onstartcommand()安排工作要在另一個線程異步完成,那么你可能想使用start_flag_redelivery讓系統為你提供一個意圖使它不會丟失之前的服務。**
## 二、具體實例
### 1.最基本的用法
~~~
package com.servicedetail;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void StartService(View v) {
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);
}
public void StopService(View v) {
Intent startIntent = new Intent(this, MyService.class);
stopService(startIntent);
}
}
~~~
~~~
package com.servicedetail;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class MyService extends Service {
@Override
public void onCreate() {
super.onCreate();
Log.i("--","onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("--","onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
Log.i("--","onBind");
return null;
}
@Override
public void onDestroy() {
Log.i("--","onDestroy");
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
Log.i("--","onUnbind");
return super.onUnbind(intent);
}
@Override
public void onRebind(Intent intent) {
Log.i("--","onRebind");
super.onRebind(intent);
}
}
~~~
—–>最簡單的startService, stopService
第一次點擊startService,stopService:

在destroy之前點擊兩次startService,只會調用一次onCreate方法
這是由于onCreate()方法只會在Service第一次被創建的時候調用,如果當前Service已經被創建過了,不管怎樣調用startService()方法,onCreate()方法都不會再執行。因此你可以再多點擊幾次StartService按鈕試一次,每次都只會有onStartCommand()方法中的打印日志

### 2.Service和Activity通信
上面我們學習了Service的基本用法,啟動Service之后,就可以在onCreate()或onStartCommand()方法里去執行一些具體的邏輯了。不過這樣的話Service和Activity的關系并不大,只是Activity通知了Service一下:“你可以啟動了。”然后Service就去忙自己的事情了。那么有沒有什么辦法能讓它們倆的關聯更多一些呢?比如說在Activity中可以指定讓Service去執行什么任務。當然可以,只需要讓Activity和Service建立關聯就好了。
觀察MyService中的代碼,你會發現一直有一個onBind()方法我們都沒有使用到,這個方法其實就是用于和Activity建立關聯的,修改MyService中的代碼,如下所示:
~~~
package com.servicedetail;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
public class MainActivity extends Activity {
private MyService.MyBinder myBinder;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i("--", "MainActivity-->onServiceConnected");
myBinder = (MyService.MyBinder) service;
myBinder.conServer();
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i("--", "MainActivity-->onServiceDisconnected");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void StartService(View v) {
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);
}
public void StopService(View v) {
Intent startIntent = new Intent(this, MyService.class);
stopService(startIntent);
}
public void BindService(View v) {
Intent bindIntent = new Intent(this, MyService.class);
bindService(bindIntent, connection, BIND_AUTO_CREATE);
}
public void UnbindService(View v) {
if (connection != null)
unbindService(connection);
}
}
~~~
運行效果:
(1):點擊BindService

再點擊UnbindService

—>可以看到activity和service建立連接了,而且這種步驟會destroy掉service。
(2):點擊startService,在點擊BindService ,再點擊UnbindService,可以看到不會destroy掉service

如果再點擊stopService就會destroy service。
### 3.如何銷毀Service
在Service的基本用法這一部分,我們介紹了銷毀Service最簡單的一種情況,點擊Start Service按鈕啟動Service,再點擊Stop Service按鈕停止Service,這樣MyService就被銷毀了,可以看到打印日志如下所示:
~~~
Service-->onCreateService
Service-->onStartCommand
Service-->onDestroy
~~~
那么如果我們是點擊的Bind Service按鈕呢?由于在綁定Service的時候指定的標志位是BIND_AUTO_CREATE,說明點擊Bind Service按鈕的時候Service也會被創建,這時應該怎么銷毀Service呢?其實也很簡單,點擊一下Unbind Service按鈕,將Activity和Service的關聯解除就可以了。
先點擊一下Bind Service按鈕,再點擊一下Unbind Service按鈕,打印日志如下所示:
~~~
Service-->onCreate
Service-->onBind
Service-->onUnbind
Service-->onDestroy
~~~
以上這兩種銷毀的方式都很好理解。那么如果我們既點擊了Start Service按鈕,又點擊了Bind Service按鈕會怎么樣呢?這個時候你會發現,不管你是單獨點擊Stop Service按鈕還是Unbind Service按鈕,Service都不會被銷毀,必要將兩個按鈕都點擊一下,Service才會被銷毀。也就是說,點擊Stop Service按鈕只會讓Service停止,點擊Unbind Service按鈕只會讓Service和Activity解除關聯,一個Service必須要在既沒有和任何Activity關聯又處理停止狀態的時候才會被銷毀。
### 4.創建前臺Service
Service幾乎都是在后臺運行的,一直以來它都是默默地做著辛苦的工作。但是Service的系統優先級還是比較低的,當系統出現內存不足情況時,就有可能會回收掉正在后臺運行的Service。如果你希望Service可以一直保持運行狀態,而不會由于系統內存不足的原因導致被回收,就可以考慮使用前臺Service。前臺Service和普通Service最大的區別就在于,它會一直有一個正在運行的圖標在系統的狀態欄顯示,下拉狀態欄后可以看到更加詳細的信息,非常類似于通知的效果。當然有時候你也可能不僅僅是為了防止Service被回收才使用前臺Service,有些項目由于特殊的需求會要求必須使用前臺Service,比如QQ或微信等聊天的會在通知欄提示收到信息。
在onCreate()方法中或onBind()方法中添加如下代碼:
~~~
Notification notification = new Notification(R.drawable.ic_launcher, "有通知到來", System.currentTimeMillis());
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
notification.setLatestEventInfo(this, "通知標題", "通知內容", pendingIntent);
startForeground(1, notification);
~~~
在開啟服務要調用startService()后,在通知欄會保持一個通知(只要不調用stopService(),就會一直處在通知欄);,這是即使程序關閉,都不會消失。 如果調用bindService,程序關閉,服務就會關閉。

最后需要注意的是:
上面的官方文檔已經說了,service不是一個單獨的線程,也就是說service就在主線程中,所以如果要處理耗時操作的話,主線程肯定會卡。所以,在service中處理耗時操作也要新開一個線程。那為什么不直接在activity中開一個線程來處理呢?
**原因有:**
1.activity難以控制線程,一旦activity銷毀后,之前創建的進程就無法再次獲得。
2.在一個activity中創建的線程無法被另一個activity操作。
3.Service可以很好的管理線程,即使activity銷毀了,只要再次綁定service還可以通過service操作處理事務的線程。
[源碼](http://download.csdn.net/detail/u011102153/8710833)