如何在安卓JNI中设置文件路径

How to set file path in Android JNI?

本文关键字:设置 文件 路径 JNI      更新时间:2023-10-16

我正在使用C++库构建一个Android应用程序,并且在发送文件路径时遇到问题。

我在jni/processing.cpp中具有我的 JNI 功能:

JNIEXPORT jfloat JNICALL Java_com_my_package_path_getMyFunction
(JNIEnv *env, jobject obj, jstring param) {
    string str = env->GetStringUTFChars(param, 0);
    string filePath = "src/textfile/";
    return getResult(str, filePath);
}

getResult()jni/src/library/myclass.cpp的成员函数。

我在 jni/src/textfiles/ 下有几个文本文件,我想将此路径作为参数发送到getResult()函数。由于processing.cppjni/文件夹中,我将 path 设置为 src/textfile/ ,但它不起作用。(getResult()函数找不到路径)

我已经尝试过filePath = "../../textfile/"这是jni/src/library/myclass.cpp的相对路径,但它也不起作用。

但是,我所有其他 JNI 函数(不使用文件路径)都工作正常。

有人可以帮忙吗?我应该使用绝对路径吗?那么,我怎样才能得到它呢?

我自己找到了解决方案。

根据Chris上面的评论,我将文本文件放入assets文件夹中。

我尝试从 JNI 访问assets文件夹(像这样),但有些不起作用。

所以我用Java读取文件,并将文件再次存储到内部存储中。由于我们知道data/data/your_app_package_name/是内部存储路径,因此我可以从 JNI 读取文件。

这是我如何从assets读取文件并存储到内部存储的代码:

AssetManager assetManager = getResources().getAssets();
    String[] files = null;
    try {
        files = assetManager.list("Files");
    } catch (Exception e) {
        Log.d(MYLOG, "ERROR : " + e.toString());
    }
    for (int i = 0; i < files.length; i++) {
        InputStream in = null;
        OutputStream out = null;
        FileOutputStream fileOutStream = null;
        try {
            Log.d(MYLOG, "file names : " + files[i]);
            in = assetManager.open("Files/" + files[i]);
            out = new FileOutputStream(getApplicationContext().getFilesDir() + files[i]);
            File file = new File(getApplicationContext().getFilesDir(), files[i]);
            byte[] buffer = new byte[65536 * 2];
            int read;
            while ((read = in.read(buffer)) != -1) {
                out.write(buffer, 0, read);
            }
            in.close();
            in = null;
            out.flush();
            fileOutStream = new FileOutputStream(file);
            fileOutStream.write(buffer);
            out.close();
            out = null;
            Log.d(MYLOG, "File Copied in storage");
        } catch (Exception e) {
            Log.d(MYLOG, "ERROR: " + e.toString());
        }
    }

我不确定这是正确的解决方案,但它运行良好! :)

我不知道是否真的可以使用 JNI 获取assets目录的路径(不过我不是专家):我不知情的意见是 Android 开发人员可能希望我们通过代理访问文件无论如何,这样做可能是个好主意以确保未来的兼容性。

您可能可以使用类似于您在答案中解释的技巧来获取裸路径,并从 java 获取资产路径,然后通过 JNI 将其传递给 C。

无论如何,我认为从 jni 访问 Assets 中的文件的性能(更不用说空间)有效方法是使用 AAssetManager 函数:

安卓使用 C 从资产文件夹中读取文本文件 (ndk)

在 JNI 中获取项目中文件的相对路径

尽管如此,对独创性的公认答案+1 :)