最近在做图片和视频保存功能,之前做的是保存到sd卡目录下,现在是保存到系统相册中.
遇到问题:
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:
还可以学习约束布局的使用:
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也没有适配,如果有兴趣可以加上.后面我也会加上.
项目完整地址:https://gitee.com/jackning_admin/SaveImageAndVideo