Android实现保存图片和视频到系统相册

·  阅读 2884
  •     最近在做图片和视频保存功能,之前做的是保存到sd卡目录下,现在是保存到系统相册中.流程就是读取一张网络图片,通过AndroidDownLoadManager下载管理类把图片下载到本地相册,然后通过ContentResolver刷新相册

  • 遇到问题:

  • 1.Android 9.0网络请求适配,在Manifest中设置android:usesCleartextTraffic="true"即可解决AndroidP加载网络问题.

  • 2.下载完成后进度不更新,在Manifest中配置下载权限.

  • 3.保存到本地相册不刷新问题.解决方法:先动态请求读写权限,然后调用系统数据库用广播通知界面刷新.

  • 4.MainActivity完整代码:

  •   public class MainActivity extends AppCompatActivity {
          private TextView tvSaveImage, tvSaveVideo;
          private boolean flag = true;
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
              // 请求权限
              loadPermission();
              initView();
              initListener();
          }
      
          /**
           * 动态请求权限
           */
          private void loadPermission() {
              PermissionsUtil.requestCamera(this, aBoolean -> {
      
                      }
              );
          }
      
          private void initView() {
              tvSaveImage = findViewById(R.id.tv_save_image);
              tvSaveVideo = findViewById(R.id.tv_save_video);
          }
      
          private void initListener() {
              tvSaveImage.setOnClickListener(v -> {
                  if (false) {
                      Toast.makeText(MainActivity.this, "图片开始下载", Toast.LENGTH_SHORT).show();
                      flag = false;
                  } else {
                      Toast.makeText(MainActivity.this, "图片正在下载", Toast.LENGTH_SHORT).show();
                  }
                  //String url = "https://pic.cnblogs.com/avatar/1142647/20170416093225.png";
                  //String url = "http://ww3.sinaimg.cn/bmiddle/6e91531djw1e8l3c7wo7xj20f00qo755.jpg";
                  //String url = "https://ae01.alicdn.com/kf/U29ad1424fd024374bf8ba95a61a60d8ai.jpg";
                  String url = "https://ae01.alicdn.com/kf/Ua227945b506241af975a9b0a16d6df3bA.jpg";
                  //保存图片
                  downLoadImage(url);
              });
      
              tvSaveVideo.setOnClickListener(v -> {
                  if (false) {
                      Toast.makeText(MainActivity.this, "视频下载开始", Toast.LENGTH_SHORT).show();
                      flag = false;
                  } else {
                      Toast.makeText(MainActivity.this, "视频正在下载", Toast.LENGTH_SHORT).show();
                  }
                  downLoadVideo("https://www.w3school.com.cn/example/html5/mov_bbb.mp4");
              });
          }
      
          /**
           * 保存图片到相册
           * @param path
           */
          private void downLoadImage(String path) {
              new Thread(() -> new AndroidDownloadManager(MainActivity.this, path)
                      .setListener(new AndroidDownloadManagerListener() {
                          @Override
                          public void onPrepare() {
                              Log.d("downloadVideo", "onPrepare");
                          }
      
                          @Override
                          public void onSuccess(String path) {
                              Toast.makeText(MainActivity.this, "图片已保存到相册", Toast.LENGTH_SHORT).show();
                              FileUtils.saveImage(MainActivity.this,new File(path));
                              flag = true;
                              Log.d("downloadVideo", "onSuccess >>>>" + path);
                          }
      
                          @Override
                          public void onFailed(Throwable throwable) {
                              Toast.makeText(MainActivity.this, "图片下载失败,请重新下载!", Toast.LENGTH_SHORT).show();
                              Log.e("downloadVideo", "onFailed", throwable);
                              flag = true;
                          }
                      }).download()).start();
          }
      
          /**
           * 保存视频到相册
           * @param path
           */
          private void downLoadVideo(String path) {
              new Thread(() -> new AndroidDownloadManager(MainActivity.this, path)
                      .setListener(new AndroidDownloadManagerListener() {
                          @Override
                          public void onPrepare() {
                              Log.d("downloadVideo", "onPrepare");
                          }
      
                          @Override
                          public void onSuccess(String path) {
                              Toast.makeText(MainActivity.this, "视频已保存到相册", Toast.LENGTH_SHORT).show();
                              FileUtils.saveVideo(MainActivity.this,new File(path));
                              flag = true;
                              Log.d("downloadVideo", "onSuccess >>>>" + path);
                          }
      
                          @Override
                          public void onFailed(Throwable throwable) {
                              Toast.makeText(MainActivity.this, "视频下载失败,请重新下载!", Toast.LENGTH_SHORT).show();
                              Log.e("downloadVideo", "onFailed", throwable);
                              flag = true;
                          }
                      }).download()).start();
          }
      
      
      }
      
    复制代码

    activity_main.xml:

      <?xml version="1.0" encoding="utf-8"?>
      <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:app="http://schemas.android.com/apk/res-auto"
          xmlns:tools="http://schemas.android.com/tools"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          tools:context=".MainActivity">
      
          <TextView
              android:id="@+id/tv_save_image"
              android:layout_width="0dp"
              android:layout_height="50dp"
              android:text="保存图片到相册"
              android:textSize="16sp"
              android:textColor="#ffffff"
              android:gravity="center"
              android:background="@color/colorPrimary"
              app:layout_constraintBottom_toBottomOf="parent"
              app:layout_constraintLeft_toLeftOf="parent"
              app:layout_constraintRight_toLeftOf="@+id/tv_save_video"
              app:layout_constraintTop_toTopOf="parent" />
          <TextView
              android:id="@+id/tv_save_video"
              android:layout_width="0dp"
              android:layout_height="50dp"
              android:text="保存视频"
              android:textSize="16sp"
              android:textColor="#ffffff"
              android:gravity="center"
              android:layout_marginStart="20dp"
              app:layout_constraintLeft_toRightOf="@+id/tv_save_image"
              app:layout_constraintRight_toRightOf="parent"
              app:layout_constraintTop_toBottomOf="parent"
              app:layout_constraintBottom_toTopOf="parent"
              android:background="@color/colorPrimary"/>
      <androidx.constraintlayout.widget.Group
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:visibility="visible"
          app:constraint_referenced_ids="tv_save_image,tv_save_video"/>
      </androidx.constraintlayout.widget.ConstraintLayout>
    复制代码
  • 5.FileUtils:

  •   /**
       * @anthor:njb
       * @date: 2020-04-21 04:36
       * @desc: 文件保存工具类
       **/
      public class FileUtils {
          /**
           * 保存图片
           * @param context
           * @param file
           */
          public static void saveImage(Context context, File file) {
              ContentResolver localContentResolver = context.getContentResolver();
              ContentValues localContentValues = getImageContentValues(context, file, System.currentTimeMillis());
              localContentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, localContentValues);
      
              Intent localIntent = new Intent("android.intent.action.MEDIA_SCANNER_SCAN_FILE");
              final Uri localUri = Uri.fromFile(file);
              localIntent.setData(localUri);
              context.sendBroadcast(localIntent);
          }
      
          public static ContentValues getImageContentValues(Context paramContext, File paramFile, long paramLong) {
              ContentValues localContentValues = new ContentValues();
              localContentValues.put("title", paramFile.getName());
              localContentValues.put("_display_name", paramFile.getName());
              localContentValues.put("mime_type", "image/jpeg");
              localContentValues.put("datetaken", Long.valueOf(paramLong));
              localContentValues.put("date_modified", Long.valueOf(paramLong));
              localContentValues.put("date_added", Long.valueOf(paramLong));
              localContentValues.put("orientation", Integer.valueOf(0));
              localContentValues.put("_data", paramFile.getAbsolutePath());
              localContentValues.put("_size", Long.valueOf(paramFile.length()));
              return localContentValues;
          }
      
      
          /**
           * 保存视频
           * @param context
           * @param file
           */
          public static void saveVideo(Context context, File file) {
              //是否添加到相册
              ContentResolver localContentResolver = context.getContentResolver();
              ContentValues localContentValues = getVideoContentValues(context, file, System.currentTimeMillis());
              Uri localUri = localContentResolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, localContentValues);
              context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, localUri));
          }
      
          public static ContentValues getVideoContentValues(Context paramContext, File paramFile, long paramLong) {
              ContentValues localContentValues = new ContentValues();
              localContentValues.put("title", paramFile.getName());
              localContentValues.put("_display_name", paramFile.getName());
              localContentValues.put("mime_type", "video/mp4");
              localContentValues.put("datetaken", Long.valueOf(paramLong));
              localContentValues.put("date_modified", Long.valueOf(paramLong));
              localContentValues.put("date_added", Long.valueOf(paramLong));
              localContentValues.put("_data", paramFile.getAbsolutePath());
              localContentValues.put("_size", Long.valueOf(paramFile.length()));
              return localContentValues;
          }
      }
      
    复制代码

    6.文件下载工具类:

      /**
       * @anthor:njb
       * @date: 2020-04-21 04:36
       * @desc: 文件下载工具类
       **/
      public class AndroidDownloadManager {
          private DownloadManager downloadManager;
          private Context context;
          private long downloadId;
          private String url;
          private String name;
      
          private String path;
      
          private AndroidDownloadManagerListener listener;
      
          public AndroidDownloadManager(Context context, String url) {
              this(context, url, getFileNameByUrl(url));
          }
      
          public AndroidDownloadManager(Context context, String url, String name) {
              this.context = context;
              this.url = url;
              this.name = name;
          }
      
          public AndroidDownloadManager setListener(AndroidDownloadManagerListener listener) {
              this.listener = listener;
              return this;
          }
      
          /**
           * 开始下载
           */
          public void download() {
              DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
              //移动网络情况下是否允许漫游
              request.setAllowedOverRoaming(false);
              //在通知栏中显示,默认就是显示的
              request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
              request.setTitle(name);
              request.setDescription("文件正在下载中......");
              request.setVisibleInDownloadsUi(true);
      
              //设置下载的路径
              File file = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), name);
              request.setDestinationUri(Uri.fromFile(file));
              path = file.getAbsolutePath();
      
              //获取DownloadManager
              if (downloadManager == null) {
                  downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
              }
              //将下载请求加入下载队列,加入下载队列后会给该任务返回一个long型的id,通过该id可以取消任务,重启任务、获取下载的文件等等
              if (downloadManager != null) {
                  if (listener != null) {
                      listener.onPrepare();
                  }
                  downloadId = downloadManager.enqueue(request);
              }
      
              //注册广播接收者,监听下载状态
              context.registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
          }
      
          //广播监听下载的各个状态
          private BroadcastReceiver receiver = new BroadcastReceiver() {
              @Override
              public void onReceive(Context context, Intent intent) {
                  DownloadManager.Query query = new DownloadManager.Query();
                  //通过下载的id查找
                  query.setFilterById(downloadId);
                  Cursor cursor = downloadManager.query(query);
                  if (cursor.moveToFirst()) {
                      int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
                      switch (status) {
                          //下载暂停
                          case DownloadManager.STATUS_PAUSED:
                              break;
                          //下载延迟
                          case DownloadManager.STATUS_PENDING:
                              break;
                          //正在下载
                          case DownloadManager.STATUS_RUNNING:
                              break;
                          //下载完成
                          case DownloadManager.STATUS_SUCCESSFUL:
                              if (listener != null) {
                                  listener.onSuccess(path);
                              }
                              cursor.close();
                              context.unregisterReceiver(receiver);
                              break;
                          //下载失败
                          case DownloadManager.STATUS_FAILED:
                              if (listener != null) {
                                  listener.onFailed(new Exception("下载失败"));
                              }
                              cursor.close();
                              context.unregisterReceiver(receiver);
                              break;
                      }
                  }
              }
          };
      
      
          // ——————————————————————私有方法———————————————————————
      
          /**
           * 通过URL获取文件名
           *
           * @param url
           * @return
           */
          private static final String getFileNameByUrl(String url) {
              String filename = url.substring(url.lastIndexOf("/") + 1);
              filename = filename.substring(0, filename.indexOf("?") == -1 ? filename.length() : filename.indexOf("?"));
              return filename;
          }
      
      }
    复制代码
  • public interface AndroidDownloadManagerListener { 

  •  void onPrepare(); 

  •  void onSuccess(String path); 

  •  void onFailed(Throwable throwable); }

  • 7.适配了7.0文件共享权限:

  • ​ 8.最后放一个完整的效果图:可以看到图片和视频到保存到系统,并且图片和视频都可以打开.

  • 9.目前只是测试了华为、小米、魅族、联想等几种机型,可能在某些机型出现问题,小伙伴们可以自行测试,AndroidQ也没有适配,如果有兴趣可以加上.后面我也会加上.

  • 项目完整地址:gitee.com/jackning_ad…

分类:
Android
标签:
分类:
Android
标签:
收藏成功!
已添加到「」, 点击更改