19

Currently I'm loading MediaStore Image Thumbnails using picasso into the ListView with the following snippet: (video.getData() returns the actual path of the image such as mnt/sdcard/...)

Picasso.with(this.context)
       .load(new File(photo.getData()))
       .resize(50, 50).config(config)
       .centerCrop()
       .into(viewHolder.imageViewItem);

Now I'm and unable to load the MediaStore Video Thumbnails by just passing the video.getData() instead of photo.getData()?

Marcus
  • 6,697
  • 11
  • 46
  • 89
Mohammad Sharaf Ali
  • 569
  • 1
  • 4
  • 19
  • Unless they added something for this since I last looked, Picasso didn't have support for video thumbnails. I wound up switching to `SmartImageView`. – CommonsWare Jun 04 '14 at 13:37
  • Is SmartImageView a library like picasso? – Mohammad Sharaf Ali Jun 04 '14 at 17:18
  • https://github.com/loopj/android-smart-image-view – CommonsWare Jun 04 '14 at 17:20
  • I don't see any example of loading MediaStore Image and Video thumbnail. Do you have any snippet for it? – Mohammad Sharaf Ali Jun 04 '14 at 17:34
  • https://github.com/commonsguy/cw-omnibus/tree/master/Media/VideoList – CommonsWare Jun 04 '14 at 17:43
  • You are certainly welcome to your opinion. I have not received complaints about this particular sample app to date. – CommonsWare Jun 04 '14 at 18:07
  • Its just doing the same. Its querying the MediaStore to get Video Thumbnail that I'm already doing. But doing this makes my app laggy and sometimes I get null getVideoFrame(). – Mohammad Sharaf Ali Jun 04 '14 at 18:12
  • None of that has anything to do with your question. Your question is about using Picasso, and then you asked for a sample of using `SmartImageView` when I cited it as an alternative. If you are encountering performance issues *in addition to* your problems with integrating Picasso, please ask a separate Stack Overflow question so that you can get help on that topic (preferably after using Traceview). FWIW, my sample uses a `Loader` to asynchronously query the `MediaStore`, and `SmartImageView` itself loads the image asynchronously. – CommonsWare Jun 04 '14 at 18:16
  • The sole problem is that picasso takes new File("file path") and SmartImageView takes string in setImageUrl. Android doc says that it automagically generates thumbnails for all the images but not for videos. Than I found this link: https://github.com/square/picasso/blob/master/picasso/src/maian/java/com/squareup/picasso/MediaStoreBitmapHunter.java – Mohammad Sharaf Ali Jun 04 '14 at 18:27
  • Can you guide me how to use this MediaStoreBitmapHunter.java class. Its not already included in picasso lib .jar? Or I need to do something else? – Mohammad Sharaf Ali Jun 04 '14 at 18:28
  • Your link is broken. I do not recall `MediaStoreBitmapHunter` being around when I was working on this problem before, so it would appear that Picasso is at least in the process of adding more support for this scenario. Whether that is part of the released code, I cannot say. In general, the "hunter" classes are used internally, based upon path/URL structures, so you'd need to look through the code base and see what triggers the use of `MediaStoreBitmapHunter`. – CommonsWare Jun 04 '14 at 18:35
  • https://github.com/square/picasso/blob/master/picasso/src/maian/java/com/squareup/picasso/MediaStoreBitmapHunter.java – Mohammad Sharaf Ali Jun 04 '14 at 18:49
  • On github: https://github.com/square/picasso I see they have many classes. But the picasso lib that I have included in my project have very few classes in it. Am I missing something? – Mohammad Sharaf Ali Jun 04 '14 at 18:51

4 Answers4

40

First You need to create VideoRequestHandler

public class VideoRequestHandler extends RequestHandler{
    public String SCHEME_VIDEO="video";
    @Override
    public boolean canHandleRequest(Request data) 
    {
        String scheme = data.uri.getScheme();
        return (SCHEME_VIDEO.equals(scheme));
    }

    @Override
    public Result load(Request data, int arg1) throws IOException 
    {
         Bitmap bm;
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
         try {
            Size size = new Size(250, 250);
            bm = ThumbnailUtils.createVideoThumbnail(new File(data.uri.getPath()), size, null);
         } catch (IOException e) {
            e.printStackTrace();
        }
        }
        else
        {
         bm = ThumbnailUtils.createVideoThumbnail(data.uri.getPath(), MediaStore.Images.Thumbnails.MINI_KIND);
        }
         return new Result(bm,LoadedFrom.DISK);  
    }
}

After That

 VideoRequestHandler videoRequestHandler;
 Picasso picassoInstance;

Build only once

 videoRequestHandler = new VideoRequestHandler();
 picassoInstance = new Picasso.Builder(context.getApplicationContext())
  .addRequestHandler(videoRequestHandler)
  .build();

Then load file from path

 picassoInstance.load(VideoRequestHandler.SCHEME_VIDEO+":"+filepath).into(holder.videoThumbnailView);

Updated October 2020

ThumbnailUtils.createVideoThumbnail(data.uri.getPath(), MediaStore.Images.Thumbnails.MINI_KIND);

is deprecated in Android Q. I will write in Kotlin:

val bm = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            ThumbnailUtils.createVideoThumbnail(
                File(data.uri.path!!),
                Size(200f.toPx(), 200f.toPx()),
                CancellationSignal()
            )
        } else {
            ThumbnailUtils.createVideoThumbnail(
                data.uri.path!!,
                MediaStore.Images.Thumbnails.MINI_KIND
            )
        }

