在上面我們高高興興的啓動了Service了,但是細心的你可能發現了,貌似我們僅僅只是啓動了而已,Activity跟Service並沒有多少"交流",下面我們就讓Activity跟Service交流一下。
public class MyService extends Service {
public static final String TAG = "MyService";
private MyBinder mBinder = new MyBinder();
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate() executed");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand() executed");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy() executed");
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
class MyBinder extends Binder {
public void startDownload() {
Log.d("TAG", "startDownload() executed");
// 執行具體的下載任務
}
}
}
接下來我們在MainActivity中通過Button來綁定Service和解除綁定
public class MainActivity extends Activity implements OnClickListener {
private Button bindService;
private Button unbindService;
private MyService.MyBinder myBinder;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myBinder = (MyService.MyBinder) service;
myBinder.startDownload();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindService = (Button) findViewById(R.id.bind_service);
unbindService = (Button) findViewById(R.id.unbind_service);
bindService.setOnClickListener(this);
unbindService.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bind_service:
Intent bindIntent = new Intent(this, MyService.class);
bindService(bindIntent, connection, BIND_AUTO_CREATE);
break;
case R.id.unbind_service:
unbindService(connection);
break;
default:
break;
}
}
}
可以看到,這裏我們首先創建了一個ServiceConnection的匿名類,在裏面重寫了onServiceConnected()方法和onServiceDisconnected()方法,這兩個方法分別會在Activity與Service建立關聯和解除關聯的時候調用。在onServiceConnected()方法中,我們又通過 向下轉型 得到了MyBinder的實例,有了這個實例,Activity和Service之間的關係就變得非常緊密了。現在我們可以在Activity中根據具體的場景來調用MyBinder中的任何public方法,即實現了Activity指揮Service幹什麼Service就去幹什麼的功能。
當然,現在Activity和Service其實還沒關聯起來了呢,這個功能是在Bind Service按鈕的點擊事件裏完成的。可以看到,這裏我們仍然是構建出了一個Intent對象,然後調用bindService()方法將Activity和Service進行綁定。bindService()方法接收三個參數,第一個參數就是剛剛構建出的Intent對象,第二個參數是前面創建出的ServiceConnection的實例,第三個參數是一個標誌位,這裏傳入BIND_AUTO_CREATE表示在Activity和Service建立關聯後自動創建Service,這會使得MyService中的onCreate()方法得到執行,但onStartCommand()方法不會執行(只有當我們通過 startService()方法請求啓動服務時,調用此方法)。
解除Activity和Service之間的關聯,調用
unbindService(connection);
關於銷燬Service說明
在MyService的內部通過stopSelf()方法來銷燬的;
一個Service必須要在既沒有和任何Activity關聯又處理停止狀態的時候纔會被銷燬;
在Service的onDestroy()方法裏去清理掉那些不再使用的資源,防止在Service被銷燬後還會有一些不再使用的對象仍佔用着內存;
IntentService
IntentService是Service的子類,在介紹IntentService之前,先來了解使用Service時需要注意的兩個問題
Service 不會專門啓動一個線程執行耗時操作,所有的操作都是在主線程中進行的,以至於容易出現ANR,所以需要手動開啓一個子線程;
Service 不會自動停止,需要調用stopSelf()方法 或者 是stopService() 方法停止;
使用IntentService不會出現這兩個問題,因爲IntentService在開啓Service時,會自動開啓一個新的線程來執行它,另外,當Service運行結束後,會自動停止。
如何保證服務不會被殺死
第一種方式,返回 START_STICKY 或 START_REDELIVER_INTENT
當Service因內存不足而被系統kill後,一段時間後內存再次空閒時,系統將會嘗試重新創建此Service,一旦創建成功後將回調onStartCommand方法,但其中的Intent將是null,除非有掛起的Intent,如pendingintent,這個狀態下比較適用於不執行命令、但無限期運行並等待作業的媒體播放器或類似的服務。
/**
* 返回 START_STICKY 或 START_REDELIVER_INTENT
* @param intent
* @param flags
* @param startId
* @return
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//return super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
第二種方式,提高service的優先權
<service
android:name="com.demo.UploadService"
android:enabled="true" >
<intent-filter android:priority="1000" >
<action android:name="com.demo.MyService" />
</intent-filter>
</service>