调用MediaStore.ACTION_IMAGE_CAPTURE拍照后图片自动存入相册原因排查
嘿,我来帮你捋清楚这个问题——你用MediaStore.ACTION_IMAGE_CAPTURE调用系统相机后,照片自动存进相册,其实核心原因是系统相机应用本身的默认行为,不是你的代码直接触发的~
为什么会自动存相册?
当你调用MediaStore.ACTION_IMAGE_CAPTURE但没有指定照片的输出路径时,大部分厂商的系统相机(比如原生Android、小米、华为等)都会默认把拍摄的原图保存到系统相册的默认目录里,而你通过data.getExtras().get("data")获取到的只是相机返回的缩略图,原图早就被相机应用自动存起来了,这就是相册里出现照片的原因。
怎么解决?
最靠谱的办法是指定自定义的输出路径,让相机把照片存到你指定的位置(比如应用的私有存储目录),这样就能避免相机自动把照片存进系统相册。具体步骤如下:
1. 创建私有存储目录下的临时文件
先写一个方法生成唯一的图片文件,存在应用的外部私有存储里(这样既不会污染系统相册,也不需要额外的存储权限):
private File createImageFile() throws IOException { // 生成唯一文件名,避免重复 String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date()); String imageFileName = "JPEG_" + timeStamp + "_"; // 获取应用外部存储的Pictures目录 File storageDir = requireContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES); return File.createTempFile( imageFileName, // 文件前缀 ".jpg", // 文件后缀 storageDir // 存储目录 ); }
2. 修改相机调用代码,指定输出Uri
调用相机时,通过MediaStore.EXTRA_OUTPUT参数告诉相机把照片存到我们刚才创建的文件里,注意要用FileProvider来生成安全的Uri(Android 7.0+要求):
// 声明成员变量保存照片文件 private File photoFile; // 调用相机的代码 private void takePhoto() { photoFile = null; try { photoFile = createImageFile(); } catch (IOException ex) { // 处理文件创建失败的情况,比如弹个Toast提示用户 Toast.makeText(requireContext(), "创建图片文件失败", Toast.LENGTH_SHORT).show(); return; } if (photoFile != null) { // 生成FileProvider的Uri,替换成你的应用包名+fileprovider Uri photoURI = FileProvider.getUriForFile(requireContext(), "com.your.package.name.fileprovider", photoFile); Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // 指定照片输出路径 intent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); // 授予相机临时访问Uri的权限 intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); startActivityForResult(intent, CAMERA_01); } }
3. 配置FileProvider(Android 7.0+必备)
在AndroidManifest.xml里添加FileProvider的配置,避免Uri暴露的安全问题:
<application> ... <provider android:name="androidx.core.content.FileProvider" android:authorities="com.your.package.name.fileprovider" <!-- 和刚才代码里的一致 --> android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider> ... </application>
然后在res/xml目录下创建file_paths.xml文件,指定FileProvider可以访问的路径:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 允许访问应用外部存储的Pictures目录 --> <external-files-path name="my_images" path="Pictures" /> </paths>
4. 修改onActivityResult处理逻辑
现在照片已经存在我们指定的文件里了,不需要再从data.getExtras()获取缩略图,直接读取文件即可:
@Override public void onActivityResult(int requestCode, int resultCode, Intent data){ super.onActivityResult(requestCode,resultCode,data); if(requestCode == CAMERA_01){ if(resultCode == Activity.RESULT_OK){ if(photoFile != null && photoFile.exists()){ // 从指定文件读取原图Bitmap Bitmap bitmap = BitmapFactory.decodeFile(photoFile.getAbsolutePath()); // 后续的Base64转换和ImageView设置 ByteArrayOutputStream output = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, output); byte[] byte_arr = output.toByteArray(); i11a1 = Base64.encodeToString(byte_arr, Base64.DEFAULT); ((SiteBefore)getActivity().getApplication()).seti11a1(i11a1); // 用setImageBitmap比setBackgroundDrawable更适合展示图片 img11a1.setImageBitmap(bitmap); } }else if(resultCode == Activity.RESULT_CANCELED){ // 处理用户取消拍照的情况 } } }
额外说明
有些同学可能会问:有没有办法不指定路径,直接让相机不存相册?其实这个兼容性很差,不同厂商的相机应用对额外Intent参数的支持不一样,所以还是指定自定义路径的方法最稳妥,既能控制照片的存储位置,又能避免自动存入系统相册。
内容的提问来源于stack exchange,提问作者BrenDonie




