最近在做图片和视频保存功能,之前做的是保存到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;@Overrideprotected 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() {@Overridepublic void onPrepare() {Log.d("downloadVideo", "onPrepare");}@Overridepublic 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);}@Overridepublic 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() {@Overridepublic void onPrepare() {Log.d("downloadVideo", "onPrepare");}@Overridepublic 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);}@Overridepublic 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"><TextViewandroid: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" /><TextViewandroid: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.Groupandroid: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();//获取DownloadManagerif (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() {@Overridepublic 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也没有适配,如果有兴趣可以加上.后面我也会加上.

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

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

  1. android 录制图片、视频插入系统相册视频相册列表中,视频mediaPlayer静音和mediaPlayer恢复静音,SurfaceView+mediaplayer视频播放,自定义任意view显示

    video_duration = mediaPlayer.getDuration() / 1000 video_duration需要在prepare()监听中进行初始化 通知系统,将图片.视频更新到系 ...

  2. android 保存图片(视频)到相册

    概述 此功能麻烦的地方主要在机型适配上. 此功能实现步骤如下: 将图片存储到手机picture目录下.(一般是从原位置复制过来) 将该文件扫描到相册. 本文的例子是将应用自带的内容存储到picture ...

  3. iOS 保存图片(视频)到相册

    1.C语言函数方式实现 注意:UIImageWriteToSavedPhotosAlbum方法必须实现代理方法,否则会崩溃. //参数1:图片对象 //参数2:成功方法绑定的target //参数3: ...

  4. 考拉解析网站Android 安卓手机下载视频到手机相册

    第一步:打开网站http://www.zanqianba.com并粘贴视频链接进输入框 第二步:点击下载视频链接

  5. 基于android的图片上传分享系统相册app

    该图片上传分享系统是一款基于安卓的双端程序,客户端采用eclipse作为开发平台,服务端采用了myeclipse作为开发平台,数据库是mysql,主要实现了图片的编辑和上传的功能,界面美观大气,功能技 ...

  6. Android之靠谱的把图片和视频插入手机系统相册

    1 需求 把图片和视频插入手机系统相册,网上查了下基本上很乱,没几个靠谱的. 2 结果爆照 3 思路 图片插入系统相册(可以直接插入系统相册,但是我这里多做了一步就是先把图片拷贝到了一个目录再插入系统 ...

  7. 解决Android拍照保存在系统相册不显示的问题

    可能大家都知道我们保存相册到Android手机的时候,然后去打开系统图库找不到我们想要的那张图片,那是因为我们插入的图片还没有更新的缘故,先讲解下插入系统图库的方法吧,很简单,一句代码就能实现 [ja ...

  8. uniapp框架如何实现仿微信相册 | 图视频过滤、相册选择功能

    今天我们分享基于uniapp + vue实现仿微信相册实例,该插件完全还原了微信相册的功能 1: 相册选择 2: 图片,视频类型过滤 3: 自定义相册界面UI 技术实现 开发环境:HbuilderX ...

  9. ARFoundation系列讲解 - 56 录制屏幕并且保存到系统相册

    一.介绍 录制视频我们使用的是 "NatCorder" 插件,"NatCorder" 是一个跨平台屏幕录制软件,可以指定录制视频的相机层级.在Android.i ...

  10. iOS 下载视频并导入相册

    知识点1: 只能(也可能有别的步骤,不过我暂时没有想出来)先把mp4视频文件通过AFNetWorking下载到沙盒路径,(个人建议下载到NSCachesDirectory缓存下,不要放到NSDocum ...

最新文章

  1. 【C语言探索之旅】 第一部分第六课:条件表达式
  2. log4net配置学习 之 日志等级
  3. java中flush 函数,Java DataOutputStream.flush()类型
  4. ajaxbootstrap
  5. JavaScript——易班优课YOOC课群在线测试自动答题解决方案(十九)强制重做
  6. jq select操作全集
  7. python哪个方向简单_现在学Python,哪个方向最简单?哪个方向最吃香 ?
  8. c语言求最多啤酒数,C语言,算法、动态规划:有一个箱子的容量为v(正整数,0=v=20000),同时有n个物品(0n=30),...
  9. keras中文文档_Keras分词器Tokenizer
  10. 一天一点linux(17):安装与使用Tmux
  11. FMS集群的安装和配置
  12. 百度网盘断点续传下载工具IDM
  13. WSAGetLastError错误列表
  14. 招聘后台投递设置联动按钮迭代开发总结
  15. Android APP极限瘦身—— WebP 图片优化
  16. 1.1.1 操作系统的层次结构、基本概念、功能和目标
  17. 【NLP】从WE、ELMo、GPT到Bert模型—自然语言处理中的预训练技术发展史
  18. Java实验:编写网络聊天程序(图形界面)
  19. 自编记单词小程序项目(自定义词库,多功能)C/C++语言实现
  20. 交通安全管理毕业论文范文

热门文章

  1. Ubuntu锐捷校园网连接不上问题,认证成功但是上不去网。
  2. Python 大数据的进行信用卡欺诈检测(附源码与注释)
  3. [ctfshow]web入门——命令执行(web54-web71)
  4. idea中Gsonformat插件工具使用
  5. 《Axure RP 9实战指南》Axure RP 9.0最新版汉化问题
  6. 如何评价一个专业PKM软件?
  7. 软件项目管理案例教程课后答案
  8. 这几个开源的商城实战项目,良月柒强烈推荐!
  9. 转载:vc6.0 打开文件的时候出现Microsoft Visual C++:MSDEV.EXE 应用程序错误
  10. PVE安装Linux提示:error: /vmlinuz has invalid signature.