本文转自:http://www.poemcode.net/2009/11/android_music/

Android 1.6的源码共包括了21个核心应用,分布在 package/apps下,其中 Music 应用提供了音乐播放功能,在各 GPhone 中差不多都能看到。但是这些核心应用本不属于 Framework,因此无法在 SDK Document 中看到其类和方法的说明,更无法在外部引入它们的类,Music也不例外。

工作中遇到这么一个应用场景:用户在文档阅读的 Activity 中,要能够控制音乐播放,包括:上一首、下一首、暂停和继续,以及获取正在播放的音乐的名称。由于无法引入 Music 应用的类,自然也就无法通过 API 直接实现这些功能。

查遍了 Dev Guide 和 Reference,也没有找到蛛丝马迹,于是索性直接进入到 Music 的源码探个究竟。经过初步的分析,将问题的焦点定位在 com.android.music.MediaPlaybackService 上,该类是个 Service 类,负责在后台播放音乐等工作。

该类声明并实例化了一个 BroadcastReceiver,并在 onCreate 中进行了注册,那么这个 BroadcastReceiver 到底接收哪些 Intent 呢?通过代码可以一目了然:

IntentFilter commandFilter = new IntentFilter();    commandFilter.addAction(SERVICECMD);    commandFilter.addAction(TOGGLEPAUSE_ACTION);    commandFilter.addAction(PAUSE_ACTION);    commandFilter.addAction(NEXT_ACTION);    commandFilter.addAction(PREVIOUS_ACTION);    registerReceiver(mIntentReceiver, commandFilter);

找到上述代码中的常量声明,可以看出这些就是控制音乐播放的action name了。

public static final String SERVICECMD = “com.android.music.musicservicecommand;    public static final String CMDNAME = “command”;    public static final String CMDTOGGLEPAUSE = “togglepause”;    public static final String CMDSTOP = “stop”;    public static final String CMDPAUSE = “pause”;    public static final String CMDPREVIOUS = “previous”;    public static final String CMDNEXT = “next”;    public static final String TOGGLEPAUSE_ACTION = “com.android.music.musicservicecommand.togglepause;    public static final String PAUSE_ACTION = “com.android.music.musicservicecommand.pause;    public static final String PREVIOUS_ACTION = “com.android.music.musicservicecommand.previous;    public static final String NEXT_ACTION = “com.android.music.musicservicecommand.next;

然后再回过头来看 BroadcastReceiver是如何处理这些 Intent 的,通过其 onCreate 方法可以看出控制音乐播放有两种方式。其一是设置 action name 为 SERVICECMD,然后通过 Intent 的 extra 设置 command,其值可以是 CMDTOGGLEPAUSE、CMDSTOP、CMDPAUSE、CMDPREVIOUS 或 CMDNEXT。

其二是设置 action name 为 TOGGLEPAUSE_ACTION、PAUSE_ACTION、PREVIOUS_ACTION 或 NEXT_ACTION。

看起来第二种方式更简洁,依此思路,逆向操作也就可以解决起初的问题了,如下代码演示了如何控制下一首:

Intent intent = new Intent (”com.android.music.musicservicecommand.next);    sendBroadcast(intent);

如果我们在此基础上更深入一步,控制音乐播放的同时,我们还需要得到正在播放的音乐名称,这又该怎么实现呢?

Android Framework 提供了非常棒的 android.media,凡音乐播放都离不开 MediaPlayer,该类定义了七个内部类,其中 MediaPlayer.OnPreparedListener 是这么描述的:

Interface definition for a callback to be invoked when the media source is ready for playback.

媒体文件准备结束,准备播放时,Android 就会调用这个这个内部类,在 MediaPlaybackService 则是 notifyChange(String what) 方法进行处理:

private void notifyChange(String what) {        Intent i = new Intent(what);        i.putExtra(”id”, Integer.valueOf(getAudioId()));        i.putExtra(”artist”, getArtistName());        i.putExtra(”album”,getAlbumName());        i.putExtra(”track”, getTrackName());        sendBroadcast(i);       // ……    }

那么在我们的应用当中,则需要创建 一个BroadcastReceiver,过滤对应的 action name,也就是常量 META_CHANGED 对应的值即可达到目标。

到了这里,回顾一下解决问题的过程,不由让人有些愤愤不平,为什么 Android 不把接口以文档的形式公布于众呢?真是“犹抱琵琶半遮面”。–或者它有公布,我没有看到?

更多相关文章

  1. Android(安卓)Studio重构之路,我们重新来了解一下Google官方的And
  2. Launcher桌面点击&长按&拖动事件处理流程分析
  3. Android(安卓)init.c简析
  4. android:webView总结
  5. Android(安卓)Studio快捷键汇总
  6. Android(安卓)Shell 常用命令
  7. Android三级目录、ListView单选/GridView单选、ListView多选/Gri
  8. Android- NDK编译APK中native死机调试
  9. Android原生(Native)C开发之九:OpenGL ES初探

随机推荐

  1. android之hardwareAccelerated你不知道的
  2. android apilevel和android系统版本对应
  3. Android开发技术文章整理
  4. android studio多渠道号,多包名打包
  5. android中GPS信息的获取
  6. Android(安卓)WIFI热点默认安全性的修改
  7. [51CTO]Android消息机制
  8. android获取电话号码实例
  9. Android:创建快捷方式
  10. Android(安卓)framwork 锁屏界面开发 笔