|  | @@ -2,12 +2,14 @@ package com.cooleshow.base.utils;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import android.app.Application;
 | 
	
		
			
				|  |  |  import android.content.ContentResolver;
 | 
	
		
			
				|  |  | +import android.content.ContentValues;
 | 
	
		
			
				|  |  |  import android.content.Context;
 | 
	
		
			
				|  |  |  import android.content.Intent;
 | 
	
		
			
				|  |  |  import android.content.res.AssetFileDescriptor;
 | 
	
		
			
				|  |  |  import android.database.Cursor;
 | 
	
		
			
				|  |  |  import android.graphics.Bitmap;
 | 
	
		
			
				|  |  |  import android.graphics.BitmapFactory;
 | 
	
		
			
				|  |  | +import android.media.MediaScannerConnection;
 | 
	
		
			
				|  |  |  import android.net.Uri;
 | 
	
		
			
				|  |  |  import android.os.Build;
 | 
	
		
			
				|  |  |  import android.os.Environment;
 | 
	
	
		
			
				|  | @@ -18,11 +20,8 @@ import android.text.TextUtils;
 | 
	
		
			
				|  |  |  import android.util.Base64;
 | 
	
		
			
				|  |  |  import android.util.Log;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -import com.luck.picture.lib.tools.BitmapUtils;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -import org.w3c.dom.Text;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  import java.io.BufferedInputStream;
 | 
	
		
			
				|  |  | +import java.io.BufferedOutputStream;
 | 
	
		
			
				|  |  |  import java.io.ByteArrayInputStream;
 | 
	
		
			
				|  |  |  import java.io.ByteArrayOutputStream;
 | 
	
		
			
				|  |  |  import java.io.File;
 | 
	
	
		
			
				|  | @@ -34,6 +33,7 @@ import java.io.IOException;
 | 
	
		
			
				|  |  |  import java.io.InputStream;
 | 
	
		
			
				|  |  |  import java.io.OutputStream;
 | 
	
		
			
				|  |  |  import java.net.URL;
 | 
	
		
			
				|  |  | +import java.nio.file.Files;
 | 
	
		
			
				|  |  |  import java.security.DigestInputStream;
 | 
	
		
			
				|  |  |  import java.security.MessageDigest;
 | 
	
		
			
				|  |  |  import java.security.NoSuchAlgorithmException;
 | 
	
	
		
			
				|  | @@ -1656,7 +1656,7 @@ public final class FileUtils {
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          String targetFileName = "IMG_" + new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date()) + ".png";
 | 
	
		
			
				|  |  |          File file = new File(parentFile, targetFileName);
 | 
	
		
			
				|  |  | -        FileUtils.saveImagToGallery(bitmap, file.getAbsolutePath());
 | 
	
		
			
				|  |  | +        FileUtils.saveImag(bitmap, file.getAbsolutePath());
 | 
	
		
			
				|  |  |          if (file != null && file.exists()) {
 | 
	
		
			
				|  |  |              try {
 | 
	
		
			
				|  |  |                  MediaStore.Images.Media.insertImage(Utils.getApp().getContentResolver(),
 | 
	
	
		
			
				|  | @@ -1672,11 +1672,11 @@ public final class FileUtils {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /**
 | 
	
		
			
				|  |  | -     * 保存图片到图库
 | 
	
		
			
				|  |  | +     * 保存图片
 | 
	
		
			
				|  |  |       *
 | 
	
		
			
				|  |  |       * @param bmp
 | 
	
		
			
				|  |  |       */
 | 
	
		
			
				|  |  | -    public static void saveImagToGallery(Bitmap bmp, String path) throws Exception {
 | 
	
		
			
				|  |  | +    public static void saveImag(Bitmap bmp, String path) throws Exception {
 | 
	
		
			
				|  |  |          // 首先保存图片
 | 
	
		
			
				|  |  |          File file = new File(path);
 | 
	
		
			
				|  |  |          FileOutputStream fos = new FileOutputStream(file);
 | 
	
	
		
			
				|  | @@ -1727,7 +1727,7 @@ public final class FileUtils {
 | 
	
		
			
				|  |  |       *
 | 
	
		
			
				|  |  |       * @param bmp
 | 
	
		
			
				|  |  |       */
 | 
	
		
			
				|  |  | -    public static void saveImageToGallery(Bitmap bmp, String path) {
 | 
	
		
			
				|  |  | +    public static void saveImageToLocal(Bitmap bmp, String path) {
 | 
	
		
			
				|  |  |          // 首先保存图片
 | 
	
		
			
				|  |  |          File file = new File(path);
 | 
	
		
			
				|  |  |          try {
 | 
	
	
		
			
				|  | @@ -1753,12 +1753,12 @@ public final class FileUtils {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      public static boolean isMatchTargetFileType(String targetType, String filePath) {
 | 
	
		
			
				|  |  |          try {
 | 
	
		
			
				|  |  | -            Log.i("FileUtils","filePath:"+filePath);
 | 
	
		
			
				|  |  | +            Log.i("FileUtils", "filePath:" + filePath);
 | 
	
		
			
				|  |  |              if (TextUtils.isEmpty(targetType)) {
 | 
	
		
			
				|  |  |                  Log.i("FileUtils", "targetType is null");
 | 
	
		
			
				|  |  |                  return true;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -            if (TextUtils.equals(targetType,"video") || TextUtils.equals(targetType,"img")) {
 | 
	
		
			
				|  |  | +            if (TextUtils.equals(targetType, "video") || TextUtils.equals(targetType, "img")) {
 | 
	
		
			
				|  |  |                  //忽略video或者img格式
 | 
	
		
			
				|  |  |                  Log.i("FileUtils", "video or img type is ignore");
 | 
	
		
			
				|  |  |                  return true;
 | 
	
	
		
			
				|  | @@ -1789,4 +1789,101 @@ public final class FileUtils {
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          return true;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public static boolean saveVideoToGallery(Context context, String filePath) {
 | 
	
		
			
				|  |  | +        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
 | 
	
		
			
				|  |  | +            return saveVideoToAlbumBeforeQ(context, filePath);
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +            return saveVideoToAlbumAfterQ(context, filePath);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private static boolean saveVideoToAlbumAfterQ(Context context, String videoFile) {
 | 
	
		
			
				|  |  | +        try {
 | 
	
		
			
				|  |  | +            ContentResolver contentResolver = context.getContentResolver();
 | 
	
		
			
				|  |  | +            File tempFile = new File(videoFile);
 | 
	
		
			
				|  |  | +            ContentValues contentValues = getVideoContentValues(context, tempFile, System.currentTimeMillis());
 | 
	
		
			
				|  |  | +            Uri uri = contentResolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, contentValues);
 | 
	
		
			
				|  |  | +            copyFileAfterQ(context, contentResolver, tempFile, uri);
 | 
	
		
			
				|  |  | +            contentValues.clear();
 | 
	
		
			
				|  |  | +            contentValues.put(MediaStore.MediaColumns.IS_PENDING, 0);
 | 
	
		
			
				|  |  | +            context.getContentResolver().update(uri, contentValues, null, null);
 | 
	
		
			
				|  |  | +            context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));
 | 
	
		
			
				|  |  | +            return true;
 | 
	
		
			
				|  |  | +        } catch (Exception e) {
 | 
	
		
			
				|  |  | +            e.printStackTrace();
 | 
	
		
			
				|  |  | +            return false;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 获取视频的contentValue
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public static ContentValues getVideoContentValues(Context context, File paramFile, long timestamp) {
 | 
	
		
			
				|  |  | +        ContentValues localContentValues = new ContentValues();
 | 
	
		
			
				|  |  | +        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
 | 
	
		
			
				|  |  | +            localContentValues.put(MediaStore.Video.Media.RELATIVE_PATH, Environment.DIRECTORY_DCIM
 | 
	
		
			
				|  |  | +                    + File.separator + context.getPackageName());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        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.SIZE, paramFile.length());
 | 
	
		
			
				|  |  | +        return localContentValues;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private static void copyFileAfterQ(Context context, ContentResolver localContentResolver, File tempFile, Uri localUri) throws IOException {
 | 
	
		
			
				|  |  | +        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q &&
 | 
	
		
			
				|  |  | +                context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q) {
 | 
	
		
			
				|  |  | +            //拷贝文件到相册的uri,android10及以上得这么干,否则不会显示。可以参考ScreenMediaRecorder的save方法
 | 
	
		
			
				|  |  | +            OutputStream os = localContentResolver.openOutputStream(localUri);
 | 
	
		
			
				|  |  | +            Files.copy(tempFile.toPath(), os);
 | 
	
		
			
				|  |  | +            os.close();
 | 
	
		
			
				|  |  | +            tempFile.delete();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private static boolean saveVideoToAlbumBeforeQ(Context context, String videoFile) {
 | 
	
		
			
				|  |  | +        File picDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
 | 
	
		
			
				|  |  | +        File tempFile = new File(videoFile);
 | 
	
		
			
				|  |  | +        File destFile = new File(picDir, context.getPackageName() + File.separator + tempFile.getName());
 | 
	
		
			
				|  |  | +        FileInputStream ins = null;
 | 
	
		
			
				|  |  | +        BufferedOutputStream ous = null;
 | 
	
		
			
				|  |  | +        try {
 | 
	
		
			
				|  |  | +            ins = new FileInputStream(tempFile);
 | 
	
		
			
				|  |  | +            ous = new BufferedOutputStream(new FileOutputStream(destFile));
 | 
	
		
			
				|  |  | +            long nread = 0L;
 | 
	
		
			
				|  |  | +            byte[] buf = new byte[1024];
 | 
	
		
			
				|  |  | +            int n;
 | 
	
		
			
				|  |  | +            while ((n = ins.read(buf)) > 0) {
 | 
	
		
			
				|  |  | +                ous.write(buf, 0, n);
 | 
	
		
			
				|  |  | +                nread += n;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            MediaScannerConnection.scanFile(
 | 
	
		
			
				|  |  | +                    context,
 | 
	
		
			
				|  |  | +                    new String[]{destFile.getAbsolutePath()},
 | 
	
		
			
				|  |  | +                    new String[]{"video/*"},
 | 
	
		
			
				|  |  | +                    (path, uri) -> {
 | 
	
		
			
				|  |  | +                        // Scan Completed
 | 
	
		
			
				|  |  | +                    });
 | 
	
		
			
				|  |  | +            return true;
 | 
	
		
			
				|  |  | +        } catch (Exception e) {
 | 
	
		
			
				|  |  | +            e.printStackTrace();
 | 
	
		
			
				|  |  | +            return false;
 | 
	
		
			
				|  |  | +        } finally {
 | 
	
		
			
				|  |  | +            try {
 | 
	
		
			
				|  |  | +                if (ins != null) {
 | 
	
		
			
				|  |  | +                    ins.close();
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                if (ous != null) {
 | 
	
		
			
				|  |  | +                    ous.close();
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            } catch (IOException e) {
 | 
	
		
			
				|  |  | +                e.printStackTrace();
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  }
 |