15235313_z0yP

Android JNI开发基础(一)

什么是JNI

  • JNI是Java Native Interface的简称,即Java本地开发接口
  • JNI是一个协议,用来沟通Java代码和本地代码(C/C++)

jni-1 jni-2

为什么使用JNI

  • Java语言没有的功能(很少)
  • 代码已经有现成的C/C++版本,不想重写(一般情况)
  • Java太慢了(怎么慢?)
  • 跨平台实现(Mac, Windows, Android, iOS)
  • 特殊的功能性语言(Fortran的数学计算)

使用JNI的注意事项

  • 只提供了C/C++的支持,其他语言需要额外的步骤
  • 不安全,特别是内存管理,以及Java对象的引用计数
  • 不可移值,不同的CPU架构需要重新编译(arm, mips, x86)

如何使用JNI

基础知识

  • Android SDK(Java)
  • C/C++语言
  • NDK(Android.mk, ndk-build)

C/C++语言基础

  • 指针的使用
  • 内存管理:malloc, free, new, delete
  • 变量类型:int, float, double, char, …
  • C++导出C函数:extern “C” { }

基本过程

  1. 下载NDK,支持Windows、Linux和Mac OS X;
  2. 解压NDK到本地磁盘,设置好PATH;
  3. 新建Android工程,在工程目录下新建jni文件夹(文件夹名称必须是jni);
  4. 在jni文件夹下建立Android.mk文件(Android.mk文件的编写方法见后文);
  5. 在jni文件夹下编写好C/C++代码文件;
  6. 命令行切换到当前目录,运行ndk-build,等待编译完成,编译完成后so文件在libs/armeabi文件夹下;
  7. 在eclipse里运行Android工程,so文件会打包到apk里。

TIPS:ADT插件安装选择Native Development,在工程的右键菜单有Android Tools/Add Native Support,集成了CDT的C/C++ IDE环境,在Java编译前执行ndk-build

JNI语法

  • HelloJni例子(NDK_DIR/samples/hello-jni)
  • HelloJni.java
  • HelloJni.c
  • Android.mk

HelloJni.java

public class HelloJni extends Activity
{
	// ...
       public native String  stringFromJNI(); // 声明native
       static {
             // 在libs/armeabi下加载libhello-jni.so
             System.loadLibrary("hello-jni"); 
             // 指定路径加载libhello-jni.so		
             // System.load("path/libhello-jni.so");
    	}
}
  • 声明native函数,不用在Java中实现,建议native函数为private
  • 加载jni so文件,有以下两种方式,按需选择一种即可
    • 调用System.loadLibrary默认在libs/armeabi下加载so文件,名称与Android.mk里的LOCAL_MODULE一样
    • 调用System.load,指定so文件的完整路径,必须写完整so文件名

HelloJni.c

#include <string.h>
#include <jni.h>

jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
                                                  jobject thiz )
{
    // C的写法
    return (*env)->NewStringUTF(env, "Hello from JNI !");
    // C++的写法
    // return env->NewStringUTF("Hello form JNI !");
}
  • 函数名规则:Java_包名_类名_Java函数名( JNIEnv* env, jobject thiz, 其他参数)
  • 函数名可以用javah自动生成,命令行
    $ cd bin
    $ javah -classpath . -jni com.example.hellojni.HelloJni
  • 产生对应包名的.h文件,实现.h的函数
  • JNIEnv* env:JNI环境的指针,JVM当前线程的句柄,JNI函数调用入口
  • jobject thiz:调用JNI函数当前对象的引用,相当于this指针

类型对应表

Java Type Native Type Size in bits
boolean jboolean 8, unsigned
byte jbyte 8
char jchar 16, unsigned
short jshort 16
int jint 32
long jlong 64
float jfloat 32
double jdouble 64
void void N/a
byte [] jbyteArray 8*n
class Object jobject 32

Java对象对应表

jni-3

字符串

访问jstring:

char *str = (*env)->GetStringUTFChars(env,prompt,0);
/* this maps into regular C char* */
printf(“%s”, str); /* now it is ok to print */
(*env)->ReleaseStringUTFChars(env, prompt, str);
/* must release String to avoid memory leaks */

返回jstring:

char buf[128]; /* allocate memory for local char* in C */
scanf(“%s”, buf); /* read into char* from stdio */
return( (*env)->NewStringUTF(env, buf));
/* construct and return the Java String */

数组

jsize len = (*env)->GetArrayLength(env,arr);
jint *body = (*env)->GetIntArrayElements(env,arr,0);
for (i=0;i<len;++i){
   sum += body[i];
}
(*env)->ReleaseIntArrayElements(env,arr,body,0);
/* very important – copies back to java array if copy had to be made */
  • 其他类型(float, byte, double)的调用方式类似:
    • Get<type>ArrayElements
    • Release<type>ArrayElements
  • 注意: 这些Get函数会拷贝数组,如果不需要内存拷贝,使用:Get/Set<type>ArrayRegion functions
Get Function Release Function Array Type
GetBooleanArrayElements ReleaseBooleanArrayElements boolean
GetByteArrayElements ReleaseByteArrayElements byte
GetShortArrayElements ReleaseShortArrayElements short
GetIntArrayElements RelaseIntArrayElements int
GetLongArrayElements ReleaseLongArrayElements long
GetFloatArrayElements ReleaseFloatArrayElements float
GetDoubleArrayElements ReleaseDoubleArrayElements double
GetObjectArrayElements ReleaseObjectArrayElements object

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

This site uses Akismet to reduce spam. Learn how your comment data is processed.