返回介绍

3.1 构造函数

发布于 2024-12-23 21:17:29 字数 1976 浏览 0 评论 0 收藏

在 MediaPlayer 的构造函数中调用了 native 的 android_media_MediaPlayer_native_setup 方法:

public MediaPlayer() {
  ...

  /* Native setup requires a weak reference to our object.
   * It's easier to create it here than in C++.
   */
  native_setup(new WeakReference<MediaPlayer>(this));
}

setup 方法中创建了 MediaPlayer,同时也设置了回调函数。其中最后一行的 setMediaPlayer 将 MediaPlayer 的指针保存成一个 Java 对象,之后可以看到 getMediaPlayer 通过同样的方法获取到该对象的指针。

static void
android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)

{
  ALOGV("native_setup");
  sp<MediaPlayer> mp = new MediaPlayer();
  if (mp == NULL) {
    jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
    return;
  }
  // create new listener and give it to MediaPlayer
  sp<JNIMediaPlayerListener> listener = new JNIMediaPlayerListener(env, thiz, weak_this);
  mp->setListener(listener);
  // Stow our new C++ MediaPlayer in an opaque field in the Java object.
  setMediaPlayer(env, thiz, mp);

}

static sp<MediaPlayer> setMediaPlayer(JNIEnv* env, jobject thiz, const sp<MediaPlayer>& player)
{
  Mutex::Autolock l(sLock);
  /* 由于指针的大小和 long 的大小是一样的,所以这里的 get 和 set 可以将
     MediaPlayer 的指针取出或存入*/
  sp<MediaPlayer> old = (MediaPlayer*)env->GetLongField(thiz, fields.context);
  // 判断 mediaplayer 是否为空指针,如果不是,这 sp 引用计数加 1
  if (player.get()) {
    player->incStrong((void*)setMediaPlayer);
  }
  // 如果之前存过 mediaplayer,检查之前存的是否为空,如果不为空,则引用计数减 1
  if (old != 0) {
    old->decStrong((void*)setMediaPlayer);
  }
  // 将新的 mediaplayer 指针存入 Java 对象中
  env->SetLongField(thiz, fields.context, (jlong)player.get());
  return old;
}

这里解释两点:

1 .由于指针的大小和 long 的大小是一样的,所以可以通过 SetLongField 和 GetLongField 来保存函数指针。

2 .由于 shared_ptr 和 weak_ptr 是 C++11 中才加入的,所以源码中实现了 sp 和 wp 作为智能指针来使用,这里可以看到代码中手动控制了引用计数。

现在一个 mediaplayer 对象就创建好了,其他的 jni 中对应的方法几乎都是调用 mediaplayer 来完成的。

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。