11

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.

Mark DeSpain
  • 63
  • 1
  • 13

1 Answers1

4

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)
Igor Khvostenkov
  • 714
  • 5
  • 15
  • thank you, this working good, but some images returns "java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.drawable.Drawable.getIntrinsicWidth()' " when there's no connections in setDrawable method – Mark DeSpain Feb 14 '19 at 08:51
  • @MarkDeSpain Could you please post the full stack trace? – Igor Khvostenkov Feb 14 '19 at 12:13
  • E/AndroidRuntime: FATAL EXCEPTION: main Process: www.pro_cs_is.com, PID: 10595 java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.drawable.Drawable.getIntrinsicWidth()' on a null object reference at www.pro_cs_is.com.PicassoImageGetter$BitmapDrawablePlaceHolder.setDrawable(PicassoImageGetter.java:49) at www.pro_cs_is.com.PicassoImageGetter$BitmapDrawablePlaceHolder.onBitmapFailed(PicassoImageGetter.java:65) at com.squareup.picasso.TargetAction.error(TargetAction.java:49) at com.squareup.picasso.Picasso.deliverAct – Mark DeSpain Feb 14 '19 at 12:58
  • 1
    @MarkDeSpain I can explain that, as in some case you try to load with no connection and without an image in the cache. So, my proposal will be in this case show some placeholder image from local device: ```PicassoCache.getPicassoInstance(getContext()).load(source).placeholder(R.placeholder_image_on_local_device).into(drawable)``` – Igor Khvostenkov Feb 14 '19 at 14:43
  • @MarkDeSpain Should be error not placeholder, messed up here:```PicassoCache.getPicassoInstance(getContext()).load(source).error(R.placeholder_image_on_local_device).into(drawable)``` – Igor Khvostenkov Feb 14 '19 at 15:04
  • @MarkDeSpain if this answer has solved your question please consider [accepting it](https://meta.stackexchange.com/q/5234/179419) by clicking the check-mark. This indicates to the wider community that you've found a solution and gives some reputation to both the answerer and yourself. There is no obligation to do this. – Igor Khvostenkov Feb 15 '19 at 10:30
  • Khvostenko don't worry, I'll do that at last day of bounty If there's no new answers – Mark DeSpain Feb 15 '19 at 11:14