Android服務(wù)Service詳解電子版本_第1頁(yè)
Android服務(wù)Service詳解電子版本_第2頁(yè)
Android服務(wù)Service詳解電子版本_第3頁(yè)
Android服務(wù)Service詳解電子版本_第4頁(yè)
Android服務(wù)Service詳解電子版本_第5頁(yè)
已閱讀5頁(yè),還剩132頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、Good is good, but better carries it.精益求精,善益求善。Android服務(wù)Service詳解-第8章Android服務(wù)HYPERLINK/art/201006/206884.htmo8.1Service起步t_blank8.1Service起步HYPERLINK/art/201006/206885.htmo8.1.1Service的生命周期t_blank8.1.1Service的生命周期HYPERLINK/art/201006/206886.htmo8.1.2綁定Activity和Servicet_blank8.1.2綁定Activity和ServiceHY

2、PERLINK/art/201006/206887.htmo8.1.3在BroadcastReceiver中啟動(dòng)Servicet_blank8.1.3在BroadcastReceiver中啟動(dòng)Ser.HYPERLINK/art/201006/206889.htmo8.2.1獲得系統(tǒng)服務(wù)t_blank8.2.1獲得系統(tǒng)服務(wù)HYPERLINK/art/201006/206891.htmo8.2.2在模擬器上模擬重力感應(yīng)t_blank8.2.2在模擬器上模擬重力感應(yīng)HYPERLINK/art/201006/206892.htmo8.3.1計(jì)時(shí)器:Chronometert_blank8.3.1計(jì)時(shí)器:

3、ChronometerHYPERLINK/art/201006/207064.htmo8.3.2預(yù)約時(shí)間Handlert_blank8.3.2預(yù)約時(shí)間HandlerHYPERLINK/art/201006/207065.htmo8.3.4在線程中更新GUI組件t_blank8.3.4在線程中更新GUI組件HYPERLINK/art/201006/207066.htmo8.3.5全局定時(shí)器AlarmManager(1)t_blank8.3.5全局定時(shí)器AlarmManager(1)HYPERLINK/art/201006/207067.htmo8.3.5全局定時(shí)器AlarmManager(2)t

4、_blank8.3.5全局定時(shí)器AlarmManager(2)HYPERLINK/art/201006/207068.htmo8.3.5全局定時(shí)器AlarmManager(3)t_blank8.3.5全局定時(shí)器AlarmManager(3)HYPERLINK/art/201006/207069.htmo8.4.1什么是AIDL服務(wù)t_blank8.4.1什么是AIDL服務(wù)HYPERLINK/art/201006/207070.htmo8.4.2建立AIDL服務(wù)的步驟(1)t_blank8.4.2建立AIDL服務(wù)的步驟(1)HYPERLINK/art/201006/207071.htmo8.4.

5、2建立AIDL服務(wù)的步驟(2)t_blank8.4.2建立AIDL服務(wù)的步驟(2)HYPERLINK/art/201006/207072.htmo8.4.2建立AIDL服務(wù)的步驟(3)t_blank8.4.2建立AIDL服務(wù)的步驟(3)HYPERLINK/art/201006/207073.htmo8.5本章小結(jié)t_blank8.5本章小結(jié)第8章Android服務(wù)服務(wù)(Service)是Android系統(tǒng)中4個(gè)應(yīng)用程序組件之一(其他的組件詳見3.2節(jié)的內(nèi)容)。服務(wù)主要用于兩個(gè)目的:后臺(tái)運(yùn)行和跨進(jìn)程訪問(wèn)。通過(guò)啟動(dòng)一個(gè)服務(wù),可以在不顯示界面的前提下在后臺(tái)運(yùn)行指定的任務(wù),這樣可以不影響用戶做其他事情

6、。通過(guò)AIDL服務(wù)可以實(shí)現(xiàn)不同進(jìn)程之間的通信,這也是服務(wù)的重要用途之一。本章內(nèi)容Service的生命周期綁定Activity和Service在BroadcastReceiver中啟動(dòng)Service系統(tǒng)服務(wù)時(shí)間服務(wù)在線程中更新GUI組件AIDL服務(wù)在AIDL服務(wù)中傳遞復(fù)雜的數(shù)據(jù)8.1Service起步Service并沒有實(shí)際界面,而是一直在Android系統(tǒng)的后臺(tái)運(yùn)行。一般使用Service為應(yīng)用程序提供一些服務(wù),或不需要界面的功能,例如,從Internet下載文件、控制Video播放器等。本節(jié)主要介紹Service的啟動(dòng)和結(jié)束過(guò)程(Service的生命周期)以及啟動(dòng)Service的各種方法。8

