Android如何判断当前手机是否正在播放音乐,并获取到正在播放的音乐的信息
我想实现如下的场景,判断当前Android手机上是否正在播放音乐,如果是,通过某个特定的手势,
或者点击某个按键,将当前我正在听的音乐共享出去。
第一步,就是判断当前是否有音乐正在播放。
最开始我想得有点复杂,以为要深入framework或更下层去做手脚才行,找了一下资料,发现AudioManager对外暴露了接口。
/** Checks whether any music is active. */isMusicActive()
通过这个接口就可以判断当前系统是否有音乐在播放了。
还有一个问题,如果我想在音乐一开始就已经播放的时候,就知道这个事件,以便进行特殊的处理。
再进一步看一下 AudioManager 的源码,发现其中有如下方法:
/** * Request audio focus. * Send a request to obtain the audio focus * @param l the listener to be notified of audio focus changes * @param streamType the main audio stream type affected by the focus request * @param durationHint use {@link #AUDIOFOCUS_GAIN_TRANSIENT} to indicate this focus request * is temporary, and focus will be abandonned shortly. Examples of transient requests are * for the playback of driving directions, or notifications sounds. * Use {@link #AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK} to indicate also that it's ok for * the previous focus owner to keep playing if it ducks its audio output. * Use {@link #AUDIOFOCUS_GAIN} for a focus request of unknown duration such * as the playback of a song or a video. * @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED} */ public int requestAudioFocus(OnAudioFocusChangeListener l, int streamType, int durationHint)
从字面意思来看:请求音频焦点,再看这个函数的返回值:
/** * A failed focus change request. */ public static final int AUDIOFOCUS_REQUEST_FAILED = 0; /** * A successful focus change request. */ public static final int AUDIOFOCUS_REQUEST_GRANTED = 1;
这个函数可能对我有帮助,进一步查一下Google官方的帮助:http://developer.android.com/training/managing-audio/audio-focus.html
和 天天动听 结合起来测试,先打开天天动听播放音乐,再启动这个Service,发现天天动听自动暂停,再停止这个Service,天天动听又开始播放了。
反过来,我先启动这个Service,再播放、暂停天天动听,“Log.i(TAG, "focusChange=" + focusChange);” 这个确实有输出日志。
主流的音乐播放器,都遵循此规则的,所以通过使用Android的这个机制,我们就可以监控音乐的播放了。
还有一个问题,如何知道当前播放的音乐信息呢?两个思路:
1、通过在后台自动截取音频流的输出,通过服务器进行听歌识曲;
2、通过在SystemUI中拦截主流音乐播放器的通知;
第1个思路,从原理上是可行的,但是实现起来难度比较大,而且严重依赖网络;
还是先来分析一下第2个思路。
先找主流的Android音乐播放器来做个简单地测试,比如:天天动听、QQ音乐、酷狗音乐、酷我音乐、百度音乐等,在播放过程中,都会向状态栏中发一个Notification消息,其中已经包含歌曲信息。那我只需要做一个特殊的拦截并进行包名匹配,就可以获取正在播放的音乐了。
具体思路如下:
1、实现一个服务,这个服务在Android手机启动时,自动运行起来,通过 AudioManager.requestAudioFocus() 获取音频焦点,但什么事都不干,只为有其它音乐播放器开始运行时,得到一个通知消息;
2、修改SystemUI,当主流音乐播放器发Notification到状态栏时,从中获取到音乐信息;
3、步骤1的Listener就可以集成到SystemUI中,这样当音乐焦点被其它音乐播放器抢走后,再结合最近收到的Notification通知,这样更准确一些;
这样,基本上就可以实现我们想要的场景了。
