Here is a detailed example of how to read a file located in the apk,
from within native code, using an AssetFileDescriptor:
The file name is myFile.mp3 (I use the .mp3 suffix to avoid file
compression), and it is located in the res/raw/ directory.
--------------------------------------------
--------------------------------------------
In the Java side:
package com.myApp;
public final class myClass{
public static int init(MyActivity activity)
{
AssetFileDescriptor afd =
activity.getApplicationContext().getResources().openRawResourceFd(R.raw.myF
ile);
int res = 0;
if (afd != null)
{
FileDescriptor fd = afd.getFileDescriptor();
int off = (int) afd.getStartOffset();
int len = (int) afd.getLength();
res = initNative(fd, off, len);
}
return res;
}
public static native int initNative(FileDescriptor fd, long
off, long
len);
}
-------------------------------------------
-------------------------------------------
In C++ side:
in the .h file:
----------------
#include <stdio.h>
#include <jni.h>
extern "C" {
JNIEXPORT jint JNICALL Java_com_myApp_myClass_initNative
(JNIEnv * env, jclass thiz, jobject fd_sys, jlong off, jlong len);
}
in the .cpp file:
--------------------
#define
SUCCESS
0
#define ERROR_CODE_CANNOT_OPEN_MYFILE 100
#define ERROR_CODE_CANNOT_GET_DESCRIPTOR_FIELD 101
#define ERROR_CODE_CANNOT_GET_FILE_DESCRIPTOR_CLASS 102
JNIEXPORT jint JNICALL Java_com_myApp_myClass_initNative
(JNIEnv * env, jclass thiz, jobject fd_sys, jlong off, jlong len)
{
jclass fdClass = env->FindClass("java/io/FileDescriptor");
if (fdClass != NULL){
jfieldID fdClassDescriptorFieldID = env-
>GetFieldID(fdClass,
"descriptor", "I");
if (fdClassDescriptorFieldID != NULL && fd_sys != NULL)
{
jint fd = env->GetIntField(fd_sys,
fdClassDescriptorFieldID);
int myfd = dup(fd);
FILE* myFile = fdopen(myfd, "rb");
if (myFile){
fseek(myFile, off, SEEK_SET);
/
***************************************************
here myFile is a regular FILE*
pointing to
the file I want to read.
I use the fscanf function:
***************************************************/
fscanf(fp, "%d%d", &var1, &var2);
fscanf(fp, "%d%d", &var3, &var4);
...
...
...
return (jint)SUCCESS;
}
else {
return (jint)
ERROR_CODE_CANNOT_OPEN_MYFILE;
}
}
else {
return
(jint)ERROR_CODE_CANNOT_GET_DESCRIPTOR_FIELD;
}
}
else {
return
(jint)ERROR_CODE_CANNOT_GET_FILE_DESCRIPTOR_CLASS;
}
}
Just a short warning, quoting fadden (
http://groups.google.com/group/
android-ndk/browse_thread/thread/a69084018e87a5a8):
>"descriptor" is a package-private field inside FileDescriptor, and as
>such isn't part of the API, is subject to change, etc.
"descriptor" field is used in the C++ code, so pay attention that the
above code is using non API fields, and may crash in the future.
I hope that until this happens, the NDK team will come up with an
official solution to reading assets in native code :-).
Hope this helps,
Fulanito.
> You can see the whole source file here:
http://wlan-lj.net/browser/trunk/meshapp/android/meshapp/src/net/wlan...