7、.1.1Service的生命周期本節(jié)的例子代碼所在的工程目錄是srcch08ch08_servicelifecycleService與Activity一樣,也有一個(gè)從啟動(dòng)到銷毀的過(guò)程,但Service的這個(gè)過(guò)程比Activity簡(jiǎn)單得多。Service啟動(dòng)到銷毀的過(guò)程只會(huì)經(jīng)歷如下3個(gè)階段:創(chuàng)建服務(wù)開始服務(wù)銷毀服務(wù)一個(gè)服務(wù)實(shí)際上是一個(gè)繼承android.app.Service的類,當(dāng)服務(wù)經(jīng)歷上面3個(gè)階段后,會(huì)分別調(diào)用Service類中的3個(gè)事件方法進(jìn)行交互,這3個(gè)事件方法如下:publicvoidonCreate();/創(chuàng)建服務(wù)publicvoidonStart(Intentintent,int

8、startId);/開始服務(wù)publicvoidonDestroy();/銷毀服務(wù)一個(gè)服務(wù)只會(huì)創(chuàng)建一次,銷毀一次,但可以開始多次,因此,onCreate和onDestroy方法只會(huì)被調(diào)用一次,而onStart方法會(huì)被調(diào)用多次。下面編寫一個(gè)服務(wù)類,具體看一下服務(wù)的生命周期由開始到銷毀的過(guò)程。packagenet.blogjava.mobile.service;importandroid.app.Service;importandroid.content.Intent;importandroid.os.IBinder;importandroid.util.Log;/MyService是一個(gè)服務(wù)類,

9、該類必須從android.app.Service類繼承publicclassMyServiceextendsServiceOverridepublicIBinderonBind(Intentintent)returnnull;/當(dāng)服務(wù)第1次創(chuàng)建時(shí)調(diào)用該方法OverridepublicvoidonCreate()Log.d(MyService,onCreate);super.onCreate();/當(dāng)服務(wù)銷毀時(shí)調(diào)用該方法OverridepublicvoidonDestroy()Log.d(MyService,onDestroy);super.onDestroy();/當(dāng)開始服務(wù)時(shí)調(diào)用該方法Ove

10、rridepublicvoidonStart(Intentintent,intstartId)Log.d(MyService,onStart);super.onStart(intent,startId);在MyService中覆蓋了Service類中3個(gè)生命周期方法,并在這些方法中輸出了相應(yīng)的日志信息,以便更容易地觀察事件方法的調(diào)用情況。讀者在編寫Android的應(yīng)用組件時(shí)要注意,不管是編寫什么組件(例如,Activity、Service等),都需要在AndroidManifest.xml文件中進(jìn)行配置。MyService類也不例外。配置這個(gè)服務(wù)類很簡(jiǎn)單,只需要在AndroidManifest

