【问题标题】:How to set file path in Android JNI?如何在 Android JNI 中设置文件路径?
【发布时间】:2014-04-01 23:48:01
【问题描述】:

我正在使用 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/ 文件夹中,我将路径设置为src/textfile/,但它不起作用。 (getResult()函数找不到路径)

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

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

有人可以帮忙吗?我应该使用绝对路径吗?那么,如何获得呢?

【问题讨论】:

  • 项目随机位置中的文件(包括 src/ 文件夹)将不会在运行时在设备上可用。打包在 res/ 或 assets/ 文件夹下的项目可能可用,但实际上并不是文件系统中的文字 files,因此只能通过特殊的 Android-unique 访问API。
  • @ChrisStratton :我正在研究使用assets/ 文件夹,非常感谢!

标签: android c++ android-ndk java-native-interface


【解决方案1】:

我自己找到了解决办法。

根据上面 Chris 的评论,我把我的文本文件放到了assets 文件夹中。

我尝试从 JNI 访问 assets 文件夹(如 this),但有点不起作用。

所以我用 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());
        }
    }

我不确定这是不是正确的解决方案,但效果很好! :)

【讨论】:

  • +1 用于智能解决方法:D 我正在添加一个答案,其中包含指向另一种(更好但更难的 IMO)方式的链接......
【解决方案2】:

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

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

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

Android read text file from asset folder using C (ndk)

Get relative path to file within project in JNI

不过,对于聪明才智的公认答案 +1 :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-16
    • 1970-01-01
    • 2012-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多