打开文件
在底层open一个文件时只是返回一个fd号,而Java打开一个文件用的是FileDescriptor来打开一个文件,如何在两者之间建立一个联系呢?有两种方法:
方法一:在jni层有提供一个API,jniCreateFileDescriptor(env, fd); 生成的是一个临时变量,最终还是要通过NewObject创建一个对象才能return回去。在Android.mk里还要加入这些库,这些库从系统里的jni的Android.mk里抄过来的,jniCreateFileDescriptor要用到的是哪个库还有待研究。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
jclass clazz = env->FindClass("android/os/ParcelFileDescriptor");if(clazz
== NULL){ XLOGE("Unable
to find class android.os.ParcelFileDescriptor"); return -1;}
gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
gParcelFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "(Ljava/io/FileDescriptor;)V"); jobject
fileDescriptor = jniCreateFileDescriptor(env, fd);if(fileDescriptor
== NULL){ XLOGE("jniCreateFileDescriptor
error"); return NULL;}return env->NewObject(gParcelFileDescriptorOffsets.mClass, gParcelFileDescriptorOffsets.mConstructor,
fileDescriptor); |
Android.mk用到的库
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
LOCAL_SHARED_LIBRARIES
:= \ libandroid_runtime
\ libandroidfw
\ libbinder
\ libcutils
\ liblog
\ libhardware
\ libhardware_legacy
\ libnativehelper
\ libutils
\ libui
\ libinput
\ libinputservice
\ libsensorservice
\ libskia
\ libgui
\ libusbhost
\ libsuspend
\ libdl
\ libEGL
\ libGLESv2 |
方法二:
直接创建找到这个类,并调用这个对象的构建函数创建这个对象
|
1
2
3
4
5
6
7
8
|
/*
Create a corresponding file descriptor */{ jclass
cFileDescriptor = env->FindClass("java/io/FileDescriptor"); jmethodID
iFileDescriptor = env->GetMethodID(cFileDescriptor, "<init>", "()V"); jfieldID
descriptorID = env->GetFieldID(cFileDescriptor, "descriptor", "I"); mFileDescriptor
= env->NewObject(cFileDescriptor, iFileDescriptor); env->SetIntField(mFileDescriptor,
descriptorID, (jint)fd);} |
关闭文件
关闭文件也有两种文件
一. 在打开的时候把fd保存为全局变量,关闭的时候只要close(fd)。即可
二. 这是一个比较显高端的方法,就是找到打开这个文件的类,然后在这里类里找到FileDescriptor变量,再找出该FileDescriptor对象里的fd变量,关闭fd即可
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
void closeFile(JNIEnv
*env, jobject thiz){ //根据对象this获取这个对象的类 jclass
SerialPortClass = env->GetObjectClass(thiz); //找出FileDescriptor类 jclass
FileDescriptorClass = env->FindClass( "java/io/FileDescriptor"); //在SerialPortClass这个类里找出mFd这个变量的ID,这个变量的类型是FileDescriptor jfieldID
mFdID = env->GetFieldID(SerialPortClass, "mFd","Ljava/io/FileDescriptor;"); //在FileDescriptor里找出descriptor的ID,这是一个整型。就是我们用open打开返回的那个fd jfieldID
descriptorID = env->GetFieldID(FileDescriptorClass, "descriptor", "I"); //根据上面找出来的mFd的ID,从在erialPortClass这个类里找出mFd这个实例变量 jobject
mFd = env->GetObjectField(thiz, mFdID); //根据上面找出来的mFd的实例变量,再从里面这个类里找出mFD实例变量里的descriptor jint
descriptor = env->GetIntField(mFd, descriptorID); close(descriptor);} |
本文详细探讨了如何在Java与JNI之间建立联系,实现文件操作的高级功能,包括文件打开、关闭及使用特定类进行文件管理。通过两种方法介绍了在JNI层创建FileDescriptor对象的过程,以及如何在Android环境中进行文件操作。重点分析了在打开文件时保存文件描述符和通过类实例直接管理文件描述符的两种策略。
777

被折叠的 条评论
为什么被折叠?



