书写javanative接口

知识点:

javah-classpath .-jni com.test.jni.FileJNILib

将Java的String转为C的字符串,字符串的转换如下:

const charconst *p_passwd = (*env)->GetStringUTFChars(env, j_passwd, NULL);

c 代码中声明字符串数组,调用NewStringUTF,即可转为Java String
char szName[256];
(*env)->NewStringUTF(env,szName);

下面我们进入实战的阶段,写代码。

建立一个android1.5的项目,NDK不支持1.5以下的版本


JNI.java的代码:



JniTest.java的代码:


4.生成JNI头文件

下面生成JNI头文件啦,使用javah命令,对JNI..java这个文件生成,别搞错啦!

使用cmd进入android项目的bin目录中,然后执行javah-classpath.-jnicc.androidos.jni.JNI这个命令。别忘记包名!(^_^


生成了一个cc_androidos_jni_JNI.h

打开看看:


里面都是c语言的头文件声明

5.书写C代码,写入数据

下面进行c语言代码的阶段,不会C的,可以去学习一下。

我这里使用eclipseforc/c++的进行开发,简单的代码大家可以使用记事本。

工程如下:


cc_androidos_jni_JNI.h内容不变

cc_androidos_jni_JNI.c的内容:


在这里的代码会在运行的时候向sdcard写入androidos.cc.txt文件。然后写入aaaa数据。

6.编译SO文件

进行编译so文件:

NDKapps目录下面创建一个myjni文件夹,在myjni文件夹中创建一个Application.mk文件,文件的内容为:


NDKsources目录下创建myjni文件夹,在myjni文件中创建一个Android.mk文件,然后将cc_androidos_jni_JNI.hcc_androidos_jni_JNI.c文件copy进来:


Android.mk中的内容如下: LOCAL_SRC_FILES := com_test_jni_FileJNILib.c common.c


里面内容的关键字含义请自行查看docs\OVERVIEW.TXT文件

编译:


7.加入到Android项目中进行运行

apps\myjni\libs整个文件夹copyandroid项目下:


运行android项目使用adbshell进行查看:


进入sdcard查看数据。

注意:sdcard具有system的权限,如果你的目录是root权限的,那么是不能写成功的,除非是真机越权,模拟器是不成功的,并且在Eclipselogcat下会有DEBUG信息出现。


NOT FOUND JNI_OnLoad问题:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <stdio.h>

#include <stdlib.h>

#include <jni.h> //jni的主要头文件


#include "com_test_jni_FileJNILib.h"
/* Header for class com_test_jni_FileJNILib */

/*
* Class: com_test_jni_FileJNILib
* Method: fileCrypt
* Signature: (Ljava/lang/String;Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_com_test_jni_FileJNILib_fileCrypt__Ljava_lang_String_2Ljava_lang_String_2
(JNIEnv * env, jclass thiz, jstring source, jstring dest){
return 1;
}

/*
* Class: com_test_jni_FileJNILib
* Method: fileCrypt
* Signature: (Ljava/io/File;)Ljava/io/File;
*/
JNIEXPORT jobject JNICALL Java_com_test_jni_FileJNILib_fileCrypt__Ljava_io_File_2
(JNIEnv * env, jclass thiz, jobject source){
return NULL;
}

static const JNINativeMethod gMethods[] = { //定义批量注册的数组,是注册的关键部分

{"fileCrypt", "(Ljava/lang/String;Ljava/lang/String;)I", (void*)Java_com_test_jni_FileJNILib_fileCrypt__Ljava_lang_String_2Ljava_lang_String_2} ,// func2是在java中声明的native函数名,"()V"是函数的签名,可以通过javah获取。
{"fileCrypt", "(Ljava/io/File;)Ljava/io/File;", (void*)Java_com_test_jni_FileJNILib_fileCrypt__Ljava_io_File_2}
};


JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void *reserved) //这是JNI_OnLoad的声明,必须按照这样的方式声明

{

JNIEnv* env = NULL; //注册时在JNIEnv中实现的,所以必须首先获取它

jint result = -1;


if((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_4) != JNI_OK) //从JavaVM获取JNIEnv,一般使用1.4的版本

return -1;

jclass clazz;

static const char* const kClassName="com/test/jni/FileJNILib";

clazz = (*env)->FindClass(env, kClassName); //这里可以找到要注册的类,前提是这个类已经加载到java虚拟机中。 这里说明,动态库和有native方法的类之间,没有任何对应关系。

if(clazz == NULL)

{

printf("cannot get class:%s\n", kClassName);

return -1;

}

if((*env)->RegisterNatives(env, clazz,gMethods, sizeof(gMethods)/sizeof(gMethods[0]))!= JNI_OK) //这里就是关键了,把本地函数和一个java类方法关联起来。不管之前是否关联过,一律把之前的替换掉!

{

printf("register native method failed!\n");

return -1;

}

return JNI_VERSION_1_4; //这里很重要,必须返回版本,否则加载会失败。

}

更多相关文章

  1. Android实现关机重启的方法
  2. Android安全卫士-检测升级(一)
  3. Android(安卓)当媒体变更后,通知其他应用重新扫描
  4. More than one file was found with OS independent path 'lib/a
  5. Android下使用GDB调试无符号ELF文件
  6. Android(安卓)Studio 配置应用自动签名
  7. Didn't find class "androidx.core.content.FileProvider" on pa
  8. Android+Listview+分页+动态加载网络数据
  9. Android(安卓)国际化语言设置,简单粗暴。

随机推荐

  1. Android在layout xml中使用include
  2. Android(安卓)文件的上传
  3. Android 编译系统分析之返璞归真(一)
  4. Android极致优化
  5. Android的多语言文件转IOS多语言文件格式
  6. 安卓系统框架介绍
  7. Android与JNI(一)
  8. textview中自动换行显示文本内容
  9. [Android Studio]-基本快捷键大全
  10. C#开发Android