0

I have a native shared library compiled using android-ndk

one of the C API functions is:

int load_config(const char *fn, Config *cfg)

I have wrapped the function with JNI and successfuly called it from Java, e.g.

Config cfg = new Config();
my_shared_lib.load_config("test.gcf", cfg);
System.out.println("cfg.rx_id = " + cfg.getRx_id());

This prints the expected value from the Config data structure

But now that I have ported it on to an Android emulator I am confused as how to handle the string representing the filename of the configuration data

I have tried adding test.gcf to the $(PROJECT)/assets dir then:

Config cfg = new Config();
my_shared_lib.load_config("assets/test.gcf", cfg);
outputText.append("cfg.rx_id = " + cfg.getRx_id());

but this doesn't work, i.e. the expected value from the Config data structure isn't ouput (I just get a blank)

In other words, what do you do when your native library function expects a filename as a parameter?

bph
  • 9,306
  • 10
  • 51
  • 120

1 Answers1

1

Assets are not stored as files, neither on the device nor on the emulator. They're stored in the APK, which is a ZIP archive; using C/C++ file access functions won't ever work on them. For access to assets from JNI code, use AAssetManager.

Now, the config file probably does not belong to the assets. Assets are by definition read-only; you want your config to be changeable, right? The writeable data folder on Android is retrieved on the Java side via the Context.getDir() function; you derive your filename from that, and pass it to the C side. Something like this:

File Path = Ctxt.getDir("MyData", 0);
File FileName = new File(Path, "test.gcf");
my_shared_lib.load_config(FileName.toString(), cfg); 

The said folder would map to the following path in the Android filesystem: /data/data/com.mypackagename/app_MyData . Different if moving the app to an SD card is enabled.

If you want to ship a default config file in assets but keep it as writeable in the data folder as the app runs, you just have to copy it from assets to the data folder on the first run. Example here.

Community
  • 1
  • 1
Seva Alekseyev
  • 55,897
  • 22
  • 151
  • 252
  • that looks useful - i've gone down the SD card route for now, i.e. adb push files to /mnt/sdcard on the AVD and then specifying that location, e.g. "/mnt/sdcard/test.gcf" as the filename - seems to work but your answer looks more portable... – bph Aug 03 '12 at 15:54
  • 1
    Requiring an SD card for your app to run is a bad, bad design. Some devices don't even support them; some users simply don't have a card. Using `getDir()` allows for both card and internal phone storage; the user would decide. – Seva Alekseyev Aug 03 '12 at 15:55