課程內容
Ø Radio Turner
Ø The NetworkInterface.InterfaceType Property
Local FM Radio應用程序提供了一種特定的接口來操作手機內置的FM收音機。與“Music + Videos hub”中手機內置的收音機不同,該應用程序允許用戶直接輸入想要收聽的電台頻率。而且,應用程序還顯示當前的接收信號強度,這也是對我們所處的無線環境的一個驗證。該應用程序的目的是展示手機中使用簡單有效的收音機操作接口,即Microsoft.Devices.Radio命名空間中的FMRadio類。雖然它提供的功能非常有限,但是也具備了一些優點。比如,它能夠與“Music + Video hub”中的歷史記錄和播放列表自動集成。
該應用程序需要獲取手機中的媒體庫(即具備ID_CAP_MEDIALIB能力)。如果沒有這個能力的話,雖然應用程序仍舊可以顯示收音機的一些基本信息,但是在啟動收音機時,程序會拋出一個名為“RadioDisabledException”的異常。
The User Interface
正如我們從應用程序的截圖所看到的那樣,該應用程序的用戶界面就是“Tip Calculator”與“Alarm Clock”的混合。
圖32.1 應用程序主頁面
注意:
➔ 除了double-zero按鈕被power按鈕所替代以外,頁面資源集合中的button和相關的canvas樣式與第10章“Tip Calculator”應用程序中使用的極其相似。
➔ 顯示頻率用的自定義七段數碼管字體在FrequencyDisplay這個用戶控件中實現。它幾乎與第20章“Alarm Clock”中的TimeDisplay用戶控件一致,但還是要稍微簡單一些。本章不涉及這方面的內容介紹,但是我們可以查看工程源代碼。
The Code-Behind
➔ 這里使用的大多數代碼與第10章“Tip Calculator”有很多相似之處。除了與FMRadio類交互以及處理power按鈕的代碼不同之外,它們之間最大的差異就是:顯示頻率值的時候,只保留了一位小數;而“Tip Calculator”中使用了兩位小數。
➔我們可以通過靜態的FMRadio.Instance屬性,得到一個FMRadio類的實例。該實例包含了三個可讀寫的屬性,用來控制手機中的收音機操作:
* Frequency,表示當前播放電台頻率的double類型值。
* PowerMode,只能是On或者是Off。
* CurrentRegion,可以是美國,日本,或者是歐洲。后者的含義就是“除了美國和日本之外的所有地域”。
FMRadio還包含一個只讀的、類型為double的SignalStrength屬性,它用來指示接收信號強度(RSSI)。該屬性值的范圍還沒有規定,但從我測試的結果來看,它是一個0到1之間的值,其中0表示無信號,1表示最強信號。
在手機通過Zune與PC機相連時,為什么收音機不工作?
桌面端運行的Zune軟件會鎖定媒體庫,這就使得需要ID_CAP_MEDIALIB能力的程序無法正常工作(同樣,在手機與Zune連接時,我們無法使用Marketplace這個應用程序)。如果我們需要測試具備這種功能的程序,我們可以使用“Windows Phone Connect Tool”這個工具,它包含在“Windows Phone Developer Tools”中,使得PC機可以不運行Zune的情況下,建立於手機的連接。
由於這個功能的限制,我們用戶不得不關閉Zune,或者斷開與手機的連接。但最好的方法是,在程序中檢測這種情況,在發生時,我們知道出現這種現象的原因。Local FM Radio應用程序在StartRadio方法中檢測這種情況。它假設PowerMode設置失敗就是手機連接Zune的緣故,這不失為一種安全的假設。
檢測這種情況的另一種方法就是,檢查NetworkInterface. InterfaceType屬性值(位於Microsoft.Phone.Net.NetworkInformation命名空間中)是否是Ethernet,它只有在與Zune建立連接后,值變為Ethernet。但是,這是一個並不可靠的屬性,因為獲取它的值,需要經歷一個長時間的阻塞過程。如果我們決定使用這種方式的話,最好是在后台線程中使用它。
➔由於收音機的信號強度值是可變的,但它並沒有與收音機相關的事件,所以主頁面的構造函數使用定時器對信號強度值每隔兩秒進行刷新一次。雖然這種循環的方式比較耗電,但一般情況下,用戶不會長時間地運行該應用程序。那是因為在應用程序退出以后,收音機仍舊保持工作(重要的是,該應用程序在鎖屏狀態下停止運行)。構造函數同時初始化FM頻率為上一次設置的FM頻率值。
FMRadio中的Frequency屬性是一個全局設置!
如果我們改變了收音機的電台,這會影響內置的收音機應用(同樣,其他任何使用收音機的第三方應用程序也會受影響)。一方面,這個操作非常的方便,因為在應用程序啟動時,不需要記住上一次的收音機頻率(事實上,Local FM Radio應用程序並沒有在隔離存儲空間中存放任何的數據)。另一方面,如果我們希望應用程序與手機內置的收音機進行隔離,那么我們就需要做一些額外的工作。
StartRadio 和 StopRadio這兩個方法可以改變PowerMode屬性的值。如果接收信號強度為0,StartRadio方法同樣顯示與內置收音機應用程序一樣的信息,如圖32.2所示。本應用程序假設這種情況發生時,用戶的耳機線沒有處於插入狀態,因為對於當前的手機來說,耳機線就充當了FM廣播的接收天線。
圖32.2 在沒有連接手機的耳機線時,應用程序無法獲取任何FM信號。
FMRadio的PowerMode屬性在Windows Phone 7.0版本中存在bug!
在一些手機上,把PowerMode設置為Off后,收音機會停止一小段時間,但隨后,即使PowerMode不設置回來,收音機仍舊處於工作狀態。這就使得無法實現一個顯示與收音機狀態同步的按鈕。相反,該應用程序中的power按鍵表現得非常怪異。在這種情況下,假如應用程序啟動時,由於連接Zune的原因,導致收音機無法工作,那么這種方式就可以用於啟動收音機。
➔ 在收音機打開的情況下,將頻率設置為一個無效的值會引發異常。有效或者無效的值是相對於本地電台頻率來說的,如果這通過用戶邏輯來實現的話,就顯得有些復雜。因此,本應用程序采用了最簡單的方法,那就是在異常發生時,將顯示的頻率值變紅(當然,如果當前的主題顏色是紅色,那就無法看到效果了)。
➔ 在用戶離開應用程序后(這時應用程序還在運行),我們仍舊可以通過點擊volume-up 或者是 volume-down 按鈕來控制收音機。應用程序這時會在屏幕上方彈出一個界面,如圖32.3所示。有趣的是,通過后退或者是前進按鈕,我們還可以搜索上一個/下一個電台,所以,如果在Local FM Radio運行過程中,我們按了上述的兩個按鈕,當前播放的電台就會和顯示的頻率值不一致。雖然本應用程序可以通過它定時器的Tick事件處理程序來檢測並驗證這種情況,但是,這並不是一個什么大問題。
圖32.3 除了更改音量以外,音量控制界面還可以進行開啟收音機或者停止收音機的操作,甚至還可以通過接收信號的強度,來搜索前一個或者后一個電台。
我們是否可以獲取當前播放電台的呼叫號碼、名稱、或者是“當前播放節目”的信息?
答案是否定的,雖然內置的收音機應用程序可以顯示這些信息,但是從目前向開發者開放的API來看,我們無法做到這些。