如何在Activity中从相册保存图片?SharedPreferences存图失败求助
问题解决与功能实现
一、SharedPreferences保存图片的正确处理方式
SharedPreferences是为小体量键值对数据设计的,直接存储图片字节数组(尤其是尺寸较大的图片)容易引发性能问题或保存失败。更合理的方案是将图片保存到本地文件,再用SharedPreferences存储文件路径;如果必须存字节数组,需做Base64转换(仅适合极小图片)。
1. 直接存储字节数组(不推荐)
// 保存图片到SharedPreferences SharedPreferences sp = getSharedPreferences("ImageStorage", MODE_PRIVATE); SharedPreferences.Editor editor = sp.edit(); // 将字节数组转为Base64字符串 String imageBase64 = Base64.encodeToString(byteArray, Base64.DEFAULT); editor.putString("saved_image", imageBase64); editor.apply(); // 读取并还原图片 String savedBase64 = sp.getString("saved_image", null); if (savedBase64 != null) { byte[] savedBytes = Base64.decode(savedBase64, Base64.DEFAULT); Bitmap bitmap = BitmapFactory.decodeByteArray(savedBytes, 0, savedBytes.length); imageView.setImageBitmap(bitmap); }
2. 推荐方案:保存图片到文件,SharedPreferences存路径
// 将Bitmap保存到本地文件 private String saveBitmapToFile(Bitmap bitmap) { File filesDir = getFilesDir(); File imageFile = new File(filesDir, "saved_image.jpg"); try (FileOutputStream fos = new FileOutputStream(imageFile)) { bitmap.compress(Bitmap.CompressFormat.JPEG, 80, fos); return imageFile.getAbsolutePath(); } catch (IOException e) { e.printStackTrace(); return null; } } // 保存文件路径到SharedPreferences String imagePath = saveBitmapToFile(resize); if (imagePath != null) { SharedPreferences sp = getSharedPreferences("ImageStorage", MODE_PRIVATE); sp.edit().putString("image_path", imagePath).apply(); } // 从文件读取图片 SharedPreferences sp = getSharedPreferences("ImageStorage", MODE_PRIVATE); String savedPath = sp.getString("image_path", null); if (savedPath != null) { Bitmap bitmap = BitmapFactory.decodeFile(savedPath); imageView.setImageBitmap(bitmap); }
二、从相册选择图片的实现步骤
1. 配置权限
在AndroidManifest.xml中添加存储权限:
<!-- Android 12及以下 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- Android 13+ 替换为以下权限 --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" android:minSdkVersion="33" />
2. 启动相册选择Intent
private static final int PICK_IMAGE_REQUEST = 1; // 绑定打开相册的按钮点击事件 Button pickBtn = findViewById(R.id.pick_image_btn); pickBtn.setOnClickListener(v -> { Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); startActivityForResult(intent, PICK_IMAGE_REQUEST); });
3. 处理选择结果
推荐:使用ActivityResultLauncher(替代旧版onActivityResult)
// 在Activity的onCreate方法中初始化 ActivityResultLauncher<Intent> pickImageLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == RESULT_OK && result.getData() != null) { Uri imageUri = result.getData().getData(); try { // 将Uri转换为Bitmap Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), imageUri); imageView.setImageBitmap(bitmap); // 调用前面的方法保存图片并记录路径到SharedPreferences String imagePath = saveBitmapToFile(bitmap); if (imagePath != null) { SharedPreferences sp = getSharedPreferences("ImageStorage", MODE_PRIVATE); sp.edit().putString("image_path", imagePath).apply(); } } catch (IOException e) { e.printStackTrace(); } } } ); // 按钮点击事件改为启动Launcher pickBtn.setOnClickListener(v -> { Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); pickImageLauncher.launch(intent); });
旧版兼容:onActivityResult
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null) { Uri imageUri = data.getData(); try { Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), imageUri); imageView.setImageBitmap(bitmap); // 保存图片到文件并记录路径 String imagePath = saveBitmapToFile(bitmap); if (imagePath != null) { SharedPreferences sp = getSharedPreferences("ImageStorage", MODE_PRIVATE); sp.edit().putString("image_path", imagePath).apply(); } } catch (IOException e) { e.printStackTrace(); } } }
内容的提问来源于stack exchange,提问作者Young
相关产品推荐
相关产品推荐

