如何在Android JNI中设置文件路径?

时间:2014-04-01 23:48:02

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

我正在构建一个带有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.cpp位于jni/文件夹中,因此我将路径设置为src/textfile/,但它不起作用。 (getResult()函数无法找到路径)

我已经尝试filePath = "../../textfile/"这是jni/src/library/myclass.cpp的相对路径,但它也无法正常工作。

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

有没有人可以提供帮助?我应该使用绝对路径吗?然后,我怎么能得到它?

2 个答案:

答案 0 :(得分:3)

我自己找到了解决方案。

根据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 :(得分:2)

我不知道它是否真的可以通过JNI获取public class CustomListAdapter extends BaseAdapter { private final Context context; private final List<ListItem> dataSet; public CustomListAdapter(Context context, List<ListItem> dataSet) { super(); this.context = context; this.dataSet = dataSet; } @Override public int getCount() { return dataSet.size(); } @Override public Object getItem(int position) { return dataSet.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); View rowView = inflater.inflate(R.layout.list_item, parent, false); ListItem item = dataSet.get(position); ImageView imageView = (ImageView) rowView.findViewById(R.id.icon); TextView textView = (TextView) rowView.findViewById(R.id.name); imageView.setImageResource(item.getId()); textView.setText(item.getName()); return rowView; } } 目录的路径(虽然我不是专家):我不知情的意见是Android开发人员可能希望我们无论如何都要通过代理访问文件,这样做可能是一个好主意,以确保将来的兼容性。

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

无论如何,我认为从jni访问public class ListItem { private String name; private int id; public ListItem(String name, int id) { this.name = name; this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } } 中文件的性能(更不用说空间)的有效方法是使用assets函数:

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

Get relative path to file within project in JNI

仍然,+1为接受的聪明才智的答案:)