我使用以下意图允许用户选择文件的保存位置:
// https://developer.android.com/guide/topics/providers/document-provider
var intent = new Intent(Intent.ActionCreateDocument);
intent.AddCategory(Intent.CategoryOpenable);
intent.SetType("image/png");
intent.PutExtra(Intent.ExtraTitle, "myfile");
StartActivityForResult(Intent.CreateChooser(intent, "Select Save Location"), 43);
它将创建文件并返回文件的uri:
content://com.android.providers.downloads.documents/document/436
但是现在我被绞死了,因为文档的该部分以
结尾创建新文档后,可以在onActivityResult()中获取其URI,以便您可以继续对其进行写入。
我不知道该怎么做。由于我的结果是使用content
方案,所以我不能仅仅将其视为常规的Java.IO.File
并将其写入磁盘。那么如何将文件保存到我拥有的内容uri中?
答案 0 :(得分:1)
当您在OnActivityResult
中取回内容Uri时,您对该Uri具有临时权限(因此具有写访问权),因此可以在写模式下打开基于宗地的文件描述符,并创建输出流从该包裹的文件描述符中写入所需内容。
protected async override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
if (resultCode == Result.Ok && requestCode == 43)
{
var buffer = new byte[1024];
using (var pFD = ContentResolver.OpenFileDescriptor(data.Data, "w"))
using (var outputSteam = new FileOutputStream(pFD.FileDescriptor))
using (var inputStream = Assets.Open("somePicture.png"))
{
while (inputStream.CanRead && inputStream.IsDataAvailable())
{
var readCount = await inputStream.ReadAsync(buffer, 0, buffer.Length);
await outputSteam.WriteAsync(buffer, 0, readCount);
}
}
}
base.OnActivityResult(requestCode, resultCode, data);
}
仅供参考,如果要保存/流式传输大文件,请避免在流上读取和写入异步版本,而只需旋转一个线程(或通过Task.Run从线程池使用一个线程)。
注意:由于所有异步/等待开销,这将总是 更快,并且有点像我通常的做法(通常快2倍(+ ),具体取决于文件大小。
if (resultCode == Result.Ok && requestCode == 43)
{
await Task.Run(() =>
{
// Buffer size can be "tuned" to enhance read/write performance
var buffer = new byte[1024];
using (var pFD = ContentResolver.OpenFileDescriptor(data.Data, "w"))
using (var outputSteam = new FileOutputStream(pFD.FileDescriptor))
using (var inputStream = Assets.Open("her.png"))
{
while (inputStream.CanRead && inputStream.IsDataAvailable())
{
var readCount = inputStream.Read(buffer, 0, buffer.Length);
outputSteam.Write(buffer, 0, readCount);
}
}
});
}