java - 在 Android Q 中从外部存储访问照片

标签 java android mediastore android-10.0 scoped-storage

我最近将应用程序的目标版本升级到 API 29。由于 Android 10 中的范围存储,我使用 MediaStore API 从应用程序外部存储存储和检索图像。早些时候,我使用了 getExternalStoragePublicDirectory存储通过相机拍摄的图像,现在我使用 MediaStore.Images.Media.EXTERNAL_CONTENT_URI将文件写入外部存储位置。

我现在面临的问题是,
当我打开我的应用程序并拍照时,它存储在我给“myapp”的文件夹名称下,我可以通过 Mediastore 光标检索我的图像并将它们显示在自定义画廊中。当我卸载我的应用程序'myapp'文件夹仍然存在。当我再次安装我的应用程序并尝试从图库中读取图像时,光标没有返回任何图像。但如果我再次拍照,那么我可以将它们加载到我的自定义画廊。自定义图库 View 只是屏幕底部的一行图像,因此用户无需浏览照片文件夹即可将图像加载到应用程序。

这就是我将图像存储在 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; ```

最佳答案

由于不清楚的原因,Android 10 将两个按时间分开的应用程序安装视为单独的应用程序,这与它们是两个完全不同的应用程序没有什么不同。
因此,一旦您的应用程序被卸载,它就会失去对它创建的所有文件的访问权限……即使后来重新安装了同一个应用程序。
因此,您需要像处理来自完全不相关的应用程序的文件一样处理以前安装的应用程序中的文件:请求 READ_EXTERNAL_STORAGE能够查询它们并阅读它们的内容。 “阅读他们的内容”部分需要android:requestLegacyExternalStorage="true"<application>在 list 中。

关于java - 在 Android Q 中从外部存储访问照片,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61073122/

相关文章:

android - MediaStore音频ID是否保留在SD卡重新插拔上?

java - 整数数组中的 NullPointerException

android - Android 应用中 google +1 按钮的客户端 ID

android - 如何在 Android 的 PDFTron 中提取注释并保存到数据库?

android - 键盘出现时隐藏ImageView,键盘消失时显示

android - 如何从 MediaStore.File 和 MediaStore.File.FileColumn 获取数据

android - 如何从 Android 中的 .mov 文件中获取缩略图?

java - 我如何自定义 EditText Box 以仅允许使用货币?

java - JUnit 比较字符串

JAVA密码检查程序-检查密码是否有2位以上数字+仅字母和数字