How to read file from APK in NDK ?

7,652 views
Skip to first unread message

MXADD

unread,
May 6, 2010, 4:00:53 PM5/6/10
to android-ndk
Hi

Meybe a stupid question ... but how to get access to files from NDK.
I have activity that calls some native code.
The apk hawe binary file in /res/raw/level.bsp
How to read this file from native code ?

I'v tried:
FILE *f = fopen("/data/data/com.mx.MXEngine/res/raw/level.bsp", "rb")
and
FILE *f = fopen("/data/data/com.mx.MXEngine/files/level.bsp", "rb")
but both return NULL
what is the location of files stored inside res/raw in apk

(and side question: is there any hackish way to have directories
inside res/raw ? - i could pack whole filestree to single zip and deal
with it inside my native code -- but for fast prototyping it's
painfull)

Thanks a lot!

--
You received this message because you are subscribed to the Google Groups "android-ndk" group.
To post to this group, send email to andro...@googlegroups.com.
To unsubscribe from this group, send email to android-ndk...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/android-ndk?hl=en.

David Turner

unread,
May 7, 2010, 1:55:35 AM5/7/10
to andro...@googlegroups.com
The file is inside the .apk file, which is itself a zip file. You will need to use zlib to extract data from it.
Moreover, you should use Java to get the location of the .apk itself. Sorry if I do not remember which exact API to use.

fulanito

unread,
May 7, 2010, 6:07:18 AM5/7/10
to android-ndk
Take a look at the second post in the following thread:
http://groups.google.com/group/android-ndk/browse_thread/thread/a69084018e87a5a8
It worked for me.
> > android-ndk...@googlegroups.com<android-ndk%2Bunsubscribe@googlegr oups.com>
> > .
> > For more options, visit this group at
> >http://groups.google.com/group/android-ndk?hl=en.
>
> --
> You received this message because you are subscribed to the Google Groups "android-ndk" group.
> To post to this group, send email to andro...@googlegroups.com.
> To unsubscribe from this group, send email to android-ndk...@googlegroups.com.
> For more options, visit this group athttp://groups.google.com/group/android-ndk?hl=en.

Doug Schaefer

unread,
May 7, 2010, 11:20:43 AM5/7/10
to andro...@googlegroups.com
Does anyone have a complete example of this. The method in the thread just talks about getting the offset of your file in the apk, but not how to extract it. The recommendation to use zlib suggests that the contents are compressed. Are they?

Dianne Hackborn

unread,
May 7, 2010, 3:36:09 PM5/7/10
to andro...@googlegroups.com
There are two main directories in an .apk:

res/ contains the processed resources.  It contains one level of directory nesting, organizing the contents by resource type and configuration.  Data here is accessed through Resources.
assets/ contains an arbitrary directory hierarchy of arbitrary files.  The AssetManager class has APIs for opening data here.

An .apk is a .zip file, so each file is usually compressed.  There are some file types that are not compressed, such as .png and .jpeg, since there is no reason to.  For compressed files you CAN NOT get the file descriptor, since what you would get a pointer to would be compressed data.  So if you are using the API to get a FileDescriptor (actually an AssetFileDescritor, because the fd itself is the entire .apk file and AssetFileDescriptor tells you where to find the data in it), then you are not dealing with a compressed entry.

For a compressed entry, the only way to access its data is through InputStream, and the file size is currently limited to 1MB because it needs to decompress the data upon open.  (Some day I really want to have this to progressive decompression, but haven't had time yet.)
--
Dianne Hackborn
Android framework engineer
hac...@android.com

Note: please don't send private questions to me, as I don't have time to provide private support, and so won't reply to such e-mails.  All such questions should be posted on public forums, where I and others can see and answer them.

Kelly

unread,
May 8, 2010, 5:40:20 PM5/8/10
to android-ndk
I had to grab some resource files natively so I asked good ol' uncle
google and came up with:
http://www.anddev.org/ndk_opengl_-_loading_resources_and_assets_from_native_code-t11978.html

The example took a bit to reverse-engineer but basically you end up
with a zip_file type that has the file info. Using one of the libzip
functions I just copy the file into a buffer and use it that way.

Cheers.


On May 7, 8:20 am, Doug Schaefer <cdtd...@gmail.com> wrote:
> Does anyone have a complete example of this. The method in the thread just
> talks about getting the offset of your file in the apk, but not how to
> extract it. The recommendation to use zlib suggests that the contents are
> compressed. Are they?
>
>
>
>
>
> On Fri, May 7, 2010 at 6:07 AM, fulanito <fulanito...@gmail.com> wrote:
> > Take a look at the second post in the following thread:
>
> >http://groups.google.com/group/android-ndk/browse_thread/thread/a6908...

fulanito

unread,
May 10, 2010, 4:49:43 AM5/10/10
to android-ndk
Doug,
I just rename the file I need to read from within NDK, using the .mp3
suffix, to avoid file compression.
For those using Ant to build the application, it is possible to mark a
specific file to avoid it being compressed;
I´ll make an educated guess you use Eclipse, like me :-).
Fulanito.

On May 7, 5:20 pm, Doug Schaefer <cdtd...@gmail.com> wrote:
> Does anyone have a complete example of this. The method in the thread just
> talks about getting the offset of your file in the apk, but not how to
> extract it. The recommendation to use zlib suggests that the contents are
> compressed. Are they?
>
>
>
>
>
> On Fri, May 7, 2010 at 6:07 AM, fulanito <fulanito...@gmail.com> wrote:
> > Take a look at the second post in the following thread:
>
> >http://groups.google.com/group/android-ndk/browse_thread/thread/a6908...

fulanito

unread,
May 12, 2010, 12:10:13 PM5/12/10
to android-ndk
Ok, finally I got a few minutes to rewrite it all.
I hope it will be helpfull.
So, here goes:
a detailed example of using an AssetFileDescriptor for reading a file
from apk, from inside native code.

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.myFile);
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 :-).
Fulanito.
Reply all
Reply to author
Forward
0 new messages