说明

这个是封装Message的结构, 稍微了解linphone的都知道, linphone的数据都存储在jni层, 所以这个结构就显得尤为重要。

看来,得专门写一篇文章,看看linphone是怎样在底层存取数据的,好期待

写到现在, 突然就没有了什么动力去详细的往下追踪。 估计是因为从刚开始分析第二阶段的第一个类开始,跟现在的分析步骤, 和结构出奇的移植, 所以我决定, 往下的文章还是简单的略过, 快快的进入下一个阶段。

native函数

private native Object getContent(long infoptr);
private native void setContent(long nativePtr, String type, String subtype, String data);
private native void addHeader(long nativePtr, String name, String value);
private native String getHeader(long nativePtr, String name);
private native void delete(long nativePtr);

具体的函数分析

getContent

/*
 * Class:     org_linphone_core_LinphoneInfoMessageImpl
 * Method:    getContent
 * Signature: (J)Ljava/lang/Object;
 */
JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_getContent(JNIEnv *env, jobject jobj, jlong infoptr){
    const LinphoneContent *content=linphone_info_message_get_content((LinphoneInfoMessage*)infoptr);
    if (content){
        return create_java_linphone_content(env,content);
    }
    return NULL;
}

让我们来看看LinphoneContent是个什么结构体。

LinphoneContent

