inputstream - How to store large blobs in an android content provider? -
i have large files (images , video) need store in content provider. android documentation indicates...
if exposing byte data that's big put in table — such large bitmap file — field exposes data clients should contain content: uri string. field gives clients access data file. record should have field, named "_data" lists exact file path on device file. field not intended read client, contentresolver. client call contentresolver.openinputstream() on user-facing field holding uri item. contentresolver request "_data" field record, , because has higher permissions client, should able access file directly , return read wrapper file client. -- http://developer.android.com/guide/topics/providers/content-providers.html#creating
i having difficulty finding example. in particular wish use bitmap in context imageview. consider following code quasi-code (it doesn't work)...
imageview iv = .... string iconuri = cursor.getstring(cursor.getcolumnindex(table.icon)); iv.setimageuri(uri.parse(iconuri));
observations/problems...
- how can stored/recovered uri reconstructed correctly? (it text in table)
the setimageuri implementation makes use of content resolve openinputstream should work.
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);
--frameworks/base/core/java/android/widget/imageview.java
i got working. took hint mediastore , mediaprovider. files contain data named based on content provider (directory), column name, row id , media type. content resolver acquires file descriptor so...
uri iconuri = uri.withappendedpath(table.geturi(cursor), table.icon); ib.setimageuri(iconuri);
...and content provider responds in kind...
@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<string> pseg = uri.getpathsegments(); if (pseg.size() < 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; }
the solution phreed gives in bottom half of question correct. i'll try add more details here.
when getcontentresolver().openinputstream(...)
, content resolver go content provider , call openfile
method. how openfile
looks in contentprovider.java:
public parcelfiledescriptor openfile(uri uri, string mode) throws filenotfoundexception { throw new filenotfoundexception("no files supported provider @ " + uri); }
so explains "no files supported ..." error comes from! around overriding openfile
method in subclass , providing own implementation. it's neat: perfect control of files placed when client openinputstream
or openoutputstream
.
code sample in phreed's question gives hint how implementation like. here's modified version creates directories , files needed. i'm novice @ stuff might not optimal way of doing things, gives idea. 1 thing, should check if external storage available.
@override public parcelfiledescriptor openfile(uri uri, string mode) throws filenotfoundexception { file root = new file(environment.getexternalstoragedirectory(), "/android/data/com.example.myapp/cache"); root.mkdirs(); file path = new file(root, uri.getencodedpath()); // so, if uri content://com.example.myapp/some/data.xml, // we'll end accessing /android/data/com.example.myapp/cache/some/data.xml int imode = 0; if (mode.contains("w")) { imode |= parcelfiledescriptor.mode_write_only; if (!path.exists()) { try { path.createnewfile(); } catch (ioexception e) { // todo decide it, whom notify... e.printstacktrace(); } } } if (mode.contains("r")) imode |= parcelfiledescriptor.mode_read_only; if (mode.contains("+")) imode |= parcelfiledescriptor.mode_append; return parcelfiledescriptor.open(path, imode); }
Comments
Post a Comment