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

    最近在做图片和视频保存功能,之前做的是保存到sd卡目录下,现在是保存到系统相册中.

    遇到问题:

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

Android实现保存图片和视频到系统相册_第1张图片

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













Android实现保存图片和视频到系统相册_第2张图片

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

Android实现保存图片和视频到系统相册_第3张图片

Android实现保存图片和视频到系统相册_第4张图片

 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:




    
    


还可以学习约束布局的使用:

5.FileUtils:

Android实现保存图片和视频到系统相册_第5张图片

/**
 * @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;
    }

}

Android实现保存图片和视频到系统相册_第6张图片

public interface AndroidDownloadManagerListener {
    void onPrepare();

    void onSuccess(String path);

    void onFailed(Throwable throwable);
}

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

Android实现保存图片和视频到系统相册_第7张图片

Android实现保存图片和视频到系统相册_第8张图片 8.最后放一个完整的效果图:可以看到图片和视频到保存到系统,并且图片和视频都可以打开.

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

项目完整地址:https://gitee.com/jackning_admin/SaveImageAndVideo

你可能感兴趣的:(开发实例)