網站首頁 編程語言 正文
有三種方法如下:三個方法都需要動態申請讀寫權限否則保存圖片到相冊也會失敗
方法一
/**
* 保存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
相關推薦
- 2022-04-20 教你python?中如何取出colomap部分的顏色范圍_python
- 2022-10-16 Qt實現TCP網絡編程_C 語言
- 2022-04-08 C語言互換最大值與最小值的位置_C 語言
- 2022-07-06 python數據分析之DateFrame數據排序和排名方式_python
- 2022-04-22 electron設置最小大小和最大大小
- 2022-12-05 Spark中的數據讀取保存和累加器實例詳解_相關技巧
- 2023-04-04 C/C++關于實現CAN信號的獲取方法_C 語言
- 2024-01-15 IDEA 常量字符串過長問題
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支