Android App&x27;本机代码中外部存储的路径

Android App&x27;本机代码中外部存储的路径,android,c++,android-ndk,java-native-interface,storage,Android,C++,Android Ndk,Java Native Interface,Storage,我正在尝试为我的应用程序编写一个本机库,这样我就可以在本机代码中执行所有文件操作。我读到getExternalStorageDirectory()给出目录的外部存储路径 我的问题是,如何在不将位置硬编码到某个字符串的情况下访问相同的位置?在Android NDK中,是否有任何功能可以在C++代码中给出与java的代码> GETEngultSturrAdvestRoTyTyle()/相同的函数?< /P> < P>我不确定该函数的存在,但我认为您可以通过读取/进程/安装来实现它,然后获取外部存储的

我正在尝试为我的应用程序编写一个本机库,这样我就可以在本机代码中执行所有文件操作。我读到
getExternalStorageDirectory()
给出目录的外部存储路径


我的问题是,如何在不将位置硬编码到某个字符串的情况下访问相同的位置?在Android NDK中,是否有任何功能可以在C++代码中给出与java的代码> GETEngultSturrAdvestRoTyTyle()/<代码>相同的函数?< /P> < P>我不确定该函数的存在,但我认为您可以通过读取/进程/安装来实现它,然后获取外部存储的信息,例如JellyBean上的G/Sturt/SDCLDX,在旧版本上的MNT/SDCKX。您可以签入*.rc文件,也许可以将其定义为向后兼容的符号链接。存在另一个用于定义外部存储的环境变量,
external\u storage
,因此您可以尝试
getenv(external\u storage)
获取装入点。希望能对您有所帮助。

JNI是您的朋友,这并不太复杂,因为getExternalStorageDirectory是一种静态方法。此函数获取值,并将工作目录更改为该值

#include <jni.h>
#include <unistd.h> // chdir()
#include <sys/param.h> // MAXPATHLEN

// To call Java methods when running native code inside an Android activity,
// a reference is needed to the JavaVM.
static JavaVM *gJavaVM;

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
{
    gJavaVM = vm;
    return JNI_VERSION_1_6;
}

