学习实践(由于最近也恰好想学习一下service 所以看了一下mediaplayer)
该图为MediaPlayer 的 状态转换图。
Frameworks/base/media/java/android/media/MediaPlayer.java
果断从MediaPlayer.create 该静态方法开始 ,该方法初始化MediaPlayer,并且获取到一个实例
构造函数走起
Looper 一直也没有完全的明白,但是知道差不多是handle的功能,暂时留着以后学习
static JNINativeMethod gMethods[] = {
{"native_setup" , "Ljava/lang/Object;)V", (void *)android_media_MediaPlayer_native_setup)
看着舒服,只传了一个Object 返回值为void 爽,不像以前看什么都蒙。
注意 native_setup为非静态方法,所以再JNI层中的第二个参数是jobject 也就是java层的mediaplayer对象
这里有一个问题 jobject thiz 是mediaplayer的实例对象,第三个参数jobject weak_this 是mediaplayer的弱引用,有什么区别呢?
sp
下面才是重头戏,关于回调什么的乱七八糟的事情。
下面完成的这个JNIMediaPlayerListener 将一个 初始化绑定了java层MediaPlayer实例的listener传给了 MediaPlayer.cpp 用于将来的回调事件
回调过程稍微一提示()
setListener(listenter);
/frameworks/base/media/libmedia/mediaplayer.cpp
回JNI层看那个notify
看下面那个mClass 和那个mObject 还有那个 构造函数 很清晰吧
看看实现
这个fields.post_event就是那个所谓的方法名,所以就是调用fields.post_event这个名字的函数 然后 实例也有 数据也有了。
接下来看最后执行的这个setMediaPlayer(env,thiz,mp);
Thiz 是Java层的实例,mp是C测的一个实例
源代码中的描述
在java不透明的区域展示给我们一个 新的 C++ 的MediaPlayer实例
由于在源码中 还没有找到这个play.get()方法 故这里只能猜测一下了,主要是为了绑定
然后继续回到MediaPlayer.java::create(Context context , int resid)
设置数据资源设置开始位置,并且 获取长度
是第三个 返回值为void 三个参数 第一个参数java.io.FileDescriptor,第二个long -> J,第三个long ->J 为引用对象之间可以不加分号。
首先获取绑定的那个 mp 获取一个fd(关于音频文件的)
process_media_player_call()
在分析这个方法的时候得看一下mp->setDataSource这个方法
获取一个 MediaPlayerService 看到这的时候 挡住了一下没有找到这个getMediaPlayerService方法 找了半天后来才找到该方法并没有定义在mediaplayer.cpp中,
而是定义在一个/frameworks/base/media/libmedia/IMediaDethNotifier.cpp中定义的 定义如下
在学习Camera 的时候已经遇到过这种形式了,所以很清晰是binder获取service实例
以后的调用中就等于直接调用MediaPlayerService实例了
继续回到mediaplayer.cpp 中的setDataSource(int fd,int64_t offset , int64_t length)
Sp
也就是Service 的内部类 继承了BnMediaPlayer 这个和Camera 一样的
然后就setDataSource(player);
开始执行JNI中的process_dedia_player_call,没什么太大的意义
继续回到java层
关闭文件流,然后准备mp
因为没有Surface 故该函数实际上没有什么意义
继续回到java层 现在将java层的mp 返还给ap侧,然后可以开始start()了
这个Awake(true)是为了 视频屏幕不黑
JNI 不解释
先获取 一个MediaPlayer 然后 ->start()
这个mPlayer 就是那个BnMediaPlayer
现在只知道这个p 是mPlayer 这个mPlayer是什么时候创建的呢
这是后明白了 通过 fd文件 判断 player的类型,然后createPlayer
Return 这个 P
在 这里根据playerType的类型建立不同的播放器:对于大多数情况,类型将是PV_PLAYER,这时会调用了new PVPlayer()建立一个PVPlayer,然后将其指针转换成MediaPlayerBase来使用;对于Mini文件的情况,类型为 SONIVOX_PLAYER,将会建立一个MidiFile;最后一个就不清楚了
值 得注意的是PVPlayer、MidiFile两个个类都是继承MediaPlayerInterface得到的,而 MediaPlayerInterface又是继承MediaPlayerBase得到的,因此二者具有相同接口类型。只有建立的时候会调用各自的构造函 数,在建立之后,将只通过MediaPlayerBase接口来MediaPlayerBase控制它们。
然后这个PVPlayer.setDataSource()
最后start的时候就是调用这个PVPlayer.start()的
目前 暂时到这 由于PVPlayer 没有分析出来,暂时留空间,以待后面分析。
http://blog.csdn.net/chang_xing/article/details/7972725 该文章的有些内容作为了参考,在此谢谢作者!