服務(wù)作為安卓開發(fā)的四大組件之一,發(fā)揮著非常重要的作用,下面我們以一些簡(jiǎn)單實(shí)例嘱能,總結(jié)一下服務(wù)的基本用法。
定義一個(gè)服務(wù)
新建一個(gè)項(xiàng)目员咽,在項(xiàng)目中定義一個(gè)服務(wù):com.example.adiqueen.servicetest->New->Service->Service,我們會(huì)看到對(duì)話框:
exported表示是否允許當(dāng)前程序意外的其他程序本服務(wù)退客。
enabled表示是否啟用這個(gè)服務(wù)骏融。
點(diǎn)擊finish完成創(chuàng)建。
這個(gè)時(shí)候我們可以看到MyService中的代碼:
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
MyService繼承自Service 有一個(gè)方法onBind()方法萌狂,這個(gè)方法是Service惟一的一個(gè)抽象方法档玻,必須要在子類中實(shí)現(xiàn)。如果我們要處理一些事情的話茫藏,就要用到幾個(gè)常見的其他方法误趴。
/*
服務(wù)中最常用的幾個(gè)方法
*/
//服務(wù)在創(chuàng)建的時(shí)候調(diào)用的方法
@Override
public void onCreate() {
Log.d("MyService","onCreate()-------");
super.onCreate();
}
//服務(wù)在每次啟動(dòng)的時(shí)候調(diào)用的方法 如果某些行為在服務(wù)已啟動(dòng)的時(shí)候就執(zhí)行,可以把處理邏輯寫在這個(gè)方法里面
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("MyService","onStartCommand()-------");
return super.onStartCommand(intent, flags, startId);
}
//服務(wù)銷毀的時(shí)候調(diào)用的方法 可以回收部分不再使用的資源
@Override
public void onDestroy() {
Log.d("MyService","onDestroy()-------");
super.onDestroy();
}
這個(gè)時(shí)候還沒完务傲,如果我們是使用此服務(wù)的話 這個(gè)服務(wù)在manifest中注冊(cè)才能正常使用凉当。
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"></service>
啟用和停止服務(wù)
服務(wù)的啟用和停止我們不會(huì)感到陌生,因?yàn)橹饕墙柚鶬ntent來實(shí)現(xiàn)的售葡。下面我們看一下如何啟用和停止服務(wù)看杭。在這里我們?cè)O(shè)置兩個(gè)按鈕,分別點(diǎn)擊按鈕實(shí)現(xiàn)服務(wù)的啟用和停止挟伙。
public class MainActivity extends AppCompatActivity {
private Button start_servece;
private Button stop_servece;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
start_servece = (Button)findViewById(R.id.start_servece);
stop_servece = (Button)findViewById(R.id.stop_servece);
start_servece.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent startIntent = new Intent(MainActivity.this,MyService.class);
startService(startIntent); //啟動(dòng)服務(wù)
}
});
stop_servece.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent stopIntent = new Intent(MainActivity.this,MyService.class);
stopService(stopIntent); //停止服務(wù)
//MyService類中的任何一個(gè)位置調(diào)用stopSelf()也能停止服務(wù)
}
});
}
}
因?yàn)榍懊嫖覀円呀?jīng)在服務(wù)的部分方法中添加了打印日志的代碼楼雹,這個(gè)時(shí)候我們點(diǎn)擊開啟按鈕,再點(diǎn)擊關(guān)閉按鈕之后的控制臺(tái)信息如下:
說明我們完成了服務(wù)的啟用和停止。
活動(dòng)和服務(wù)進(jìn)行通信
服務(wù)是在活動(dòng)里啟動(dòng)的贮缅,但是服務(wù)啟動(dòng)之后就和活動(dòng)沒有關(guān)系了榨咐。但是,活動(dòng)具體運(yùn)行的是什么邏輯呢谴供?活動(dòng)就控制不了了块茁。如果這樣的話,我們對(duì)服務(wù)的可控性是不是就差了很多桂肌。有沒有什么方式可以把活動(dòng)和服務(wù)綁定一下呢数焊?能夠方便活動(dòng)對(duì)服務(wù)更好的控制。答案是肯定的崎场。這個(gè)時(shí)候就要用到前面我們提到的Service的唯一抽象方法onBind()昌跌。我們來看一個(gè)簡(jiǎn)單的實(shí)例:在服務(wù)里實(shí)現(xiàn)下載的功能,并能實(shí)時(shí)查看下載的進(jìn)度照雁。
實(shí)現(xiàn)的思路是在MyService類中創(chuàng)建一個(gè)Buider對(duì)象來對(duì)下載功能進(jìn)行管理。
//新建一個(gè)DownloadBinder類繼承自Binder
//接著在MyService的onBind()方法中返回DownloadBinder實(shí)例答恶。
private DownloadBinder mBinder = new DownloadBinder();
class DownloadBinder extends Binder{
public void startDownLoad(){
Log.d("MyService","startDownLoad()----");
}
public int getProgress(){
Log.d("MyService","getProgress()----");
return 0;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
MainActivity類中
public class MainActivity extends AppCompatActivity {
private Button bind_servece;
private Button unbind_servece;
private MyService.DownloadBinder downloadBinder;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
downloadBinder = (MyService.DownloadBinder) iBinder;
downloadBinder.startDownLoad();
downloadBinder.getProgress();
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bind_servece = (Button)findViewById(R.id.bind_servece);
unbind_servece = (Button)findViewById(R.id.unbind_servece);
bind_servece.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent bindIntent = new Intent(MainActivity.this,MyService.class);
bindService(bindIntent,serviceConnection,BIND_AUTO_CREATE);//綁定服務(wù)
}
});
unbind_servece.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
unbindService(serviceConnection);//解綁服務(wù)
}
});
}
}
在MainActivity類中:
創(chuàng)建了ServiceConnection匿名類 重寫了onServiceConnected()和onServiceDisconnected()方法饺蚊。這兩個(gè)方法會(huì)在活動(dòng)與服務(wù)綁定和解綁的時(shí)候調(diào)用。
在onServiceConnected()方法中我們向下轉(zhuǎn)型得到downloadBinder的實(shí)例悬嗓,有了這個(gè)實(shí)例活動(dòng)和服務(wù)之間的關(guān)系就變得很緊密了污呼。
在這里只是一個(gè)簡(jiǎn)單的打印日志,并未做過多的任務(wù)包竹。
部署程序燕酷、點(diǎn)擊按鈕可以看到日志:
服務(wù)的生命周期
服務(wù)和活動(dòng)一樣,也有自己的生命周期周瞎。前面有幾個(gè)方法我們都已經(jīng)使用到了苗缩。
一旦在項(xiàng)目中調(diào)用了Context的startService()方法,服務(wù)就會(huì)被啟動(dòng)起來声诸,并回調(diào)onStartCommand()方法酱讶。如果這個(gè)服務(wù)之前沒有被創(chuàng)建過,還會(huì)在onStartCommand()方法運(yùn)行之前彼乌,執(zhí)行onCreate() 方法泻肯。
服務(wù)一旦被啟用就會(huì)保持啟用的狀態(tài),知道調(diào)用了方法stopService()或者stopSelf()慰照。
另外灶挟,還可以調(diào)用Context的bindService()方法獲取一個(gè)持久的鏈接,Service的onBind()方法會(huì)被執(zhí)行毒租。而作為調(diào)用方的話可以或者onBind()方法里返回的IBinder對(duì)象的實(shí)例稚铣,這樣就能自由的和服務(wù)進(jìn)行通訊了。
調(diào)用了startService()方法以后,再調(diào)用stopService()方法的話榛泛,Service的onDestroy()方法就會(huì)執(zhí)行蝌蹂,證明服務(wù)已經(jīng)銷毀了。類似的調(diào)用bindService()曹锨、unbindService()方法后onDestroy()方法也會(huì)執(zhí)行孤个。加入我們同時(shí)調(diào)用了startService()和bindService(),那么這種情況該如何讓服務(wù)銷毀呢沛简?根據(jù)Android系統(tǒng)的機(jī)制齐鲤,一個(gè)服務(wù)只要調(diào)用startService()或bindService()中的一個(gè),就會(huì)一直處于運(yùn)行態(tài)椒楣。必須以上通知滿足给郊,onDestroy()方法才會(huì)執(zhí)行,服務(wù)才能銷毀捧灰。這個(gè)時(shí)候要同事調(diào)用stopService()和unbindService()方法淆九。