11、.xml文件的標(biāo)簽中添加如下代碼即可:其中android:enabled屬性的值為true,表示MyService服務(wù)處于激活狀態(tài)。雖然目前MyService是激活的,但系統(tǒng)仍然不會(huì)啟動(dòng)MyService,要想啟動(dòng)這個(gè)服務(wù)。必須顯式地調(diào)用startService方法。如果想停止服務(wù),需要顯式地調(diào)用stopService方法,代碼如下:publicvoidonClick(Viewview)switch(view.getId()caseR.id.btnStartService:startService(serviceIntent);/單擊【StartService】按鈕啟動(dòng)服務(wù)break;case

12、R.id.btnStopService:stopService(serviceIntent);/單擊【StopService】按鈕停止服務(wù)break;其中serviceIntent是一個(gè)Intent對(duì)象,用于指定MyService服務(wù),創(chuàng)建該對(duì)象的代碼如下:serviceIntent=newIntent(this,MyService.class);運(yùn)行本節(jié)的例子后,會(huì)顯示如圖8.1所示的界面。HYPERLINK/files/uploadimg/20060921/153223104.gift_blank圖8.1開始和停止服務(wù)第1次單擊【StartService】按鈕后,在DDMS透視圖的LogC

13、at視圖的Message列會(huì)輸出如下兩行信息:onCreateonStart然后單擊【StopService】按鈕,會(huì)在Message列中輸出如下信息:onDestroy下面按如下的單擊按鈕順序的重新測(cè)試一下本例?!維tartService】【StopService】【StartService】【StartService】【StartService】【StopService】測(cè)試完程序,就會(huì)看到如圖8.2所示的輸出信息??梢钥闯?,只在第1次單擊【StartService】按鈕后會(huì)調(diào)用onCreate方法,如果在未單擊【StopService】按鈕時(shí)多次單擊【StartService】按鈕,系統(tǒng)

14、只在第1次單擊【StartService】按鈕時(shí)調(diào)用onCreate和onStart方法,再單擊該按鈕時(shí),系統(tǒng)只會(huì)調(diào)用onStart方法,而不會(huì)再次調(diào)用onCreate方法。HYPERLINK/files/uploadimg/20100621/171557332.jpgt_blankHYPERLINK/files/uploadimg/20060921/153223104.gift_blank圖8.2服務(wù)的生命周期方法的調(diào)用情況在討論完服務(wù)的生命周期后,再來(lái)總結(jié)一下創(chuàng)建和開始服務(wù)的步驟。創(chuàng)建和開始一個(gè)服務(wù)需要如下3步:(1)編寫一個(gè)服務(wù)類,該類必須從android.app.Service繼承。S

15、ervice類涉及到3個(gè)生命周期方法,但這3個(gè)方法并不一定在子類中覆蓋,讀者可根據(jù)不同需求來(lái)決定使用哪些生命周期方法。在Service類中有一個(gè)onBind方法,該方法是一個(gè)抽象方法,在Service的子類中必須覆蓋。這個(gè)方法當(dāng)Activity與Service綁定時(shí)被調(diào)用(將在8.1.3節(jié)詳細(xì)介紹)。(2)在AndroidManifest.xml文件中使用標(biāo)簽來(lái)配置服務(wù),一般需要將標(biāo)簽的android:enabled屬性值設(shè)為true,并使用android:name屬性指定在第1步建立的服務(wù)類名。(3)如果要開始一個(gè)服務(wù),使用startService方法,停止一個(gè)服務(wù)要使用stopServic

16、e方法。8.1.2綁定Activity和Service本節(jié)的例子代碼所在的工程目錄是srcch08ch08_serviceactivity如果使用8.1.1節(jié)介紹的方法啟動(dòng)服務(wù),并且未調(diào)用stopService來(lái)停止服務(wù),這個(gè)服務(wù)就會(huì)隨著Android系統(tǒng)的啟動(dòng)而啟動(dòng),隨著Android系統(tǒng)的關(guān)閉而關(guān)閉。也就是服務(wù)會(huì)在Android系統(tǒng)啟動(dòng)后一直在后臺(tái)運(yùn)行,直到Android系統(tǒng)關(guān)閉后服務(wù)才停止。但有時(shí)我們希望在啟動(dòng)服務(wù)的Activity關(guān)閉后服務(wù)自動(dòng)關(guān)閉,這就需要將Activity和Service綁定。通過(guò)bindService方法可以將Activity和Service綁定。bindServ

17、ice方法的定義如下:publicbooleanbindService(Intentservice,ServiceConnectionconn,intflags)該方法的第1個(gè)參數(shù)表示與服務(wù)類相關(guān)聯(lián)的Intent對(duì)象,第2個(gè)參數(shù)是一個(gè)ServiceConnection類型的變量,負(fù)責(zé)連接Intent對(duì)象指定的服務(wù)。通過(guò)ServiceConnection對(duì)象可以獲得連接成功或失敗的狀態(tài),并可以獲得連接后的服務(wù)對(duì)象。第3個(gè)參數(shù)是一個(gè)標(biāo)志位,一般設(shè)為Context.BIND_AUTO_CREATE。下面重新編寫8.1.1節(jié)的MyService類,在該類中增加了幾個(gè)與綁定相關(guān)的事件方法。package

18、net.blogjava.mobile.service;importandroid.app.Service;importandroid.content.Intent;importandroid.os.Binder;importandroid.os.IBinder;importandroid.util.Log;publicclassMyServiceextendsServiceprivateMyBindermyBinder=newMyBinder();/成功綁定后調(diào)用該方法OverridepublicIBinderonBind(Intentintent)Log.d(MyService,onBin

19、d);returnmyBinder;/重新綁定時(shí)調(diào)用該方法OverridepublicvoidonRebind(Intentintent)Log.d(MyService,onRebind);super.onRebind(intent);/解除綁定時(shí)調(diào)用該方法OverridepublicbooleanonUnbind(Intentintent)Log.d(MyService,onUnbind);returnsuper.onUnbind(intent);OverridepublicvoidonCreate()Log.d(MyService,onCreate);super.onCreate();Ov

20、erridepublicvoidonDestroy()Log.d(MyService,onDestroy);super.onDestroy();OverridepublicvoidonStart(Intentintent,intstartId)Log.d(MyService,onStart);super.onStart(intent,startId);publicclassMyBinderextendsBinderMyServicegetService()returnMyService.this;現(xiàn)在定義一個(gè)MyService變量和一個(gè)ServiceConnection變量,代碼如下:priv

21、ateMyServicemyService;privateServiceConnectionserviceConnection=newServiceConnection()/連接服務(wù)失敗后,該方法被調(diào)用OverridepublicvoidonServiceDisconnected(ComponentNamename)myService=null;Toast.makeText(Main.this,ServiceFailed.,Toast.LENGTH_LONG).show();/成功連接服務(wù)后,該方法被調(diào)用。在該方法中可以獲得MyService對(duì)象OverridepublicvoidonServ

22、iceConnected(ComponentNamename,IBinderservice)/獲得MyService對(duì)象myService=(MyService.MyBinder)service).getService();Toast.makeText(Main.this,ServiceConnected.,Toast.LENGTH_LONG).show();最后使用bindService方法來(lái)綁定Activity和Service,代碼如下:bindService(serviceIntent,serviceConnection,Context.BIND_AUTO_CREATE);如果想解除綁定

23、,可以使用下面的代碼:unbindService(serviceConnection);在MyService類中定義了一個(gè)MyBinder類,該類實(shí)際上是為了獲得MyService的對(duì)象實(shí)例的。在ServiceConnection接口的onServiceConnected方法中的第2個(gè)參數(shù)是一個(gè)IBinder類型的變量,將該參數(shù)轉(zhuǎn)換成MyService.MyBinder對(duì)象,并使用MyBinder類中的getService方法獲得MyService對(duì)象。在獲得MyService對(duì)象后,就可以在Activity中隨意操作MyService了。運(yùn)行本節(jié)的例子后,單擊【BindService】按鈕,

