问题
当我们的应用在自身内部存储空寂那存储了一张图片后,想进行分享,为什么分享到第三方应用时,它可以自由读取该图片?
前提
使用了 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)
}
网友评论