Android 下载到MediaStore.Downloads的文件的输入流为空

Android 下载到MediaStore.Downloads的文件的输入流为空,android,inputstream,mediastore,Android,Inputstream,Mediastore,我正在尝试将一个文本文件下载到MediaStore.Downloads(以支持Android R中的作用域存储),然后读取该文件的内容 我最初使用DownloadManager将文件下载到环境中。DIRECTORY\u下载,然后使用ContentResolver查询通过MediaStore.DOWNLOADS查找内容://Uri。但我发现该文件通常不能立即通过MediaStore获得(尽管它会在将来某个时候出现) 因此,我转而使用JobIntentService,使用OkHttp将文件下载到Me

我正在尝试将一个文本文件下载到MediaStore.Downloads(以支持Android R中的作用域存储),然后读取该文件的内容

我最初使用DownloadManager将文件下载到
环境中。DIRECTORY\u下载
,然后使用ContentResolver查询通过MediaStore.DOWNLOADS查找
内容://
Uri。但我发现该文件通常不能立即通过MediaStore获得(尽管它会在将来某个时候出现)

因此,我转而使用JobIntentService,使用OkHttp将文件下载到MediaStore

ContentResolver resolver = getApplicationContext().getContentResolver();
Uri downloads = MediaStore.Downloads.EXTERNAL_CONTENT_URI;
// Originally using MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);

ContentValues fileContent = new ContentValues();
fileContent.put(MediaStore.Downloads.DISPLAY_NAME, file.name());
fileContent.put(MediaStore.Downloads.SIZE, fileSize);
fileContent.put(MediaStore.Downloads.IS_PENDING, 1);

Uri downloadedFileUri = resolver.insert(downloads, fileContent);  // Save this Uri for later access

try (InputStream inputStream = response.body().byteStream();
     OutputStream outputStream = resolver.openOutputStream(downloadedFileUri)) {
    // ... Download and write the file ...
}

fileContent.put(MediaStore.Downloads.IS_PENDING, 0);
resolver.update(downloadedFileUri, fileContent, null, null);
然后,我将保存的Uri
downloadedFileUri
传递给另一个使用输入流加载文件的类,例如

try (InputStream inputStream = resolver.openInputStream(downloadedFileUri)) {
    Log.d(TAG, "Input stream size has " + inputStream.available() + " bytes available"); // This returns 0
    // ... read the file using a BufferedReader ...
}
但是InputStream不包含任何数据。我已创建了对MediaStore的ContentResolver查询。请下载以确认文件位于MediaStore中:

try (Cursor cursor = resolver.query(MediaStore.Downloads.EXTERNAL_CONTENT_URI,
                        projection, null, null, idSortOrder)) {
    Log.i(TAG, DatabaseUtils.dumpCursorToString(cursor));  // I can see the file in the cursor dump here

    while (cursor.moveToNext()) {
        int id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Downloads._ID));
        Uri uri = ContentUris.withAppendedId(MediaStore.Downloads.EXTERNAL_CONTENT_URI, id);
        if (downloadedFileUri.equals(uri)) {
            Log.d(TAG, "Uri from cursor matches params, Uri: " + uri); // Getting a match here
        }
    }
}

我还可以通过文件浏览器找到下载的文件,并确认该文件不是空的。那么为什么InputStream不返回任何数据呢?

作为一项测试,尝试执行
openInputStream()
-并在第一个活动中读取数据(在完成写入并且
正在挂起更新后),而不是第二个活动。它有用吗?您还可以尝试清除
文件内容.put(MediaStore.Downloads.IS_PENDING,0)
之前的
ContentValues
,以及随后的
update()
调用,这样您就不会试图更新其他列(例如,
显示\u NAME
)。最后,您可以尝试不设置
SIZE
,因为
MediaStore
应该自己计算。@commonware谢谢您,在
更新完成后立即打开流。看起来我是在别处读这条小溪,所以当我准备真正读它的时候,小溪已经空了!啊!作为测试,尝试执行
openInputStream()
-并读入第一个活动(在您完成写入并且
处于挂起状态
更新之后),而不是第二个活动。它有用吗?您还可以尝试清除
文件内容.put(MediaStore.Downloads.IS_PENDING,0)
之前的
ContentValues
,以及随后的
update()
调用,这样您就不会试图更新其他列(例如,
显示\u NAME
)。最后,您可以尝试不设置
SIZE
,因为
MediaStore
应该自己计算。@commonware谢谢您,在
更新完成后立即打开流。看起来我是在别处读这条小溪,所以当我准备真正读它的时候,小溪已经空了!啊!