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
How Does One Implement Drag and Drop for Android Marker
How to Copy Selected Files from Android with Adb Pull
How to Use Mediacodec Without Mediaextractor for H264
Android - Periodic Background Service - Advice
Setting a Maximum Width on a Viewgroup
Android App Integrated with Ok Google
Do Gcm Registration Id's Expire
How to Add a Hint in Spinner in Xml
Network_Provider Not Providing Updated Locations
Android: Custom Separator (Or Even Item) in Listview Depening on Content of Item
Upload an Image Using Google Volley
Clear All Activities in a Task
What Happens If a Android Service Is Started Multiple Times