24、如果綁定成功,會(huì)顯示如圖8.3所示的信息提示框。關(guān)閉應(yīng)用程序后,會(huì)看到在LogCat視圖中輸出了onUnbind和onDestroy信息,表明在關(guān)閉Activity后,服務(wù)先被解除綁定,最后被銷毀。如果先啟動(dòng)(調(diào)用startService方法)一個(gè)服務(wù),然后再綁定(調(diào)用bindService方法)服務(wù),會(huì)怎么樣呢?在這種情況下,雖然服務(wù)仍然會(huì)成功綁定到Activity上,但在Activity關(guān)閉后,服務(wù)雖然會(huì)被解除綁定,但并不會(huì)被銷毀,也就是說(shuō),MyService類的onDestroy方法不會(huì)被調(diào)用。HYPERLINK/files/uploadimg/20060921/153223104.gi

25、ft_blank圖8.3綁定服務(wù)8.1.3在BroadcastReceiver中啟動(dòng)Service本節(jié)的例子代碼所在的工程目錄是srcch08ch08_startupservice在8.1.1節(jié)和8.1.2節(jié)都是先啟動(dòng)了一個(gè)Activity,然后在Activity中啟動(dòng)服務(wù)。如果是這樣,在啟動(dòng)服務(wù)時(shí)必須要先啟動(dòng)一個(gè)Activity。在很多時(shí)候這樣做有些多余,閱讀完第7章的內(nèi)容,會(huì)發(fā)現(xiàn)實(shí)例43可以利用BroadcastReceiver在Android系統(tǒng)啟動(dòng)時(shí)運(yùn)行一個(gè)Activity。也許我們會(huì)從中得到一些啟發(fā),既然可以在BroadcastReceiver中啟動(dòng)Activity,為什么不能啟動(dòng)S

26、ervice呢?說(shuō)做就做,現(xiàn)在讓我們來(lái)驗(yàn)證一下這個(gè)想法。先編寫一個(gè)服務(wù)類,這個(gè)服務(wù)類沒什么特別的,仍然使用前面兩節(jié)編寫的MyService類即可。在AndroidManifest.xml文件中配置MyService類的代碼也相同。下面來(lái)完成最關(guān)鍵的一步,就是建立一個(gè)BroadcastReceiver,代碼如下:packagenet.blogjava.mobile.startupservice;importandroid.content.BroadcastReceiver;importandroid.content.Context;importandroid.content.Intent;pub

27、licclassStartupReceiverextendsBroadcastReceiverOverridepublicvoidonReceive(Contextcontext,Intentintent)/啟動(dòng)一個(gè)ServiceIntentserviceIntent=newIntent(context,MyService.class);context.startService(serviceIntent);IntentactivityIntent=newIntent(context,MessageActivity.class);/要想在Service中啟動(dòng)Activity,必須設(shè)置如下標(biāo)志a

28、ctivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);context.startActivity(activityIntent);在StartupReceiver類的onReceive方法中完成了兩項(xiàng)工作:?jiǎn)?dòng)服務(wù)和顯示一個(gè)Activity來(lái)提示服務(wù)啟動(dòng)成功。其中MessageActivity是一個(gè)普通的Activity類,只是該類在配置時(shí)使用了android:style/Theme.Dialog主題,因此,如果服務(wù)啟動(dòng)成功,會(huì)顯示如圖8.4所示的信息。HYPERLINK/files/uploadimg/20100621/1703220.j

29、pgt_blankHYPERLINK/files/uploadimg/20060921/153223104.gift_blank圖8.4在BroadcastReceiver中啟動(dòng)服務(wù)如果安裝本例后,在重新啟動(dòng)模擬器后并未出現(xiàn)如圖8.4所示的信息提示框,最大的可能是沒有在AndroidManifest.xml文件中配置BroadcastReceiver和Service,下面來(lái)看一下AndroidManifest.xml文件的完整代碼。現(xiàn)在運(yùn)行本例,然后重啟一下模擬器,看看LogCat視圖中是否輸出了相應(yīng)的日志信息。8.2系統(tǒng)服務(wù)在Android系統(tǒng)中有很多內(nèi)置的軟件,例如,當(dāng)手機(jī)接到來(lái)電時(shí),會(huì)顯

30、示對(duì)方的電話號(hào)。也可以根據(jù)周圍的環(huán)境將手機(jī)設(shè)置成震動(dòng)或靜音。如果想把這些功能加到自己的軟件中應(yīng)該怎么辦呢?答案就是系統(tǒng)服務(wù)。在Android系統(tǒng)中提供了很多這種服務(wù),通過(guò)這些服務(wù),就可以像Android系統(tǒng)的內(nèi)置軟件一樣隨心所欲地控制Android系統(tǒng)了。本節(jié)將介紹幾種常用的系統(tǒng)服務(wù)來(lái)幫助讀者理解和使用這些技術(shù)。8.2.1獲得系統(tǒng)服務(wù)系統(tǒng)服務(wù)實(shí)際上可以看作是一個(gè)對(duì)象,通過(guò)Activity類的getSystemService方法可以獲得指定的對(duì)象(系統(tǒng)服務(wù))。getSystemService方法只有一個(gè)String類型的參數(shù),表示系統(tǒng)服務(wù)的ID,這個(gè)ID在整個(gè)Android系統(tǒng)中是唯一的。例如,

