8

How do you access an Android asset, such as a .txt file, from C with the JNI?

I'm trying "file:///android_asset/myFile.txt", and locally "myFile.txt" with a duplicate of myFile.txt in the jni folder with the C implementation file.

Ken
  • 30,811
  • 34
  • 116
  • 155
  • See this answer: http://stackoverflow.com/questions/10409125/android-read-text-file-from-asset-folder-using-c-ndk – Derzu Jan 15 '14 at 13:06

2 Answers2

12

The thing with assets is that you can't access them directly as files. This is because the assets are read directly from the APK. They're not unzipped to a given folder upon installation.

Starting from Android 2.3, there is a C API to access assets. Have a look at <android/asset_manager.h> and the assetManager field in <android/native_activity.h>. I've never used this though, and I'm not sure that you can use this asset manager API if you don't rely on a native activity. And anyway, this won't work on Android 2.2 and below.

So I see three options:

  • you could extract the assets into some directory but this will take extra space
  • you could (bunlde and) use something like libzip to read the assets from the APK in pure C.
  • or, to avoid bundling an extra library, my personal preference is to read data in C, using JNI, from the Java InputStream object returned by AssetManager.open(). It takes a little code but it works great.
olivierg
  • 10,200
  • 4
  • 30
  • 33
3

If you cannot use the AssetManager C API, because you need to call a C/C++ library that requires a filename, a raw resource can be used, instead.

The only disadvantage is that it needs to be copied to your app's data (temp) dir at runtime.

Place the File in res/raw

Place the file you want to read from native code in the res/raw dir.

Make a Copy

At runtime, copy the file from res/raw/myfile.xml to the data dir:

File dstDir = getDir("data", Context.MODE_PRIVATE);
File myFile = new File(dstDir, "tmp_myfile.xml");
FileMgr.copyResource(getResources(), R.raw.my_file, myFile);

Now the filename to pass to your native code is myFile.getAbsolutePath()

copyResource (rsrcId, dstFile)

public static File copyResource (Resources r, int rsrcId, File dstFile) throws IOException
{
    // load cascade file from application resources
    InputStream is =  r.openRawResource(rsrcId);
    FileOutputStream os = new FileOutputStream(dstFile);

    byte[] buffer = new byte[4096];
    int bytesRead;
    while ((bytesRead = is.read(buffer)) != -1)
        os.write(buffer, 0, bytesRead);
    is.close();
    os.close();

    return dstFile;
}
Brent Faust
  • 9,103
  • 6
  • 53
  • 57
  • Sorry for making this thread live again after a long time. I read a file from `asset` folder and then wrote that file using `FileOutputStream`. My question is what the path of the file saved by `FileOutputStream`. – Saad Saadi Aug 26 '15 at 04:47