提问者:小点点

在android中保存媒体文件


我刚刚开始android开发,对于如何将媒体文件保存到外部存储的自定义文件夹非常困惑。我读过关于内窥镜存储,纵隔,但我还是不明白。

我正在尝试将文件保存到外部存储中自己的文件夹中(就像外部存储中的Whatsapp文件夹一样)。我希望结构是这样的:

(EXTERNAL STORAGE ROOT)
 |--- (RandomFolder)
 |--- (Whatsapp)
 |--- (MyFolder)
        |---(Images)
        |---(Videos)
 |--- ...

我不希望媒体文件存储在默认媒体目录(如Pictures/或DCIM/)中。我有些问题:

  1. 要用哪一个?作用域存储或纵隔API?
  2. 如何实现上述操作?

其他信息:

  1. 即使卸载了应用程序,我也希望文件保持不变
  2. 我的应用程序以Android 10(API 29)为目标,但minSdkVersion是Android 8.0(API 26)
  3. 我将使用OutputStream保存文件。

那么应该采取哪种方法呢?


共1个答案

匿名用户

您可以将图像和其他媒体文件保存到外部存储中,但是,为了让这些文件显示在其他应用程序中,比如Gallery应用程序中,您需要将它们注册到纵隔存储中。你是怎么保存文件的?您是从头开始创建文件,还是简单地从另一个目录复制文件?

下面是一个如何将位图对象(jpg或png)保存到外部存储器并将其注册到纵隔器中的示例。首先,从纵隔存储中删除文件的任何现有记录,然后使用ContentResolver.Insert()方法将位图保存到外部存储。

请注意,纵隔中的数据列指的是文件的完整路径。

import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.graphics.Bitmap;
import android.net.Uri;
import android.provider.MediaStore;
import java.io.File;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Objects;

public class SaveImageToMediaStore
{
    public static boolean saveImage(
            Context context, Bitmap bitmap,
            int jpgQuality, int pngQuality, String fileFullPath)
    {
        try
        {
            deleteFileFromMediaStore(context, fileFullPath);

            saveImageAndInsertIntoMediaStore(context, fileFullPath, bitmap, jpgQuality, pngQuality);

            return true;
        }
        catch (Exception ex) { return false; }
    }

    public static boolean saveImageAndInsertIntoMediaStore(
            Context context, String fileFullPath,
            Bitmap bitmap, int jpgQuality, int pngQuality)
    {
        try
        {
            Bitmap.CompressFormat format;
            int quality;
            String mimeType;

            if (fileFullPath.toLowerCase().endsWith(".jpg") ||
                    fileFullPath.toLowerCase().endsWith(".jpeg"))
            {
                format = Bitmap.CompressFormat.JPEG;
                quality = jpgQuality;
                mimeType = "image/jpg";
            }
            else if (fileFullPath.toLowerCase().endsWith(".png"))
            {
                format = Bitmap.CompressFormat.PNG;
                quality = pngQuality;
                mimeType = "image/png";
            }
            else
            {
                return false;
            }

            ContentValues contentValues = new ContentValues();
            contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, getShortName(fileFullPath));
            contentValues.put(MediaStore.MediaColumns.MIME_TYPE, mimeType);
            contentValues.put(MediaStore.MediaColumns.DATA, fileFullPath);

            ContentResolver resolver = context.getContentResolver();
            Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
            OutputStream out = resolver.openOutputStream(Objects.requireNonNull(uri));
            bitmap.compress(format, quality, out);
            Objects.requireNonNull(out).close();

            return true;
        }
        catch (Exception ex) { return false; }
    }

    public static boolean deleteFileFromMediaStore(
            Context context, String fileFullPath)
    {
        File file = new File(fileFullPath);

        String absolutePath, canonicalPath;
        try { absolutePath = file.getAbsolutePath(); }
        catch (Exception ex) { absolutePath = null; }
        try { canonicalPath = file.getCanonicalPath(); }
        catch (Exception ex) { canonicalPath = null; }

        ArrayList<String> paths = new ArrayList<>();

        if (absolutePath != null) paths.add(absolutePath);
        if (canonicalPath != null && !canonicalPath.equalsIgnoreCase(absolutePath))
            paths.add(canonicalPath);

        if (paths.size() == 0) return false;

        ContentResolver resolver = context.getContentResolver();
        Uri uri = MediaStore.Files.getContentUri("external");

        boolean deleted = false;

        for (String path : paths)
        {
            int result = resolver.delete(uri,
                    MediaStore.Files.FileColumns.DATA + "=?",
                    new String[] { path });

            if (result != 0) deleted = true;
        }

        return deleted;
    }

    public static String getShortName(String path)
    {
        if (path.endsWith("/")) path = path.substring(0, path.length() - 1);

        int pos = path.lastIndexOf('/');

        if (pos == -1) return path;

        return path.substring(pos + 1);
    }

}