31、audio表示音頻服務(wù),window表示窗口服務(wù),notification表示通知服務(wù)。為了便于記憶和管理,AndroidSDK在android.content.Context類中定義了這些ID,例如,下面的代碼是一些ID的定義。publicstaticfinalStringAUDIO_SERVICE=audio;/定義音頻服務(wù)的IDpublicstaticfinalStringWINDOW_SERVICE=window;/定義窗口服務(wù)的IDpublicstaticfinalStringNOTIFICATION_SERVICE=notification;/定義通知服務(wù)的ID下面的代碼獲得了剪貼

32、板服務(wù)(android.text.ClipboardManager對(duì)象)。/獲得ClipboardManager對(duì)象android.text.ClipboardManagerclipboardManager=(android.text.ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE);clipboardManager.setText(設(shè)置剪貼版中的內(nèi)容);在調(diào)用ClipboardManager.setText方法設(shè)置文本后,在Android系統(tǒng)中所有的文本輸入框都可以從這個(gè)剪貼板對(duì)象中獲得這段文本,讀者不妨自己試一試!窗口

33、服務(wù)(WindowManager對(duì)象)是最常用的系統(tǒng)服務(wù)之一,通過(guò)這個(gè)服務(wù),可以獲得很多與窗口相關(guān)的信息,例如,窗口的長(zhǎng)度和寬度,如下面的代碼所示:/獲得WindowManager對(duì)象android.view.WindowManagerwindowManager=(android.view.WindowManager)getSystemService(Context.WINDOW_SERVICE);/在窗口的標(biāo)題欄輸出當(dāng)前窗口的寬度和高度,例如,320*480setTitle(String.valueOf(windowManager.getDefaultDisplay().getWidth()

34、+*+String.valueOf(windowManager.getDefaultDisplay().getHeight();本節(jié)簡(jiǎn)單介紹了如何獲得系統(tǒng)服務(wù)以及兩個(gè)常用的系統(tǒng)服務(wù)的使用方法,在接下來(lái)的實(shí)例47和實(shí)例48中將給出兩個(gè)完整的關(guān)于獲得和使用系統(tǒng)服務(wù)的例子以供讀者參考。實(shí)例47:監(jiān)聽手機(jī)來(lái)電工程目錄:srcch08ch08_phonestate當(dāng)來(lái)電話時(shí),手機(jī)會(huì)顯示對(duì)方的電話號(hào),當(dāng)接聽電話時(shí),會(huì)顯示當(dāng)前的通話狀態(tài)。在這期間存在兩個(gè)狀態(tài):來(lái)電狀態(tài)和接聽狀態(tài)。如果在應(yīng)用程序中要監(jiān)聽這兩個(gè)狀態(tài),并進(jìn)行一些其他處理,就需要使用電話服務(wù)(TelephonyManager對(duì)象)。本例通過(guò)Tele

35、phonyManager對(duì)象監(jiān)聽來(lái)電狀態(tài)和接聽狀態(tài),并在相應(yīng)的狀態(tài)顯示一個(gè)Toast提示信息框。如果是來(lái)電狀態(tài),會(huì)顯示對(duì)方的電話號(hào),如果是通話狀態(tài),會(huì)顯示正在通話.信息。下面先來(lái)看看來(lái)電和接聽時(shí)的效果,如圖8.5和圖8.6所示。HYPERLINK/files/uploadimg/20060921/153223104.gift_blank圖8.5來(lái)電狀態(tài)HYPERLINK/files/uploadimg/20060921/153223104.gift_blank圖8.6接聽狀態(tài)要想獲得TelephonyManager對(duì)象,需要使用Context.TELEPHONY_SERVICE常量,代碼如下:

36、TelephonyManagertm=(TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);MyPhoneCallListenermyPhoneCallListener=newMyPhoneCallListener();/設(shè)置電話狀態(tài)監(jiān)聽器tm.listen(myPhoneCallListener,PhoneStateListener.LISTEN_CALL_STATE);其中MyPhoneCallListener類是一個(gè)電話狀態(tài)監(jiān)聽器,該類是PhoneStateListener的子類,代碼如下:publicclassMyP

37、honeCallListenerextendsPhoneStateListenerOverridepublicvoidonCallStateChanged(intstate,StringincomingNumber)switch(state)/通話狀態(tài)caseTelephonyManager.CALL_STATE_OFFHOOK:Toast.makeText(Main.this,正在通話.,Toast.LENGTH_SHORT).show();break;/來(lái)電狀態(tài)caseTelephonyManager.CALL_STATE_RINGING:Toast.makeText(Main.this,

38、incomingNumber,Toast.LENGTH_SHORT).show();break;super.onCallStateChanged(state,incomingNumber);如果讀者是在模擬器上測(cè)試本例,可以使用DDMS透視圖的【EmulatorControl】視圖模擬打入電話。進(jìn)入【EmulatorControl】視圖,會(huì)看到如圖8.7所示的界面。在【Incomingnumber】文本框中輸入一個(gè)電話號(hào),選中【Voice】選項(xiàng),單擊【Call】按鈕,這時(shí)模擬器就會(huì)接到來(lái)電。如果已經(jīng)運(yùn)行本例,在來(lái)電和接聽狀態(tài)就會(huì)顯示如圖8.5和圖8.6所示的Toast提示信息。HYPERLIN

39、K/files/uploadimg/20100622/125002633.jpgt_blankHYPERLINK/files/uploadimg/20060921/153223104.gift_blank圖8.7用【EmulatorControl】視圖模擬撥打電話實(shí)例48:來(lái)電黑名單工程目錄:srcch08ch08_phoneblacklist雖然手機(jī)為我們帶來(lái)了方便,但有時(shí)實(shí)在不想接聽某人的電話,但又不好直接掛斷電話,怎么辦呢?很簡(jiǎn)單,如果發(fā)現(xiàn)是某人來(lái)的電話,直接將手機(jī)設(shè)成靜音,這樣就可以不予理睬了。本例與實(shí)例47類似,也就是說(shuō),仍然需要獲得TelephonyManager對(duì)象,并監(jiān)聽手機(jī)的

40、來(lái)電狀態(tài)。為了可以將手機(jī)靜音,還需要獲得一個(gè)音頻服務(wù)(AudioManager對(duì)象)。本例需要修改實(shí)例47中的手機(jī)接聽狀態(tài)方法onCallStateChanged中的代碼,修改后的結(jié)果如下:publicclassMyPhoneCallListenerextendsPhoneStateListenerOverridepublicvoidonCallStateChanged(intstate,StringincomingNumber)/獲得音頻服務(wù)(AudioManager對(duì)象)AudioManageraudioManager=(AudioManager)getSystemService(Cont

41、ext.AUDIO_SERVICE);switch(state)caseTelephonyManager.CALL_STATE_IDLE:/在手機(jī)空閑狀態(tài)時(shí),將手機(jī)音頻設(shè)為正常狀態(tài)audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);break;caseTelephonyManager.CALL_STATE_RINGING:/在來(lái)電狀態(tài)時(shí),判斷打進(jìn)來(lái)的是否為要靜音的電話號(hào),如果是,則靜音if(12345678.equals(incomingNumber)/將電話靜音audioManager.setRingerMode(Audio

42、Manager.RINGER_MODE_SILENT);break;super.onCallStateChanged(state,incomingNumber);在上面的代碼中,只設(shè)置了12345678為靜音電話號(hào),讀者可以采用實(shí)例47的方法使用12345678打入電話,再使用其他的電話號(hào)打入,看看模擬器是否會(huì)響鈴。8.2.2在模擬器上模擬重力感應(yīng)眾所周知,Android系統(tǒng)支持重力感應(yīng),通過(guò)這種技術(shù),可以利用手機(jī)的移動(dòng)、翻轉(zhuǎn)來(lái)實(shí)現(xiàn)更為有趣的程序。但遺憾的是,在Android模擬器上是無(wú)法進(jìn)行重力感應(yīng)測(cè)試的。既然Android系統(tǒng)支持重力感應(yīng),但又在模擬器上無(wú)法測(cè)試,該怎么辦呢?別著急,天無(wú)絕

43、人之路,有一些第三方的工具可以幫助我們完成這個(gè)工作,本節(jié)將介紹一種在模擬器上模擬重力感應(yīng)的工具(sensorsimulator)。這個(gè)工具分為服務(wù)端和客戶端兩部分。服務(wù)端是一個(gè)在PC上運(yùn)行的JavaSwingGUI程序,客戶端是一個(gè)手機(jī)程序(apk文件),在運(yùn)行時(shí)需要通過(guò)客戶端程序連接到服務(wù)端程序上才可以在模擬器上模擬重力感應(yīng)。讀者可以從下面的地址下載這個(gè)工具:/p/openintents/downloads/list進(jìn)入下載頁(yè)面后,下載如圖8.8所示的黑框中的zip文件。HYPERLINK/files/uploadimg/20060921/153223104.gift_blank(點(diǎn)擊查看大

44、圖)圖8.8sensorsimulator下載頁(yè)面將zip文件解壓后,運(yùn)行bin目錄中的sensorsimulator.jar文件,會(huì)顯示如圖8.9所示的界面。界面的左上角是一個(gè)模擬手機(jī)位置的三維圖形,右上角可以通過(guò)滑桿來(lái)模擬手機(jī)的翻轉(zhuǎn)、移動(dòng)等操作。HYPERLINK/files/uploadimg/20060921/153223104.gift_blank(點(diǎn)擊查看大圖)圖8.9sensorsimulator主界面下面來(lái)安裝客戶端程序,先啟動(dòng)Android模擬器,然后使用下面的命令安裝bin目錄中的SensorSimulatorSettings.apk文件。adbinstallSensorS

45、imulatorSettings.apk如果安裝成功,會(huì)在模擬器中看到如圖8.10所示黑框中的圖標(biāo)。運(yùn)行這個(gè)程序,會(huì)進(jìn)入如圖8.11所示的界面。在IP地址中輸入如圖8.9所示黑框中的IP(注意,每次啟動(dòng)服務(wù)端程序時(shí)這個(gè)IP可能不一樣,應(yīng)以每次啟動(dòng)服務(wù)端程序時(shí)的IP為準(zhǔn))。最后進(jìn)入【Testing】頁(yè),單擊【Connect】按鈕,如果連接成功,會(huì)顯示如圖8.12所示的效果。HYPERLINK/files/uploadimg/20060921/153223104.gift_blank圖8.10安裝客戶端設(shè)置軟件HYPERLINK/files/uploadimg/20060921/153223104

46、.gift_blank圖8.11進(jìn)行客戶端設(shè)置下面來(lái)測(cè)試一下SensorSimulator自帶的一個(gè)demo,在這個(gè)demo中輸出了通過(guò)模擬重力感應(yīng)獲得的數(shù)據(jù)。這個(gè)demo就在samples目錄中,該目錄有一個(gè)SensorDemo子目錄,是一個(gè)Eclipse工程目錄。讀者可以直接使用Eclipse導(dǎo)入這個(gè)目錄,并運(yùn)行程序,如果顯示的結(jié)果如圖8.13所示,說(shuō)明成功使用SensorSimulator在Android模擬器上模擬了重力感應(yīng)。HYPERLINK/files/uploadimg/20060921/153223104.gift_blank圖8.12測(cè)試連接狀態(tài)HYPERLINK/files

47、/uploadimg/20060921/153223104.gift_blank圖8.13測(cè)試重力感應(yīng)demo在實(shí)例49中將給出一個(gè)完整的例子來(lái)演示如何利用重力感應(yīng)的功能來(lái)實(shí)現(xiàn)手機(jī)翻轉(zhuǎn)靜音的效果。實(shí)例49:手機(jī)翻轉(zhuǎn)靜音工程目錄:srcch08ch08_phonereversal與手機(jī)來(lái)電一樣,手機(jī)翻轉(zhuǎn)狀態(tài)(重力感應(yīng))也由系統(tǒng)服務(wù)提供。重力感應(yīng)服務(wù)(android.hardware.SensorManager對(duì)象)可以通過(guò)如下代碼獲得:SensorManagersensorManager=(SensorManager)getSystemService(Context.SENSOR_SERVICE

48、);本例需要在模擬器上模擬重力感應(yīng),因此,在本例中使用SensorSimulator中的一個(gè)類(SensorManagerSimulator)來(lái)獲得重力感應(yīng)服務(wù),這個(gè)類封裝了SensorManager對(duì)象,并負(fù)責(zé)與服務(wù)端進(jìn)行通信,監(jiān)聽重力感應(yīng)事件也需要一個(gè)監(jiān)聽器,該監(jiān)聽器需要實(shí)現(xiàn)SensorListener接口,并通過(guò)該接口的onSensorChanged事件方法獲得重力感應(yīng)數(shù)據(jù)。本例完整的代碼如下:packagenet.blogjava.mobile;importorg.openintents.sensorsimulator.hardware.SensorManagerSimulator;i

49、mportandroid.app.Activity;importandroid.content.Context;importandroid.hardware.SensorListener;importandroid.hardware.SensorManager;importandroid.media.AudioManager;importandroid.os.Bundle;importandroid.widget.TextView;publicclassMainextendsActivityimplementsSensorListenerprivateTextViewtvSensorState

50、;privateSensorManagerSimulatorsensorManager;OverridepublicvoidonAccuracyChanged(intsensor,intaccuracy)OverridepublicvoidonSensorChanged(intsensor,floatvalues)switch(sensor)caseSensorManager.SENSOR_ORIENTATION:/獲得聲音服務(wù)AudioManageraudioManager=(AudioManager)getSystemService(Context.AUDIO_SERVICE);/在這里規(guī)

51、定翻轉(zhuǎn)角度小于-120度時(shí)靜音,values2表示翻轉(zhuǎn)角度,也可以設(shè)置其他角度if(values2-120)audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);elseaudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);tvSensorState.setText(角度:+String.valueOf(values2);break;OverrideprotectedvoidonResume()/注冊(cè)重力感應(yīng)監(jiān)聽事件sensorManager.registerLi

52、stener(this,SensorManager.SENSOR_ORIENTATION);super.onResume();OverrideprotectedvoidonStop()/取消對(duì)重力感應(yīng)的監(jiān)聽sensorManager.unregisterListener(this);super.onStop();OverridepublicvoidonCreate(BundlesavedInstanceState)super.onCreate(savedInstanceState);setContentView(R.layout.main);/通過(guò)SensorManagerSimulator對(duì)

53、象獲得重力感應(yīng)服務(wù)sensorManager=(SensorManagerSimulator)SensorManagerSimulator.getSystemService(this,Context.SENSOR_SERVICE);/連接到服務(wù)端程序(必須執(zhí)行下面的代碼)sensorManager.connectSimulator();在上面的代碼中使用了一個(gè)SensorManagerSimulator類,該類在SensorSimulator工具包帶的sensorsimulator-lib.jar文件中,可以在lib目錄中找到這個(gè)jar文件。在使用SensorManagerSimulator類

54、之前,必須在相應(yīng)的Eclipse工程中引用這個(gè)jar文件?,F(xiàn)在運(yùn)行本例,并通過(guò)服務(wù)端主界面右側(cè)的【Roll】滑動(dòng)桿移動(dòng)到指定的角度,例如,-74.0和-142.0,這時(shí)設(shè)置的角度會(huì)顯示在屏幕上,如圖8.14和圖8.15所示。HYPERLINK/files/uploadimg/20100622/140139977.jpgt_blankHYPERLINK/files/uploadimg/20060921/153223104.gift_blank圖8.14翻轉(zhuǎn)角度大于-120度HYPERLINK/files/uploadimg/20100622/140139977.jpgt_blankHYPERLI

55、NK/files/uploadimg/20060921/153223104.gift_blank圖8.15翻轉(zhuǎn)角度小于-120度讀者可以在如圖8.14和圖8.15所示的翻轉(zhuǎn)狀態(tài)下?lián)苋腚娫?,?huì)發(fā)現(xiàn)翻轉(zhuǎn)角度在-74.0度時(shí)來(lái)電仍然會(huì)響鈴,而翻轉(zhuǎn)角度在-142.0度時(shí)就不再響鈴了。由于SensorSimulator目前不支持AndroidSDK1.5及以上版本,因此,只能使用AndroidSDK1.1中的SensorListener接口來(lái)監(jiān)聽重力感應(yīng)事件。在AndroidSDK1.5及以上版本并不建議繼續(xù)使用這個(gè)接口,代替它的是android.hardware.SensorEventListener

