android - 自定义 ContentProvider - openInputStream()、openOutputStream()

标签 android file-io android-contentprovider

内容提供者/解析器 API 提供了一种复杂但稳健的方式,使用 URI 和 openInputStream()openOutputStream() 方法在进程之间传输数据。自定义内容提供者能够使用自定义代码覆盖 openFile() 方法,从而有效地将 URI 解析为 Stream;但是,openFile() 的方法签名具有 ParcelFileDescriptor 返回类型,并且不清楚如何为从该方法返回的动态生成的内容生成适当的表示。

Returning a memory mapped InputStream from a content provider?

现有代码库中是否有实现动态内容的ContentProvider.openFile()方法的例子?如果没有,您能建议这样做的源代码或流程吗?

最佳答案

从总是很有帮助的 CommonsWare 中查看这个很棒的示例项目。它允许您创建一个 ParcelFileDescriptor 管道,其中一侧带有您想要的任何 InputStream,另一侧带有接收应用程序:

https://github.com/commonsguy/cw-omnibus/tree/master/ContentProvider/Pipe

关键部分是在openFile中创建管道:

public ParcelFileDescriptor openFile(Uri uri, String mode)
                                                        throws FileNotFoundException {
    ParcelFileDescriptor[] pipe=null;

    try {
      pipe=ParcelFileDescriptor.createPipe();
      AssetManager assets=getContext().getResources().getAssets();

      new TransferThread(assets.open(uri.getLastPathSegment()),
                       new AutoCloseOutputStream(pipe[1])).start();
    }
    catch (IOException e) {
      Log.e(getClass().getSimpleName(), "Exception opening pipe", e);
      throw new FileNotFoundException("Could not open pipe for: "
          + uri.toString());
    }

    return(pipe[0]);
  }

然后创建一个保持管道满的线程:

static class TransferThread extends Thread {
    InputStream in;
    OutputStream out;

    TransferThread(InputStream in, OutputStream out) {
        this.in = in;
        this.out = out;
    }

    @Override
    public void run() {
        byte[] buf = new byte[8192];
        int len;

        try {
            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
            }

            in.close();
            out.flush();
            out.close();
        } catch (IOException e) {
            Log.e(getClass().getSimpleName(),
                    "Exception transferring file", e);
        }
    }
}

关于android - 自定义 ContentProvider - openInputStream()、openOutputStream(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2148301/

相关文章:

android - 在 Android 中向 ListView 项目添加复选框

Android 清理虚拟内存

c# - Silverlight 是否能够更改本地用户计算机上的文件?

android - 如何使用 Intent 共享数组中的所有项目?

android - WebView 和 Button 的 LinearLayout

java - 整个文本文件到Java中的字符串

c++ - 子进程中的间歇性文件访问错误

android - Android与其他平台应用逻辑代码复用 : To ContentProvider or not to ContentProvider?

android - 内容提供商 uri 如何工作?

android - 我可以在 Android 的 Settings.NameValueTable 内容提供者中添加/检索/删除条目吗?