int cdToExtStorage(void) {

    // Make JNI calls to get the external storage directory, and cd to it.

    // To begin, get a reference to the env and attach to it.
    JNIEnv *env;
    int isAttached = 0;
    int ret = 0;
    jthrowable exception;
    if (((*gJavaVM)->GetEnv(gJavaVM, (void**)&env, JNI_VERSION_1_6)) < 0) {
        // Couldn't get JNI environment, so this thread is native.
        if (((*gJavaVM)->AttachCurrentThread(gJavaVM, &env, NULL)) < 0) {
            fprintf(stderr, "Error: Couldn't attach to Java VM.\n");
            return (-1);
        }
        isAttached = 1;
    }

    // Get File object for the external storage directory.
    jclass classEnvironment = (*env)->FindClass(env, "android/os/Environment");
    if (!classEnvironment) goto bailAndroid;
    jmethodID methodIDgetExternalStorageDirectory = (*env)->GetStaticMethodID(env, classEnvironment, "getExternalStorageDirectory", "()Ljava/io/File;"); // public static File getExternalStorageDirectory ()
    if (!methodIDgetExternalStorageDirectory) goto bailAndroid;
    jobject objectFile = (*env)->CallStaticObjectMethod(env, classEnvironment, methodIDgetExternalStorageDirectory);
    exception = (*env)->ExceptionOccurred(env);
    if (exception) {
        (*env)->ExceptionDescribe(env);
        (*env)->ExceptionClear(env);
    }

    // Call method on File object to retrieve String object.
    jclass classFile = (*env)->GetObjectClass(env, objectFile);
    if (!classFile) goto bailAndroid;
    jmethodID methodIDgetAbsolutePath = (*env)->GetMethodID(env, classFile, "getAbsolutePath", "()Ljava/lang/String;");
    if (!methodIDgetAbsolutePath) goto bailAndroid;
    jstring stringPath = (*env)->CallObjectMethod(env, objectFile, methodIDgetAbsolutePath);
    exception = (*env)->ExceptionOccurred(env);
    if (exception) {
        (*env)->ExceptionDescribe(env);
        (*env)->ExceptionClear(env);
    }
    // Extract a C string from the String object, and chdir() to it.
    const char *wpath3 = (*env)->GetStringUTFChars(env, stringPath, NULL);
    if (chdir(wpath3) != 0) {
        fprintf(stderr, "Error: Unable to change working directory to %s.\n", wpath3);
        perror(NULL);
    } else if (path) {
        if (chdir(path) != 0) {
            fprintf(stderr, "Error: Unable to change working directory to %s.\n", path);
            perror(NULL);
        }
    }

    (*env)->ReleaseStringUTFChars(env, stringPath, wpath3);

    goto retAndroid;

bailAndroid:
    ARLOGe("Error: JNI call failure.\n");
    ret = -1;
retAndroid:
    if (isAttached) (*gJavaVM)->DetachCurrentThread(gJavaVM); // Clean up.
    return (ret);
}
#包括
#include//chdir()
#包括//MAXPATHLEN
//要在Android活动中运行本机代码时调用Java方法,
//需要对JavaVM进行引用。
静态JavaVM*gJavaVM;
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM*vm,void*reserved)
{
gJavaVM=vm;
返回JNI_版本_1_6;
}
int CDTOEXT存储(无效){
//进行JNI调用以获取外部存储目录,并将cd发送到该目录。
//首先,获取对环境的引用并附加到它。
JNIEnv*env;
int isAttached=0;
int-ret=0;
jthrowable异常;
如果((*gJavaVM)->GetEnv(gJavaVM,(void**)和env,JNI_版本1_6))<0){
//无法获取JNI环境,因此此线程是本机线程。
if((*gJavaVM)->AttachCurrentThread(gJavaVM,&env,NULL))<0{
fprintf(stderr,“错误:无法连接到Java虚拟机。\n”);
返回(-1);
}
isAttached=1;
}
//获取外部存储目录的文件对象。
jclass classEnvironment=(*env)->FindClass(env,“android/os/Environment”);
如果(!classEnvironment)转到Android;
jMethodIdGetExternalStorageDirectory=(*env)->GetStaticMethodID(env,classEnvironment,“getExternalStorageDirectory”,“()Ljava/io/File;”;”;//公共静态文件getExternalStorageDirectory()
如果(!methodIDgetExternalStorageDirectory)转到Android;
jobject objectFile=(*env)->CallStaticObjectMethod(env,classEnvironment,methodIDgetExternalStorageDirectory);
异常=(*env)->异常发生(env);
如果(例外){
(*env)->例外说明(env);
(*env)->例外清除(env);
}
//对文件对象调用方法以检索字符串对象。
jclass类文件=(*env)->GetObjectClass(env,objectFile);
如果(!classFile)转到Android;
jMethodIdGetAbsolutePath=(*env)->GetMethodID(env,类文件,“getAbsolutePath”,“()Ljava/lang/String;”;
如果(!methodIDgetAbsolutePath)转到Android;
jstring stringPath=(*env)->CallObjectMethod(env,objectFile,methodIDgetAbsolutePath);
异常=(*env)->异常发生(env);
如果(例外){
(*env)->例外说明(env);
(*env)->例外清除(env);
}
//从string对象中提取一个C字符串,并将chdir()添加到该字符串中。
const char*wpath3=(*env)->GetStringUTFChars(env,stringPath,NULL);
如果(chdir(wpath3)!=0){
fprintf(stderr,“错误:无法将工作目录更改为%s。\n”,wpath3);
perror(空);
}else if(路径){
如果(chdir(路径)!=0){
fprintf(stderr,“错误:无法将工作目录更改为%s。\n”,路径);
perror(空);
}
}
(*env)->释放StringUTFChars(env、stringPath、wpath3);
后藤复雄体;
安卓:
ARLOGe(“错误:JNI调用失败。\n”);
ret=-1;
复雄激素:
如果(isAttached)(*gJavaVM)->DetachCurrentThread(gJavaVM);//清理。
返回(ret);
}

为什么不从Java API中确定信息,并在加载后立即将其传递到本机库中?
getenv(外部存储)
是最好的方法,因为Alex支持这种方法。否则我会避免它。我相信您想要
getenv(“外部存储”)这在安卓7.1上可以工作吗?我不能让它工作。我在清单文件中授予了读/写权限,并将adb shell中的
$EXTERNAL\u STORAGE
检查为
/sdcard/
。我试图读取
/sdcard/
下的文本文件,您确定这不是太复杂吗?对象管理组织