说明

linphone主要的功能逻辑基本都是C/C++语言实现的,这时候在Android端就必须要用到JNI了,这里并不是要分析JNI怎样使用的逻辑,这里有几篇文章是java部分JNI的官方说明。

这份说明并没有怎样说怎么样配置Android的JNI环境,只是说了语法部分
java-jni-01-Introduction
java-jni-02-Design-Overview
java-jni-03-JNI Types and Data Structure
java-jni-04-JNI Functions
java-jni-05-The Invocation API

如果想知道怎样配置Android端的JNI环境(NDK环境),可以购买下面这部书籍, 非常棒,当工具书非常好。网络上有英文版的,但是里面的内容不全。

生成代码

分析到这里,我并不清楚使用什么生成的custom_rules.xml 文件,不过我很清楚,这肯定是那个脚本文件打包生成的, 也许是Ant,也许是Python。这里并不影响分析,所以清楚这些就好。下面的XML文件清楚的说明了,生成linphonecore_jni.h所需要的源文件,我们可以从这些源文件下手了。

<target name="javah" depends="-set-debug-mode,-compile">
        <echo level="info">Generate JNI header</echo>
        <javah outputfile="gen/linphonecore_jni.h">
            <classpath>
                <pathelement location="${out.classes.absolute.dir}" />
            </classpath>
            <class name="org.linphone.core.LinphoneAddressImpl" />
            <class name="org.linphone.core.LinphoneAuthInfoImpl" />
            <class name="org.linphone.core.LinphoneCallImpl" />
            <class name="org.linphone.core.LinphoneCallLogImpl" />
            <class name="org.linphone.core.LinphoneCallParamsImpl" />
            <class name="org.linphone.core.LinphoneCallStatsImpl" />
            <class name="org.linphone.core.LinphoneChatMessageImpl" />
            <class name="org.linphone.core.LinphoneChatRoomImpl" />
            <class name="org.linphone.core.LinphoneCoreFactoryImpl" />
            <class name="org.linphone.core.LinphoneCoreImpl" />
            <class name="org.linphone.core.LinphoneFriendImpl" />
            <class name="org.linphone.core.LinphoneProxyConfigImpl" />
            <class name="org.linphone.core.PayloadTypeImpl" />
            <class name="org.linphone.core.LpConfigImpl" />
            <class name="org.linphone.core.LinphoneInfoMessageImpl" />
            <class name="org.linphone.core.LinphoneEventImpl" />
            <class name="org.linphone.core.PresenceActivityImpl" />
            <class name="org.linphone.core.PresenceModelImpl" />
            <class name="org.linphone.core.PresenceNoteImpl" />
            <class name="org.linphone.core.PresencePersonImpl" />
            <class name="org.linphone.core.PresenceServiceImpl" />
            <class name="org.linphone.core.ErrorInfoImpl" />
            <class name="org.linphone.core.TunnelConfigImpl" />
        </javah>
        <javah outputfile="gen/xml2lpc_jni.h">
            <classpath>
                <pathelement location="${out.classes.absolute.dir}" />
            </classpath>
            <class name="org.linphone.tools.Xml2Lpc" />
        </javah>
        <javah outputfile="gen/lpc2xml_jni.h">
            <classpath>
                <pathelement location="${out.classes.absolute.dir}" />
            </classpath>
            <class name="org.linphone.tools.Lpc2Xml" />
        </javah>
    </target>

可以参考下面的文件链接

linphone-LinphoneAddress.java文件分析
linphone-LinphoneAuthInfo.java
linphone-PayloadType.java文件分析

linphonecore_jni.h

这个文件比较大,我就不把它的代码全部贴出来了,反正大致形式也就这样,java层的代码参考上面的。

部分代码节选。

* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_linphone_core_LinphoneAddressImpl */

#ifndef _Included_org_linphone_core_LinphoneAddressImpl
#define _Included_org_linphone_core_LinphoneAddressImpl
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     org_linphone_core_LinphoneAddressImpl
 * Method:    newLinphoneAddressImpl
 * Signature: (Ljava/lang/String;Ljava/lang/String;)J
 */
JNIEXPORT jlong JNICALL Java_org_linphone_core_LinphoneAddressImpl_newLinphoneAddressImpl
  (JNIEnv *, jobject, jstring, jstring);

/*
 * Class:     org_linphone_core_LinphoneAddressImpl
 * Method:    ref
 * Signature: (J)J
 */
JNIEXPORT jlong JNICALL Java_org_linphone_core_LinphoneAddressImpl_ref
  (JNIEnv *, jobject, jlong);

/*
 * Class:     org_linphone_core_LinphoneAddressImpl
 * Method:    unref
 * Signature: (J)V
 */
JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneAddressImpl_unref
  (JNIEnv *, jobject, jlong);

/*
 * Class:     org_linphone_core_LinphoneAddressImpl
 * Method:    clone
 * Signature: (J)J
 */
JNIEXPORT jlong JNICALL Java_org_linphone_core_LinphoneAddressImpl_clone
  (JNIEnv *, jobject, jlong);

/*
 * Class:     org_linphone_core_LinphoneAddressImpl
 * Method:    getDisplayName
 * Signature: (J)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneAddressImpl_getDisplayName
  (JNIEnv *, jobject, jlong);

××××××

最后的思考

最后想了一想, 其实linphonecore_jni.h无非就是javah命令生成的对应的头文件而已。并没有什么难度, 要说难度的还是里面具体的实现逻辑。所以我决定,按上面每个文件对应的函数进行逻辑性的分析,分析的深度为:到c代码的存取部分。