56、接口。8.3.1計(jì)時(shí)器:Chronometer8.3時(shí)間服務(wù)在AndroidSDK中提供了多種時(shí)間服務(wù)。這些時(shí)間服務(wù)主要處理在一定時(shí)間間隔或未來(lái)某一時(shí)間發(fā)生的任務(wù)。Android系統(tǒng)中的時(shí)間服務(wù)的作用域既可以是應(yīng)用程序本身,也可以是整個(gè)Android系統(tǒng)。本節(jié)將詳細(xì)介紹這些時(shí)間服務(wù)的使用方法,并給出大量的實(shí)例供讀者學(xué)習(xí)。8.3.1計(jì)時(shí)器:Chronometer本節(jié)的例子代碼所在的工程目錄是srcch08ch08_chronometerChronometer是TextView的子類,也是一個(gè)Android組件。這個(gè)組件可以用1秒的時(shí)間間隔進(jìn)行計(jì)時(shí),并顯示出計(jì)時(shí)結(jié)果。Chronometer類有3個(gè)

57、重要的方法:start、stop和setBase,其中start方法表示開始計(jì)時(shí);stop方法表示停止計(jì)時(shí);setBase方法表示重新計(jì)時(shí)。start和stop方法沒有任何參數(shù),setBase方法有一個(gè)參數(shù),表示開始計(jì)時(shí)的基準(zhǔn)時(shí)間。如果要從當(dāng)前時(shí)刻重新計(jì)時(shí),可以將該參數(shù)值設(shè)為SystemClock.elapsedRealtime()。還可以對(duì)Chronometer組件做進(jìn)一步設(shè)置。在默認(rèn)情況下,Chronometer組件只輸出MM:SS或H:MM:SS的時(shí)間格式。例如,當(dāng)計(jì)時(shí)到1分20秒時(shí),Chronometer組件會(huì)顯示01:20。如果想改變顯示的信息內(nèi)容,可以使用Chronometer類的

