views:

1512

answers:

3

Does anyone know how to integrate with the new Gallery3D app (cooliris android gallery)? I want to launch that app so it shows the thumbnails for only a specific folder.

For example, say my app downloads images from my server and stores them in a folder on the sd-card (/sdcard/myapp/image-cache/someid/*). I'd like to be able to do something like the following:

// within an activity
Uri uri = Uri.withAppendedPath(Media.EXTERNAL_CONTENT_URI, "myapp/image-cache/someid");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);

Thanks.

+1  A: 

I'm told you need to launch it like this:

Uri targetUri = Media.EXTERNAL_CONTENT_URI;
String folderPath = Environment.getExternalStorageDirectory().toString() + "/" + "testFolder";
int folderBucketId = folderPath.toLowerCase().hashCode();
targetUri = targetUri.buildUpon().appendQueryParameter("bucketId", folderBucketId).build();

Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);

Further info:

Ensure that you have the right path (check trailing slashes etc). As a test, you can check if the bucket id that comes out from your method equals the bucket id in the database (which you can query for using the MediaProvider class).

What you are doing right now is passing the first image in that bucket, and gallery automatically shows other images in view, but the difference is that you are trying to view an image, not a bucket, which is why it doesn't show up in a thumbnail view.

As far as your MediaScanner issue goes, connect() is an async call, so you should do everything in the method onMediaScannerConnected in you implementation of the MediaScannerConnectionClient interface. You already implemented this interface for onScanCompleted, so you just need to put the logic there instead of polling the MediaScannerService to see if it has connected.

jeffamaphone
Unfortunately this didn't work for me. It displayed the folder for some random set of pics I had on my phone. Admittedly, I may have implemented your answer incorrectly.I managed to find a close-enough solution that I'll post for anyone else that's interested.
mefesto
See my edits above wrt your close-enough solution and continued issues.
jeffamaphone
Ok I reworked things the way you described. The onMediaScannerConnected method starts the rest of this process and it's working really well. Thanks a lot! I still can't get the bucketId thing working. On the emulator it looks like it's working but on my phone it keeps opening a different folder. Just to be sure I performed a query to get the BUCKET_ID for the first image Uri and still got the wrong folder. Oh well, I can live without it.
mefesto
A: 

I wasn't able to get the thumbnail view for a folder working. Instead, I managed something almost as good by launching the gallery on the first image in the folder.

Here's a description of what I wanted to accomplish. A user selects a specific record from a list view. This record can have a few images associated with it. I wanted to be able to browse these images using the cool Gallery3D app on the Nexus One (now with multitouch zoom!). If the images for that record are not already cached on the device's sdcard I'll download them as a zip file. I then extract that file to a cache dir for that record on the sdcard. Afterwards, I wanted to launch the gallery and only display the images in that cache dir.

Performing the download and extracting the zip file to the sdcard was not a problem. But, in order to get the gallery working, I had to use the MediaScannerConnection with a MediaScannerConnectionClient. After getting the scanner to connect (which was kind of flakey), I looped through all the files in the cache dir calling scanner.scanFile.

The MediaScannerConnectionClient#onScanCompleted would append the resulting uri's to an ArrayList member variable. When the whole process was done I'd launch the gallery passing the first uri in that list. This would view the first image in the directory. I would've preferred the thumbnail view but this is good enough.

I'm not totally comfortable with this solution. It seems that the MediaScannerConnection works asynchronously so my AsyncTask does a poll/sleep to see if it's done scanning.

Has anyone else had issues with the MediaScannerConnection not connecting on the first call? To work around this I'm doing something like:

MediaScannerConnection scanner = ...;
for (int attempts = 0; attempts < MAX_ATTEMPTS; attempts++) {
  scanner.connect();
  if (scanner.isConnected()) { break; }
  else {
    try { Thread.sleep(5); }
    catch (Exception e){}
  }
}

if (!scanner.isConnected()) {
  throw new IllegalStateException("Unable to establish media scanner connection!");
}

Ugly I know but I'm not sure why it has trouble connecting the first time. :-/

UPDATE: Thanks to jeffamaphone, I was able to dump that ugly code. Now the OnItemClickListener just calls scanner.connect(). The client that is passed to the scanner's constructor initializes the DownloadAsyncTask which updates a ProgressDialog as it unzips the files and calls scanner.scanFiles(...);

mefesto
A: 

I tried Jeff's code as well. it appears that it only works in the old gallery and not in the new gallery3D.

Gallery3D is currently returning this in logcat:

E/CacheService(  503): Error finding album -280923911

and browsing the source for CacheService, I found this:

    if (albumData != null && albumData.length > 0) {
        DataInputStream dis = new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(albumData), 256));
        try {
            final int numAlbums = dis.readInt();
            for (int i = 0; i < numAlbums; ++i) {
                final long setId = dis.readLong();
                MediaSet mediaSet = null;
                if (setId == bucketId) {
                    mediaSet = feed.getMediaSet(setId);
                    if (mediaSet == null) {
                        mediaSet = feed.addMediaSet(setId, source);
                    }
                } else {
                    mediaSet = new MediaSet();
                }
                mediaSet.mName = Utils.readUTF(dis);
                if (setId == bucketId) {
                    mediaSet.mPicasaAlbumId = Shared.INVALID;
                    mediaSet.generateTitle(true);
                    return;
                }
            }
        } catch (IOException e) {
            Log.e(TAG, "Error finding album " + bucketId);
            sAlbumCache.deleteAll();
            putLocaleForAlbumCache(Locale.getDefault());
        }
    } else {
        Log.d(TAG, "No album found for album id " + bucketId);
    }

And since I'm getting the "Error finding album" error instead of the "No album found for album id", this means android is finding the album, but is running into an IOException somewhere in those lines. Is this then an android source problem?

makeramen