Retrieving the Default Files Directory from NDK

4,860 views
Skip to first unread message

Oceanblue

unread,
Feb 17, 2011, 12:45:17 PM2/17/11
to android-ndk
As per the design requirement of my app, I have to write a file from
the NDK layer and then read it from the java layer.

No problem, I am able to do this.

However, I don't want to use any hardcoded pathnames, as these might
change in the future...

In the Java layer, I can use Context.getFilesDir() to access this
pathname.

In C layer, how do I access it? Right now I am using this line in my
NDK part:
f = fopen( "data/data/com.test.testjni/files/my_file.txt", "a+" );

I don't want to hardcode the first part, any suggestions?

Olivier Guilyardi

unread,
Feb 17, 2011, 1:46:23 PM2/17/11
to andro...@googlegroups.com
On 02/17/2011 06:45 PM, Oceanblue wrote:
> In the Java layer, I can use Context.getFilesDir() to access this
> pathname.
>
> In C layer, how do I access it? Right now I am using this line in my
> NDK part:
> f = fopen( "data/data/com.test.testjni/files/my_file.txt", "a+" );
>
> I don't want to hardcode the first part, any suggestions?

You need to pass the private files path from Java to C, as a string.
Alternatively, you could pass the context and call getFilesDir() through JNI but
that's unnecessary overhead IMO. There may be some other solution with the new
APIs introduced with Android 2.3, but that won't work on earlier Android releases.

--
Olivier

Jon Paul Schelter

unread,
Feb 18, 2011, 10:18:53 AM2/18/11
to andro...@googlegroups.com, Oceanblue
Pass the string result from getFilesDir() to a native function,
something like this;

java side:
----------------------------
public class MainActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
    {
...
java.io.File dataDir = getFilesDir();
Log.w(TAG, String.format("external files dir is %s", dataDir.toString()));
JNI_SetFilesPath(dataDir.toString());
...
    }
    public static native void JNI_SetFilesPath(String);
    static {
        System.loadLibrary("my_library");
    }
}
----------------------------------
native side:
----------------------------------
#include "jni.h"
char g_FilesDir[MAX_PATH];
void JNICALL JNI_SetFilesPath( JNIEnv* env, jobject thiz, jstring path)
{
    strncpy(g_FilesDir,env-> GetStringUTFChars(path, null),MAX_PATH);
}
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
    JNIEnv* env = NULL;
    vm->GetEnv((void**) &env, JNI_VERSION_1_4)
    const char* activityClass = "com/example/app/MainActivity";
    JNINativeMethod activityMethods[] = {
        {"JNI_SetFilesPath", "(Ljava/lang/String;)V", (void*)JNI_SetFilesPath }
    };
    jclass clazz = env->FindClass(className);
    env->RegisterNatives(clazz, activityMethods, 1) ;
    return JNI_TRUE;
 }
----------------------------------

HTH

> --
> 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.
>

Oceanblue

unread,
Feb 18, 2011, 6:00:26 PM2/18/11
to android-ndk
Thanks for the answers, guys.

Jon, I'm not quite sure what your second JNI function is doing (I know
it will execute when JNI loads, but beyond that?), Also it seems to me
that the following line ends up hardcoding path, which is exactly what
I want to avoid:

Also, I did pass in the path in a string from Java to C as suggested &
that works great. But when I get out of that function & then go back
to the same C file within another function (from another JNI
function), the value is lost. I am storing it in a static char, so not
sure why it's getting lost.

Here is my code:
// android_support.c

#include <stdio.h>
#include <jni.h>
char android_files_dir[128];
const char* utf_string;

#include <android/log.h>
int prior = ANDROID_LOG_DEBUG;

JNIEXPORT void JNICALL Java_com_test_testjni_NativeLib_setLogFilesDir
(JNIEnv * env, jobject obj, jstring filesdir) {

utf_string = (*env)->GetStringUTFChars(env, filesdir, NULL);
if (utf_string == NULL) {
/* OutOfMemoryError already thrown. In some way indicate there has
been an error */
}

strcpy(android_files_dir, utf_string); //value in android_files_dir
available here
(*env)->ReleaseStringUTFChars(env, filesdir, utf_string);
}

char* get_full_log_file_path(char* logfile_name,
char* logfile_full_path, int* length) {

strcpy(logfile_full_path, android_files_dir); //value in
android_files_dir NOT available here
strcat(logfile_full_path, logfile_name);
return logfile_full_path;

}


Not quite sure what I'm doing wrong. Any help would be appreciated.

Nasif Noorudeen

unread,
Feb 20, 2011, 1:51:37 AM2/20/11
to andro...@googlegroups.com
Just  make jstring in c-layer and pass to it java by using a jni wrapper,

Oceanblue

unread,
Feb 22, 2011, 10:41:51 AM2/22/11
to android-ndk
@Nasif,

I actually need to pass the value from Java to C, rather than the
other way around. That part is working but when I come back from Java
to C, the value is lost.
Reply all
Reply to author
Forward
0 new messages