Search code examples
androidpicassoandroid-imageandroid-bitmapandroid-internal-storage

How to save/read inline images in html content to internal/extrenal memory


According to this question I used a custom ImageGatter class to display images that I'm getting from a server in TextView using Picasso

    public class PicassoImageGetter implements Html.ImageGetter {

    private TextView textView = null;
    Context mContext;

    public PicassoImageGetter() {

    }

    public PicassoImageGetter(TextView target, Context context) {
        textView = target;
        mContext = context;
    }

    @Override
    public Drawable getDrawable(String source) {

        BitmapDrawablePlaceHolder drawable = new BitmapDrawablePlaceHolder();
        Picasso.get().load(source).into(drawable);
        return drawable;

    }

    private class BitmapDrawablePlaceHolder extends BitmapDrawable implements com.squareup.picasso.Target {

        protected Drawable drawable;

        @Override
        public void draw(final Canvas canvas) {
            if (drawable != null) {
                drawable.draw(canvas);
            }
        }

        public void setDrawable(Drawable drawable) {
            this.drawable = drawable;
            int width = drawable.getIntrinsicWidth();
            int height = drawable.getIntrinsicHeight();
            drawable.setBounds(0, 0, width, height);
            setBounds(0, 0, width, height);
            if (textView != null) {
                textView.setText(textView.getText());
            }
        }

        @Override
        public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
            setDrawable(new BitmapDrawable(mContext.getResources(), bitmap));
        }

        @Override
        public void onBitmapFailed(Exception e, Drawable errorDrawable) {
            setDrawable(errorDrawable);
        }

        @Override
        public void onPrepareLoad(Drawable placeHolderDrawable) {

        }

    }
}

and used like this

imageGetter = new PicassoImageGetter(contentTextView, this);
    Spannable html;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
        html = (Spannable) Html.fromHtml(content, Html.FROM_HTML_MODE_LEGACY, imageGetter, null);
    } else {
        html = (Spannable) Html.fromHtml(content, imageGetter, null);
    }

    contentTextView.setText(html);

I need to catch this images into internal or external storage to display it if there's no connection, but I don't know the path or file name.


Solution

  • You need to implement picasso cache by your own. This should be like this:

    public class PicassoCache {
    
        private static Picasso picassoInstance = null;
    
        private PicassoCache(Context context) {
    
            Downloader downloader = new OkHttp3Downloader(context, Integer.MAX_VALUE);
            Picasso.Builder builder = new Picasso.Builder(context);
            builder.downloader(downloader);
    
            picassoInstance = builder.build();
        }
    
        public static Picasso getPicassoInstance(Context context) {
    
            if (picassoInstance == null) {
    
                new PicassoCache(context);
                return picassoInstance;
            }
    
            return picassoInstance;
        }
    }
    

    Then in your code:

        @Override
        public Drawable getDrawable(String source) {
    
            BitmapDrawablePlaceHolder drawable = new BitmapDrawablePlaceHolder();
            PicassoCache.getPicassoInstance(getContext()).load(source).into(drawable);
            return drawable;
    
        }
    

    OkHttp3Downloader will install an image cache into your application cache directory. You can also use another constructor with your own provided directory public OkHttp3Downloader(final File cacheDir, final long maxSize)

    As an alternative, you can use Glide. This is like picasso but also allows you to show gifs with animation and cache strategy IMHO is a bit easier.

    Glide.with(context)
         .load(source)
         .apply(RequestOptions().diskCacheStrategy(DiskCacheStrategy.ALL))
         .into(drawable)