服務是什麼
服務(Service)是Android中實現後臺運行程序的解決方案,他非常適合用於那些不需要和用戶進行交互的並且需要長期運行的任務,即使用戶打開了另一個應用程序,程序被切到了後臺,服務依然能夠運行。需要注意的是服務的運行並不是再一個新的線程中,而是在主線程中運行的。
服務的基本用法
首先定義一個MyService類繼承Service類,這樣就可以重寫他的幾個方法了
public class MyService extends Service{
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
官方API文檔中對這幾個方法的解釋
onBind方法:當其他組件調用onBind方法請求綁定Service時該方法被調用,該方法返回一個IBinder接口,這個IBinder接口是Service與請求綁定者之間的橋樑,如果沒有組件與Service進行綁定,則該方法返回null。
onCreate方法:在服務第一次被創建的時候回調該方法,只會被回調一次,並且在onStartCommand方法和OnBind方法被回調之前調用,如果服務正在運行,則該方法不會被調用。
onStartCommand方法:當其他組件調用startService方法請求啓動Service時該方法回調,一旦服務啓動,服務處於後臺運行狀態,如果需要結束服務的運行,需要調用stopSelf或stopService方法結束服務的運行(如果僅僅是bindService,則無需調用這些方法)
onDestory方法:在服務銷燬時調用,再改房中應該釋放一些資源,如停止線程或者解除綁定的監聽器或者一些BroadcastReceiver,該方法是Service中的最後一個回調
作爲四大組件之一,服務還需要在androidmanifest.xml文件中進行註冊
<service android:name=".MyService"></service>
服務的啓動與停止
定義兩個按鈕,一個用來啓動服務,一個停止服務,佈局代碼不再給出
mStartButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(MainActivity.this,MyService.class);
startService(intent);
}
});
mStopButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(MainActivity.this,MyService.class);
stopService(intent);
}
});
使用Context類的startService和stopService方法啓動或停止服務,使用顯示Intent指定需要開啓或關閉的服務
在MyService中我在每個發那個方法中調用了Log日誌打印,這樣就可以知道哪個方法被調用了
public class MyService extends Service{
private static final String TAG="MyService";
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "---------------onBind");
return null;
}
@Override
public void onCreate() {
Log.i(TAG, "---------------onCreate");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "---------------onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.i(TAG, "---------------onDestroy");
super.onDestroy();
}
}
點擊startService
- onCreate
- onStratCommand
再次點擊startService
- onStartCommand
點擊stopService
- onDestroy
可以看到onCreate方法只會調用一次,之後再次開啓服務,只會調用onStartCommand方法
活動與服務進行通信
雖然已經啓動了服務,但是在啓動之後好像Activity與Service就沒有關係了,要想知道服務到底幹了什麼,並且完成的進度等,就需要服務與活動進行通信,這時候就需要用到剛纔介紹的onBind方法了
private DownloadBinder mBinder=new DownloadBinder();
class DownloadBinder extends Binder{
public void startDownload(){
Log.i(TAG, "-------------startDownload");
}
public int getProcess(){
Log.i(TAG, "--------------getProcess");
return 0;
}
}
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "---------------onBind");
return mBinder;
}
首先我定義了一個內部類DownloadBinder繼承Binder類,裏面實現了兩個方法,一個是開始下載,一個是查看下載的進度,方然這都是虛擬的方法。然後在MyService中創建了DownloadBinder的實例,並且在onBind方法中返回這個mBinder實例。這樣工作幾乎就完成了。
再定義兩個按鈕bindService和unBindService
修改MainActivity中的代碼,使得MainActivity與MyService建立連接
private MyService.DownloadBinder mBinder;
private ServiceConnection connection=new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mBinder=(DownloadBinder) service;
mBinder.startDownload();
mBinder.getProcess();
}
};
首先定義了一個匿名類ServiceConnection,在裏面重寫了onServiceConnected方法和onServiceDisconnected方法,這兩個方法分別在服務與活動進行綁定和解除綁定時調用。然後我在onServiceConnected方法中通過向下轉型得到了mBinder實例,也就是在MyService的onBind方法中返回的mBinder,這樣就可以調用MyBinder中的任何public方法,例如開始下載的方法和查看進度的方法。
mBindButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent bindIntent=new Intent(MainActivity.this,MyService.class);
bindService(bindIntent, connection, BIND_AUTO_CREATE);
}
});
mUnBindButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
unbindService(connection);
}
});
綁定的關鍵是bindService方法,第一個是Intent對象,第二個是剛剛創建的connection對象,第三個是參數,這裏傳入的BIND_AUTO_CREATE指的是在綁定後立即創建服務,即調用onCreate方法,但onstartCommand方法不會調用.
取消綁定很簡單,調用unBindService方法,傳入剛纔創建的connection對象就可以取消綁定了。
運行
點擊bindService按鈕
可以看到分別調用了
- onCreate
- onBind
- startDownload
- getProcess
點擊unBindService
- onDestroy
注意,經過試驗後得到如果只調用了startService方法,只需要調用stopService方法就會調用onDestroy方法,如果只調用了bindService方法,則只需要調用unBindService方法就會回掉onDestroy方法,如果startService和bindService方法都調用了,則需要stopService和unBindService方法都被調用後,服務纔會停止。
使用前臺服務
前段時間剛學了通知的使用即Notification,這裏前臺服務其實與Notification很相似的
在MyService的onCreate方法中
public void onCreate() {
Log.i(TAG, "---------------onCreate");
super.onCreate();
Notification notification=new Notification(R.drawable.ic_launcher, "通知來了!",System.currentTimeMillis());
Intent intent=new Intent(this,MainActivity.class);
PendingIntent pendingIntent=PendingIntent.getActivity(this,0, intent,0);
notification.setLatestEventInfo(this, "前臺服務標題", "前臺服務內容", pendingIntent);
notification.defaults=Notification.DEFAULT_ALL;
startForeground(1, notification);
}
可以看到前臺服務其實和通知是一樣的,只不過沒用NotificationManager,而使用startForeground來開啓通知。