Glide: Save image on phone

Created on 8 Jul 2014  路  18Comments  路  Source: bumptech/glide

Is it possible to automatically save the image on the phone? I am loading an image from the internet and want to download it.

I implemented the listener, but could not find a function to get an Image object and save it manually.

question

Most helpful comment

Glide doesn't support doing this explicitly, but its not too complicated to do yourself since you can get at the Bitmap directly:

Glide.load(yourUrl).into(new SimpleTarget(yourDesiredWidth, yourDesiredHeight {
    @Override
    public void onImageReady(final Bitmap bitmap) {
        new AsyncTask<Void, Void, Void>() {
            @Override
            public Void doInBackground() { 
                File file = new File("your/desired/file/path");
                OutputStream os = new FileOutputStream(file);
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
            }
        }.execute();
    }
}

That won't quite compile but hopefully it's enough to give you a reasonable idea of how this might work. The only important thing to keep in mind is that onImageReady is called on the main thread, so to do any I/O like writing to a file you want to use some kind of background thread like an AsyncTask or a HandlerThread.

Hope that helps and thanks for asking!

All 18 comments

Glide doesn't support doing this explicitly, but its not too complicated to do yourself since you can get at the Bitmap directly:

Glide.load(yourUrl).into(new SimpleTarget(yourDesiredWidth, yourDesiredHeight {
    @Override
    public void onImageReady(final Bitmap bitmap) {
        new AsyncTask<Void, Void, Void>() {
            @Override
            public Void doInBackground() { 
                File file = new File("your/desired/file/path");
                OutputStream os = new FileOutputStream(file);
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
            }
        }.execute();
    }
}

That won't quite compile but hopefully it's enough to give you a reasonable idea of how this might work. The only important thing to keep in mind is that onImageReady is called on the main thread, so to do any I/O like writing to a file you want to use some kind of background thread like an AsyncTask or a HandlerThread.

Hope that helps and thanks for asking!

Thank you very much.

I tried to implement it, but the onImageReady function never gets called. I also tried to use .into(new ImageViewTarget(myImageView)), but that one did not work as well.

Also did I double test it. .into(myImageView) still works. So there is nothing wrong with the 'backend', where I load the images from.

Oh right. You need to do Glide.load("myUrl").into(new SimpleTarget(....){}).with(context);

I always forget the .with(context) call on the end. I've fixed this api in the 3.0a branch, but we're stuck with it in v2 (sorry!).

Any non view needs with the with call at the end so that we can get a context. Views don't need it because we can get the context from the view. This is confusing so in the 3.0a branch all calls start with Glide.with(context).

Thank you very much. It does work now.

Maybe a sample with a Target should be put in the readme?

I've tried your solution, but I get a little of problems. I want to show a placeholder image when glide.load is failed or during processing. It works fine when I use Glide.load(imgUrl).placeholder(placeholderResouceId).into(imgView); , but when I use SimpleTarget, the placeholder seems did not work.

Here's my code

Glide.load(url).placeholder(defImgId).into(new SimpleTarget() {
    @Override
    public void onImageReady(Bitmap bitmap) {
        mImgView.setImageBitmap(bitmap);
    }

    @Override
    protected int[] getSize() {
        return new int[] { mImgView.getWidth(), mImgView.getHeight() };
    }
}).with(mActivity);

I also tried .listen(new RequestListener) , but it seems that there's nothing about placeholder.

@liuwei-tapatalk If you're just trying to load into a view, you usually want to use just Glide.load(...).into(imageView). If you want to do something in addition to setting the bitmap on a view, you want to subclass ImageViewTarget instead of SimpleTarget. That will save you from having to calculate the size as well.

@sjudd
Thank you for your help. ImageViewTarget works well with placeholder.

There is now some documentation on using SimpleTarget in the wiki and since the 3.x release this is now a legacy issue so I'm going to close it.

This is the only way that I've found to get bitmaps and files storage inside device! Happy coding!

Glide.with(context).load("image_url").into(new SimpleTarget() {
            @Override
            public void onResourceReady(Object resource, GlideAnimation glideAnimation) {

                final Bitmap b;

                try{
                    imageView.setImageDrawable((GlideBitmapDrawable) resource);
                }catch (ClassCastException e) {
                    imageView.setImageDrawable((GifDrawable) resource);
                }

                imageView.setDrawingCacheEnabled(true);

                imageView.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                        View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
                imageView.layout(0, 0, imageView.getMeasuredWidth(), imageView.getMeasuredHeight());

                imageView.buildDrawingCache(true);
                b = Bitmap.createBitmap(appicon.getDrawingCache());
                imageView.setDrawingCacheEnabled(false);

                new AsyncTask<Void, Void, Void>() {
                    @Override
                    protected Void doInBackground(Void... params) {

                        File dir = new File(android.os.Environment.getExternalStorageDirectory() + "/YourDir");
                        if(!dir.exists()){
                            dir.mkdirs();
                        }

                        File file = new File(android.os.Environment.getExternalStorageDirectory() + "/YourDir", "imageName" + ".jpg");
                        try{
                            OutputStream os = new FileOutputStream(file);
                            b.compress(Bitmap.CompressFormat.JPEG, 100, os);
                        } catch (Exception e){

                        }

                        return null;
                    }
                }.execute();

            }
        });

@mkiisoft I don't suggest using an ImageView like this, consider this more Glide-y solution:

Glide
    .with(context)
    .load("image_url")
    .asBitmap()
    .toBytes(Bitmap.CompressFormat.JPEG, 80)
    .into(new SimpleTarget<byte[]>() {
        @Override public void onResourceReady(final byte[] resource, GlideAnimation<? super byte[]> glideAnimation) {
            new AsyncTask<Void, Void, Void>() {
                @Override protected Void doInBackground(Void... params) {
                    File sdcard = Environment.getExternalStorageDirectory();
                    File file = new File(sdcard + "/YourDir/imageName.jpg");
                    File dir = file.getParentFile();
                    try {
                        if (!dir.mkdirs() && (!dir.exists() || !dir.isDirectory())) {
                            throw new IOException("Cannot ensure parent directory for file " + file);
                        }
                        BufferedOutputStream s = new BufferedOutputStream(new FileOutputStream(file));
                        s.write(resource);
                        s.flush();
                        s.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return null;
                }
            }.execute();
        }
    })
;

Notice that 2/3 of this is writing the byte[] into a file and async networking/loading/transforming/caching is 7 lines formatted loosely.

If this is a one-off writing by user request from UI, I also suggest adding these:

.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)

You can also control the size and transformation via the following methods:

.fitCenter().atMost().override(2000, 2000)

@TWiStErRob yep, this is one off image (over API with parsing, etc would be crazy) I'm using it to get the full image to crop it later and I rather have it on my phone and then save it anywhere I want. All the other cached images with this gets delete it after the user close the app.

Thanks for the tips.

@TWiStErRob please a i have a problem with API 23 or above when i try to download image :

Glide
    .with(context)
    .load("image_url")
    .asBitmap()
    .toBytes(Bitmap.CompressFormat.JPEG, 80)
    .into(new SimpleTarget<byte[]>() {
        @Override public void onResourceReady(final byte[] resource, GlideAnimation<? super byte[]> glideAnimation) {
            new AsyncTask<Void, Void, Void>() {
                @Override protected Void doInBackground(Void... params) {
                    File sdcard = Environment.getExternalStorageDirectory();
                    File file = new File(sdcard + "/YourDir/imageName.jpg");
                    File dir = file.getParentFile();
                    try {
                        if (!dir.mkdirs() && (!dir.exists() || !dir.isDirectory())) {
                            throw new IOException("Cannot ensure parent directory for file " + file);
                        }
                        BufferedOutputStream s = new BufferedOutputStream(new FileOutputStream(file));
                        s.write(resource);
                        s.flush();
                        s.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return null;
                }
            }.execute();
        }
    })
;

@Mouadabdelghafouraitali at first glance you probably miss the permission to write to /sdcard/. Take a look at #459 for a better solution than this.

@TWiStErRob THANKS so much for reply and sorry to disturb i already added

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
and i have another problem when i save image (API < 23 )he doesn't appear in my gallery

please help me

@Mouadabdelghafouraitali http://stackoverflow.com/a/19794372/253468, but please don't use the mounting broadcast or a full directory scan; specify your file exactly!

@TWiStErRob yeah i did this :

File file = new File(Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES), "/ARTApp/"+"ART_"+System.currentTimeMillis()+".jpg");

Hello,
I have found multiple ways to download Images from url to the SD card, and they all work perfectly on the Emulator but on the mobile phone they download an extremely small sized image, how can I fix that? even the code here gives the same results, on the mobile the image is perfect and huge even 4mb, but on the phone its barley 300kb and mostly even less. What am i missing?

I am having an issue with Glide 4.
Below code is not working in Glide 4.
Does anyone know how to copy the code in the Glide 4.
Glide
.with(context)
.load("image_url")
.asBitmap()
.toBytes(Bitmap.CompressFormat.JPEG, 80)
.into(new SimpleTarget @Override public void onResourceReady(final byte[] resource, GlideAnimation new AsyncTask() {
@Override protected Void doInBackground(Void... params) {
File sdcard = Environment.getExternalStorageDirectory();
File file = new File(sdcard + "/YourDir/imageName.jpg");
File dir = file.getParentFile();
try {
if (!dir.mkdirs() && (!dir.exists() || !dir.isDirectory())) {
throw new IOException("Cannot ensure parent directory for file " + file);
}
BufferedOutputStream s = new BufferedOutputStream(new FileOutputStream(file));
s.write(resource);
s.flush();
s.close();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}.execute();
}
})
;

Was this page helpful?
0 / 5 - 0 ratings