網(wǎng)站首頁 編程語言 正文
有三種方法如下:三個(gè)方法都需要?jiǎng)討B(tài)申請(qǐng)讀寫權(quán)限否則保存圖片到相冊(cè)也會(huì)失敗
方法一
/**
* 保存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());
}
方法二
針對(duì)小于API29以下方法,此方法會(huì)通知圖庫更新
/**
* API 29及以下保存圖片到相冊(cè)的方法
*
* @param toBitmap 要保存的圖片
*/
private void saveImage(Bitmap toBitmap) {
String insertImage = MediaStore.Images.Media.insertImage(getContentResolver(), toBitmap, "壁紙", "搜索貓相關(guān)圖片后保存的圖片");
if (!TextUtils.isEmpty(insertImage)) {
Toast.makeText(this, "圖片保存成功!" + insertImage, Toast.LENGTH_SHORT).show();
Log.e("打印保存路徑", insertImage + "-");
}
}
方法三
針對(duì)大于API29以下方法,此方法也會(huì)通知圖庫更新
/**
* API29 中的最新保存圖片到相冊(cè)的方法
*/
private void saveImage29(Bitmap toBitmap) {
//開始一個(gè)新的進(jìn)程執(zhí)行保存圖片的操作
Uri insertUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new ContentValues());
//使用use可以自動(dòng)關(guān)閉流
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)
}
//設(shè)置輪播圖片后的滑動(dòng)當(dāng)前頁
vp2Banner.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
tvShowImagePage.text =
StringBuffer().append(position + 1).append("/").append(photoList?.size)
}
})
//設(shè)置 ViewPager2 的當(dāng)前頁要在設(shè)置 ViewPager2 的數(shù)據(jù)后在設(shè)置當(dāng)前頁面,否則不生效
vp2Banner.setCurrentItem(currentPosition ?: 0, false)
//設(shè)置縱向滾動(dòng)的方法
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) {
//權(quán)限申請(qǐng)成功可以保存圖片
viewLifecycleOwner.lifecycleScope.launch { saveImage29() }
}
}
/**
* 保存圖片到相冊(cè)的方法
* 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, "壁紙", "搜索貓相關(guān)圖片后保存的圖片"
)
if (insertImage.isNotEmpty()) {
Toast.makeText(requireActivity(), "圖片保存成功!-${insertImage}", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(requireActivity(), "圖片保存失敗!}", Toast.LENGTH_SHORT).show()
}
}
/**
* API29 中的最新保存圖片到相冊(cè)的方法
*/
private suspend fun saveImage29() {
//開始一個(gè)新的進(jìn)程執(zhí)行保存圖片的操作
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可以自動(dòng)關(guān)閉流
requireActivity().contentResolver.openOutputStream(insertUri).use {
if (toBitmap.compress(Bitmap.CompressFormat.JPEG, 90, it)) {
showSaveToast("保存成功!")
} else {
showSaveToast("保存失敗!")
}
}
}
}
/**
* 顯示保存圖片結(jié)果的方法
*/
private fun showSaveToast(showMsg: String) =
MainScope().launch {
Toast.makeText(requireActivity(), showMsg, Toast.LENGTH_SHORT).show()
}
}
原文鏈接:https://blog.csdn.net/xiayiye5/article/details/115251706
相關(guān)推薦
- 2022-11-14 Django?ORM?事務(wù)和查詢優(yōu)化的操作方法_python
- 2022-08-30 Linux常用tar命令
- 2022-11-23 詳解Android創(chuàng)建Handler的必備知識(shí)點(diǎn)_Android
- 2022-06-15 oracle多表簡單查詢實(shí)例代碼_oracle
- 2022-09-25 注解@Autowired如何自動(dòng)裝配
- 2022-04-26 SQL?Server中Sequence對(duì)象用法_MsSql
- 2022-05-24 C++中的Qt?QTableView詳解_C 語言
- 2022-09-23 Pandas多列值合并成一列的實(shí)現(xiàn)_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支