Android “Uri方案”;文件";问题:获取文件大小,在外部查看器中打开PDF,然后打开inputstream(与scheme“content”相比)?
当我在我的应用程序中打开PDF时,提供的uri可以是两种模式:“文件”和“内容”:Android “Uri方案”;文件";问题:获取文件大小,在外部查看器中打开PDF,然后打开inputstream(与scheme“content”相比)?,android,pdf,uri,dropbox,url-scheme,Android,Pdf,Uri,Dropbox,Url Scheme,当我在我的应用程序中打开PDF时,提供的uri可以是两种模式:“文件”和“内容”: 使用Dropbox:file:///data/data/com.dropbox.android/global/external/docpreviews/test2.pdf 使用Google Drive:content://media/external/file/142 对于“内容”,我的所有功能都按预期工作,但对于“文件”,我遇到了一些问题: 我不知道如何获得PDF的文件大小 在外部PDF查看器中打开PDF会
- 使用Dropbox:file:///data/data/com.dropbox.android/global/external/docpreviews/test2.pdf
- 使用Google Drive:content://media/external/file/142
<activity android:name=".activities.PdfActivity"
....
<intent-filter android:label="Open PDF">
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="application/pdf"/>
</intent-filter>
</activity>
1) 然后获取文件大小:
switch (uri.getScheme()) {
case "file":
// How to get the filesize here?
break;
case "content":
// Get filesize using cursor
Cursor cursor = getContentResolver().query(uri, new String[]{MediaColumns.SIZE}, null, null, null);
cursor.moveToFirst();
size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaColumns.SIZE));
cursor.close();
break;
}
2) 使用以下代码在外部查看器中打开PDF:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
// Show dialog: no PDF viewer on device
}
3) 使用inputstream将PDF转换为字节[]:
public byte[] getByteArrayFromPdf(Uri uri) throws IOException {
InputStream inputStream = null;
try {
switch (uri.getScheme()) {
case "file":
// How to do this?
break;
case "content":
inputStream = getContentResolver().openInputStream(uri);
break;
default:
// Something going wrong...
}
return getByteArrayUsingInputStream(inputStream);
} finally {
if (inputStream != null) {
inputStream.close();
}
}
}
编辑:我的文件保存在下载文件夹中(因此是来自Google Drive的内容uri)
getContentResolver().openInputStream(uri)导致方案“文件”的FileNotFoundException。即使两个uri方案都来自同一个文件。这意味着FileNotFoundException应该由不存在的文件以外的其他文件生成
显然,这是由libcore.io.ErrnoException:open failed:EACCES(权限被拒绝)引起的,当我从Dropbox查看uri(文件)时,这更有意义:Dropbox似乎会打开文件并将其保存在com.Dropbox.android中,我在其中没有访问权限。我想这解释了所有的麻烦,对吗
最终编辑:
如上所述,Dropbox PDF viewer应用程序生成的文件的隐私可能有问题,因为对于Adobe(以及其他应用程序,也会生成带有“file”的uri),我没有任何问题:新文件(uri.getPath()).length()给我文件大小,接收inputstream与“content”uri的工作原理相同
但这给了我一个新问题:我是否可以:使用Dropbox应用程序打开一个外部PDF文件(如下载地图),“发送PDF”在我的应用程序中打开它,然后以某种方式访问该文件,以便我可以读取大小,在另一个PDF查看器中打开它,并将其转换为inputstream
在我的应用程序中以这种方式打开PDF时,是否可能使用其他uri方案
我不知道如何获得PDF的文件大小
在Uri
上调用getPath()
。将该路径包装在文件
对象中,并在文件
对象上调用length()
或者,将现有代码替换为DocumentFile
。对内容方案使用fromsingeluri()
,对文件方案使用fromFile()
。然后,在DocumentFile
上调用getSize()
在外部PDF查看器中打开PDF会导致类似“无法打开文件”的错误(无论这是dropbox、Google Drive还是任何其他应用程序)
另一个应用对该内容没有权限。您可以尝试通过将标志\u授予\u读取\u URI\u权限
添加到意图
来转移权限
打开inputstream(将PDF转换为字节[])也会导致问题:FileNotFoundException
您不显示导致此异常的代码openInputStream()
支持file
和content
方案,因此在这两种情况下都使用该方案。不幸的是,没有一种方案有效:1)file.length(),返回0。使用documentFile时,fromSingleUri返回null(我猜您是指documentFile上的.length()而不是size()?)。。。2) 国旗没有什么区别。。。3) 我使用openInputStream来表示“file”,这导致了FileNotFoundException(我澄清了我描述这一点的帖子)。在东方,最后一个解决方案应该是可行的,也许例外给了我们一个提示?也许在那个uri上它真的不存在?嗯,我用两个PDF查看器打开了同一个PDF(一个提供“文件”,另一个提供“内容”),所以这不可能。@PKuijpers:Dropbox提供给你的Uri
是你无法访问的,因为他们的应用程序中有一些bug。“我是否可以……”当然欢迎您在
上执行操作发送
以接收PDF文件,如果这是您的意思。。。但你已经有了。所以,试试这个流程,看看你从你选择的PDF查看器应用程序中得到了什么。请注意,并非所有PDF查看器都可以提供“共享”选项。“以这种方式在我的应用程序中打开PDF时,是否可以使用其他uri方案?”--当然可以http
,https
,android。
public byte[] getByteArrayFromPdf(Uri uri) throws IOException {
InputStream inputStream = null;
try {
switch (uri.getScheme()) {
case "file":
// How to do this?
break;
case "content":
inputStream = getContentResolver().openInputStream(uri);
break;
default:
// Something going wrong...
}
return getByteArrayUsingInputStream(inputStream);
} finally {
if (inputStream != null) {
inputStream.close();
}
}
}