说明
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代码的存取部分。