to Px is an extension function which is like below;

fun Float.toPx() =
    TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this, Resources.getSystem().displayMetrics)
        .toInt()

You can use any dp value for it :) I hope this can help you :)

Ram
  • 1,408
  • 13
  • 29
  • what is holder.videoThumbnailView in the load file from path section? – Lion789 May 08 '15 at 20:46
  • 2
    @Lion789 An `ImageView` in a [view holder](http://developer.android.com/training/improving-layouts/smooth-scrolling.html#ViewHolder). – Jake Wharton May 08 '15 at 20:50
  • 2
    Still showing a black screen... I tried putting the videoThumbnailView item before and after the videoViewItem... and it does not change the result still a black screen – Lion789 Jun 10 '15 at 15:13
  • @Lion789 I guess in picassoInstance.load(videoRequestHandler.SCHEME_VIEDEO+":"+filepath), you are sending video:filepath as URI which is invalid. That's the reason you are still getting black screen. – Tejas Pawar Jul 13 '15 at 18:52
  • I am passing a String that has the path... "http:// example.com/vjd342ie. mp4" for example... – Lion789 Jul 14 '15 at 19:42
  • There are several ways to initialize Picassa. I rather use `Picasso.setSingletonInstance(new Picasso.Builder( getApplicationContext()).addRequestHandler( new VideoRequestHandler()).build());` before the very first call of `Picassa.with(this).load(..` – OneWorld Mar 21 '16 at 11:19
  • @Lion789 I'd rather change the check in `canHandleRequest` for your needs. E.g. check for file extension. – OneWorld Mar 21 '16 at 11:26
  • It works for me but video thumbnails are loading very slow. Is there a way to speed it up? – user4500 Nov 04 '17 at 03:31
  • but why Disk cache doesn't work for thumbnails? it always loads thumbnail from videofile after restarting the app... – user25 Jun 05 '18 at 16:19
  • cache isn't working, I even checked private app folder and `/cache/picasso-cache` – user25 Jun 05 '18 at 16:31
  • +1 this is definitely the way to go because it allows using stuff like `resize` and `placeholder` while the thumbnail is being created – 0101100101 Jun 24 '19 at 03:34
0

Before, you had two options:

1) Do a call beforehand, when you were retrieving your videos for example and storing the bitmap:

Bitmap thumbnailBitmap = MediaStore.Video.Thumbnails.getThumbnail(content, id, MediaStore.Video.Thumbnails.MINI_KIND, options);

2) Creating a custom Downloader (not verified for local media)

But now, with Picasso 2.4, you can create a RequestHandler. You can have a look at this page for example: http://blog.jpardogo.com/requesthandler-api-for-picasso-library/

In my current usage, I fetch the thumbnail path and then call Picasso with that path. To get the thumbnail path, I referred to: android get video thumbnail PATH, not Bitmap.

Community
  • 1
  • 1
Renaud C.
  • 123
  • 8
0
public void bindTo(MediaListHolder mediaListRowHolder, int i) {
    DataPictures message = itemList.get(i);
    try {
        Uri uri = Uri.fromFile(new File(message.getFilePath()));
        if (message.getFileType().equalsIgnoreCase("video")) {
            Bitmap bmThumbnail = ThumbnailUtils.extractThumbnail(ThumbnailUtils.createVideoThumbnail(message.getFilePath(),
                    MediaStore.Video.Thumbnails.FULL_SCREEN_KIND), MAX_WIDTH, MAX_HEIGHT);
            mediaListRowHolder.thumbnail.setImageBitmap(bmThumbnail);
        } else {
            Picasso.with(ApplicationSingleton.getInstance()).load(uri)
                    .resize(size, size)
                    .placeholder(R.drawable.logo_slogan)
                    .into(mediaListRowHolder.thumbnail);
        }
        Log.i(TAG, "bindTo: ");
    } catch (Exception e) {
        e.printStackTrace();
    }
}
Devix
  • 432
  • 5
  • 16
-2

Note - Follow this comment if you simply want to show thumbnail in your image view and apply no extra Picasso functions on it . I just modified it a little to show circular thumbnail coz it looks cool .

Don't use Picasso . Here's a very simple way to do it .

videoPathUrl = /*your Video File Url */
Bitmap bMap = ThumbnailUtils.createVideoThumbnail(videoPathUrl , MediaStore.Video.Thumbnails.MICRO_KIND);
bMap = transformBitmapToCircularBitmap(bMap);
yourImageView.setImageBitmap(bMap);

and transformBitmapToCircularBitmap function is as follows -

public static Bitmap transformBitmapToCircularBitmap(Bitmap source)
{
    int size = Math.min(source.getWidth(), source.getHeight());

    int x = (source.getWidth() - size) / 2;
    int y = (source.getHeight() - size) / 2;

    Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);
    if (squaredBitmap != source) {
        source.recycle();
    }

    Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig());

    Canvas canvas = new Canvas(bitmap);
    Paint paint = new Paint();
    BitmapShader shader = new BitmapShader(squaredBitmap,
            BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
    paint.setShader(shader);
    paint.setAntiAlias(true);

    float r = size / 2f;
    canvas.drawCircle(r, r, r, paint);

    squaredBitmap.recycle();
    return bitmap;
}
Shubham Arora
  • 807
  • 9
  • 10