submodules/linphone/coreapi/content.h:struct _LinphoneContent;
submodules/linphone/coreapi/content.h:typedef struct _LinphoneContent LinphoneContent;
submodules/linphone/coreapi/private.h:struct _LinphoneContent {

搜索_LinphonContent关键字, 搜到了结果。什么鬼, 竟然出现在两个不同的头文件中。

content.h ,我肯定在其它的文章中找到过, 看来得再找一遍了。、

/**
 * The LinphoneContent object holds data that can be embedded in a signaling message.
**/
struct _LinphoneContent;
/**
 * The LinphoneContent object holds data that can be embedded in a signaling message.
**/
typedef struct _LinphoneContent LinphoneContent;

什么, 没有定义结构体, 好尴尬啊。 我怎么办。
fuk, 结果在:private.h文件中

struct _LinphoneContent {
    belle_sip_object_t base;
    void *user_data;
    SalBodyHandler *body_handler;
    char *name; /**< used by RCS File transfer messages to store the original filename of the file to be downloaded from server */
    char *key; /**< used by RCS File transfer messages to store the key to encrypt file if needed */
    size_t keyLength; /**< Length of key in bytes */
    void *cryptoContext; /**< crypto context used to encrypt file for RCS file transfer */
    bool_t owned_fields;
};

可是为什么content.h要声明_LinphoneContent呢, 哦, 原来是content.c文件中生命声明了头文件,content.h中没有声明,所以必须得声明一下。 不行, 还是云里雾里, 找个时间得好好补补c/c++的基础了。

linphone_info_message_get_content

submodules/linphone/coreapi/linphonecore.h:LINPHONE_PUBLIC const LinphoneContent * linphone_info_message_get_content(const LinphoneInfoMessage *im);

submodules/linphone/coreapi/info.c:const LinphoneContent * linphone_info_message_get_content(const LinphoneInfoMessage *im){
/**
 * Returns the info message's content as a #LinphoneContent structure.
**/
const LinphoneContent * linphone_info_message_get_content(const LinphoneInfoMessage *im){
    return (im->content && linphone_content_get_type(im->content)) ? im->content : NULL;
}

这里运用了三目运算符。

create_java_linphone_content

static jobject create_java_linphone_content(JNIEnv *env, const LinphoneContent *icontent){
    jclass contentClass;
    jmethodID ctor;
    jstring jtype, jsubtype, jencoding, jname;
    jbyteArray jdata = NULL;
    jint jsize = 0;
    const char *tmp;
    void *data;

    contentClass = (jclass)env->FindClass("org/linphone/core/LinphoneContentImpl");
    ctor = env->GetMethodID(contentClass,"<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[BLjava/lang/String;I)V");

    jtype = env->NewStringUTF(linphone_content_get_type(icontent));
    jsubtype = env->NewStringUTF(linphone_content_get_subtype(icontent));
    jencoding = ((tmp = linphone_content_get_encoding(icontent))) ? env->NewStringUTF(tmp) : NULL;
    jname = ((tmp = linphone_content_get_name(icontent))) ? env->NewStringUTF(tmp) : NULL;
    jsize = (jint) linphone_content_get_size(icontent);

    data = (!linphone_content_is_multipart(icontent) ? linphone_content_get_buffer(icontent) : NULL);
    if (data){
        jdata = env->NewByteArray(linphone_content_get_size(icontent));
        env->SetByteArrayRegion(jdata, 0, linphone_content_get_size(icontent), (jbyte*)data);
    }

    jobject jobj = env->NewObject(contentClass, ctor, jname, jtype, jsubtype, jdata, jencoding, jsize);

    env->DeleteLocalRef(contentClass);
    env->DeleteLocalRef(jtype);
    env->DeleteLocalRef(jsubtype);
    if (jencoding) {
        env->DeleteLocalRef(jencoding);
    }
    if (jname) {
        env->DeleteLocalRef(jname);
    }

    return jobj;
}

这个函数就字啊linphonecore_jni.cc文件中, 说明它是直接跟java代码操作相关系的。 分析到这里, 突然脑子一过, 好像所有的有关于jni层的东西都放在这一个类中。

setContent

/*
 * Class:     org_linphone_core_LinphoneInfoMessageImpl
 * Method:    setContent
 * Signature: (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_setContent(JNIEnv *env, jobject jobj, jlong infoptr, jstring jtype, jstring jsubtype, jstring jdata){
    LinphoneInfoMessage *infomsg = (LinphoneInfoMessage*) infoptr;
    LinphoneContent * content = linphone_content_new();
    const char *tmp;

    linphone_content_set_type(content, tmp = env->GetStringUTFChars(jtype,NULL));
    env->ReleaseStringUTFChars(jtype, tmp);

    linphone_content_set_type(content, tmp = env->GetStringUTFChars(jsubtype,NULL));
    env->ReleaseStringUTFChars(jsubtype, tmp);


    linphone_content_set_string_buffer(content, tmp = env->GetStringUTFChars(jdata,NULL));
    env->ReleaseStringUTFChars(jdata, tmp);

    linphone_info_message_set_content((LinphoneInfoMessage*)infoptr, content);
    linphone_content_unref(content);
}

LinphoneInfoMessage

submodules/linphone/coreapi/info.c:struct _LinphoneInfoMessage{

我摸到一个很有用的经验, 那就是要想搜某一个具体的结构体定义, 就搜同名+”_” , 百分百能搜到。

struct _LinphoneInfoMessage{
    LinphoneContent *content;
    SalCustomHeader *headers;
};

addHeader

/*
 * Class:     org_linphone_core_LinphoneInfoMessageImpl
 * Method:    addHeader
 * Signature: (JLjava/lang/String;Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_addHeader(JNIEnv *env, jobject jobj, jlong infoptr, jstring jname, jstring jvalue){
    const char *name=NULL,*value=NULL;
    name=env->GetStringUTFChars(jname,NULL);
    value=env->GetStringUTFChars(jvalue,NULL);
    linphone_info_message_add_header((LinphoneInfoMessage*)infoptr,name,value);
    env->ReleaseStringUTFChars(jname,name);
    env->ReleaseStringUTFChars(jvalue,value);
}

getHeader

/*
 * Class:     org_linphone_core_LinphoneInfoMessageImpl
 * Method:    getHeader
 * Signature: (JLjava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_getHeader(JNIEnv *env, jobject jobj, jlong infoptr, jstring jname){
    const char *name=env->GetStringUTFChars(jname,NULL);
    const char *ret=linphone_info_message_get_header((LinphoneInfoMessage*)infoptr,name);
    env->ReleaseStringUTFChars(jname,name);
    return ret ? env->NewStringUTF(ret) : NULL;
}

delete

/*
 * Class:     org_linphone_core_LinphoneInfoMessageImpl
 * Method:    delete
 * Signature: (J)V
 */
JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_delete(JNIEnv *env, jobject jobj , jlong infoptr){
    linphone_info_message_destroy((LinphoneInfoMessage*)infoptr);
}