您的位置:首页 > 编程语言 > C语言/C++

NDK工具使用,JNI开发

2016-06-07 23:52 295 查看
博客转移到个人站点:http://www.wangchengmeng.club/2018/02/04/NDK%E5%B7%A5%E5%85%B7%E4%BD%BF%E7%94%A8%EF%BC%8CJNI%E5%BC%80%E5%8F%91/

欢迎来吐槽

小编最近遇到一个需求,寻思着用平常(Android)的解决方案去解决但是没找到,还好小编曾经的曾经学过C/C++,虽然很多都已经忘记,但是语言嘛,想再去学习就不那么难了。需求是:在你应用被卸载的完毕后,弹出一个网页,这种需求并不少见,但是仔细一推敲,本应用程序都已经被卸载了,随之进程也肯定被杀死了不在内存了,进程没了,怎么去实现弹出一个网页呢?于是救命稻草来了,JNI,使用java+c的模式来开发自己的应用程序,大家应该知道在C中,进程是可以自己fork出来的,因为在C中是没有GC机制的,需要手动去申请和释放内存,那么接下来就学学JNI吧。

NDK开发工具

NDK的理解

1.其实NDK就是一系列的工具的集合它提供了一系列的工具,帮助开发者去快速的开发C/C++的动态库,并且可以自动的将so和java应用一起打包成apk。帮助很大

2.NDK集成了交叉编译器,开发人员只需要简单的修改mk文件,就可以创建出so

3.NDK发布以后,官方也支持了java+c的这种模式

4.java的包都是可以进行反编译的,使用NDK我们可以将需要保密的应用逻辑使用C开发。这样提高了安全性。

接下来就使用NDK工具来进行JNI开发吧,这里使用eclipse(studio的方式暂时还没研究过,虽然小编早已经不用eclipse了)

===============================

首先你需要下载NDK并解压到一个文件夹下面:

1.打开eclipse下preference中android下的NDK,将NDK工具关联进来

2.右击工程,android tools下的 add Native suport

3.命名,xxxx-jni ,

4.会生成jni文件夹,将.cpp文件后缀改成.c,同时将android.mk中的.cpp,改成.c

5.为了支持更多平台,在jni文件夹中创建一个Application.mk,写入APP_ABI := all

6.右击 demo-jni.c 文件 选择properties,C/C++ 下的 path and symble 添加iclude文件夹

7.在本工程下的src下打开ndk-builde.cmd命令窗口(先配置环境变量,在path下配置ndk-builde.cmd目录),然后输入javah 包名.类名,在该目录下生成一个文件,该文件中有native方法的名字,拷贝方法名,然后将该文件添加到jni文件夹中,并在src中删除,然后在xxx-jni.c文件里粘贴上刚刚复制的方法名,在该方法中用C实现即可。

8.动态加载库文件

//生成的是动态的os文件  要动态的加载库文件
static{
System.loadLibrary("demo-jni");
}


JNI常见的几个错误

找不到库 java.lang.UnsatisfiedLinkError: Couldn’t load calc-jn1:

原因1 : 加载的库名不正确

原因2 : 库的代码与运行平台的不符合,新建 Application.mk其中添所有支持平台的库的生成APP_ABI := all

找不方法 java.lang.UnsatisfiedLinkError: Native method not found: com.itheima.resultfromc.MainActivity.resultFromC:(II)I

原因1 : 本地方法名没按jni规范

原因2 : 没有加载库

eg1:将java中的字符串传递到C中,进行逆向加密,然后到java中



char *rever_string(char *s){
//传入的是指针变量,地址传递,将S中的元素 逆向排序  然后直接将S返回去

//s是一个字符数组  s这个数组名就代表数组的首地址

char *p = s;  //分成两句就是:char *p; p = &s;
char *q = s;
char temp = 0;

//让q指向字符数组中 \0的位置
while( *q != '\0'){
q++;  //q是char类型指针,加1,一次数值上 也是加1,一次往后面移动直到\0
}

q--;  //让q移动到\0前一个的位置上
//交换p q的位置
while(p < q){
temp = *p;
*p = *q;
*q = temp;
p++;  //前面的往后面移动
q--;  //后面的往前面移动
}

return s;
}

JNIEXPORT jstring JNICALL Java_com_example_jnidemo_MainActivity_code
(JNIEnv *evn, jobject obj, jstring jstr){

//加密  逆向加密
//首先获取字符串的长度
jstring len = (*evn)->GetStringLength(evn, jstr);
char *ch = NULL;
jstring jNewStr;
//动态申请内存   字符指针<=>声明一个字符数组  c中字符数组要多申请一个字节来存储 \0,
ch = (char *)malloc(len + 1);
//将java传递过来的字符串jstr中的内容拷贝到C中的字符数组中
(*evn)->GetStringUTFRegion(evn,jstr,0,len,ch);
//将字符数组中的元素逆向排序   定义一个方法  返回值 是 char *, 传入的参数是 char *
ch = rever_string(ch);
jNewStr = (*evn)->NewStringUTF(evn,ch);
//申请了内存空间一定要自己手动释放掉
free(ch);
return jNewStr;
}


回到正题,上面说哪个需求,接下来就是实现的代码了,直接上:



希望大家多多回馈项目中使用JNI开发的案例,多多交流多多学习。Thanks
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  jni c语言 android ndk