Android NDK Fopen返回错误2“没有此类文件或目录”在文件上我知道退出
我的应用程序正在访问音频文件,我正在双簧管对它们进行一些处理。因此,我有JNI工作,文件位于我的文档
树中。所有零件都在那里,通常我将文件加载到字节数组中,并将其传递到JNI上进行处理。
现在,我想直接在本机代码中打开一个文件。
从本质上讲,在Java侧,我正在用onActivityResult
进行以下操作,该由action_open_document
intent触发。
AudioUri = data.getData();
String filepath = AudioUri.getPath();
因此,filepath
正在JNI方法中作为JString传递。在C ++方面,我正在执行以下
JNIEXPORT void JNICALL
Java_com_myco_fileload_MainActivity_setFilepathNative(JNIEnv *env, jobject thiz,
jstring filepath) {
std::string file_path = ConvertJString( env, filepath );
__android_log_print(ANDROID_LOG_INFO, TAG, "%s", file_path.c_str());
FILE* file = fopen(file_path.c_str(),"rb");
if(file){
__android_log_print(ANDROID_LOG_INFO, TAG, "%s", "it's a file");
} else {
__android_log_print(ANDROID_LOG_INFO, TAG, "%s", "it's null");
__android_log_print(ANDROID_LOG_INFO, TAG, "%d", errno);
__android_log_print(ANDROID_LOG_INFO, TAG, "%s", strerror(errno));
}
}
fopen()
始终导致错误代码2-'no这样的文件或目录'
filepath
is /document/document/document/主题:Documents/MyFolder/MyFile.wav ,
这是什么问题?那是错误的道路吗?权限错误?有什么想法吗?
编辑#1 我发现,如果将filepath更改为/storage/emulation/0/documents/myfolder/myfile.wav error conformcode 13会更改,则拒绝了权限。
所以我的问题是现在w我得到正确的文件路径吗?
为什么我会拒绝阅读与Java一起阅读的本机的文件的许可?
顺便说一句,我的清单包含用户权限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>
编辑#2 事实证明这是文件权限问题。我必须将权限设置为action_manage_all_files_access_permission
,这对我的用例很好,但似乎有点过大。
因此,我现在的问题是 - 如何将本机代码提供给我应用程序的Java侧的权限?
My app is accessing audio files and I'm doing some processing on them in OBOE. So I have JNI working, the files are located in my documents
tree. All the parts are there and normally I'm loading the file into a byte array and passing it over the JNI for processing.
Now, I want to open a file directly in the Native code.
Essentially, on the Java side, I'm doing the following in an onActivityResult
which is triggered by an ACTION_OPEN_DOCUMENT
intent.
AudioUri = data.getData();
String filepath = AudioUri.getPath();
So filepath
is being passed as a jstring in the JNI method. On the C++ side I'm doing the following
JNIEXPORT void JNICALL
Java_com_myco_fileload_MainActivity_setFilepathNative(JNIEnv *env, jobject thiz,
jstring filepath) {
std::string file_path = ConvertJString( env, filepath );
__android_log_print(ANDROID_LOG_INFO, TAG, "%s", file_path.c_str());
FILE* file = fopen(file_path.c_str(),"rb");
if(file){
__android_log_print(ANDROID_LOG_INFO, TAG, "%s", "it's a file");
} else {
__android_log_print(ANDROID_LOG_INFO, TAG, "%s", "it's null");
__android_log_print(ANDROID_LOG_INFO, TAG, "%d", errno);
__android_log_print(ANDROID_LOG_INFO, TAG, "%s", strerror(errno));
}
}
fopen()
always results in null with errorcode 2 - 'No such file or directory'
filepath
is /document/primary:Documents/myFolder/myfile.wav
So what is the issue? Is that the path is wrong? A permission error? Any thoughts?
edit #1
I found that if I change the filepath to /storage/emulated/0/Documents/myFolder/myfile.wav the error changes to errorcode 13, Permission Denied.
So my question is now w do I get the correct file path?
And why would I get permission denied on reading a file with Native that I can read with Java?
btw, my manifest contained the user permissions
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>
edit #2 It turns out this was a file permissions issue. I had to set permission to ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION
, which is fine for my use case, but seems a bit excessive.
So, my question is now - how can I give the native code the permissions that are available to the java-side of my app?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好吧,
action_open_document
返回content://
和getPath()
它仅对相应的内容提供商有效(其“权限” )。因此,您只能通过内容解析器接口访问它。我假设您是通过
ContentResolver#OpenFiledScriptor
以及在Java中进行操作。您应该做的是从parcelfiledScriptor
获得文件描述符(parcelfiledScriptor#getfd()
)并将其传递给NDK,您可以像其他任何文件描述符一样在其中操作。但是,您应该照顾文件描述符的寿命。Well,
ACTION_OPEN_DOCUMENT
returns acontent://
and thegetPath()
on it is only valid for the respective content provider (its "authority"). So you can only access it through the content resolver interface.I'd assume you're opening a file descriptor through
ContentResolver#openFileDescriptor
and the operating on it in Java. What you should do is get the file descriptor from theParcelFileDescriptor
(ParcelFileDescriptor#getFd()
) and pass it on to NDK where you can operate on it like any other file descriptor. Just an FYI you should take care of the life time of the file descriptor however.