Write File to Location Other Than Sdcard Using Android Ndk

File Operations in Android NDK

Other answers are correct. You can open a file through the NDK using FILE and fopen, but don't forget to place a permission for it.

In the Android manifest place:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 

Android - writing/saving files from native code only

For relatively small files(application config files, parameter files, log files etc.)
is best to use the internal application private storage, that is /data/data/<package>/files.
The external storage if it exists at all (being it SD card or not) should be used for large files that do not need frequent access or updates.

For the external data storage the native application has to "request" the correct permissions in the application's AndroidManifest.xml:

<manifest>
...
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">
</uses-permission>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE">
</uses-permission>
</manifest>

For the internal application private storage fopen/fclose(or C++ stream equivalents if available) API could be used. Following example illustrates using the Android NDK AssetManager to retrieve and read a configuration file. The file must be placed into the assets directory inside the native application’s project folder so that the NDK build could pack them inside the APK. The internalDataPath/externalDataPath bug I was mentioning in the question was fixed for the NDK r8 version.

...
void android_main(struct android_app* state)
{
// Make sure glue isn't stripped
app_dummy();

ANativeActivity* nativeActivity = state->activity;
const char* internalPath = nativeActivity->internalDataPath;
std::string dataPath(internalPath);
// internalDataPath points directly to the files/ directory
std::string configFile = dataPath + "/app_config.xml";

// sometimes if this is the first time we run the app
// then we need to create the internal storage "files" directory
struct stat sb;
int32_t res = stat(dataPath.c_str(), &sb);
if (0 == res && sb.st_mode & S_IFDIR)
{
LOGD("'files/' dir already in app's internal data storage.");
}
else if (ENOENT == errno)
{
res = mkdir(dataPath.c_str(), 0770);
}

if (0 == res)
{
// test to see if the config file is already present
res = stat(configFile.c_str(), &sb);
if (0 == res && sb.st_mode & S_IFREG)
{
LOGI("Application config file already present");
}
else
{
LOGI("Application config file does not exist. Creating it ...");
// read our application config file from the assets inside the apk
// save the config file contents in the application's internal storage
LOGD("Reading config file using the asset manager.\n");

AAssetManager* assetManager = nativeActivity->assetManager;
AAsset* configFileAsset = AAssetManager_open(assetManager, "app_config.xml", AASSET_MODE_BUFFER);
const void* configData = AAsset_getBuffer(configFileAsset);
const off_t configLen = AAsset_getLength(configFileAsset);
FILE* appConfigFile = std::fopen(configFile.c_str(), "w+");
if (NULL == appConfigFile)
{
LOGE("Could not create app configuration file.\n");
}
else
{
LOGI("App config file created successfully. Writing config data ...\n");
res = std::fwrite(configData, sizeof(char), configLen, appConfigFile);
if (configLen != res)
{
LOGE("Error generating app configuration file.\n");
}
}
std::fclose(appConfigFile);
AAsset_close(configFileAsset);
}
}
}

How do I write to the internal storage file system with NativeActivity?

I finally found it. Turns out the path to the internal storage directory is declared as a member of ANativeActivity in android/native_activity.h:

/**
* Path to this application's internal data directory.
*/
const char* internalDataPath;

Removable Storage Access in Android with NDK API

I could get the path of secondary removable storage(sdcard) with below code

There is no requirement for that environment variable to exist, let alone point to something meaningful.

I couldn't create and read file with fopen

You do not have direct filesystem access to arbitrary locations on removable storage on Android 4.4+.

can you please tell me how to create and read file with fopen api in removable path(secondary_storage) ?

Your only places for direct filesystem access to removable storage is in the locations returned by getExternalFilesDirs(), getExternalCacheDirs(), and getExternalMediaDirs(). Those are all methods on Context (e.g., an activity or service). If they return 2+ values, the second and subsequent ones are on removable storage. Your Java code can supply those paths to your NDK code.

Simultaneously write and read a file from NDK in android

This should be possible using pthreads. So you need to spawn 2 threads, one doing the writing and other doing the reading. If you are doing it from the same file, you may run into race conditions, so be careful.

More more info on pthreads, kindly google. It's commonly used by the Linux world.

Writeable and Executable location on Android

If you want to avoid rooting the device then basically SD card is the only place you can assume is world writeable


EDIT: mind recent changes in Android framework as of 2014/2015!.

It's better to make your binary part of installable APK which then extract this binary out of APK into private storage, make it world executable etc and somehow announce binary location, but in general expect some problems depending on OS version and vendor



Related Topics



Leave a reply



Submit