Android开发之保存图片到相册的三种方法详解

作者:xiayiye5 时间:2022-07-26 04:49:10 

有三种方法如下:三个方法都需要动态申请读写权限否则保存图片到相册也会失败

方法一

/**
    * 保存bitmap到本地
    *
    * @param bitmap Bitmap
    */
   public static void saveBitmap(Bitmap bitmap, String path) {
       String savePath;
       File filePic;
       if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
           savePath = path;
       } else {
           Log.e("tag", "saveBitmap failure : sdcard not mounted");
           return;
       }
       try {
           filePic = new File(savePath);
           if (!filePic.exists()) {
               filePic.getParentFile().mkdirs();
               filePic.createNewFile();
           }
           FileOutputStream fos = new FileOutputStream(filePic);
           bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
           fos.flush();
           fos.close();
       } catch (IOException e) {
           Log.e("tag", "saveBitmap: " + e.getMessage());
           return;
       }
       Log.i("tag", "saveBitmap success: " + filePic.getAbsolutePath());
   }

方法二

针对小于API29以下方法,此方法会通知图库更新


   /**
    * API 29及以下保存图片到相册的方法
    *
    * @param toBitmap 要保存的图片
    */
   private void saveImage(Bitmap toBitmap) {
       String insertImage = MediaStore.Images.Media.insertImage(getContentResolver(), toBitmap, "壁纸", "搜索猫相关图片后保存的图片");
       if (!TextUtils.isEmpty(insertImage)) {
           Toast.makeText(this, "图片保存成功!" + insertImage, Toast.LENGTH_SHORT).show();
           Log.e("打印保存路径", insertImage + "-");
       }
   }

方法三

针对大于API29以下方法,此方法也会通知图库更新

/**
    * API29 中的最新保存图片到相册的方法
    */
   private void saveImage29(Bitmap toBitmap) {
       //开始一个新的进程执行保存图片的操作
       Uri insertUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new ContentValues());
       //使用use可以自动关闭流
       try {
           OutputStream outputStream = getContentResolver().openOutputStream(insertUri, "rw");
           if (toBitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream)) {
               Log.e("保存成功", "success");
           } else {
               Log.e("保存失败", "fail");
           }
       } catch (FileNotFoundException e) {
           e.printStackTrace();
       }
   }

上面方法二和方法三是java的写法,kotlin写法如下

package com.xiayiye.jetpackstudy.gallery

import android.Manifest
import android.content.ContentValues
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.os.Build
import android.os.Bundle
import android.provider.MediaStore
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.toBitmap
import androidx.core.view.get
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import com.xiayiye.jetpackstudy.R
import kotlinx.android.synthetic.main.fragment_view_pager2_image.*
import kotlinx.android.synthetic.main.pager_photo_view.view.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

/**
* 显示轮播大图和保存图片的页面
*/

class ViewPager2ImageFragment : Fragment() {
   companion object {
       const val REQUEST_WRITE_EXTERNAL_STORAGE_CODE = 1000
   }

override fun onCreateView(
       inflater: LayoutInflater, container: ViewGroup?,
       savedInstanceState: Bundle?
   ): View? {
       return inflater.inflate(R.layout.fragment_view_pager2_image, container, false)
   }

override fun onActivityCreated(savedInstanceState: Bundle?) {
       super.onActivityCreated(savedInstanceState)
       val photoList = arguments?.getParcelableArrayList<PhotoItem>("photo_list")
       val currentPosition = arguments?.getInt("photo_position", 0)
       PagerPhotoListAdapter().apply {
           vp2Banner.adapter = this
           submitList(photoList)
       }
       //设置轮播图片后的滑动当前页
       vp2Banner.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
           override fun onPageSelected(position: Int) {
               super.onPageSelected(position)
               tvShowImagePage.text =
                   StringBuffer().append(position + 1).append("/").append(photoList?.size)
           }
       })
       //设置 ViewPager2 的当前页要在设置 ViewPager2 的数据后在设置当前页面,否则不生效
       vp2Banner.setCurrentItem(currentPosition ?: 0, false)
       //设置纵向滚动的方法
       vp2Banner.orientation = ViewPager2.ORIENTATION_VERTICAL
       //保存图片的方法
       ivSaveImg.setOnClickListener {
           if (Build.VERSION.SDK_INT < 29 && ContextCompat.checkSelfPermission(
                   requireContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE
               ) != PackageManager.PERMISSION_GRANTED
           ) {
               requestPermissions(
                   arrayOf<String>(Manifest.permission.WRITE_EXTERNAL_STORAGE),
                   REQUEST_WRITE_EXTERNAL_STORAGE_CODE
               )
           } else {
               viewLifecycleOwner.lifecycleScope.launch { saveImage29() }
           }
       }
   }

