Hot questions for Using Glide in android bitmap

Top 10 Java Open Source / Glide / android bitmap

Question:

Trying to share a GIF i loaded into my ImageView into Whatsapp. I can see the GIF animating in my imageview perfectly fine, but it will get this error when I try to share to Whatsapp:-

java.lang.ClassCastException: com.bumptech.glide.load.resource.gif.GifDrawable cannot be cast to android.graphics.drawable.BitmapDrawable

My sharing to Whatsapp method code :-

BitmapDrawable drawable = (BitmapDrawable) img1.getDrawable();
Bitmap imgBitmap = drawable.getBitmap();
String imgBitmapPath = MediaStore.Images.Media.insertImage(getContentResolver(), imgBitmap, "Whatsapp", null);

Uri imgUri = Uri.parse(imgBitmapPath);

Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
shareIntent.putExtra(Intent.EXTRA_STREAM, imgUri);
shareIntent.setType("image/*");
shareIntent.setPackage("com.whatsapp");
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
shareIntent.putExtra(Intent.EXTRA_TEXT, "My Custom Text ");
startActivity(Intent.createChooser(shareIntent, "Share this"));

My Glide load code:-

Glide.with(getApplicationContext()).asGif().load(gifUrl).into(img1);

Answer:

You can't convert GifDrawable to BitmapDrawable.

Get bytebuffer from gifdrawable and save it using bytearray in file. then you can share it using uri. Check below,

Java

Glide.with(this)
         .asGif()
         .load("your_gif_url")
         .addListener(new RequestListener<GifDrawable>() {
               @Override
               public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<GifDrawable> target, boolean isFirstResource) {

                   return false;
               }

               @Override
               public boolean onResourceReady(GifDrawable resource, Object model, Target<GifDrawable> target, DataSource dataSource, boolean isFirstResource) {
                   saveImageAndShare(resource);
                   return false;
               }
          }).into(img1);

convert gifdrawable to bytearray and save it file then share it using uri

private void saveImageAndShare(GifDrawable gifDrawable) {
    if (gifDrawable != null) {
        String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
        String fileName = "sharingGif.gif";
        File sharingGifFile = new File(baseDir, fileName);
        gifDrawableToFile(gifDrawable, sharingGifFile);
        Uri uri = FileProvider.getUriForFile(this, getPackageName() + ".provider", sharingGifFile);
        this.shareFile(uri);
    }

}

private void shareFile(Uri uri) {
    Intent shareIntent = new Intent(Intent.ACTION_SEND);
    shareIntent.setType("image/gif");
    shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
    startActivity(Intent.createChooser(shareIntent, "Share Emoji"));
}

