代码之家  ›  专栏  ›  技术社区  ›  user875234

使用content sheme时,保存文件的正确方法是什么?

  •  3
  • user875234  · 技术社区  · 8 年前

    我使用以下意图允许用户选择文件的保存位置:

    // 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?

    1 回复  |  直到 8 年前
        1
  •  2
  •   SushiHangover    8 年前

    当您在 OnActivityResult 您对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);
    }
    

    更新(性能):

    只是一个FYI,如果你正在保存/流大文件,避免流上读写的异步版本,只需旋转一个线程(或者通过任务从线程池中使用一个。运行)。

    注:本遗嘱 总是 由于所有的异步/等待开销,所以速度要快一点,这有点像我通常所做的那样(通常根据文件大小快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);
                }
            }
        });
    }
    
    推荐文章