Reputation: 2499
I'm building an Android app with C++ library, and I have a problem with sending file path.
I have my JNI function in jni/processing.cpp
:
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);
}
and getResult()
is a member function of jni/src/library/myclass.cpp
.
I have several text files under jni/src/textfiles/
, and I want to send this path to getResult()
function as a parameter. Since processing.cpp
is in jni/
folder, I set path as src/textfile/
, but it doesn't work. (getResult()
function can't find the path)
I've been tried filePath = "../../textfile/"
which is relative path from jni/src/library/myclass.cpp
, and it also doesn't work.
However, all my other JNI functions (not using file path) are working fine.
Is there anyone who can help? Should I use absolute path? Then, how can I get it?
Upvotes: 1
Views: 8495
Reputation: 3211
I don't know if it's actually possible to get the path to the assets
directory with JNI (I'm not an expert, though): my uninformed opinion is that the Android developers might want us to access the files by proxy anyway, and it might be a good idea doing so to ensure future compatibility.
You can probably get the naked path with a trick similar to the one you explained in your answer, and get the assets path from java then pass it to C via JNI.
Regardless, I think that the performance (not to mention space) efficient way to access the files in Assets
from jni is to use the AAssetManager
function:
Android read text file from asset folder using C (ndk)
and
Get relative path to file within project in JNI
Still, +1 to the accepted answer for the ingenuity :)
Upvotes: 2
Reputation: 2499
I found the solution by myself.
According to Chris' comment above, I put my text files into the assets
folder.
I tried to access assets
folder from JNI (like this), but somewhat it didn't work.
So I read files in Java, and store files again into internal storage. Since we know the data/data/your_app_package_name/
is the internal storage path, I can read files from JNI.
Here's the code how I read files from assets
and store to internal storage :
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());
}
}
I'm not sure this is the right solution, but it worked well! :)
Upvotes: 3