从 Android Q 中的外部存储访问照片
Access photos from external storage in Android Q
我最近将应用程序的目标版本升级到 API 29。由于 Android 10 中的范围存储,我使用 MediaStore API 从应用程序外部存储中存储和检索图像.早些时候,我使用 getExternalStoragePublicDirectory
存储通过相机拍摄的图像,现在我使用 MediaStore.Images.Media.EXTERNAL_CONTENT_URI
将文件写入外部存储位置。
我现在面临的问题是,
当我打开我的应用程序并拍照时,它会存储在我给定的文件夹名称 'myapp' 下,我可以通过 Mediastore 光标检索我的图像并将它们显示在自定义图库中。当我卸载我的应用程序时 'myapp' 文件夹仍然存在。当我再次安装我的应用程序并尝试从图库中读取图像时,光标不会返回任何图像。但是如果我再次拍照,那么我可以将它们加载到我的自定义图库中。自定义画廊视图只是屏幕底部的一行图像,因此用户无需浏览照片文件夹即可将图像加载到应用程序。
这就是我在 MediaStore 中存储图像的方式
内容值:
String RELATIVE_PATH = Environment.DIRECTORY_PICTURES + File.separator + "myApp";
final ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, generateImageName(new Date()));
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg");
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, RELATIVE_PATH);
生成名称方法:
int sameSecondCount;
protected String generateName(Date now)
{
String result = formatter.format(now);
long nowMillis = now.getTime();
if (nowMillis / 1000 == lastMillis / 1000)
{
sameSecondCount++;
result += "_" + sameSecondCount;
}
else
sameSecondCount = 0;
lastMillis = nowMillis;
return result + PICTURE_EXTENSION_JPG;
}
@WorkerThread
private Uri writePictureToFile(ContentValues contentValues, byte[] bitmapBytes) throws IOException
{
final ContentResolver resolver = getApplication().getContentResolver();
Uri uri = null;
final Uri contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
try
{
uri = resolver.insert(contentUri, contentValues);
if (uri == null)
throw new IOException("Failed to create new MediaStore record.");
OutputStream stream = resolver.openOutputStream(uri);
if (stream == null)
{
throw new IOException("Failed to get output stream.");
}
stream.write(bitmapBytes);
}
catch (IOException e)
{
// Delete the content from the media store
if (uri != null)
resolver.delete(uri, null, null);
throw e;
}
return uri;
}
读图
{
String selectionMimeType = MediaStore.Files.FileColumns.MIME_TYPE + " in (?,?,?)";
String[] args = new String[]{
MimeTypeMap.getSingleton().getMimeTypeFromExtension("jpg"),
MimeTypeMap.getSingleton().getMimeTypeFromExtension("png")};
Cursor cursor = context.getContentResolver()
.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, selectionMimeType, selectionArgs,
orderBy + " DESC");
if (cursor != null)
{
int idColumnIndex = imageCursor.getColumnIndex(MediaStore.Images.Media._ID);
imageCursor.moveToFirst();
int imageCount = imageCursor.getCount();
for (int i = 0; i < imageCount && i < totalCount; i++)
{
final long imageId = imageCursor.getLong(idColumnIndex);
Uri uriImage = Uri.withAppendedPath(uriExternal, "" + imageId);
GalleryData galleryImageData = new GalleryImageData(imageId, uriImage); // Custom class with id and Uri
galleryViewModelList.add(galleryImageData);
imageCursor.moveToNext();
}
imageCursor.close();
}
为什么当我重新安装我的应用程序时,上面的代码没有返回我存储在 Mediastore 文件夹中的图像。是设计使然还是我遗漏了什么?
这些是我正在检索的列,
final String[] columns = { MediaStore.Images.Media.DATA, MediaStore.Images.Media._ID, MediaStore.Images.Media.MIME_TYPE };
final String orderBy = MediaStore.Images.Media.DATE_TAKEN; ```
由于不明确的原因,Android10 将按时间间隔安装的两个应用程序视为单独的应用程序,与两个完全不同的应用程序没有区别。
因此,一旦您的应用程序被卸载,它就无法访问其创建的所有文件...即使稍后重新安装相同的应用程序也是如此。
因此,您需要像对待完全不相关的应用程序中的文件一样处理以前安装的应用程序中的文件:请求 READ_EXTERNAL_STORAGE
以便能够查询它们并读取它们的内容。 “阅读其内容”部分需要清单中 <application>
上的 android:requestLegacyExternalStorage="true"
。
我最近将应用程序的目标版本升级到 API 29。由于 Android 10 中的范围存储,我使用 MediaStore API 从应用程序外部存储中存储和检索图像.早些时候,我使用 getExternalStoragePublicDirectory
存储通过相机拍摄的图像,现在我使用 MediaStore.Images.Media.EXTERNAL_CONTENT_URI
将文件写入外部存储位置。
我现在面临的问题是, 当我打开我的应用程序并拍照时,它会存储在我给定的文件夹名称 'myapp' 下,我可以通过 Mediastore 光标检索我的图像并将它们显示在自定义图库中。当我卸载我的应用程序时 'myapp' 文件夹仍然存在。当我再次安装我的应用程序并尝试从图库中读取图像时,光标不会返回任何图像。但是如果我再次拍照,那么我可以将它们加载到我的自定义图库中。自定义画廊视图只是屏幕底部的一行图像,因此用户无需浏览照片文件夹即可将图像加载到应用程序。
这就是我在 MediaStore 中存储图像的方式
内容值:
String RELATIVE_PATH = Environment.DIRECTORY_PICTURES + File.separator + "myApp";
final ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, generateImageName(new Date()));
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg");
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, RELATIVE_PATH);
生成名称方法:
int sameSecondCount;
protected String generateName(Date now)
{
String result = formatter.format(now);
long nowMillis = now.getTime();
if (nowMillis / 1000 == lastMillis / 1000)
{
sameSecondCount++;
result += "_" + sameSecondCount;
}
else
sameSecondCount = 0;
lastMillis = nowMillis;
return result + PICTURE_EXTENSION_JPG;
}
@WorkerThread
private Uri writePictureToFile(ContentValues contentValues, byte[] bitmapBytes) throws IOException
{
final ContentResolver resolver = getApplication().getContentResolver();
Uri uri = null;
final Uri contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
try
{
uri = resolver.insert(contentUri, contentValues);
if (uri == null)
throw new IOException("Failed to create new MediaStore record.");
OutputStream stream = resolver.openOutputStream(uri);
if (stream == null)
{
throw new IOException("Failed to get output stream.");
}
stream.write(bitmapBytes);
}
catch (IOException e)
{
// Delete the content from the media store
if (uri != null)
resolver.delete(uri, null, null);
throw e;
}
return uri;
}
读图
{
String selectionMimeType = MediaStore.Files.FileColumns.MIME_TYPE + " in (?,?,?)";
String[] args = new String[]{
MimeTypeMap.getSingleton().getMimeTypeFromExtension("jpg"),
MimeTypeMap.getSingleton().getMimeTypeFromExtension("png")};
Cursor cursor = context.getContentResolver()
.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, selectionMimeType, selectionArgs,
orderBy + " DESC");
if (cursor != null)
{
int idColumnIndex = imageCursor.getColumnIndex(MediaStore.Images.Media._ID);
imageCursor.moveToFirst();
int imageCount = imageCursor.getCount();
for (int i = 0; i < imageCount && i < totalCount; i++)
{
final long imageId = imageCursor.getLong(idColumnIndex);
Uri uriImage = Uri.withAppendedPath(uriExternal, "" + imageId);
GalleryData galleryImageData = new GalleryImageData(imageId, uriImage); // Custom class with id and Uri
galleryViewModelList.add(galleryImageData);
imageCursor.moveToNext();
}
imageCursor.close();
}
为什么当我重新安装我的应用程序时,上面的代码没有返回我存储在 Mediastore 文件夹中的图像。是设计使然还是我遗漏了什么?
这些是我正在检索的列,
final String[] columns = { MediaStore.Images.Media.DATA, MediaStore.Images.Media._ID, MediaStore.Images.Media.MIME_TYPE };
final String orderBy = MediaStore.Images.Media.DATE_TAKEN; ```
由于不明确的原因,Android10 将按时间间隔安装的两个应用程序视为单独的应用程序,与两个完全不同的应用程序没有区别。
因此,一旦您的应用程序被卸载,它就无法访问其创建的所有文件...即使稍后重新安装相同的应用程序也是如此。
因此,您需要像对待完全不相关的应用程序中的文件一样处理以前安装的应用程序中的文件:请求 READ_EXTERNAL_STORAGE
以便能够查询它们并读取它们的内容。 “阅读其内容”部分需要清单中 <application>
上的 android:requestLegacyExternalStorage="true"
。