private void gifDrawableToFile(GifDrawable gifDrawable, File gifFile) {
    ByteBuffer byteBuffer = gifDrawable.getBuffer();
    try {
        FileOutputStream output = new FileOutputStream(gifFile);
        byte[] bytes = new byte[byteBuffer.capacity()];
        ((ByteBuffer) byteBuffer.duplicate().clear()).get(bytes);
        output.write(bytes, 0, bytes.length);
        output.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Kotlin

Glide.with(this)
                .asGif()
                .load("your_gif_url")
                .addListener(object : RequestListener<GifDrawable> {
                    override fun onLoadFailed(
                        e: GlideException?,
                        model: Any?,
                        target: Target<GifDrawable>?,
                        isFirstResource: Boolean
                    ): Boolean {
                        Log.e("GIF", "GIf failed")
                        return false
                    }

                    override fun onResourceReady(
                        resource: GifDrawable?,
                        model: Any?,
                        target: Target<GifDrawable>?,
                        dataSource: DataSource?,
                        isFirstResource: Boolean
                    ): Boolean {
                        Log.e("GIF", "Test gif done")
                        saveImageAndShare(resource)

                        return false
                    }
                })
                .into(img1)


private fun saveImageAndShare(gifDrawable: GifDrawable?) {

        gifDrawable?.let {

            val baseDir: String = Environment.getExternalStorageDirectory().getAbsolutePath()
            val fileName = "sharingGif.gif"

            val sharingGifFile = File(baseDir, fileName)
            gifDrawableToFile(gifDrawable, sharingGifFile)

            val uri: Uri = FileProvider.getUriForFile(
                this, BuildConfig.APPLICATION_ID + ".provider",
                sharingGifFile
            )

            shareFile(uri)


        }

    }

    private fun shareFile(uri: Uri) {
        val shareIntent = Intent(Intent.ACTION_SEND)
        shareIntent.type = "image/gif"

        shareIntent.putExtra(Intent.EXTRA_STREAM, uri)
        startActivity(Intent.createChooser(shareIntent, "Share Emoji"))
    }

    private fun gifDrawableToFile(gifDrawable: GifDrawable, gifFile: File) {
        val byteBuffer = gifDrawable.buffer
        val output = FileOutputStream(gifFile)
        val bytes = ByteArray(byteBuffer.capacity())
        (byteBuffer.duplicate().clear() as ByteBuffer).get(bytes)
        output.write(bytes, 0, bytes.size)
        output.close()
    }

Question:

My app stores images in FirebaseFirestore; they can be in jpg or png format. I have an Activity which draws a grid on a Canvas, and I want to put the images into the grid. The overall grid + images is called an ImageGrid and is defined like this (a few things left out for readability):

    public class ImageGrid extends View {

        private final Context mContext;
        private int mNumRows, mNumCols;
        private float canvas_height, canvas_width;
        private final Paint mPaint;
        private float image_cell_size;
        private String[][] image_urls;

        public ImageGrid(Context thisContext, AttributeSet attrs) {
            super(thisContext, attrs);

            mContext = getContext();
            mPaint = new Paint();

        }

        public void setSize(int numRows, int numCols) {
            mNumRows = numRows;
            mNumSts = numCols;
            invalidate();
        }

        public void setImages(String[][] images) {
            image_urls = images;
        }

        // DRAW GRID FUNCTIONS set up the grid and add the images

        protected void onDraw(Canvas canvas) {

            canvas_height = canvas.getHeight();
            canvas_width = canvas.getWidth();

            get_cell_size();    // Get the size of the cells
            // image_cell_size has now been set by get_cell_size

            // Draw axes & chart
            draw_images(canvas);      // Draw the images

        }

        // Draw images
        private void draw_images(final Canvas canvas) {

          if (mChart == null) return;

          final Resources resources = mContext.getResources();
          FirebaseStorage mStorage = FirebaseStorage.getInstance();
          final StorageReference mStorageRef = mStorage.getReference();

          for (int rr = 0; rr < mNumRows; rr++) {

            for (int cc = 0; cc < mNumSts; cc++) {

              String drawableUrl = image_urls[rr][cc];

              if(drawableUrl != null) {

* THIS IS WHERE I NEED TO GET THE IMAGE AND DISPLAY IT *

              }
            }
          }
        }
    }

So, after hunting online for how to get the image and then draw it on the Canvas, I have this:

mStorageRef.child(drawableUrl)
  .getDownloadUrl()
  .addOnSuccessListener(
    new OnSuccessListener<Uri>() {
      public void onSuccess(Uri uri) {    
        Glide.with(getContext())
             .asBitmap()
             .load(uri)
             .into(new CustomTarget<Bitmap>() {
               public void onResourceReady(
                 Bitmap resource,
                 Transition<? super Bitmap> transition) {
                   Drawable d = new BitmapDrawable(getResources(), resource);
                   d.setBounds(
                       cc * cell_size, 
                       rr * cell_size,
                       (cc + 1)*cell_size,
                       (rr + 1) * cell_size);
                   d.draw(canvas);
                 }}});

This retrieves the image from the database; when I check the debugger, d looks fine - it contains the correct image. I then set the corners of the image using setBounds - again, the values being computed here look correct, when compared to the size of the canvas and the number of images I'm fitting in. Finally, the image should be drawn on the canvas - there is no error message, but nothing appears.

I don't really know what to check next, or what else to try. Can anyone suggest anything that might work?


Answer:

Ok, I figured this out. The problem was that canvas had to be declared final in draw_images, because it was being accessed from within the inner class. This meant that the inner class couldn't update it.

So, I created a class variable called mDrawables, which is an array of Drawables. Then I retrieve the Drawables one at a time in setImages and store them in mDrawables. As each is retrieved, I update the count of how many have been retrieved so far; once this is equal to the total number of images, I invalidate the ImageGrid.

Then in draw_images, when looping over the cells, I have the drawables already in mDrawables and can use them directly from there.

Question:

I was wondering about, how to implement Glide along with using Bitmap compression in Kotlin and thought that any of the code below would work. But unfortunately, the app closes as soon as I add an image into any of the imageView for the fourth time. Here's the code which I tried to implement

val selectedImage = data?.data
val bitmap = MediaStore.Images.Media.getBitmap(contentResolver, selectedImage) 
//method 1
Glide.with(this).asBitmap().load(compressBitmap(bitmap,5)).into(imageView!!)
//method 2
var bitmapDrawable = BitmapDrawable( resources , compressBitmap(bitmap,5))
Glide.with(this).load(bitmapDrawable).into(imageView!!)

What would be the correct code, if i'm somewhere wrong here. Thankyou in advance


Answer:

Try using Recycler View or another component to load the images in. They will handle the load.