Android开发艺术探索_JNI和NDK编程(十四)

JNI:Java Native Interface
是为了方便java调用java和c等本地代码所封装的一层接口.专门用于和本地代码交互,可以调用C C++所编写的本地代码;

NDK:是Android所提供的一个工具集合,通过NDK可以在Android中更加方便的通过JNI来访问本地代码;
NDK还提供了交叉编译器,开发人员只需要通过简单地修改mk文件就可以生成特定的CPU平台的动态库;
作用:
1.提高了代码的安全性,so库反编译比较困难
2.可以很方便的使用目前已经有的c++
3.便于平台间的移植.
4.提高程序在某些特定情形下的执行效率

JNI和NDK主要用于底层和嵌入式开发

JNI的开发流程

1.在java中声明native方法

public class JniTest {
    static {
        System.loadLibrary("jni-test");
    }
    //jni的头部有一个加载动态库的过程,其中jni-test是so库的标识,so库完整的名字为libjni-test.so,这是加载so库的规范
    public static void main(String args[]){
        JniTest jniTest = new JniTest();
        System.out.println(jniTest.get());
    }
    //这两个方法是需要在jni中实现的方法
    public native String get();
    public native void set(String str);
}

2.编译java源文件的到class文件,然后通过javah命令导出JNI的头文件;


在当前目录下,会产生一个com_rgy_JniTest.h的头文件,它是用javah命令自动产生的;

函数名的格式遵循如下规则:Java_包名_类名_方法名,如JniTest中的set,到这里就变成了JNIEXPORT void JNICALL Java_com_xx_JniTest_set(JNIEnv *,jobject,jstring);

JNIEXPORT JNICALL JNIEnv jobject都是JNI标准中所定义的类型或者宏;
JNIEnv*:表示一个指向JNI环境的指针,可以通过它拉斯访问JNI提供的接口方法;
jobject:表示java对象中的this;
JNIEXPORT和JNICALL:它们是JNI中宏所定义的宏,可以在jni.h这个头文件中查找到; 

3.实现jni方法

jni方法是指java中所声明的native方法,可以选中c++ c来实现;
1.在工程的主目录下创建一个子目录,名称随意,这里选择jni作为子目录的名称
2.将通过javah的生成的头文件com_xx_JniTest.h复制到目录下
3.创建test.cpp test.c两个文件
cpp:

#include "com_ryg_JniTest.h"
#include <stdio.h>
JNIEXPORT jstring JNICALL Java_com_ryg_JniTest_get(JNIEnv *env,jobject thiz){
    printf("invoke get in c++\n");
    return env->NewStringUTF("Hello from JNI!");
}
JNIEXPORT void JNICALL Java_com_ryg_JniTest_set(JNIEnv *env,jobject thiz,jstring string){
    printf("invoke set in c++\n");
    char* str=(char*)env->GetStringUTFChars(string,NULL);
    printf("%s\n",str);
    //区别在这里
    env->ReleaseStringUTFChars(string,str);
}
c:

#include "com_ryg_JniTest.h"
#include <stdio.h>

JNIEXPORT jstring JNICALL Java_com_ryg_JniTest_get(JNIEnv *env,jobject thiz){
    printf("invoke get in c\n");
    return (*env)->NewStringUTF(env,"Hello from JNI!");
}
JNIEXPORT void JNICALL Java_com_ryg_JniTest_set(JNIEnv *env,jobject thiz,jstring string){
    printf("invoke set in c++\n");
    char* str=(char*)env->GetStringUTFChars(string,NULL);
    printf("%s\n",str);
    //区别在这里
    (*env)->ReleaseStringUTFChars(env,string,str);
}

编译so库并在java中调用

so库的编译采用gcc,切换到jni目录中,
编译命令:
gcc -shared -I/usr/lib/jvm/java-7-openjdk-amd64/include-fPIC test.cpp -o libjni-test.so
gcc -shared -I/usr/lib/jvm/java-7-openjdk-amd64/include-fPIC test.c -o libjni-test.so
其中usr/lib/jvm/java-7-openjdk-amd64是本地的jdk的安装路径,libjni-test.so则是生成的so库的名字,在java中可以通过System.loadLibraray("jni-test")加载,其中so库中的lib和.so是不需要明确指出的;so库编译完成以后就可以在java程序中调用so库了

通过java指令来执行java程序,切换到主目录,执行如下命令:
java -Djava.library.path=jni com.ryg.JniTest,其中-Djava.library.path=jni指出了so库的路径
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值