58、setFormat方法。該方法需要一個(gè)String變量,并使用%s表示計(jì)時(shí)信息。例如,使用setFormat(計(jì)時(shí)信息:%s)設(shè)置顯示信息,Chronometer組件會(huì)顯示如下計(jì)時(shí)信息:計(jì)時(shí)信息:10:20Chronometer組件還可以通過(guò)onChronometerTick事件方法來(lái)捕捉計(jì)時(shí)動(dòng)作。該方法1秒調(diào)用一次。要想使用onChronometerTick事件方法,必須實(shí)現(xiàn)如下接口:android.widget.Chronometer.OnChronometerTickListener在本例中有3個(gè)按鈕,分別用來(lái)開始、停止和重置計(jì)時(shí)器,并通過(guò)onChronometerTick事件方法顯示當(dāng)

59、前時(shí)間,代碼如下:packagenet.blogjava.mobile;importjava.text.SimpleDateFormat;importjava.util.Date;importandroid.app.Activity;importandroid.os.Bundle;importandroid.os.SystemClock;importandroid.view.View;importandroid.view.View.OnClickListener;importandroid.widget.Button;importandroid.widget.Chronometer;impor

60、tandroid.widget.TextView;importandroid.widget.Chronometer.OnChronometerTickListener;publicclassMainextendsActivityimplementsOnClickListener,OnChronometerTickListenerprivateChronometerchronometer;privateTextViewtvTime;OverridepublicvoidonClick(Viewview)switch(view.getId()caseR.id.btnStart:/開始計(jì)時(shí)器chron

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論