如何实现APP拍摄图片对用户相册不可访问?已尝试多方法存疑
如何让APP拍摄的图片对用户不可访问?
我来帮你梳理下正确的实现思路,解决APP拍摄的图片对用户不可访问的问题~
一、优先选择内部存储(最安全的方案)
你提到尝试内部存储没成功,这其实是最可靠的方式——内部存储是APP的私有目录,其他应用和用户默认完全访问不到(除非设备root)。给你一个正确的Bitmap保存到内部存储的示例:
// 保存Bitmap到APP私有内部存储 private void saveBitmapToInternal(Context context, Bitmap bitmap) { try { // MODE_PRIVATE确保只有本APP能访问这个文件 FileOutputStream fos = context.openFileOutput("private_photo.png", Context.MODE_PRIVATE); // 压缩Bitmap并写入流 bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos); fos.close(); } catch (IOException e) { e.printStackTrace(); } } // 从内部存储读取图片 private Bitmap getBitmapFromInternal(Context context) { try { FileInputStream fis = context.openFileInput("private_photo.png"); return BitmapFactory.decodeStream(fis); } catch (IOException e) { e.printStackTrace(); return null; } }
这个方法保存的文件会存在 /data/data/你的APP包名/files/ 目录下,用户通过系统文件管理器根本看不到,完全符合你的需求。
二、如果必须用外部存储(退而求其次的方案)
如果内部存储空间不够,不得不使用外部存储,那可以结合两种方式来隐藏图片:
1. 创建以.开头的隐藏文件夹
这种方式能让系统文件管理器默认不显示该文件夹,但用户如果开启了“显示隐藏文件”还是能看到,所以只能作为辅助手段。代码示例:
// 获取外部存储的APP私有目录(Android 10+推荐使用,卸载APP时会自动删除) File externalPrivateDir = context.getExternalFilesDir(null); // 创建隐藏文件夹(名称以.开头) File hiddenFolder = new File(externalPrivateDir, ".app_hidden_photos"); if (!hiddenFolder.exists()) { hiddenFolder.mkdirs(); } // 保存图片到这个隐藏文件夹 File imageFile = new File(hiddenFolder, "shot_photo.png"); try { FileOutputStream fos = new FileOutputStream(imageFile); bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos); fos.close(); } catch (IOException e) { e.printStackTrace(); }
2. 添加.nomedia文件
.nomedia文件的作用是告诉系统媒体扫描器:不要扫描这个目录下的文件,这样图片就不会出现在系统相册里。把它放在刚才的隐藏文件夹里即可:
File nomediaFile = new File(hiddenFolder, ".nomedia"); if (!nomediaFile.exists()) { try { nomediaFile.createNewFile(); } catch (IOException e) { e.printStackTrace(); } }
注意:.nomedia只是阻止媒体扫描,用户还是能通过文件管理器找到文件,所以和隐藏文件夹搭配使用效果更好。
三、针对你提供的getImageUri方法优化
如果你需要生成图片的Uri供APP内部使用,结合内部存储的话,可以这样修改(适配Android 7.0+的安全机制):
public Uri getImageUri(Context inContext, Bitmap inImage) { String fileName = "temp_shot.png"; try { // 先保存到内部存储 FileOutputStream fos = inContext.openFileOutput(fileName, Context.MODE_PRIVATE); inImage.compress(Bitmap.CompressFormat.PNG, 100, fos); fos.close(); // 用FileProvider生成安全的Uri(Android 7.0+禁止直接使用file:// Uri) File imageFile = new File(inContext.getFilesDir(), fileName); return FileProvider.getUriForFile(inContext, inContext.getPackageName() + ".fileprovider", imageFile); } catch (IOException e) { e.printStackTrace(); return null; } }
使用FileProvider需要在AndroidManifest.xml中配置:
<provider android:name="androidx.core.content.FileProvider" android:authorities="你的APP包名.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
然后在res/xml目录下创建file_paths.xml:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <files-path name="internal_files" path="." /> </paths>
最后总结优先级
- 优先使用内部存储:绝对私有,用户完全无法访问,是最安全的方案;
- 必须用外部存储时,选择
getExternalFilesDir下的隐藏文件夹+.nomedia:既不会被媒体扫描到,卸载APP时也会自动清理; - 避免使用外部公共目录(比如DCIM、Pictures):即使隐藏也容易被用户找到。
内容的提问来源于stack exchange,提问作者sandy




