打开文件
在底层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); } |