Android提供Service組件用來處理耗時的操做,不須要用戶界面。 java
Service組件的優先級比不活躍的Activity高,這樣被系統殺死的機率就下降了。固然,實際上即使運行中的Service被殺,可是當系統資源又足夠的時候,Service又會被重啓。 android
當必要的時候Service的優先級可能被提到與前臺Activity相同的優先級(經過組件的標籤)。這是極端的例子,當結束掉Service會直接影響用戶體驗的時候,好比音樂的播放被打斷。 網絡
儘管Service跑起來不須要UI,可是它仍然在UI線程中執行。因此有些耗時的操做你須要放在其餘的工做線程中,好比Thread和AsynTask類等。 ide
Service主要作來:網絡查詢,處理數據,更新Content Provider,firing Intents,和觸發Notification,主要作來處理耗時的操做。 ui
若建立的Service只由本身的APP操縱,那麼須要增長權限: this
<service android:enabled=」true」 android:name=」.MyService」 android:permission=」com.paad.MY_SERVICE_PERMISSION」/>
onStartCommand可能會被屢次調用,當使用startService的時候觸發。經過stopService或者stopSelf中止服務。 線程
@Override public int onStartCommand(Intent intent, int flags, int startId) { startBackgroundTask(intent, startId); return Service.START_STICKY; }
onStartCommand返回的參數是用來決定:當系統在Service運行時殺死了Service,資源足夠的時候又重啓這個Service,系統該如何迴應。 code
下面介紹這個返回值: xml
1.START_STICKY 表明標準的行爲。若是返回的是這個值,當Service任什麼時候候的重啓,onStartCommand都會被調用。當是注意的一點:傳來的intent參數會丟失,也就是null。 進程
2.START_NOT_STICKY 當運行時被殺死的時候,若是以前還有start請求未處理(注意是未處理,而不是處理中),Service纔會被重啓,不然服務自動中止。
3.START_REDELIVER_INTENT 若是Service在運行中被殺死,若是還有請求未被處理,或者在處理中。在後者狀況,onStartCommand會被調用,傳入以前傳入的初始狀態的Intent,由於它認爲尚未徹底處理好。
注意:以上行爲只有在System kill event的狀況下有效,stopSelf和stopService都不會過問onStartCommand的返回狀態。
下面2個參數是用來判斷你的Service是怎麼啓動的:
1.START_FLAG_REDELIVERY 對應着START_REDELIVER_INTENT
2.START_FLAG_RETRY ------START_STICKY
顯式和隱式啓動:
private void explicitStart() { // Explicitly start My Service Intent intent = new Intent(this, MyService.class); // TODO Add extras if required. startService(intent); } private void implicitStart() { // Implicitly start a music Service Intent intent = new Intent(MyMusicService.PLAY_ALBUM); intent.putExtra(MyMusicService.ALBUM_NAME_EXTRA, 「United」); intent.putExtra(MyMusicService.ARTIST_NAME_EXTRA, 「Pheonix」); startService(intent); }
顯式和隱式中止:
// Stop a service explicitly. stopService(new Intent(this, MyService.class)); // Stop a service implicitly. Intent intent = new Intent(MyMusicService.PLAY_ALBUM); stopService(intent);
@Override public IBinder onBind(Intent intent) { return binder; } public class MyBinder extends Binder { MyMusicService getService() { return MyMusicService.this; } } private final IBinder binder = new MyBinder();
你還須要去實現一個ServiceConnection,重寫它的onServiceConnected和onServiceDisconneted方法去獲取一個Service實例的引用。
// Reference to the service private MyMusicService serviceRef; // Handles the connection between the service and activity private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { // Called when the connection is made. serviceRef = ((MyMusicService.MyBinder)service).getService(); } public void onServiceDisconnected(ComponentName className) { // Received when the service unexpectedly disconnects. serviceRef = null; } };
若是去執行綁定呢?
答:調用bindService。傳入一個intent(隱式或者顯式)和ServiceConnection的實例。你還能夠指定綁定標示符:
Intent bindIntent = new Intent(MyActivity.this, MyMusicService.class);
bindService(bindIntent, mConnection, Context.BIND_AUTO_CREATE);
Android 4.0(API 14) 引入了一些新的標示符:
1.BIND_ADJUST_WITH_ACTIVITY Service的優先級將相對於其綁定的Activity,Activity到前臺,則Service優先級相對提高,Activity到後臺,則Servcie優先級相對下降。
2.BIND_ABOVE_CLIENT和BIND_IMPORTANT 當你的客戶端在前臺,這個標示符下的Service也變得重要性至關於前臺的Activity,優先級迅速提高。如果BIND_ABOVE_CLIENT,則優先級已經超過了Activity,也就是說Activity要比Service先死,當資源不夠的時候。
3.BIND_NOT_FOREGROUND 你所綁定的Service優先級永遠高不過前臺Activity。
4.BIND_WAIVE_PRIORITY 綁定的服務不可調整自身的優先級。
在進程優先級中,正在運行的Service優先級是老二的位置,僅次與運行在前臺的Activity。
若是你的Service直接能夠與用戶交互的,那麼考慮將其放在前臺是必要的。經過startForeground.
startForeground一般必須指定一個不間斷的Notification。這個Notification存在的時間與你的跑在前臺的Service相同。
private void startPlayback(String album, String artist) { int NOTIFICATION_ID = 1; // Create an Intent that will open the main Activity // if the notification is clicked. Intent intent = new Intent(this, MyActivity.class); PendingIntent pi = PendingIntent.getActivity(this, 1, intent, 0); // Set the Notification UI parameters Notification notification = new Notification(R.drawable.icon, 「Starting Playback」, System.currentTimeMillis()); notification.setLatestEventInfo(this, album, artist, pi); // Set the Notification as ongoing notification.flags = notification.flags | Notification.FLAG_ONGOING_EVENT; // Move the Service to the Foreground startForeground(NOTIFICATION_ID, notification); }
結束前臺的Service經過stopForeground:
public void pausePlayback() { // Move to the background and remove the Notification stopForeground(true); }
Notification也會被取消。