I'm working on a "photo gallery"-type app for Android. It started as a Final Project for the Developing Android Apps at Udacity, so it's overall structure (activities, contentproviders etc) should be very sound, and it was accepted for certification by Udacity/Google.
However, it's still not 100% finished, and I'm still trying to improve on it.
What I want to do should really be quite straight-forward; load all images on device (as thumbnails) into a GridView in the MainActivity, with a DetailActivity which shows the full size image + some meta data (title, size, date etc).
The course required us to write a ContentProvider, so I've got a query() function which essentially fetches data from the MediaStore, and returns a cursor to MainActivity's GridView. On my device, at least, (Sony Xperia Z1, Android 5.1.1) this works almost perfectly. There are some bugs and quirks, but by and large I can consistently find all images on my phone in my app, and click on them to view details.
However, when I tried installing the app on my friend's Sony Xperia Z3, everything failed. No images showed up, although I obviously checked there were in fact ~100 photos on his phone. Same on another friend's phone (brand new Samsung S6) :-(
This is The Main Problem. On my phone, where stuff works, the "secondary" bugs involve when a new photo is taken by the camera, it's not automatically loaded into my app (as a thumbnail). It seems I need to figure out how to trigger a scan, or whatever is needed to load/generate new thumbs. That's also quite high on my wish list.
As I said, I'm confident all this really ought to be quite simple, so maybe all my difficulties indicate I'm approaching the problem in the entirely wrong way? Here's what my query() function is doing:
get a cursor of all thumbnails, from
MediaStore.Media.Thumbnails.EXTERNAL_CONTENT_URI
get a cursor of all images, from
MediaStore.Media.Images.EXTERNAL_CONTENT_URI
join these, on
MediaStore.Media.Thumbnails.IMAGE_ID = MediaStore.Media.Images._ID
using aCursorJoiner
return the resulting
retCursor
(as produced in the join)
-- please find full code in this previous post.
Although this looks correct (to me), maybe it's really not the way to go about this? I'm joining thumbs and images, by the way, such that I can show some meta data (e.g. date taken) along with the thumbnail, in the GridView. I've identified the problem to the joining, in particular, because if I simplify this to only loading thumbs into the GridView, then this all works fine -- also on my friend's phone. (With the exception of loading new photos.)
Somehow, my assumption that IMAGE_ID
and _ID
are always consistent is not correct? I've seen a post on AirPair, describing a similar gallery app, and there the tutorial actually goes about this slightly differently. Rather than attempting to join cursors, he gets the thumbnails cursor and iterates over it, adding data from Images using individual queries to the MediaStore... But is that the most efficient way to do this?
- Nevertheless, his solution does join the thumbnail to the corresponding image on ID:
Cursor imagesCursor = context.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
filePathColumn,
MediaStore.Images.Media._ID + "=?", new String[]{imageId}, // NB!
null);
In summary, I need help with the following:
- am I querying the MediaStore correctly?
- is it safe to join thumbs and images, on ID -- will that be stable/in sync at all times?
- how can my app automatically generate/fetch thumbnails of new images?