- 论坛徽章:
- 0
|
Android系统对于资源的处理是存放于apk文件中,通过公共接口进行读取。如此一来,在jni调用中,如果要与底层公用一个资源文件,则需要另存一份资源文件的拷贝。然而这种浪费空间的行为在Android系统中也有所折中:Android的JDK,是harmony版本,而非sun官方的openJDK版本,在harmony版本的jdk中,FileDescriptor中多了一个隐式的descriptor字段保存一个文件句柄。我们则可以通过此文件句柄打开此文件。
private void initPinyinEngine() {
System.load(LIBPATH);
byte usr_dict[];
usr_dict = new byte[MAX_PATH_FILE_LENGTH];
AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(
R.raw.dict_pinyin);
if (getUsrDictFileName(usr_dict)) {
inited = nativeImOpenDecoderFd(afd.getFileDescriptor(), afd
.getStartOffset(), afd.getLength(), usr_dict);
}
try {
afd.close();
} catch (IOException e) {
}
}
JNIEXPORT jboolean JNICALL nativeImOpenDecoderFd(JNIEnv* env, jclass jclazz,
jobject fd_sys_dict, jlong startoffset, jlong length,
jbyteArray fn_usr_dict) {
jclass clazz = env->FindClass("java/io/FileDescriptor");
jfieldID field = env->GetFieldID(clazz, "descriptor", "I");
jint fd = env->GetIntField(fd_sys_dict, field);
jbyte *fud = (*env).GetByteArrayElements(fn_usr_dict, 0);
jboolean jret = JNI_FALSE;
int newfd = dup(fd);
if (im_open_decoder_fd(newfd, startoffset, length, (const char*) fud))
jret = JNI_TRUE;
close(newfd);
(*env).ReleaseByteArrayElements(fn_usr_dict, fud, 0);
return jret;
}
这是在Android系统中底层利用程序资源的最佳方式,然而对于自己的动态链接库,则有不可避免的文件拷贝。如果自己的库比较大,则可以选择另建一个小的动态链接库拷贝到特定目录供系统load,通过此库,自己来做另一个动态库的操作,此方法太复杂,还是算了。
harmony的jni语法与openJDK基本相同,唯一的区别就是更加面向对象了。ndk只是简化版的Android project包,在开发方式和开发速度上与在Android项目下自己交叉编译没有多大区别,并且没有解决调试的问题。在做一些这样的项目的时候,建议自己装arm-none-eabi 工具集(建议装binary版,自己编译太虐待了),生成直接运行的程序,这样虽不能解决调试问题,却也能提高开发速度。
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/99624/showart_2033663.html |
|