深入理解Android的startservice和bindservice
一、首先,讓我們確認(rèn)下什么是service??
??????? service就是android系統(tǒng)中的服務(wù),它有這么幾個(gè)特點(diǎn):它無法與用戶直接進(jìn)行交互、它必須由用戶或者其他程序顯式的啟動(dòng)、它的優(yōu)先級比較高,它比處于前臺(tái)的應(yīng)用優(yōu)先級低,但是比后臺(tái)的其他應(yīng)用優(yōu)先級高,這就決定了當(dāng)系統(tǒng)因?yàn)槿鄙賰?nèi)存而銷毀某些沒被利用的資源時(shí),它被銷毀的概率很小哦。?
二、那么,什么時(shí)候,我們需要使用service呢??
??????? 我們知道,service是運(yùn)行在后臺(tái)的應(yīng)用,對于用戶來說失去了被關(guān)注的焦點(diǎn)。這就跟我們打開了音樂播放之后,便想去看看圖片,這時(shí)候我們還不想音樂停止,這里就會(huì)用到service;又例如,我們打開了一個(gè)下載鏈接之后,我們肯定不想瞪著眼睛等他下載完再去做別的事情,對吧?這時(shí)候如果我們想手機(jī)一邊在后臺(tái)下載,一邊可以讓我去看看新聞啥的,就要用到service。?
三、service分類:?
?????? 一般我們認(rèn)為service分為兩類,本地service和遠(yuǎn)程service。?
?????? 本地service顧名思義,那就是和當(dāng)前應(yīng)用在同一個(gè)進(jìn)程中的service,彼此之間擁有共同的內(nèi)存區(qū)域,所以對于某些數(shù)據(jù)的共享特別的方便和簡單;?
?????? 遠(yuǎn)程service:主要牽扯到不同進(jìn)程間的service訪問。因?yàn)閍ndroid的系統(tǒng)安全的原因?qū)е铝宋覀冊诓煌倪M(jìn)程間無法使用一般的方式共享數(shù)據(jù)。在這里android為我們提供了一個(gè)AIDL工具。(android interface description language)android接口描述語言。在后邊我們將會(huì)對其進(jìn)行詳細(xì)的介紹。?
四、service生命周期:?
??????? 和Activity相比,service的生命周期已經(jīng)簡單的不能再簡單了,只有onCreate()->onStart()->onDestroy()三個(gè)方法。?
?????? Activity中和service有關(guān)的方法:?
?????? startService(Intent intent):啟動(dòng)一個(gè)service?
?????? stopService(Intent intent) :停止一個(gè)service?
??????? 如果我們想使用service中的一些數(shù)據(jù)或者訪問其中的一些方法,那么我們就要通過下面的方法:?
??????? public boolean bindService(Intent intent, ServiceConnection conn, int flags) ;?
??????? public void unbindService(ServiceConnection conn);?
??????? intent是跳轉(zhuǎn)到service的intent,如 Intent intent = new Intent(); intent.setClass(this,MyService.class);?
??????? conn則是一個(gè)代表與service連接狀態(tài)的類,當(dāng)我們連接service成功或失敗時(shí),會(huì)主動(dòng)觸發(fā)其內(nèi)部的onServiceConnected或onServiceDisconnected方法。如果我們想要訪問service中的數(shù)據(jù),可以在onServiceConnected()方法中進(jìn)行實(shí)現(xiàn),
?
使用service的步驟:?
??????? 第一步:我們要繼承service類,實(shí)現(xiàn)自己的service。?
??????? 如果想要訪問service中的某些值,我們通常會(huì)提供一個(gè)繼承了Binder的內(nèi)部類,通過onBund()方法返回給service請求。這里實(shí)際上巧妙的利用了內(nèi)部類能夠訪問外部類屬性的特點(diǎn)。?
第二步:在androidManifest.xml中進(jìn)行注冊,如:?
??????? <!-- service配置開始 -->?
??????? <service android:name="MyService"></service>?
??????? <!-- service配置結(jié)束-->?
第三步:在activity中進(jìn)行啟動(dòng)、綁定、解綁或者停止service。?
??????? (很多書上說,service與用戶是不能交互的,其實(shí)這話很不正確,我們完全可以通過activity與service進(jìn)行交互!我認(rèn)為,確切的說法應(yīng)該是service與用戶不能進(jìn)行直接的交互)。
-----------------------------
bindService介紹
一、bindService簡介
bindService是綁定Service服務(wù),執(zhí)行service服務(wù)中的邏輯流程。
service通過Context.startService()方法開始,通過Context.stopService()方法停止;也可以通過Service.stopSelf()方法或者Service.stopSelfResult()方法來停止自己。只要調(diào)用一次stopService()方法便可以停止服務(wù),無論之前它被調(diào)用了多少次的啟動(dòng)服務(wù)方法。
客戶端建立一個(gè)與Service的連接,并使用此連接與Service進(jìn)行通話,通過Context.bindService()方法來綁定服務(wù),Context.unbindService()方法來關(guān)閉服務(wù)。多個(gè)客戶端可以綁定同一個(gè)服務(wù),如果Service還未被啟動(dòng),bindService()方法可以啟動(dòng)服務(wù)。
上面startService()和bindService()兩種模式是完全獨(dú)立的。你可以綁定一個(gè)已經(jīng)通過startService()方法啟動(dòng)的服務(wù)。例如:一個(gè)后臺(tái)播放音樂服務(wù)可以通過startService(intend)對象來播放音樂。可能用戶在播放過程中要執(zhí)行一些操作比如獲取歌曲的一些信息,此時(shí)activity可以通過調(diào)用bindServices()方法與Service建立連接。這種情況下,stopServices()方法實(shí)際上不會(huì)停止服務(wù),直到最后一次綁定關(guān)閉。
如果沒有程序停止它或者它自己停止,service將一直運(yùn)行。在這種模式下,service開始于調(diào)用Context.startService() ,停止于Context.stopService(). service可以通過調(diào)用Android Service 生命周期() 或 Service.stopSelfResult()停止自己。不管調(diào)用多少次startService() ,只需要調(diào)用一次 stopService() 就可以停止service。
可以通過接口被外部程序調(diào)用。外部程序建立到service的連接,通過連接來操作service。建立連接調(diào)開始于Context.bindService(), 結(jié)束于Context.unbindService(). 多個(gè)客戶端可以綁定到同一個(gè)service,如果service沒有啟動(dòng), bindService() 可以選擇啟動(dòng)它。
這2種模式不是完全分離的。你可以可以綁定到一個(gè)通過startService()啟動(dòng)的服務(wù)。如一個(gè)intent想要播放音樂,通過startService() 方法啟動(dòng)后臺(tái)播放音樂的service。然后,也許用戶想要操作播放器或者獲取當(dāng)前正在播放的樂曲的信息,一個(gè)activity就會(huì)通過bindService()建立一個(gè)到此service的連接. 這種情況下 stopService() 在全部的連接關(guān)閉后才會(huì)真正停止service。
二、bindService啟動(dòng)流程
context.bindService()? ——> onCreate()? ——> onBind()? ——> Service running? ——> onUnbind()? ——> onDestroy()? ——> Service stop
onBind()將返回給客戶端一個(gè)IBind接口實(shí)例,IBind允許客戶端回調(diào)服務(wù)的方法,比如得到Service的實(shí)例、運(yùn)行狀態(tài)或其他操作。這個(gè)時(shí)候把調(diào)用者(Context,例如Activity)會(huì)和Service綁定在一起,Context退出了,Srevice就會(huì)調(diào)用onUnbind->onDestroy相應(yīng)退出。
所以調(diào)用bindService的生命周期為:onCreate --> onBind(只一次,不可多次綁定) --> onUnbind --> onDestory。
在Service每一次的開啟關(guān)閉過程中,只有onStart可被多次調(diào)用(通過多次startService調(diào)用),其他onCreate,onBind,onUnbind,onDestory在一個(gè)生命周期中只能被調(diào)用一次。
三、bindService生命周期
像一個(gè)activity那樣,一個(gè)service有些可以用來改變狀態(tài)的生命周期方法,但是比activity的方法少,service生命周期方法只有三個(gè)public
? void onCreate()
? void onStart(Intent intent)
? void onDestroy()
通過實(shí)現(xiàn)這三個(gè)生命周期方法,你可以監(jiān)聽service的兩個(gè)嵌套循環(huán)的生命周期:
1、整個(gè)生命周期
service的整個(gè)生命周期是在onCreate()和onDestroy()方法之間。和activity一樣,在onCreate()方法里初始化,在onDestroy()方法里釋放資源。例如,一個(gè)背景音樂播放服務(wù)可以在onCreate()方法里播放,在onDestroy()方法里停止。
2、活動(dòng)的生命周期
service的活動(dòng)生命周期是在onStart()之后,這個(gè)方法會(huì)處理通過startServices()方法傳遞來的Intent對象。音樂service可以通過開打intent對象來找到要播放的音樂,然后開始后臺(tái)播放。注: service停止時(shí)沒有相應(yīng)的回調(diào)方法,即沒有onStop()方法,只有onDestroy()銷毀方法。
onCreate()方法和onDestroy()方法是針對所有的services,無論它們是否啟動(dòng),通過Context.startService()和Context.bindService()方法都可以訪問執(zhí)行。然而,只有通過startService()方法啟動(dòng)service服務(wù)時(shí)才會(huì)調(diào)用onStart()方法。
?
如果一個(gè)service允許別人綁定,那么需要實(shí)現(xiàn)以下額外的方法:
????? IBinder onBind(Intent intent)
????? boolean onUnbind(Intent intent)
????? void onRebind(Intent intent)
onBind()回調(diào)方法會(huì)繼續(xù)傳遞通過bindService()傳遞來的intent對象
onUnbind()會(huì)處理傳遞給unbindService()的intent對象。如果service允許綁定,onBind()會(huì)返回客戶端與服務(wù)互相聯(lián)系的通信句柄(實(shí)例)。
如果建立了一個(gè)新的客戶端與服務(wù)的連接,onUnbind()方法可以請求調(diào)用onRebind()方法。
記住:?任何服務(wù)無論它怎樣建立,默認(rèn)客戶端都可以連接,所以任何service都能夠接收onBind()和onUnbind()方法
四、bindService和startservice示例
(1)mainactivity
public class MainActivity extends Activity {Button startServiceButton;// 啟動(dòng)服務(wù)按鈕Button shutDownServiceButton;// 關(guān)閉服務(wù)按鈕Button startBindServiceButton;// 啟動(dòng)綁定服務(wù)按鈕 @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);getWidget();regiestListener();}/** 獲得組件 */public void getWidget() {startServiceButton = (Button) findViewById(R.id.startServerButton);startBindServiceButton = (Button) findViewById(R.id.startBindServerButton);shutDownServiceButton = (Button) findViewById(R.id.sutdownServerButton);}/** 為按鈕添加監(jiān)聽 */public void regiestListener() {startServiceButton.setOnClickListener(startService);shutDownServiceButton.setOnClickListener(shutdownService);startBindServiceButton.setOnClickListener(startBinderService);}/** 啟動(dòng)服務(wù)的事件監(jiān)聽 */public Button.OnClickListener startService = new Button.OnClickListener() {public void onClick(View view) {/** 單擊按鈕時(shí)啟動(dòng)服務(wù) */Intent intent = new Intent(MainActivity.this,CountService.class);startService(intent);Log.v("MainStadyServics", "start Service");}};/** 關(guān)閉服務(wù) */public Button.OnClickListener shutdownService = new Button.OnClickListener() {public void onClick(View view) {/** 單擊按鈕時(shí)啟動(dòng)服務(wù) */Intent intent = new Intent(MainActivity.this,CountService.class);/** 退出Activity是,停止服務(wù) */stopService(intent);Log.v("MainStadyServics", "shutDown serveice");}};/** 打開綁定服務(wù)的Activity */public Button.OnClickListener startBinderService = new Button.OnClickListener() {public void onClick(View view) {/** 單擊按鈕時(shí)啟動(dòng)服務(wù) */Intent intent = new Intent(MainActivity.this, UseBrider.class);startActivity(intent);Log.v("MainStadyServics", "start Binder Service");}};@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu);return true;}(2)service
package com.example.testservice;/**引入包*/ import android.app.Service;// 服務(wù)的類 import android.os.IBinder; import android.os.Binder; import android.content.Intent; import android.util.Log;/** 計(jì)數(shù)的服務(wù) */ public class CountService extends Service {/** 創(chuàng)建參數(shù) */boolean threadDisable;int count;public IBinder onBind(Intent intent) {return null;}public void onCreate() {super.onCreate();/** 創(chuàng)建一個(gè)線程,每秒計(jì)數(shù)器加一,并在控制臺(tái)進(jìn)行Log輸出 */new Thread(new Runnable() {public void run() {while (!threadDisable) {try {Thread.sleep(1000);} catch (InterruptedException e) {}count++;Log.v("CountService", "Count is" + count);}}}).start();}public void onDestroy() {super.onDestroy();/** 服務(wù)停止時(shí),終止計(jì)數(shù)進(jìn)程 */this.threadDisable = true;}public int getConunt() {return count;}//此方法是為了可以在Acitity中獲得服務(wù)的實(shí)例?? class ServiceBinder extends Binder {public CountService getService() {return CountService.this;}} }(3)bindservice(一定要記著這個(gè)是要獲得,鏈接的對象)
package com.example.testservice;/**引入包*/ import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.util.Log;/** 通過bindService和unBindSerivce的方式啟動(dòng)和結(jié)束服務(wù) */ public class UseBrider extends Activity {/** 參數(shù)設(shè)置 */CountService countService;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(new UseBriderFace(this));Intent intent = new Intent(UseBrider.this, CountService.class);/** 進(jìn)入Activity開始服務(wù) */bindService(intent, conn, Context.BIND_AUTO_CREATE);}private ServiceConnection conn = new ServiceConnection() {/** 獲取服務(wù)對象時(shí)的操作 */public void onServiceConnected(ComponentName name, IBinder service) {// TODO Auto-generated method stubcountService = ((CountService.ServiceBinder) service).getService();}/** 無法獲取到服務(wù)對象時(shí)的操作 */public void onServiceDisconnected(ComponentName name) {// TODO Auto-generated method stubcountService = null;}};protected void onDestroy() {super.onDestroy();this.unbindService(conn);Log.v("MainStadyServics", "out");} }注意:這個(gè)地方有朋友可能會(huì)出現(xiàn)onServiceConnected不調(diào)用的情況。
這個(gè)問題當(dāng)調(diào)用bindService方法后就會(huì)回調(diào)Activity的onServiceConnected,在這個(gè)方法中會(huì)向Activity中傳遞一個(gè)IBinder的實(shí)例,Acitity需要保存這個(gè)實(shí)例
在Service中需要?jiǎng)?chuàng)建一個(gè)實(shí)現(xiàn)IBinder的內(nèi)部類(這個(gè)內(nèi)部類不一定在Service中實(shí)現(xiàn),但必須在Service中創(chuàng)建它)。
在OnBind()方法中需返回一個(gè)IBinder實(shí)例,不然onServiceConnected方法不會(huì)調(diào)用。
不過,我在這里傳遞null也能夠調(diào)用,大家根據(jù)情況進(jìn)行判定吧,如果是返回一個(gè)ibinder實(shí)例的話,示例代碼如下:
public IBinder onBind(Intent intent) {// TODO Auto-generated method stubSystem.out.println("onBind.....");IBinder result = null; if ( null == result ) result = new MyBinder() ;Toast.makeText(this, "onBind",Toast.LENGTH_LONG);return result;}?
?
至于startservice和bindservice的使用場景,有網(wǎng)友這么說:
1.通過startservice開啟的服務(wù).一旦服務(wù)開啟, 這個(gè)服務(wù)和開啟他的調(diào)用者之間就沒有任何的關(guān)系了.?
調(diào)用者不可以訪問 service里面的方法. 調(diào)用者如果被系統(tǒng)回收了或者調(diào)用了ondestroy方法, service還會(huì)繼續(xù)存在??
2.通過bindService開啟的服務(wù),服務(wù)開啟之后,調(diào)用者和服務(wù)之間 還存在著聯(lián)系 ,?
一旦調(diào)用者掛掉了.service也會(huì)跟著掛掉 .
?
示例下載地址:http://pan.baidu.com/share/link?shareid=1614272126&uk=1428765741
還有一個(gè)多樣化的demo學(xué)習(xí)地址:http://pan.baidu.com/share/link?shareid=1616100229&uk=1428765741
?
部分內(nèi)容來源于互聯(lián)網(wǎng),感謝作者的無私提供
原文地址:http://www.cnblogs.com/yejiurui/p/3429451.html
總結(jié)
以上是生活随笔為你收集整理的深入理解Android的startservice和bindservice的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android实战技术:深入理解Andr
- 下一篇: 使用Android Studio打And