`
myhpu2008
  • 浏览: 87827 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

[转]Android Music和第三方应用

阅读更多

本文转自: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 不把接口以文档的形式公布于众呢?真是“犹抱琵琶半遮面”。–或者它有公布,我没有看到?

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics