美文网首页
Android 为什么分享图片时目标应用可以自由读取该图片

Android 为什么分享图片时目标应用可以自由读取该图片

作者: 雁过留声_泪落无痕 | 来源:发表于2022-05-11 08:44 被阅读0次

问题

当我们的应用在自身内部存储空寂那存储了一张图片后,想进行分享,为什么分享到第三方应用时,它可以自由读取该图片?

前提

使用了 FileProvider

解答

val uri = UtilsFileProvider.getUriForFile(this, "$packageName.utilcode.fileprovider", file)
var intent = Intent(Intent.ACTION_SEND)
intent.type = "image/*"
intent.putExtra(Intent.EXTRA_STREAM, uri)
intent = Intent.createChooser(intent, "")
startActivity(intent)

使用如上代码即可进行分享,但是我们并没有调用 Intent#addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION),为什么也可以成功呢?

其实问题的关键就是 Intent.ACTION_SEND,通过在 'Intent#addFlags()' 方法打断点,可以发现,在 Intent#migrateExtraStreamToClipData() 方法中调用了 Intent#addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION),如下:

public boolean migrateExtraStreamToClipData(Context context) {
    ...
    if (ACTION_CHOOSER.equals(action)) {
        ...
    } else if (ACTION_SEND.equals(action)) {
        try {
            final Uri stream = getParcelableExtra(EXTRA_STREAM);
            final CharSequence text = getCharSequenceExtra(EXTRA_TEXT);
            final String htmlText = getStringExtra(EXTRA_HTML_TEXT);
            if (stream != null || text != null || htmlText != null) {
                final ClipData clipData = new ClipData(
                        null, new String[] { getType() },
                        new ClipData.Item(text, htmlText, null, stream));
                setClipData(clipData);
                addFlags(FLAG_GRANT_READ_URI_PERMISSION);
                return true;
            }
        } catch (ClassCastException e) {
        }

    } else if (ACTION_SEND_MULTIPLE.equals(action)) {
        ...
    } else if (isImageCaptureIntent()) {
        ...
    }

    return false;
}

可以看到当 action 是 ACTION_SEND 时,自动添加了 FLAG_GRANT_READ_URI_PERMISSION 这个 flag,于是问题得到解答。

引申

我们想要三方应用往我们的目录里写文件时,可以添加 addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION) 调用即可。

比如想拍照并将照片存储在我们的私有目录,而不是先拍照再从图库里去获取图片,就可以:

  • 创建空文件
  • 通过 FileProvider 得到 uri
  • 创建 Intent,传入 uri
  • 在 Intent 上调用 addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
  • 调起相机
val imgFile = File(filesDir, "tmp_camera_capture.jpg")
if (!imgFile.exists()) {
    imgFile.createNewFile()
}
// 通过FileProvider.getUriForFile创建文件的Uri
uri = FileProvider.getUriForFile(this, "xxx.fileprovider", imgFile)

Intent().apply {
    action = MediaStore.ACTION_IMAGE_CAPTURE
    putExtra(MediaStore.EXTRA_OUTPUT, uri)
    // 为目标应用赋予当前文件的读写权限
    addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
    addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
    startActivityForResult(this, 1)
}

参考

相关文章

  • Android 为什么分享图片时目标应用可以自由读取该图片

    问题 当我们的应用在自身内部存储空寂那存储了一张图片后,想进行分享,为什么分享到第三方应用时,它可以自由读取该图片...

  • 高效加载BitMap

    在Android加载图片时,我们常常使用BitMap,但由于Android对单个应用施加的内存限制,常导致我们加载...

  • PicGo+Gitee搭建图床

    为什么要用图床 写Markdown插入图片时,可以插入本地图片或网络图片。 本地图片自然只能本地看。不少博客平台可...

  • 加载图片产生的OOM

    一、为什么加载大图片时会产生OutOfMemoryError? 这是因为Android采用图片格式是ARGB...

  • 图片点击放大

    介绍与原理   图片点击放大为点击图片时,页面弹出该图片的大图。这样可以在布局时使用缩略图,而当用户需要查看大图时...

  • iOS 封装一个图片缓存工具

    之前撸的一个简单的图片缓存工具在这里分享一下 缓存策略:### 设置图片时 先从内存中读取 -- >(没有)--...

  • 读取Bundle 图片

    项目中使用组件化Coding管理代码了,图片放到Bundle中,读取图片时读取Bundle中的图片,因而不能使用[...

  • Android中有没有必要调用Bitmap的recycle()

    在Android应用里,最耗费内存的就是图片资源。而且在Android系统中,读取位图Bitmap时,分给虚拟机中...

  • Android: Bitmap内存优化

    在Android应用里,最耗费内存的就是图片资源。而且在Android系统中,读取位图Bitmap时,分给虚拟机中...

  • Gif读取之解决ArrayIndexOutOfBoundsExc

    昨天遇到个读取图片问题,在 ImageIO.read读取大部分图片时候没有问题,可是遇到个别的gif读取就报错了:...

网友评论

      本文标题:Android 为什么分享图片时目标应用可以自由读取该图片

      本文链接:https://www.haomeiwen.com/subject/dtnlurtx.html