手机播放
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
7.2 音乐播放器
在Android平台中,以可选包的方式提供了一个名为android.media的包来提供用于播放多媒体文件的API。
7.2.1 音乐播放器开发引言
对于任何一个拥有多媒体手机的读者而言,如果能够自主开发出一款定制的手机音乐播放器是一件多么令人有成就感的事情。如果说仅仅是在WTK模拟器上,那么使用MMAPI就可以做出一个简单的音乐播放器来,然而如果要真正应用到实机上却不是那么一帆风顺的事情,在本节中笔者会逐步向读者解释这么说的原因。图7-1是一款音乐播放器在WTK模拟器和NOKIA 5310实机上的运行界面。
该款播放器在实机上支持mp3、wma、mid、aac(Advanced Audio Coding,高级音频编码)、mxmf、amr、nrt(NOKIA Ring Tone,NOKIA自谱铃声)等音乐媒体类型。
提示音乐播放器能够播放的音乐媒体类型都是实机可以支持的类型。如果实机不支持播放某种格式的音乐文件,那么音乐播放器也将无法播放该类型的文件。
图7-1 音乐播放器在WTK模拟器和NOKIA 5310实机上的运行界面
7.2.2 音乐播放器的功能说明
作为一款实用的手机音乐播放器,不仅要考虑界面的个性化,而且还要考虑较高的播放效率和手机厂商对音乐媒体类型的支持。
(1)实现播放的基本功能。它包括播放控制、音量调节、扩展卡资源读取支持等。
(2)流畅的播放效果。本案例中采用播放池(Player Pool)策略,这一策略将使播放过程更为流畅。造成播放停滞的原因主要有两个方面:一方面基于MIDlet的安全考虑,每当读取本地文件时手机系统都要求进行手动确认,这样就会间断播放过程。另外一方面,每次对音乐文件的播放预处理也会造成一定的播放间隔。
(3)完全满足手机厂商所支持的音乐媒体类型,支持尽可能多的音乐媒体类型。本案例中采用的是系统自动匹配的策略,即由手机系统本身来识别播放音乐类型。
以上的要求看似比较简单,但是由于模拟器环境和实机环境的差异,在实际开发中总会遇到一些小问题,接下来就和读者朋友们分享开发手机音乐播放器的苦闷和惊喜。
7.2.3 音乐播放池
引进播放池的策略主要是为了克服播放音乐文件时由于创建和销毁播放器对象(Player)而影响效率的情形。通过播放池方式,可将所有的播放器对象放入池中进行管理,播放指定的音乐文件时只需要在播放池中获取对应的播放器对象进行播放即可,而无须重新初始化播放器状态。这种方式的另外一个优点是还可以记录该音乐文件的播放状态,例如,播放位置、音量值等。
当然,采用播放池的方式会增加内存的消耗,在实施过程中需要结合硬件配置对池的大小进行调整。
7.2.4 设计分析
将手机音乐播放器工程定义为4个类:
(1)PlayerMIDlet,主MIDlet也是整个程序的入口,程序启动时显示音乐播放控制面板。
(2)AudioPanel,音乐播放控制面板,它是程序主界面,负责播放控制并对播放对象池进行管理。(3)PoolHelper,对象池帮助类,负责生成播放对象池。
(4)AudioSettingPanel,音量控制面板,实现对播放过程的音量控制。
另外,音乐播放器工程还引入了文件选择模块(参见第3章),用于生成播放文件列表。图7-2是该工程的框架设计图。
图7-2 手机音乐播放器工程的框架设计图
7.2.5 音乐播放器的实现过程
1.添加播放列表
如图7-3所示,当单击“添加播放列表”菜单时,播放器会调用文件选择组件来选择音乐文件,并将选择的文件添加到主界面的列表中。
图7-3 播放列表面板
代码7-1是调用文件选择组件的关键代码。
代码7-1 调用文件选择组件
//界面命令响应
public void commandAction(Command c, Displayable d) {
……
else if(c == cmdAddPlayList) {//添加播放列表
chooser = new FileChooser(this);
}
……
}
代码7-2是添加播放列表的核心代码。文件选择组件通过回调播放器主界面的finishAddList方法来实现播放列表的添加(第2行)。在添加之前还进行了播放项目的重复性判断(第19行),以免重复添加。
当播放项目添加成功后,以播放文件的资源字符串启动对象池帮助线程PoolHelper(第40行),并提供开始播放命令(第46行)。
代码7-2 添加播放列表
1 2 3 4 5 6 7 8 9 //结束添加列表
public void finishAddList() {
//显示当前界面(必须在showSelected之前)
display.setCurrent(playList);
//显示选择结果
showSelected();
}
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 //显示选择结果
private void showSelected() {
//当前选择播放资源
String uri = chooser.getCurrentFile();
if(uri == null) {//取消选择
return;
}
if(URITable.indexOf(uri) == -1) {//该资源不存在
//添加资源列表
URITable.insertElementAt(uri, 0);
//以插入方式
playList.insert(0, getRelativeName(uri),
iconHelper.getIconByExt(extractExt(uri) ) );
}
else {//该资源已经存在,无须更新
//for debug
System.out.println("Item " + uri + " already exists!!");
Alert alert = new Alert("Error",
"This item already exists!!", errorImage, AlertType.ERROR);