Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to integrate Google Drive with Picasso on Android?

I'm writing an app which stores images in Google Drive and I'd like to display a gallery of those (GridView). To be more performant (i.e. async) I'd like to integrate this with Picasso. But the Picasso.load(String) is just an alias to load(Uri.parse(path)), and I don't have a Uri because the images are loaded like this (simplified and with undisclosed utility methods):

public static Bitmap getBitmap(DriveId id) {
    GoogleApiClient client = ApiClientAsyncTask.createConnectedClient(App.getAppContext());
    DriveFile file = Drive.DriveApi.getFile(client, id);
    Metadata meta = sync(file.getMetadata(client));
    Contents contents = sync(file.openContents(client, DriveFile.MODE_READ_ONLY, null));
    InputStream imageStream = contents.getInputStream();
    try {
        return BitmapFactory.decodeStream(imageStream);
    } finally {
        IOTools.ignorantClose(imageStream);
        sync(file.discardContents(client, contents));
    }
}

Is there any other similar library maybe supporting integration of arbitrary inputs (String/Object)?

Of course I'd like to use the full support of caching (network (the above method), disk, memory) in Picasso.

like image 516
TWiStErRob Avatar asked Aug 05 '14 21:08

TWiStErRob


People also ask

How do you load an image into an imageView from an image URL using Picasso?

Image loading using Picasso is very easy, you can do it like this way Picasso. get(). load("http://i.imgur.com/DvpvklR.png").into(imageView); and in their website you can get every details. In your case you can parse every image URL and use RecyclerView to show them along with Picasso.


2 Answers

The version of Picasso at the time didn't support what I wanted so I went to use Glide 3. Here's what I managed to put together. I didn't test it yet, I pieced it together from history, because I removed this support from my app, it was an overkill; however it was working when the functionality was still present.

in ConnectionCallbacks.onConnected:

Glide.get(getContext()).register(DriveId.class, InputStream.class, new DriveIdModelLoader.Factory(mClient));

in ConnectionCallbacks.onConnectionSuspended:

Glide.get(getContext()).unregister(DriveId.class, InputStream.class);

in list Adapter:

String driveString = cursor.getString(cursor.getColumnIndex("image"));
DriveId driveId = DriveId.decodeFromString(driveString);
Glide.with(this)
     .from(DriveId.class)
     .load(driveId)
     .into(imageView);

Glide glue:

import java.io.*;

import android.content.Context;
import android.net.Uri;

import com.bumptech.glide.load.data.DataFetcher;
import com.bumptech.glide.load.model.*;
import com.bumptech.glide.load.model.stream.StreamModelLoader;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.drive.DriveId;

public class DriveIdModelLoader implements StreamModelLoader<DriveId> {
    private final GoogleApiClient client;

    public DriveIdModelLoader(GoogleApiClient client) {
        this.client = client;
    }

    public DataFetcher<InputStream> getResourceFetcher(DriveId model, int width, int height) {
        return new DriveIdDataFetcher(client, model);
    }

    public static class Factory implements ModelLoaderFactory<DriveId, InputStream> {
        private final GoogleApiClient client;

        public Factory(GoogleApiClient client) {
            this.client = client;
        }

        public ModelLoader<DriveId, InputStream> build(Context context, GenericLoaderFactory factories) {
            return new DriveIdModelLoader(client);
        }

        public void teardown() {
            client.disconnect();
        }
    }
}

Drive related Glide logic:

import java.io.InputStream;

import org.slf4j.*;

import com.bumptech.glide.Priority;
import com.bumptech.glide.load.data.DataFetcher;
import com.google.android.gms.common.api.*;
import com.google.android.gms.drive.*;

public class DriveIdDataFetcher implements DataFetcher<InputStream> {
    private static final Logger LOG = LoggerFactory.getLogger(DriveIdDataFetcher.class);

    private final GoogleApiClient client;
    private final DriveId driveId;

    private boolean cancelled = false;

    private DriveFile file;
    private Contents contents;

    public DriveIdDataFetcher(GoogleApiClient client, DriveId driveId) {
        this.client = client;
        this.driveId = driveId;
    }

    public String getId() {
        return driveId.encodeToString();
    }

    public InputStream loadData(Priority priority) {
        if (cancelled) return null;
        if (client == null) {
            LOG.warn("No connected client received, giving custom error image");
            return null;
        }
        file = Drive.DriveApi.getFile(client, driveId);
        if (cancelled) return null;
        contents = sync(file.openContents(client, DriveFile.MODE_READ_ONLY, null)).getContents();
        if (cancelled) return null;
        return contents.getInputStream();
    }

    public void cancel() {
        cancelled = true;
        if (contents != null) {
            file.discardContents(client, contents);
        }
    }

    public void cleanup() {
        if (contents != null) {
            sync(file.discardContents(client, contents));
        }
    }

    private static <T extends Result> void assertSuccess(T result) {
        if (!result.getStatus().isSuccess()) {
            throw new IllegalStateException(result.getStatus().toString());
        }
    }

    private static <T extends Result> T sync(PendingResult<T> pending) {
        T result = pending.await();
        assertSuccess(result);
        return result;
    }
}
like image 77
TWiStErRob Avatar answered Oct 08 '22 01:10

TWiStErRob


You can download an image from Google Drive in this way:

    //this is the original Google Drive link to the image
    String s="https://drive.google.com/file/d/0B9nFwumYtUw9Q05WNlhlM2lqNzQ/view?usp=sharing";

    //you have to get the part of the link 0B9nFwumYtUw9Q05WNlhlM2lqNzQ
    String[] p=s.split("/");
    //Create the new image link
    String imageLink="https://drive.google.com/uc?export=download&id="+p[5];
    ImageView imageView = (ImageView) findViewById(R.id.imageView);
    Picasso.with(YourActivity.this).load(imageLink).into(imageView);

that is all

like image 39
user5807327 Avatar answered Oct 08 '22 01:10

user5807327