日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

安卓服务Service详解

發(fā)布時(shí)間:2025/3/15 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 安卓服务Service详解 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

service(服務(wù))是安卓中的四大組件之一,它通常用作在后臺(tái)處理耗時(shí)的邏輯,與Activity一樣,它存在自己的生命周期,也需要在清單文件中配置相關(guān)信息,本博客將對(duì)Service的各個(gè)知識(shí)點(diǎn)進(jìn)行詳細(xì)講解。



一Service的基本用法:

1使用本地服務(wù)

1)服務(wù)的啟動(dòng)方式

1通過Context的startService()方法啟動(dòng)服務(wù):以該方法啟動(dòng)的服務(wù),開啟該服務(wù)的應(yīng)用組件(如Activity)與該Service不存在關(guān)聯(lián)關(guān)系,即使開啟該服務(wù)的Activity被銷毀,Service任能夠一直在后臺(tái)運(yùn)行。通常,開啟的服務(wù)執(zhí)行一個(gè)單獨(dú)的操作且不需向調(diào)用者返回一個(gè)結(jié)果。比如,可能從網(wǎng)絡(luò)進(jìn)行下載或者上傳一個(gè)文件。當(dāng)任務(wù)完成,服務(wù)就該自我停止。使用服務(wù)于使用Activity非常相似,都是先繼承其對(duì)應(yīng)的基類,然后重寫其中重要的方法,這些方法就是關(guān)于其生命周期回調(diào)的方法。代碼如下所示:

