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

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

    遇到问题:

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

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

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
<uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER" />

  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也没有适配,如果有兴趣可以加上.后面我也会加上. 

项目完整地址:SaveImageAndVideo: Android实现保存图片和视频到系统相册

  • 8
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 20
    评论
Android Studio中保存图片相册可以通过以下步骤进行: 1. 首先,确保你的应用已经申请了写入外部存储的权限。在AndroidManifest.xml文件中添加以下权限: ```xml <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> ``` 2. 创建一个用于保存图片的方法,如下所示: ```java private void saveImageToGallery(Bitmap bitmap) { // 获取存储路径 String savePath = Environment.getExternalStorageDirectory().getPath() + "/YourAppName/"; // 创建文件夹 File appDir = new File(savePath); if (!appDir.exists()) { appDir.mkdirs(); } // 生成文件名 String fileName = System.currentTimeMillis() + ".jpg"; // 创建文件对象 File file = new File(appDir, fileName); try { FileOutputStream fos = new FileOutputStream(file); // 将bitmap保存到文件中 bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); fos.flush(); fos.close(); } catch (IOException e) { e.printStackTrace(); } // 发送广播通知系统图库更新 Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); Uri uri = Uri.fromFile(file); intent.setData(uri); sendBroadcast(intent); } ``` 3. 调用该方法来保存图片相册: ```java Bitmap bitmap = ...; // 你要保存的图片Bitmap对象 saveImageToGallery(bitmap); ``` 这样就能将图片保存到相册中了。请注意,Android 10及以上版本需要额外处理,以适配分区存储的限制。这里提供的代码示例适用于Android 10以下的版本。如需适配Android 10及以上版本,请参考官方文档并进行相应修改。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值