在android中保存媒体文件



我刚开始开发android,我对如何将媒体文件保存到外部存储中的自定义文件夹感到非常困惑。我读过关于作用域存储的文章,Mediastore,但我仍然不明白

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

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

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

  1. 使用哪一个?范围存储还是媒体存储API
  2. 如何实现上述内容

附加信息:

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

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

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

以下是如何将位图对象(jpg或png(保存到外部存储并在MediaStore中注册的示例。首先从MediaStore中删除文件的任何现有记录,然后使用ContentResolver.insert((方法将位图保存到外部存储。

请注意,MediaStore中的DATA列指的是文件的完整路径。

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);
}
}

最新更新