title: How to store large blobs in an android content provider?
body: <p>I have some large files (images and video) which I need to store in a content provider.
  The android documentation indicates...</p>
  
  <blockquote>
    <p>If you are exposing byte data that's
    too big to put in the table itself —
    such as a large bitmap file — the
    field that exposes the data to clients
    should actually contain a content: URI
    string. This is the field that gives
    clients access to the data file. The
    record should also have another field,
    named "_data" that lists the exact
    file path on the device for that file.
    This field is not intended to be read
    by the client, but by the
    ContentResolver. The client will call
    ContentResolver.openInputStream() on
    the user-facing field holding the URI
    for the item. The ContentResolver will
    request the "_data" field for that
    record, and because it has higher
    permissions than a client, it should
    be able to access that file directly
    and return a read wrapper for the file
    to the client.
    --  <a href="http://developer.android.com/guide/topics/providers/content-providers.html#creating" rel="noreferrer">http://developer.android.com/guide/topics/providers/content-providers.html#creating</a></p>
  </blockquote>
  
  <p>I am having some difficulty finding an example.
  In particular I wish to use the bitmap in the context an ImageView.
  Consider the following code quasi-code (it doesn't work)...</p>
  
  <pre><code>ImageView iv = ....
  String iconUri = cursor.getString(cursor.getColumnIndex(Table.ICON));
  iv.setImageURI(Uri.parse(iconUri));
  </code></pre>
  
  <p>Observations/Problems...</p>
  
  <ol>
  <li>How can the stored/recovered uri be reconstructed correctly? (it is text in the table)</li>
  <li><p>The setImageURI implementation makes use of the content resolve openInputStream so this should work. </p>
  
  <pre><code>String scheme = mUri.getScheme();
  ...
  } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)
          || ContentResolver.SCHEME_FILE.equals(scheme)) {
    try {
      d = Drawable.createFromStream(
              mContext.getContentResolver().openInputStream(mUri),
              null);
  </code></pre>
  
  <p>--frameworks/base/core/java/android/widget/ImageView.java</p></li>
  </ol>
  
  <p>I got it working.
  I took a hint from the MediaStore and MediaProvider.
  The files which contain the data are named based on the content provider (directory), the column name, the row id and the media type.
  The content resolver then acquires the file descriptor like so...</p>
  
  <pre><code>Uri iconUri = Uri.withAppendedPath(Table.getUri(cursor), Table.ICON);
  ib.setImageURI(iconUri);
  </code></pre>
  
  <p>...and the content provider responds in kind...</p>
  
  <pre><code>@Override
  public ParcelFileDescriptor openFile (Uri uri, String mode) {
  int imode = 0;
  if (mode.contains("w")) imode |= ParcelFileDescriptor.MODE_WRITE_ONLY;
  if (mode.contains("r")) imode |= ParcelFileDescriptor.MODE_READ_ONLY;
  if (mode.contains("+")) imode |= ParcelFileDescriptor.MODE_APPEND;
  List&lt;String&gt; pseg = uri.getPathSegments();
  if (pseg.size() &lt; 3) return null;
  
  try {
      File filePath = filePathFromRecord(pseg.get(2), pseg.get(1));
      return ParcelFileDescriptor.open(filePath, imode);
  } catch (FileNotFoundException e) {
      e.printStackTrace();
  }
  return null;
  }
  </code></pre>