You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何实现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>

最后总结优先级

  1. 优先使用内部存储:绝对私有,用户完全无法访问,是最安全的方案;
  2. 必须用外部存储时,选择getExternalFilesDir下的隐藏文件夹+.nomedia:既不会被媒体扫描到,卸载APP时也会自动清理;
  3. 避免使用外部公共目录(比如DCIM、Pictures):即使隐藏也容易被用户找到。

内容的提问来源于stack exchange,提问作者sandy

火山引擎 最新活动