MediaPlayer是android播放音视频的库,我们常见播放视频的组件VideoView对MediaPlayer进行了封装,通过MediaPlayer.java类提供的接口,对视频进行相应的操作。例如,播放,暂停,获取视频的长宽,媒体文件时间等等。但这些功能的真正实现也不是在MediaPlayer.java中,而是在本地代码C++,MediaPlayer.cpp中实现的。这里就涉及到了jni的知识,可以参考《Java语言如何与本地代码(C/C++)交互》这篇文章http://www.jianshu.com/writer#/notebooks/12418576/notes/20268367
MediaPlayer.java是通过动态库media_jni.so对C++代码进行操作的,功能真正的实现是在MediaPlayer.cpp中
MediaPlayer.java中声明的本地方法如下所示,具体实现在MediaPlayer.cpp中。
MediaPlayer.java声明的相关接口如下所示,当java代码想要了解C++代码中当前操作的视频情况时,可以通过如下接口了解。
本地代码MediaPlayer.cpp传递消息给MediaPlayer.java,是通过MediaPlayer.java中的方法postEventFromNative(...),该代码是在子线程中执行的,因此想更新消息需要通过Handler把消息转移都主线程。该方法被回调时,通过Handler把消息转移到主线程,然后根据消息的类型回调上面的接口,现在已经弄明白以上接口是在哪里回调的啦,现在具体看看postEventFromNative的代码,如下所示:
//mediaplayer_ref表示播放器的弱引用对象
//what表示相应消息的代码值。
//arg1,arg2,obj表示传递的相应消息。
private static void postEventFromNative(Object mediaplayer_ref,
int what, int arg1, int arg2, Object obj)
{
//静态方法对外部类不存在引用,所有这里需要获取一个对象。
MediaPlayer mp = (MediaPlayer)((WeakReference)mediaplayer_ref).get();
if (mp == null) {
return;
}
if (what == MEDIA_INFO && arg1 == MEDIA_INFO_STARTED_AS_NEXT) {
// this acquires the wakelock if needed, and sets the client side state
mp.start();
}
//获取MediaPlayer.java中的Handler,mEventHandler。
if (mp.mEventHandler != null) {
//Handler发送消息
Message m = mp.mEventHandler.obtainMessage(what, arg1, arg2, obj);
mp.mEventHandler.sendMessage(m);
}
}