很多Android新手对于JNI开发过程中的疑问不是很清楚,根据android123@163.com邮箱中反馈的内容我们整理如下: 1. JNI中,什么情况才处理jstring、jint、jobject这样的类型,其实通过NDK开发Android C++应用,大部分仍然是常规的cpp和h的标准写法,只有需要和Java层通讯的方法才包含了类似JNIEXPORT void JNICALL XXX这样的函数,大多数的逻辑和标准C/C++没有什么区别。 2. 我有一个在Windows上开发好的dll能否在Android上使用呢? 这里Android开发网提醒大家,对于dll这样的PE文件只能在Windows平台下使用,而Linux上的动态库so文件如果是PC上的也无法通过JNI在Android上调用,由于CPU的指令不同,手机上必须使用ARM交叉编译器生成才可以使用,而PC上的为x86或64位,即使是Hello World这样代码兼容性很强,也必须在NDK中重新编译才能在Android上使用。 3. 学习JNI的基础是什么,或者说什么顺序学习? 这点Android123推荐大家先了解Java的类型,和内部编码,然后学习C/C++语言,对于NDK r5开始支持的C++语言,这里Android开发网要和大家说下了,如果需要在JNI中调用Java的类,你可以学习下反射机制,同时C++ STL在NDK r5开始支持,这样开发应用维护起来更方便些。最后看下NDK的Samples下载Android源码Framework层基本上就没有什么大问题了。 4. 学习NDK最大的困难是什么? 这里Android123认为,国内网友大多数都在Windows下做开发工作,整个NDK环境需要Cygwin,同时mk这样的makefile编译脚本的手动编写可能不是很友好,这点Android开发网已经准备了一整套的Android开发工具,将在近期公开,帮助大家在PC辅助开发Android应用,同时常见问题提供了相应的链接。 5. 在Android JNI用处大吗? 对于大多数开发者来说可能主要用于OpenGL游戏设计上,不过对于纯运算,算法上C语言比Java有着很多天生的优势,这点不容置疑,多一门技术多一个出路嘛,整个Android源代码十分庞大,开源的力量最终还是能打败更封闭的Windows Phone和iOS的。
JNI开发
Android JNI开发入门篇 Android开发技术
昨天我们大概讲了下Android NDK的开发概况和常见的技巧,很多网友感到表示十分感兴趣发来了邮件希望继续,今天Android123还是从头还是谈论下Java的调用C++的JNI,以便大家开发出一些功能较强大些的Android应用,如果有疑问可以仍然来函至 android123@163.com 1. 有关JNI的类型方法表示,很多网友不明白,下面Android开发网就,基本上C层面的类型均是j+java过去的类型,比如字符串在JNI的c层面为jstring而Java为String,对于布尔类型boolean则为jboolean对应Java中的boolean。 2. 有关Java类的表示在JNI中对应关系如下 long cwjInfo (int nAge, String sName, int[] arrSalary); 我们可以表示为 "(ILjava/lang/String;[I)J" 我们去除双引号,第一个(表示一个参数类型,接下来的I表示第一个参数为int整形,L代表是一个类class,这里为java/lang/String这个类,接下来是[代表是一个数组,后面的I代表一个整形的数组,而)后面的J代表返回类型,在JNI中J代表long长整形,相关的对应关系如下: V voidZ booleanB byteC charS shortI intJ longF floatD doubleL fully qualified class[ array type[]( arg-types 3. Java层传入的String不能在JNI中直接转化为jstring,因为Java的内部编码为unicode,中英文的字符都是每个占两个字节,而jni中我们需要使用utf-8来表示,utf-8比较特殊中英文是不等长的,比如英文等符号的ascii占用一个字节,而中文则为三个字节,同时仍然以\n结尾,所以下面这种错误的方法为 JNIEXPORT jstring JNICALL Java_Cwj_ShowLog(JNIEnv *env, jobject obj, jstring log){ printf("%s", log); //这样做是错误的,printf不能直接处理Java传来的类型。 //dosomething 返回jstring等等。} […]
Android JNI开发提高篇 Android开发技术
有关JNI的开发技术,我们继续围绕Android平台进行,JNI可以支持C或C++,从目前为止我们写过的JNI代码均为C实现的,即文件名为.C而C++的和这些有什么不同呢? Android平台上的JNI一般使用C还是C++编写呢? Android平台在中间层和大部分的类库的底层使用了C++的开发方式,后缀为.cpp,比如Android Framework、OpenCore、Webkit、SQLite等等。使用C++好处就是可以使用很多库但目前Android不支持STL,我们知道C表示字符串都是字符数组,但C++可以使用类似string这样的类型表示。 1. 代码上编写C和C++有啥区别 这里Android123就以将Java的unicode字符串转为jni中的utf8,然后再返回一个jstring类型为例子,可以看到jni和java之间字符串的转换方法。 C的实现: JNIEXPORT jstring JNICALL Java_Android123_CwjC (JNIEnv *env, jobject obj, jstring string) { const char *strUTF = (*env)->GetStringUTFChars(env, string, 0); char szBuffer[255]; strcpy(szBuffer, strUTF); (*env)->ReleaseStringUTFChars(env, string, strUTF); return (*env)->NewStringUTF(env, szBuffer);} C++的实现: JNIEXPORT jstring JNICALL Java_Android123_CwjCpp (JNIEnv *env, jobject obj, jstring string){ const char […]
Android JNI开发进阶篇 Android开发技术
今天Android123主要讲解下昨天需要详细说明有关Java JNI相关的异常处理、线程安全问题,在JNI中产生的异常主要是内存不足OutOfMemoryError、数组越界ArrayIndexOutOfBoundsException、数组赋值类型错误ArrayStoreException以及指针越界等问题。简单的我们昨天在 Android JNI开发提高篇中已经讲到。 除了Throw或ThrowNew来抛出异常外,还提供了5个函数来处理,分别为jthrowable ExceptionOccurred(JNIEnv *env);、void ExceptionDescribe(JNIEnv *env);、void ExceptionClear(JNIEnv *env); 、 jboolean (JNIEnv *env) 和void FatalError(JNIEnv *env, const char *msg); 1. ExceptionCheck 用于检测如果一个异常已经抛出,则该方法将会返回JNI_TRUE就是typedef定义为1的布尔值。 2. ExceptionOccurred 获取正在抛出一个异常的本地引用,Native或Java层必须处理该异常,并返回一个jthrowable对象。 3. ExceptionDescribe主要用于打印出异常的错误描述。 4. ExceptionClear清除刚刚抛出的异常。 5. FatalError 的作用比较特殊,产生一个致命性的错误,Android123提示这样会导致JVM将关闭,就是程序停止运行了,所以使用时要谨慎。 我们以C++的代码做个例子,简单的说明下他们的使用方法 env->FindClass("Android123CWJ"); //假设这个类本身不存在 if(env->ExceptionCheck()) { env->ExceptionDescribe(); env->ExceptionClear(); } 这样JVM因为查找Android123CWJ类不存在,导致了一个NoClassDefFoundError的异常。 在JNI中处理资源同步问题,JNI提供了一组函数分别为jint MonitorEnter(JNIEnv […]
Android JNI开发高级篇 Android开发技术
有关Android JNI开发中比较强大和有用的功能就是从JNI层创建、构造Java的类或执行Java层的方法获取属性等操作。 一、类的相关操作 1. jclass FindClass(JNIEnv *env, const char *name); 查找类 该函数可能做过Java开发的不会陌生,这个是JNI层的实现,需要注意的是第二个参数为const char*类型的,我们如果从Java从层传入unicode编码的jstring类型需要使用GetStringUTFChars函数转换成utf8的const char*,如果成功返回这个Java类的对象jclass,相关的异常可能有 (1. ClassFormatError 类的数据格式无效 (2. ClassCircularityError 该类或接口是自身的超类或超接口 (3. NoClassDefFoundError 没有找到指定名称的类或接口 (4. OOM内存不足错误,即OutOfMemoryError 2. jclass GetSuperclass(JNIEnv *env, jclass clazz); 获取父类或者说超类 该函数的第二个参数为jclass类,我们调用时传入的是子类,否则返回将是NULL 3. jboolean IsAssignableFrom(JNIEnv *env, jclass clazz1,jclass clazz2); 判断class1对象能否安全的强制转换为class2对象 如果可以将返回 JNI_TRUE,JNI_TRUE的定义值为1,否则返回JNI_FALSE即0 ,这里Android123详细说明下哪些情况可能返回真: […]

