Android-工做在後臺-Service

Android提供Service組件用來處理耗時的操做,不須要用戶界面java

Service組件的優先級比不活躍的Activity高,這樣被系統殺死的機率就下降了。固然,實際上即使運行中的Service被殺,可是當系統資源又足夠的時候,Service又會被重啓。 android

當必要的時候Service的優先級可能被提到與前臺Activity相同的優先級(經過組件的標籤)。這是極端的例子,當結束掉Service會直接影響用戶體驗的時候,好比音樂的播放被打斷。 網絡

儘管Service跑起來不須要UI,可是它仍然在UI線程中執行。因此有些耗時的操做你須要放在其餘的工做線程中,好比Thread和AsynTask類等。 ide

介紹Service

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

 

啓動和中止Service

顯式和隱式啓動:

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);

Service與Activity綁定

@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

在進程優先級中,正在運行的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也會被取消。

相關文章
相關標籤/搜索