[英]How to know whether writing to stream would result in java.io.IOException: write failed: EBADF (Bad file number)
I know there are a number of posts here on the java.io.IOException: write failed: EBADF (Bad file number)
exception, but non of them seems to answer my particular question: 我知道在
java.io.IOException: write failed: EBADF (Bad file number)
上有很多帖子java.io.IOException: write failed: EBADF (Bad file number)
异常,但是似乎没有一个可以回答我的特定问题:
Suppose my activity is called with Intent.ACTION_VIEW
and I got a Uri
via Uri uri = intent.getData()
that starts with content://
from which I read some data (for example a pdf file). 假设我的活动被
Intent.ACTION_VIEW
调用,并且我通过Uri uri = intent.getData()
获得了一个Uri
,它以content://
开头,我从中读取了一些数据(例如pdf文件)。 Now I want to find out whether I can also write to that Uri
to decide whether a "save" button should be shown to the user, or just a "save as" button. 现在,我想确定是否也可以写信给该
Uri
以决定是否应向用户显示“保存”按钮,还是仅显示“另存为”按钮。
Suppose further that I can successfully open first a ParcelFileDescriptor
and finally a FileOutputStream
as in 进一步假设我可以成功地首先打开一个
ParcelFileDescriptor
,最后一个FileOutputStream
如
ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uri, "w");
FileOutputStream fileOutputStream = new FileOutputStream(pfd.getFileDescriptor());
such that fileOutputStream != null
. 这样
fileOutputStream != null
。
Depending on the Uri
it can now happen that if I try to write to fileOutputStream
I get the exception: 根据
Uri
,如果我尝试写入fileOutputStream
,现在会发生异常:
Exception=java.io.IOException: write failed: EBADF (Bad file number)
I would like to know in advance whether this will happen without actually touching/changing the file. 我想提前知道在不实际触摸/更改文件的情况下是否会发生这种情况。 One would think that it should be possible to find out whether I can write to a given
Uri
or not before trying. 有人认为,应该可以在尝试之前找出我是否可以写给定的
Uri
。
How can I achieve that? 我该如何实现?
Additional observations: 其他观察:
I suppose that the above happens when I don't have permission to write to that particular file/uri, but then why does Android let me open a FileOutputStream
in the first place? 我想当我没有权限写入该特定文件/ uri时发生以上情况,但是为什么Android首先让我打开
FileOutputStream
?
For testing I use attachments in emails received with Kaiten mail on an ICS device. 为了进行测试,我在ICS设备上使用Kaiten邮件接收的电子邮件中使用附件。 If I my app opens after I click on "save" in Kaiten mail
uri
matches content://media/external/file/[0-9]*
and everything works, if I however clicked on "open" uri
matches content://com.kaitenmail.attachmentprovider/[-0-9a-f]*/[0-9]*/VIEW
and I run into the above error. 如果我在Kaiten邮件中单击“保存”后我的应用程序打开,则
uri
匹配content://media/external/file/[0-9]*
并且一切正常,如果我单击了“ open” uri
匹配content://com.kaitenmail.attachmentprovider/[-0-9a-f]*/[0-9]*/VIEW
,我遇到上述错误。
There are apparently two methods: 显然有两种方法:
One can call 一个可以打电话
Context.checkCallingUriPermission(Uri uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
to check whether the calling process is allowed to write to a given Uri
. 检查是否允许调用进程写入给定的
Uri
。
For the cases I could check, on API level < 19 this seems to result in PackageManager.PERMISSION_DENIED
whenever the writing to an output stream pointing to uri
fails and in PackageManager.PERMISSION_GRANTED
in all other cases. 对于情况下,我可以检查,在API级<19,这似乎导致
PackageManager.PERMISSION_DENIED
每当写入到输出流指向uri
失败,并在PackageManager.PERMISSION_GRANTED
在所有其他情况。
For API level >= 19 it however yields PackageManager.PERMISSION_DENIED
even if one has previously taken a persisted write permission with getContentResolver().takePersistableUriPermission(Uri uri, int takeFlags)
. 对于> = 19的API级别,即使以前使用
getContentResolver().takePersistableUriPermission(Uri uri, int takeFlags)
获得了持久的写许可权,它也会产生PackageManager.PERMISSION_DENIED
。 In that case however one can use 但是在那种情况下,可以使用
context.getContentResolver().getPersistedUriPermissions()
to get a list of all previously taken permissions and then look through them so see if one has permission to write to a given Uri
. 获取所有先前获得的权限的列表,然后仔细检查它们,以便查看是否有写给定
Uri
权限。
If one got he Uri
via an Intent intent
one can check its flags via intent.getFlags()
and see whether Intent.FLAG_GRANT_WRITE_URI_PERMISSION
is set. 如果有人通过
Intent intent
获得Uri
,则可以通过intent.getFlags()
检查其标志,并查看是否设置了Intent.FLAG_GRANT_WRITE_URI_PERMISSION
。 This also seems to be a way to "predict the future". 这似乎也是“预测未来”的一种方式。
Obviously, neither of the above methods can be an excuse to not properly handle exceptions that can occur while writing to the stream. 显然,以上两种方法都不能作为未正确处理写入流时可能发生的异常的借口。
The correct way to test whether any resource is available is to try to use it, and handle the exceptions or errors that result when you can't. 测试任何资源是否可用的正确方法是尝试使用它,并处理无法使用时导致的异常或错误。
Anything else amounts to fortune-telling. 其他任何事情都算命。 You might
你可能
Don't try to predict the future. 不要试图预测未来。 Coping with the present is difficult enough.
应对目前的困难已经足够了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.