我正在构建一个带有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函数(不使用文件路径)都正常工作。
有没有人可以提供帮助?我应该使用绝对路径吗?然后,我怎么能得到它?
答案 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为接受的聪明才智的答案:)