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