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

目录
  • 方法一
  • 方法二
  • 方法三

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

方法一

 /**
     * 保存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()
        }
}

到此这篇关于Android开发之保存图片到相册的三种方法详解的文章就介绍到这了,更多相关Android保存图片到相册内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Android开发实现保存图片到手机相册功能

    本文实例讲述了Android开发实现保存图片到手机相册功能.分享给大家供大家参考,具体如下: 有一种很常见的需求,当保存图片的时候,客户需要在相册里面看到那张图片.有时候确实是保存成功了(通过IO流将图片写入了SDCard),但打开相册却看不到那张图片,需要在文件管理软件上才能找到那张图片,在网上找了许多文章,貌似都保存不到相册那里,这应该就是手机品牌的原因,有的品牌的手机能显示在相册里,有的品牌的手机却不能.解决这种问题,最简单粗暴的方法是,用那台手机拍一张照片,然后找到它,查看它的路径详情,

  • Android开发实现的保存图片到相册功能示例

    本文实例讲述了Android开发实现的保存图片到相册功能.分享给大家供大家参考,具体如下: 废话不多说,先上效果: 点击图片 调用savephoto的SaveBitmapFromView(View view);方法自动保存图片 //点击图片保存 imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String[] PERMISSIONS = { "and

  • Android实现保存图片到本地并在相册中显示

    Android中拍照保存图片到本地是常见的一种需求,之前碰到了一个问题,就是在4.4中,刷新相册会出现ANR,经过一番百度解决了这个问题. 首先是保存图片到本地 private static final String SAVE_PIC_PATH = Environment.getExternalStorageState().equalsIgnoreCase(Environment.MEDIA_MOUNTED) ? Environment.getExternalStorageDirectory()

  • 基于Android实现保存图片到本地并可以在相册中显示出来

    App应用越来越人性化,不仅界面优美而且服务也很多样化,操作也非常方便.比如我们在用app的时候,发现上面有比较的图片想保存到手机,只要点一点app上提供的保存按钮就可以了.那这个图片保存到本地怎么实现的呢? 保存图片很简单,方法如下: /** 首先默认个文件保存路径 */ private static final String SAVE_PIC_PATH=Environment.getExternalStorageState().equalsIgnoreCase(Environment.MED

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

    目录 方法一 方法二 方法三 有三种方法如下:三个方法都需要动态申请读写权限否则保存图片到相册也会失败 方法一 /** * 保存bitmap到本地 * * @param bitmap Bitmap */ public static void saveBitmap(Bitmap bitmap, String path) { String savePath; File filePic; if (Environment.getExternalStorageState().equals(Environm

  • SpringMVC统一异常处理三种方法详解

    这篇文章主要介绍了SpringMVC-统一异常处理三种方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在 Spring MVC 应用的开发中,不管是对底层数据库操作,还是业务层或控制层操作,都会不可避免地遇到各种可预知的.不可预知的异常需要处理. 如果每个过程都单独处理异常,那么系统的代码耦合度高,工作量大且不好统一,以后维护的工作量也很大. 如果能将所有类型的异常处理从各层中解耦出来,这样既保证了相关处理过程的功能单一,又实现了异常信

  • Python实现解析参数的三种方法详解

    目录 先决条件 使用 argparse 使用 JSON 文件 使用 YAML 文件 最后的想法 今天我们分享的主要目的就是通过在 Python 中使用命令行和配置文件来提高代码的效率 Let's go! 我们以机器学习当中的调参过程来进行实践,有三种方式可供选择.第一个选项是使用 argparse,它是一个流行的 Python 模块,专门用于命令行解析:另一种方法是读取 JSON 文件,我们可以在其中放置所有超参数:第三种也是鲜为人知的方法是使用 YAML 文件!好奇吗,让我们开始吧! 先决条件

  • python解析命令行参数的三种方法详解

    这篇文章主要介绍了python解析命令行参数的三种方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 python解析命令行参数主要有三种方法:sys.argv.argparse解析.getopt解析 方法一:sys.argv -- 命令行执行:python test_命令行传参.py 1,2,3 1000 # test_命令行传参.py import sys def para_input(): print(len(sys.argv)) #

  • Mybatis 逆向工程的三种方法详解

    Mybatis 逆向工程   逆向工程通常包括由数据库的表生成 Java 代码 和 通过 Java 代码生成数据库表.而Mybatis 逆向工程是指由数据库表生成 Java 代码.   Mybaits 需要程序员自己编写 SQL 语句,但是 Mybatis 官方提供逆向工程可以针对单表自动生成 Mybaits 执行所需要的代码,包括 POJO.Mapper.java.Mapper.xml -. 一.通过 Eclipse 插件完成 Mybatis 逆向工程 1. 在线安装 Eclipse 插件  

  • Python中提取人脸特征的三种方法详解

    目录 1.直接使用dlib 2.使用深度学习方法查找人脸,dlib提取特征 3.使用insightface提取人脸特征 安装InsightFace 提取特征 1.直接使用dlib 安装dlib方法: Win10安装dlib GPU过程详解 思路: 1.使用dlib.get_frontal_face_detector()方法检测人脸的位置. 2.使用 dlib.shape_predictor()方法得到人脸的关键点. 3.使用dlib.face_recognition_model_v1()方法提取

  • Java比较两个对象大小的三种方法详解

    目录 一. 为什么需要比较对象 二. 元素的比较 1. 基本类型的比较 2. 引用类型的比较 三. 对象比较的方法 1. equals方法比较 2. 基于Comparable接口的比较 3. 基于Comparator接口的比较 4. 三种比较方式对比 一. 为什么需要比较对象 上一节介绍了优先级队列,在优先级队列中插入的元素必须能比较大小,如果不能比较大小,如插入两个学生类型的元素,会报ClassCastException异常 示例: class Student{ String name; in

  • C语言实现短字符串压缩的三种方法详解

    目录 前言 一.通用算法的短字符压缩 二.短字符串压缩 (1)Smaz (2)Shoco (3)Unisox2 三.总结 前言 上一篇探索了LZ4的压缩和解压性能,以及对LZ4和ZSTD的压缩.解压性能进行了横向对比.文末的最后也给了一个彩蛋:任意长度的字符串都可以被ZSTD.LZ4之类的压缩算压缩得很好吗? 本篇我们就来一探究竟. 一.通用算法的短字符压缩 开门见山,我们使用一段比较短的文本:Narrator: It is raining today. So, Peppa and George

  • Android编程实现XML解析与保存的三种方法详解

    本文实例讲述了Android编程实现XML解析与保存的三种方法.分享给大家供大家参考,具体如下: 简介 在Android开发中,关于XML解析有三种方式,分别是: 1. SAX 基于事件的解析器,解析速度快,占用内存少.非常适合在Android移动设备中使用. 2. DOM 在内存中以树形结构存放,因此检索和更新效率会更高.但是对于特别大的文档,解析和加载整个文档将会很耗资源 3. PULL 基于事件的解析器,不同于SAX是,PULL是主动请求下一个事件,所以在可控上PULL要比SAX实用.An

  • Android开发实现标题随scrollview滑动变色的方法详解

    本文实例讲述了Android开发实现标题随scrollview滑动变色的方法.分享给大家供大家参考,具体如下: 要实现某个view的背景透明度跟随scrollview滑动而改变需要重新scrollview的onOverScrolled方法,该方法随着滑动变化(包括手指滑动.手指移开惯性滑动)而响应,所以最适合做变色处理. step1:设定布局 由于我们要实现的是滑动时标题的背景透明度改变,固定顶部的标题view不能在srcollview里面跟随滑动,所以需要这样布局: <FrameLayout

随机推荐