Android 11 将(图片)文件存储至外部共享存储区域

一、简单介绍一下:

1、外部共享存储区域:主要是指系统根目录下的比如

DIRECTORY_DCIM

DIRECTORY_MUSIC

DIRECTORY_DOWNLOADS

DIRECTORY_DOCUMENTS

DIRECTORY_PICTURES等。

2、外部存储区域:指SDCard下任意路径。

在Android11以上已经不能直接newFile(),Android10.0可以通过在AndroidManifest.xml application加上android:requestLegacyExternalStorage="true"还能继续访问外部存储。Android11.0开始只能将文件先存在自己的app(Android.data.com.xxx.xxx)的目录下。

所以就有需求将图片文件从沙盒拷贝到外部共享存储区域

上代码:

 
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
import android.util.Log;
 
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
 
public class SaveUtils {
    private static final String TAG = "SaveImagevideoUtils";
 
    /**
     * 将图片保存到系统相册
     */
    public static boolean saveImgToAlbum(Context context, String imageFile) {
        Log.d(TAG, "saveImgToAlbum() imageFile = [" + imageFile + "]");
        try {
            ContentResolver localContentResolver = context.getContentResolver();
            File tempFile = new File(imageFile);
            ContentValues localContentValues = getImageContentValues(tempFile, System.currentTimeMillis());
            Uri uri = localContentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, localContentValues);
 
            copyFileAfterQ(context, localContentResolver, tempFile, uri);
            context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
 
    /**
     * 获取图片的ContentValue
     */
    public static ContentValues getImageContentValues(File paramFile, long timestamp) {
        ContentValues localContentValues = new ContentValues();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            localContentValues.put(MediaStore.Images.Media.RELATIVE_PATH, "DCIM/Camera");
        }
        localContentValues.put(MediaStore.Images.Media.TITLE, paramFile.getName());
        localContentValues.put(MediaStore.Images.Media.DISPLAY_NAME, paramFile.getName());
        localContentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
        localContentValues.put(MediaStore.Images.Media.DATE_TAKEN, timestamp);
        localContentValues.put(MediaStore.Images.Media.DATE_MODIFIED, timestamp);
        localContentValues.put(MediaStore.Images.Media.DATE_ADDED, timestamp);
        localContentValues.put(MediaStore.Images.Media.ORIENTATION, 0);
        localContentValues.put(MediaStore.Images.Media.DATA, paramFile.getAbsolutePath());
        localContentValues.put(MediaStore.Images.Media.SIZE, paramFile.length());
        return localContentValues;
    }
 
    /**
     * 将视频保存到系统相册
     */
    public static boolean saveVideoToAlbum(Context context, String videoFile) {
        Log.d(TAG, "saveVideoToAlbum() videoFile = [" + videoFile + "]");
        try {
            ContentResolver localContentResolver = context.getContentResolver();
            File tempFile = new File(videoFile);
            ContentValues localContentValues = getVideoContentValues(tempFile, System.currentTimeMillis());
 
            Uri localUri = localContentResolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, localContentValues);
 
            copyFileAfterQ(context, localContentResolver, tempFile, localUri);
            context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, localUri));
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
 
    private static void copyFileAfterQ(Context context, ContentResolver localContentResolver, File tempFile, Uri localUri) throws IOException {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R &&
                context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R) {
            //拷贝文件到相册的uri,android11及以上得这么干,否则不会显示。可以参考ScreenMediaRecorder的save方法
            OutputStream os = localContentResolver.openOutputStream(localUri, "w");
            Files.copy(tempFile.toPath(), os);
            os.close();
            tempFile.deleteOnExit();
        }
    }
 
 
    /**
     * 获取视频的contentValue
     */
    public static ContentValues getVideoContentValues(File paramFile, long timestamp) {
        ContentValues localContentValues = new ContentValues();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            localContentValues.put(MediaStore.Video.Media.RELATIVE_PATH, "DCIM/Camera");
        }
        localContentValues.put(MediaStore.Video.Media.TITLE, paramFile.getName());
        localContentValues.put(MediaStore.Video.Media.DISPLAY_NAME, paramFile.getName());
        localContentValues.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4");
        localContentValues.put(MediaStore.Video.Media.DATE_TAKEN, timestamp);
        localContentValues.put(MediaStore.Video.Media.DATE_MODIFIED, timestamp);
        localContentValues.put(MediaStore.Video.Media.DATE_ADDED, timestamp);
        localContentValues.put(MediaStore.Video.Media.DATA, paramFile.getAbsolutePath());
        localContentValues.put(MediaStore.Video.Media.SIZE, paramFile.length());
        return localContentValues;
    }
 
 
 
}

传入context和Filename,通过ContentValues进行操作其实现在基本都是用ContentValues

最后记得申请权限,后边补充

再来一个获取路径的方法,在这个路径下面进行存储等操作

if (Build.VERSION.SDK_INT < 29) {
            path = Environment.getExternalStorageDirectory() + "/" + 名称;
        } else {
//10以后
            path = activity.getExternalFilesDir("").getAbsolutePath() + 名称;
        }

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值