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

发布于 2024-08-19 12:35:06 字数 535 浏览 4 评论 0原文

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

从内容提供者返回内存映射的InputStream?

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

The content provider/ resolver APIs provide a complicated, but robust way of transferring data between processes using a URI and the openInputStream() and openOutputStream() methods. Custom content providers have the ability to override the openFile() method with custom code to effectively resolve a URI into a Stream; however, the method signature of openFile() has a ParcelFileDescriptor return type and it is not clear how one might generate a proper representation for dynamically generated content to return from this method.

Returning a memory mapped InputStream from a content provider?

Are there examples of implementing ContentProvider.openFile() method for dynamic content in the existing code base? If not can you suggest source code or process for doing so?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

怪我闹别瞎闹 2024-08-26 12:35:06

从总是有用的 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);
        }
    }
}

Check out this great example project from the always helpful CommonsWare. It lets you create a ParcelFileDescriptor pipe with whatever InputStream you want on one side, and the receiving application on the other side:

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

The key parts are creating the pipe in 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]);
  }

Then create a thread that keeps the pipe full:

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);
        }
    }
}
小清晰的声音 2024-08-26 12:35:06

MemoryFile 支持此功能,但公共 API 尚未最终确定。

MemoryFile supports this, but the public API hasn't been finalized.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文