JNI和NDK使用介绍
来源:互联网 发布:linux jdk1.7下载地址 编辑:程序博客网 时间:2024/05/28 19:25
jni 的介绍
JNI日志输出到Logcat中
#include <android/log.h>#define LOG_TAG "===xcloud==="
#define LOGI(...)
#define LOGW(...)
#define LOGE(...)
Android.mk文件添加编译模块:
LOCAL_LDLIBS=-lm -llog
使用方法:
LOGE("%s",test);
JNI调用Java方法
以调用String 的getBytes方法为例:第一步:
jclass clsstring = (*env)->FindClass(env,"java/lang/String"); //找到Java String 类
第二步:
jstring strencode = (*env)->NewStringUTF(env,"utf-8"); //得到一个jstring 对象
第三步:
jmethodID mid = (*env)->GetMethodID(env,clsstring, "getBytes", "(Ljava/lang/String;)[B"); //得到getBytes方法
第四步:
jbyteArray barr= (jbyteArray)(*env)->CallObjectMethod(env,jstr, mid, strencode); //“jstr 为传入的字符串”调用getBytes方法
第五步:
jsize alen = (*env)->GetArrayLength(env,barr); //得到数组长度
jstring 转换 char*
char* test=(char*)(*env)->GetStringUTFChars(env,jstringVariable,NULL);
返回一个java对象数组
第一步:jclass objectClass=(*env)->FindClass(env,"com/xuzhitech/xcloud/resource"); //找到对应的java 类(对象)
第二步:
jobjectArray array=(*env)->NewObjectArray(env,currentListCount,objectClass,NULL); //通过取到的java类(对象)创建一个指定固定大小的数组
第三步:
jfieldID _uri=(*env)->GetFieldID(env,objectClass,"uri","Ljava/lang/String;");//找到对象中的列
注意:在JNI中并未提供jstring 类型的对象,所以必须通过L指定包名找到该类,在有提供的类型中,可以直接使用该类型的大写首字母(jlong 需使用J)
如jint 类型可以如此编写:
jfieldID _vcr=(*env)->GetFieldID(env,objectClass,"is_vcr","I");对应的JNI提供类型可以参考如下 http://download.oracle.com/javase/1.4.2/docs/guide/jni/spec/functions.html
第四步:
jmethodID jid = (*env)->GetMethodID(env,objectClass,"<init>","()V");//"<init>"代表可以访问默认构造函数
jobject jobj=(*env)->NewObject(env,objectClass,jid); //通过第一步找到的jclass创建对应的对象
第五步:
(*env)->SetObjectField(env,jobj,_modtime,jmodtime); //为对象中的每一列赋值。注意:如果JNI有提供的数据类型,可按提供的类型为对象中的列赋值,
如:(*env)->SetIntField(env,jobj,_vcr,current->is_vcr);
第六步:
(*env)->SetObjectArrayElement(env,array,i,jobj);将对象设置进第二步声明的数组中
DeleteLocalRef(env,jobj);//删除引用对象
在JNI中循环读取对象数组
jobject
jstring
LOGE("=====uri===%s====",jstringtoChar(env,jstr));
}
上面使用到的jstringtoChar方法代码:
char*
char*
jclass
jstring
jmethodID
jbyteArray
jsize
jbyte*
if
{
rtn
memcpy(rtn,
rtn[alen]
}
(*env)->ReleaseByteArrayElements
return
}
cpp JNI与 c JNI的主要注意事项:
用C编写jni文件,访问JNI内置提供方法格式:(*env)->SetObjectArrayElement(env,array,i,jobj);
用CPP编写JNI文件,访问JNI内置提供方法格式:
env->SetObjectArrayElement(array,i,jobj);
另外,使用CPP编写的JNI代码,在调用C语言编写的库的时候,要添加以下代码,才可以正常使用(不然在链接的时候找不到相关接口:undefined reference.....):
ifdef __cplusplus
extern "C" {
#endif
... //引入的头文件
#ifdef __cplusplus
}
#endif
其他用法几乎一致。
JNI 使用Native注册
按照上面的方法写函数体,必须遵循JNI官方的一大堆标准进行方法的定义,有时候方法一多,不大好管理,也不利用查看,并且每次都要写一大堆恶心的标准方法名也不是一件好事。对此JNI有一套可以通过Native 注册的机制可以使用,以方便函数体的编写。
以下是Android 调用JNI注册Natives 的步骤:
第一步
声明Java中要调用jni 的类路径:
static const char *className="com/xuzhitech/xcloud/cadaver";
第二步
创建方法格式结构体:
struct JNINativeMethod {
const char* name;//method name
const char* signature; //java method return value
void* fnPtr;//c/c++ method
} ;
第三步
使用结构体注册需要供Android 调用的方法体:
{"StringTestOne",
{"executels","()[Lcom/xuzhitech/xcloud/resource;",(void*)executels},
{"getProgress","()Lcom/xuzhitech/xcloud/fileProgress;",(void*)getProgress},
{"getdownloadState","()I",(void*)getdownloadState},
{"changeExecutable","(Ljava/lang/String;Ljava/lang/String;)I",(void*)changeExecutable},
{"Login","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",(void*)Login},
{"getCurrentListCount","()I",(void*)getCurrentListCount},
{"mkcol","(Ljava/lang/String;)I",(void*)mkcol},
{"deleteFile","(Ljava/lang/String;)I",(void*)deleteFile},
{"deleteCol","(Ljava/lang/String;)I",(void*)deleteCol},
{"getFullUri","()Ljava/lang/String;",(void*)getFullUri},
{"cdCommand","(Ljava/lang/String;)I",(void*)cdCommand},
{"logout","()V",(void*)logout},
{"doCopy","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",(void*)doCopy},
{"doMove","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",(void*)doMove},
{"getFile","(Ljava/lang/String;Ljava/lang/String;)V",(void*)getFile},
{"putFile","(Ljava/lang/String;Ljava/lang/String;)V",(void*)putFile},
{"lock","(Ljava/lang/String;)I",(void*)lock},
{"unlock","(Ljava/lang/String;Ljava/lang/String;)I",(void*)unlock},
{"getToken","(Ljava/lang/String;)Ljava/lang/String;",(void*)getToken},
{"isSetToken","(Ljava/lang/String;)I",(void*)isSetToken},
};
第一个参数为:Java实现要调用的方法名称
第二个参数为:该方法需要的返回值与方法参数,如->(方法参数)返回值,详细使用参考如下:
具体的每一个字符的对应关系如下
字符 Java类型 C类型
Z
I
J
D
F
B
C
S
数组则以"["开始,用两个字符表示
[F
[B
[C
[S
[D
[J
[Z
第三个参数为,第一个参数需要映射的本地c/c++对应的函数指针方法。
第四步
在加载jni的时候指定JNI版本并且通过传入进来的class路径注册Natives 方法
jint
JNIEnv*
jclass
int
if
LOGE("ERROR:
return
}
//
clazz
if
LOGE("Native
return
}
methodsLenght
if
LOGE("RegisterNatives
return
}
//
result
return
}
注意,使用Natives注册运行程序时,它会先检测jni与java类使用jni 类的native 方法是否相对应与一致,即使你没有使用到该 方法也会进行检测。
第五步
通过上面的修改,c/c++编写的jni 文件就可以不带一大串标准名称了,您可以像正常编写c一样编写你的jni函数,如下:
jint
char*
char*
char*
int
//
(*env)->ReleaseStringUTFChars(env,jsrc,src);
//
(*env)->ReleaseStringUTFChars(env,jdest,dest);
//
(*env)->ReleaseStringUTFChars(env,jrename,rename);
return
}
JNI的一些基本方法的使用都可以参考这个网站:http://docs.oracle.com/javase/1.4.2/docs/guide/jni/spec/functions.html
- JNI和NDK使用介绍
- NDK和JNI的使用
- JNI和Android NDK的使用
- JNI和Android NDK的使用
- Android中JNI和NDK的使用
- 【移动开发】如何使用ndk和jni
- JNI和NDK编程-使用AndroidStudio进行NDK开发
- 使用Android NDK开发(一):Android NDK介绍(包括JNI的介绍)
- 配置NDK,使用JNI
- jni和ndk详解
- NDK 和 JNI 总结
- Android NDK和Jni
- JNI和NDK
- JNI和NDK
- JNI和NDK编程
- JNI和NDK笔记
- JNI 和NDK开发
- JNI和NDK
- MFC组件应用
- Android Dependencies
- 用标准的SQL语句实现查询记录的分页
- Android国际化(一)语言、国家/区域代码
- Postgresql 创建主键并设置自动递增的三种方法
- JNI和NDK使用介绍
- SQL Server返回最后一个标识值的三个函数:IDENT_CURRENT、@@IDENTITY、SCOPE_IDENTITY
- Android打印代码调用栈
- 数据库出现ORA-01033问题 解决方法
- 开发自己的Maven插件之四:基本概念
- Objective-C中的一些特殊的数据类型
- Amazon Flow更新 支持QR条码及增强现实购物功能
- android2.3修改ethernet默认为不选中状态
- webservice(JAX-WS)的配置