当前位置:操作系统 > 安卓/Android >>

Android Audio代码分析25 - JNI callback

今天来说说 native 中的代码是如何调用 java 侧代码的。
在看 setEnabled 代码的时候,我们了解到,最终在函数 EffectHandle::setEnabled 中会调用 java 侧的函数,
将状态改变的事件通知到 java 侧。
今天就以 AudioEffect 中的 native 侧调用 java 函数作为例子,来说明 JNI 中的 callback 函数。


#######################说明################################
1、首先,在 JNI 中会有一个 init 函数,java 侧会首先调用该 init 函数来完成初始化。
    对于 AudioEffect 来说,该函数就是 android_media_AudioEffect_native_init 函数。

++++++++++++++++++++++++++++++android_media_AudioEffect_native_init++++++++++++++++++++++++++++++++++
// This function gets some field IDs, which in turn causes class initialization.
// It is called from a static block in AudioEffect, which won't run until the
// first time an instance of this class is used.
static void
android_media_AudioEffect_native_init(JNIEnv *env)
{


    LOGV("android_media_AudioEffect_native_init");


    fields.clazzEffect = NULL;
    fields.clazzDesc = NULL;


    // Get the AudioEffect class
// 获取 java 侧的类
// static const char* const kClassPathName = "android/media/audiofx/AudioEffect";
// 此处的 path name 其实是 java 侧类所在的包。
// java 侧, AudioEffect 类所在地包为 package android.media.audiofx;
    jclass clazz = env->FindClass(kClassPathName);
    if (clazz == NULL) {
        LOGE("Can't find %s", kClassPathName);
        return;
    }


// 创建 java 侧 AudioEffect 对象的一个全局引用
    fields.clazzEffect = (jclass)env->NewGlobalRef(clazz);


    // Get the postEvent method
// 根据函数名称及参数类型从 AudioEffect 对象中获取函数
    fields.midPostNativeEvent = env->GetStaticMethodID(
            fields.clazzEffect,
            "postEventFromNative",                           // 函数名
"(Ljava/lang/Object;IIILjava/lang/Object;)V");   // 参数类型(object, int, int, int, object)
    if (fields.midPostNativeEvent == NULL) {
        LOGE("Can't find AudioEffect.%s", "postEventFromNative");
        return;
    }


    // Get the variables fields
    //      nativeTrackInJavaObj
    fields.fidNativeAudioEffect = env->GetFieldID(
            fields.clazzEffect,
            "mNativeAudioEffect", "I");
    if (fields.fidNativeAudioEffect == NULL) {
        LOGE("Can't find AudioEffect.%s", "mNativeAudioEffect");
        return;
    }
    //      fidJniData;
    fields.fidJniData = env->GetFieldID(
            fields.clazzEffect,
            "mJniData", "I");
    if (fields.fidJniData == NULL) {
        LOGE("Can't find AudioEffect.%s", "mJniData");
        return;
    }


// 查找类 Descriptor
    clazz = env->FindClass("android/media/audiofx/AudioEffect$Descriptor");
    if (clazz == NULL) {
        LOGE("Can't find android/media/audiofx/AudioEffect$Descriptor class");
        return;
    }
    fields.clazzDesc = (jclass)env->NewGlobalRef(clazz);


// 得到 Descriptor 的 init 函数
    fields.midDescCstor
            = env->GetMethodID(
                    fields.clazzDesc,
                    "<init>",
                    "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
    if (fields.midDescCstor == NULL) {
        LOGE("Can't find android/media/audiofx/AudioEffect$Descriptor class constructor");
        return;
    }
}
------------------------------android_media_AudioEffect_native_init----------------------------------


2、 java 侧会调用 native_setup 函数, 该函数中会创建 native 侧对象。
    对应 AudioEffect 来说, native_setup 函数就是 android_media_AudioEffect_native_setup 函数。
++++++++++++++++++++++++++++android_media_AudioEffect_native_setup++++++++++++++++++++++++++++++++++++
static jint
android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
        jstring type, jstring uuid, jint priority, jint sessionId, jintArray jId, jobjectArray javadesc)
{
    LOGV("android_media_AudioEffect_native_setup");
    AudioEffectJniStorage* lpJniStorage = NULL;
    int lStatus = AUDIOEFFECT_ERROR_NO_MEMORY;
    AudioEffect* lpAudioEffect = NULL;
    jint* nId = NULL;
    const char *typeStr = NULL;
    const char *uuidStr = NULL;
    effect_descriptor_t desc;
    jobject jdesc;
    char str[EFFECT_STRING_LEN_MAX];
    jstring jdescType;
    jstring jdescUuid;
    jstring jdescConnect;
    jstring jdescName;
    jstring jdescImplementor;


    if (type != NULL) {
        typeStr = env->GetStringUTFChars(type, NULL);
        if (typeStr == NULL) {  // Out of memory
            jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
            goto setup_failure;
        }
    }


    if (uuid != NULL) {
  &nb

补充:移动开发 , Android ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,