开发者

Custom ContentProvider - openInputStream(), openOutputStream()

The c开发者_StackOverflow社区ontent 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?


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);
        }
    }
}


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