override fun onRequestPermissionsResult(
       requestCode: Int,
       permissions: Array<out String>,
       grantResults: IntArray
   ) {
       super.onRequestPermissionsResult(requestCode, permissions, grantResults)
       if (requestCode == REQUEST_WRITE_EXTERNAL_STORAGE_CODE && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
           //权限申请成功可以保存图片
           viewLifecycleOwner.lifecycleScope.launch { saveImage29() }
       }
   }

/**
    * 保存图片到相册的方法
    *  API29 后此方法已废弃
    */
   private fun saveImage() {
       val holder =
           (vp2Banner[0] as RecyclerView).findViewHolderForAdapterPosition(vp2Banner.currentItem) as PagerPhotoListAdapter.PagerPhotoViewHolder
       val toBitmap = holder.itemView.ivPagerView.drawable.toBitmap()
       val insertImage = MediaStore.Images.Media.insertImage(
           requireActivity().contentResolver, toBitmap, "壁纸", "搜索猫相关图片后保存的图片"
       )
       if (insertImage.isNotEmpty()) {
           Toast.makeText(requireActivity(), "图片保存成功!-${insertImage}", Toast.LENGTH_SHORT).show()
       } else {
           Toast.makeText(requireActivity(), "图片保存失败!}", Toast.LENGTH_SHORT).show()
       }
   }

/**
    * API29 中的最新保存图片到相册的方法
    */
   private suspend fun saveImage29() {
       //开始一个新的进程执行保存图片的操作
       withContext(Dispatchers.IO) {
           val holder =
               (vp2Banner[0] as RecyclerView).findViewHolderForAdapterPosition(vp2Banner.currentItem) as PagerPhotoListAdapter.PagerPhotoViewHolder
           val toBitmap = holder.itemView.ivPagerView.drawable.toBitmap()
           val insertUri = requireActivity().contentResolver.insert(
               MediaStore.Images.Media.EXTERNAL_CONTENT_URI, ContentValues()
           ) ?: kotlin.run {
               showSaveToast("保存失败!")
               return@withContext
           }
           //使用use可以自动关闭流
           requireActivity().contentResolver.openOutputStream(insertUri).use {
               if (toBitmap.compress(Bitmap.CompressFormat.JPEG, 90, it)) {
                   showSaveToast("保存成功!")
               } else {
                   showSaveToast("保存失败!")
               }
           }
       }
   }

/**
    * 显示保存图片结果的方法
    */
   private fun showSaveToast(showMsg: String) =
       MainScope().launch {
           Toast.makeText(requireActivity(), showMsg, Toast.LENGTH_SHORT).show()
       }
}

来源:https://blog.csdn.net/xiayiye5/article/details/115251706

标签:Android,保存图片,相册
0
投稿

猜你喜欢

  • C#对Word文档的创建、插入表格、设置样式等操作实例

    2021-10-24 23:13:46
  • 详解Spring框架注解扫描开启之配置细节

    2022-11-01 18:04:14
  • C#常用字符串加密解密方法封装代码

    2022-03-04 08:50:48
  • 详解Java泛型及其应用

    2023-09-21 22:38:32
  • Android编程之OpenGL绘图技巧总结

    2022-07-25 05:47:55
  • 浅谈java8中map的新方法--replace

    2022-03-11 20:10:30
  • java 8如何自定义收集器(collector)详解

    2022-02-12 07:22:17
  • Java常用HASH算法总结【经典实例】

    2023-04-26 00:34:55
  • Android自定义图片选择器简单版

    2022-05-11 02:38:59
  • Kotlin数据容器深入讲解

    2022-03-28 05:19:34
  • Java如何利用状态模式(state pattern)替代if else

    2021-08-15 09:31:08
  • android中实现指针滑动的动态效果方法

    2023-10-07 15:54:44
  • Java对象在JVM中的生命周期详解

    2023-11-24 16:15:03
  • C#多态详解

    2023-06-25 13:42:20
  • 浅谈JAVA8给我带了什么——流的概念和收集器

    2021-09-24 03:14:04
  • C#使用Task实现异步方法

    2022-09-02 20:26:53
  • springboot2.x只需两步快速整合log4j2的方法

    2023-06-06 20:41:21
  • idea2017建立jsp工程及tomcat配置教程

    2023-06-04 20:24:40
  • Android开发之使用ExifInterface获取拍照后的图片属性

    2021-05-29 23:36:36
  • Java Swing JProgressBar进度条的实现示例

    2023-07-15 17:48:47
  • asp之家 软件编程 m.aspxhome.com