《101 Windows Phone 7 Apps》读书笔记-Local FM Radio
课程内容
Ø 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来看,我们无法做到这些。