[java] view plaincopy
  • public?class?MyService?extends?Service?{??
  • ??
  • ????public?static?final?String?TAG?=?"MyService";??
  • ??
  • ????@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?null;??
  • ????}??
  • ??
  • }??
  • 然后再Activity中使用 [java] view plaincopy
  • Intent?startIntent?=?new?Intent(this,?MyService.class);????
  • startService(startIntent);???
  • 即可開啟該服務(wù),程序運(yùn)行結(jié)果如下:


    從程序的運(yùn)行結(jié)果來看,可以知道當(dāng)啟動(dòng)一個(gè)Service的時(shí)候,會(huì)調(diào)用該Service中的onCreate()和onStartCommand()方法。

    當(dāng)我們?cè)诖吸c(diǎn)擊啟動(dòng)服務(wù)的按鈕,程序運(yùn)行結(jié)果如下:


    可以看到,此時(shí)只輸出onStartCommand() executed。這說明此時(shí)只執(zhí)行了onStartCommand()方法,而未執(zhí)行onCreate(),這說明onCreate()方法只會(huì)在Service第一次被創(chuàng)建的時(shí)候調(diào)用,如果當(dāng)前Service已經(jīng)被創(chuàng)建過了,則即使多次調(diào)用startService()方法,onCreate()方法都不會(huì)再執(zhí)行,這一點(diǎn)非常類似數(shù)據(jù)庫(kù)操作中的open一個(gè)數(shù)據(jù)庫(kù)。

    當(dāng)然上述的例子僅僅只是為了說明上述知識(shí)點(diǎn),因?yàn)镾ervice中的代碼也僅僅只是打印出log而已,而事實(shí)上Service的使用是為了處理一些耗時(shí)操作的,如網(wǎng)絡(luò)請(qǐng)求,文件上傳與下載,但都是重寫其某個(gè)生命周期函數(shù),如onStart(Intent intent, int startId),onDestroy()在這些函數(shù)中完成自己的業(yè)務(wù)邏輯的處理,下面的代碼是使用服務(wù)來進(jìn)行網(wǎng)絡(luò)通信的一個(gè)例子。

    [java] view plaincopy
  • public?class?GetMsgService?extends?Service?{??
  • ????private?Client?client;??
  • ????private?boolean?isStart;??
  • ????private?SharePreferenceUserInfoUtil?util;??
  • ????private?ClientInputThread?cit;??
  • ????@Override??
  • ????public?IBinder?onBind(Intent?intent)?{??
  • ????????//?TODO?Auto-generated?method?stub??
  • ????????return?null;??
  • ????}??
  • ??
  • ????@Override??
  • ????public?void?onCreate()?{??
  • ????????//?TODO?Auto-generated?method?stub??
  • ????????super.onCreate();??
  • ????????client=((MyApplication)?getApplication()).getClient();??
  • ????}??
  • ??
  • ????@Override??
  • ????public?void?onStart(Intent?intent,?int?startId)?{??
  • ????????//?TODO?Auto-generated?method?stub??
  • ????????super.onStart(intent,?startId);??
  • ????????util?=?new?SharePreferenceUserInfoUtil(getApplicationContext(),??
  • ????????????????Constants.SAVE_USER);??
  • ?????????
  • ????????new?Thread(){??
  • ???????????????public?void?run()??
  • ???????????????{??
  • ????????????????????try?{??
  • ????????????????????????isStart=client.create();??
  • ????????????????????}?catch?(UnknownHostException?e)?{??
  • ????????????????????????//?TODO?Auto-generated?catch?block??
  • ????????????????????????e.printStackTrace();??
  • ????????????????????}?catch?(IOException?e)?{??
  • ????????????????????????//?TODO?Auto-generated?catch?block??
  • ????????????????????????e.printStackTrace();??
  • ????????????????????}??
  • ????????????//在服務(wù)中接受來自服務(wù)器端的消息,然后通過廣播的形式傳遞給相應(yīng)的Activity處理。接受服務(wù)器端的消息一般在??
  • ????????????//服務(wù)中,因?yàn)榉?wù)可以在后臺(tái)一直運(yùn)行??
  • ??????????????????????????????????????
  • ????????????????if(isStart)??
  • ????????????????{??
  • ????????????????????cit=client.getClientInputThread();??
  • ????????????????????if(cit!=null)??
  • ????????????????????{??
  • ????????????????????????cit.setMessageListener(new?MessageListener()?{??
  • ??????????????????????????????
  • ????????????????????????????public?void?getMessage(TransportObject?msg)?{??
  • ??????????????????????????????????
  • ????????????????????????????????if(msg!=null&&msg?instanceof?TransportObject)??
  • ????????????????????????????????{??
  • ????????????????????????????????????//通過廣播向Activity傳遞消息??
  • ????????????????????????????????????Intent?intent=new?Intent();??
  • ????????????????????????????????????intent.setAction(Constants.ACTION_MSG);??
  • ????????????????????????????????????intent.putExtra(Constants.MSG,?msg);??
  • ????????????????????????????????????sendBroadcast(intent);??
  • ????????????????????????????????}??
  • ????????????????????????????}??
  • ????????????????????????});??
  • ????????????????????}??
  • ????????????????????else?{??
  • ????????????????????????Log.i("GetMsgService","服務(wù)器端連接暫時(shí)出錯(cuò)");??
  • ????????????????????//??Toast.makeText(getApplicationContext(),?"服務(wù)器端連接暫時(shí)出錯(cuò),請(qǐng)稍后重試!",0).show();??
  • ????????????????????}??
  • ????????????????}??
  • ????????????????????
  • ???????????????}??
  • ???????????}.start();??
  • ????}??
  • ??
  • ????@Override??
  • ????public?void?onDestroy()?{??
  • ????????//?TODO?Auto-generated?method?stub??
  • ????????super.onDestroy();??
  • ????????ClientOutputThread?out=client.getClientOutputThread();??
  • ????????TransportObject<User>?msg=new?TransportObject<User>(TranObjectType.LOGOUT);??
  • ????????User?user=new?User();??
  • ????????user.setId(Integer.parseInt(util.getId()));??
  • ????????msg.setObject(user);??
  • ????????out.setMsg(msg);??
  • ????????//關(guān)閉服務(wù)時(shí)關(guān)閉client??
  • ????????out.setStart(false);??
  • ????????client.getClientInputThread().setStart(false);??
  • ??????????
  • ??????????
  • ??????????
  • ????}??
  • ??????
  • ??????
  • ??
  • }??
  • 可以看到,我們?cè)趃etMsgService的onStart方法中開啟了一個(gè)線程用來進(jìn)行客戶端從服務(wù)器端讀取信息的操作,在onDestroy()方法中關(guān)閉網(wǎng)絡(luò)請(qǐng)求的操作。

    2通過Context的bindService()方法啟動(dòng)服務(wù):顧名思義,以該方法啟動(dòng)的服務(wù),開啟該服務(wù)的應(yīng)用組件(如Activity)與該Service被綁定在一起,通常用這種方式開啟的服務(wù)是為了與開啟該服務(wù)的應(yīng)用組件(如Activity)進(jìn)行消息通信。

    首先我們來看一下bindService的簽名:

    [java] view plaincopy
  • bindService(Intent?service,?ServiceConnection?conn,?int?flags)??
  • 其中service參數(shù)是通過intent指定要啟動(dòng)的Service。

    conn參數(shù)是一個(gè)ServiceConnection對(duì)象,該對(duì)象用于監(jiān)聽訪問者與service之間的連接情況,當(dāng)訪問者與Service連接成功時(shí)會(huì)回調(diào)該類的onServiceConnected(ComponentName name, IBinder service)方法,然后將服務(wù)中創(chuàng)建的Ibinder對(duì)象(此時(shí)在Service的onBinder方法中需要返回該Ibinder對(duì)象)傳遞給第二個(gè)參數(shù)service,通過該Ibinder對(duì)象就能與Service進(jìn)行通信。

    第三個(gè)參數(shù)flags指定綁定時(shí)是否自動(dòng)創(chuàng)建Service,一般我們指定為BIND_AUTO_CREATE(自動(dòng)創(chuàng)建,如果傳入0表示不自動(dòng)創(chuàng)建)示例代碼如下:

    Service中的代碼:

    [java] view plaincopy
  • 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)?{//在onBind(Intent?intent)中返回IBinder對(duì)象??
  • ????????return?mBinder;??
  • ????}??
  • ??
  • ????class?MyBinder?extends?Binder?{//定義一個(gè)類實(shí)現(xiàn)IBinder接口(?Binder實(shí)現(xiàn)了IBinder接口)??
  • ??
  • ????????public?void?doSomething()?{??
  • ????????????Log.d("TAG",?"doSomething()?executed");??
  • ??????????????
  • ????????}??
  • ??
  • ????}??
  • ??
  • }??
  • Activity中的代碼: [java] view plaincopy
  • public?class?MainActivity?extends?Activity??
  • {??
  • ??...??
  • private?ServiceConnection?connection?=?new?ServiceConnection()?{????
  • ????
  • ????????@Override????
  • ????????public?void?onServiceDisconnected(ComponentName?name)?{????
  • ????????}????
  • ????
  • ????????@Override????
  • ????????public?void?onServiceConnected(ComponentName?name,?IBinder?service)?{????
  • ????????????myBinder?=?(MyService.MyBinder)?service;????
  • ????????????myBinder.doSomething();????
  • ????????}????
  • ????};????
  • ????protected?void?onCreate(Bundle?savedInstanceState)?{????
  • ????????super.onCreate(savedInstanceState);????
  • ????????setContentView(R.layout.activity_main);????
  • ????Intent?bindIntent?=?new?Intent(this,?MyService.class);????
  • ????????bindService(bindIntent,?connection,?BIND_AUTO_CREATE);//此時(shí)使用bindService開啟服務(wù)??
  • ????}??
  • ??...??
  • ??
  • }??
  • 即在服務(wù)中定義一個(gè)IBinder的實(shí)例,然后在Service的public IBinder onBind(Intent intent)方法中將其返回,在Activity中定義一個(gè)ServiceConnection類的實(shí)例,在其onServiceConnected(ComponentName name, IBinder service)方法中獲取Service中 返回IBinder對(duì)象,利用該對(duì)象即可調(diào)用Service中的方法進(jìn)行相互通信。

    注意:一個(gè)服務(wù)在進(jìn)程中的主線程運(yùn)行——一個(gè)服務(wù)不會(huì)創(chuàng)建自己的線程,也不會(huì)在另外的進(jìn)程運(yùn)行(除非另外指定)。這意味著,如果服務(wù)需要做一些頻繁占用CPU的工作或者會(huì)發(fā)生阻塞的操作,你需要在服務(wù)中另開線程執(zhí)行任務(wù)。避免程序出現(xiàn)ANR。


    2使用AIDL跨進(jìn)程調(diào)用服務(wù):

    此種情況與上述介紹的使用bindService方法開啟的綁定本地的大的框架基本相同,只不過使用AIDL來實(shí)現(xiàn)跨進(jìn)程調(diào)用,關(guān)于此種情況的介紹,請(qǐng)參看我的博客:安卓中不同APP之間的消息通信中相關(guān)的內(nèi)容。



    二Service與線程的關(guān)系及IntentService:

    事實(shí)上Service與線程之間沒多大關(guān)系,我們之所以把Service與線程放在一起談?wù)?#xff0c;是為了更清楚的明白在哪些情況下用服務(wù)哪些情況下用線程,哪些情況下在服務(wù)中開啟一個(gè)線程,因?yàn)镾ervice默認(rèn)在主線程中運(yùn)行,不能進(jìn)行耗時(shí)操作,這也是IntentService存在的原因。因?yàn)镮ntentService會(huì)創(chuàng)建單獨(dú)的worker線程來處理intent請(qǐng)求,不需要自己創(chuàng)建一個(gè)子線程。

    IntentService處理流程
    創(chuàng)建默認(rèn)的一個(gè) worker 線程處理傳遞給 onStartCommand() 的所有 intent ,不占據(jù)應(yīng)用的主線程
    創(chuàng)建一個(gè)工作隊(duì)列一次傳遞一個(gè) intent 到你實(shí)現(xiàn)的 onHandleIntent() 方法,避免了多線程
    在所有啟動(dòng)請(qǐng)求被處理后自動(dòng)關(guān)閉服務(wù),不需要調(diào)用 stopSelf()
    默認(rèn)提供 onBind() 的實(shí)現(xiàn),且返回 null
    默認(rèn)提供 onStartCommand() 的實(shí)現(xiàn),實(shí)現(xiàn)發(fā)送intent到工作隊(duì)列再到onHandleIntent() 方法實(shí)現(xiàn)。

    正因?yàn)槿绱?#xff0c;所以使用IntentService無需重寫onBind(),onStartCommand(),只需重寫onHandleIntent() 即可。示例代碼如下:

    [java] view plaincopy
  • public?class?HelloIntentService?extends?IntentService?{??
  • ??/**?
  • ???*?A?constructor?is?required,?and?must?call?the?super?IntentService(String)?
  • ???*?constructor?with?a?name?for?the?worker?thread.?
  • ???*/??
  • ??public?HelloIntentService()?{??
  • ????super("HelloIntentService");??
  • ??}??
  • ??/**?
  • ???*?The?IntentService?calls?this?method?from?the?default?worker?thread?with?
  • ???*?the?intent?that?started?the?service.?When?this?method?returns,?IntentService?
  • ???*?stops?the?service,?as?appropriate.?
  • ???*/??
  • ??@Override??
  • ??protected?void?onHandleIntent(Intent?intent)?{??
  • ????//?Normally?we?would?do?some?work?here,?like?download?a?file.??
  • ????//?For?our?sample,?we?just?sleep?for?5?seconds.??
  • ????long?endTime?=?System.currentTimeMillis()?+?5*1000;??
  • ????while?(System.currentTimeMillis()?<?endTime)?{??
  • ??????synchronized?(this)?{??
  • ????????try?{??
  • ??????????wait(endTime?-?System.currentTimeMillis());??
  • ????????}?catch?(Exception?e)?{??
  • ????????}??
  • ??????}??
  • ????}??
  • ??}??
  • }??


  • 三Service的生命周期

    我們先來看一下谷歌官方圖片:


    從上述圖片可以看到兩種不同的啟動(dòng)方式其生命周期也不同:

    啟動(dòng)的服務(wù):?
    startService()->onCreate()->onStartCommand()->running->stopService()/stopSelf()->onDestroy()->stopped?
    其中,服務(wù)未運(yùn)行時(shí)會(huì)調(diào)用一次onCreate(),運(yùn)行時(shí)不調(diào)用。
    綁定的服務(wù):?
    bindService()->onCreate()->onBind()->running->onUnbind()->onDestroy()->stopped
    服務(wù)起始于 onCreate() ,終止于 onDestory()

    服務(wù)的開關(guān)過程,只有 onStartCommand() 可多次調(diào)用,其他在一個(gè)生命周期只調(diào)用一次。

    這兩個(gè)過程不是完全獨(dú)立,也可以綁定一個(gè)由 startService() 啟動(dòng)過的服務(wù)



    四如何創(chuàng)建不被系統(tǒng)殺死的服務(wù)

    服務(wù)不被殺死包括三種情況

    1.系統(tǒng)根據(jù)資源分配情況殺死服務(wù)

    2.用戶通過 settings -> Apps -> Running -> Stop 方式殺死服務(wù) 3.用戶通過 settings -> Apps -> Downloaded -> Force Stop 方式殺死服務(wù) 第一種情況:

    用戶不干預(yù),完全靠系統(tǒng)來控制,辦法有很多。比如 onStartCommand() 方法的返回值設(shè)為 START_STICKY ,服務(wù)就會(huì)在資源緊張的時(shí)候被殺掉,然后在資源足夠的時(shí)候再恢復(fù)。當(dāng)然也可設(shè)置為前臺(tái)服務(wù),使其有高的優(yōu)先級(jí),在資源緊張的時(shí)候也不會(huì)被殺掉。

    關(guān)于?onStartCommand() 方法的返回值做一下簡(jiǎn)單的介紹:

    START_STICKY:如果service進(jìn)程被kill掉,保留service的狀態(tài)為開始狀態(tài),但不保留遞送的intent對(duì)象。隨后系統(tǒng)會(huì)嘗試重新創(chuàng)建service,由于服務(wù)狀態(tài)為開始狀態(tài),所以創(chuàng)建服務(wù)后一定會(huì)調(diào)用onStartCommand(Intent,int,int)方法。如果在此期間沒有任何啟動(dòng)命令被傳遞到service,那么參數(shù)Intent將為null。
    START_NOT_STICKY:“非粘性的”。使用這個(gè)返回值時(shí),如果在執(zhí)行完onStartCommand后,服務(wù)被異常kill掉,系統(tǒng)不會(huì)自動(dòng)重啟該服務(wù)。
    START_REDELIVER_INTENT:重傳Intent。使用這個(gè)返回值時(shí),如果在執(zhí)行完onStartCommand后,服務(wù)被異常kill掉,系統(tǒng)會(huì)自動(dòng)重啟該服務(wù),并將Intent的值傳入。
    START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保證服務(wù)被kill后一定能重啟。

    第二種情況:
    用戶干預(yù),主動(dòng)殺掉運(yùn)行中的服務(wù)。這個(gè)過程殺死服務(wù)會(huì)通過服務(wù)的生命周期,也就是會(huì)調(diào)用 onDestory() 方法,這時(shí)候一個(gè)方案就是在 onDestory() 中發(fā)送廣播開啟自己。這樣殺死服務(wù)后會(huì)立即啟動(dòng)。如下:

    在onCreate中注冊(cè)廣播,用來開啟服務(wù),在服務(wù)的onDestroy()中發(fā)送廣播通知服務(wù)開啟自己,代碼如下:

    [java] view plaincopy
  • public?void?onCreate()?{??
  • ??//?TODO?Auto-generated?method?stub??
  • ??super.onCreate();??
  • ??mBroadcast?=?new?BroadcastReceiver()?{??
  • ????@Override??
  • ????public?void?onReceive(Context?context,?Intent?intent)?{??
  • ??????//?TODO?Auto-generated?method?stub??
  • ??????Intent?a?=?new?Intent(ServiceA.this,?ServiceA.class);??
  • ??????startService(a);??
  • ????}??
  • ??};??
  • ??mIF?=?new?IntentFilter();??
  • ??mIF.addAction("listener");??
  • ??registerReceiver(mBroadcast,?mIF);??
  • }??
  • @Override??
  • public?void?onDestroy()?{??
  • ??//?TODO?Auto-generated?method?stub??
  • ??super.onDestroy();??
  • ??Intent?intent?=?new?Intent();??
  • ??intent.setAction("listener");??
  • ??sendBroadcast(intent);??
  • ??unregisterReceiver(mBroadcast);??
  • }??
  • 第三種情況:
    強(qiáng)制關(guān)閉就不好解決。這個(gè)好像是從包的level去關(guān)的,不是走的Service的完整的生命周期。所以在服務(wù)里加代碼是無法被調(diào)用的。處理這個(gè)情況的唯一方法是屏蔽掉 force stop 和 uninstall 按鈕,讓其不可用。

    好了,以上就是本人理解的關(guān)于Service的相關(guān)知識(shí),看官如果覺得不錯(cuò)請(qǐng)不要吝嗇點(diǎn)擊一下下方的“頂”按鈕給我一點(diǎn)鼓勵(lì)哦!

    總結(jié)

    以上是生活随笔為你收集整理的安卓服务Service详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。