Как сохранять/читать встроенные изображения в html-контенте во внутреннюю/внешнюю память

В соответствии с этим вопросом Я использовал собственный класс ImageGatter для отображения изображений, которые я получаю с сервера, в TextView с помощью 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) {

        }

    }
}

и используется так

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);

Мне нужно перехватить эти изображения во внутреннюю или внешнюю память, чтобы отобразить их, если нет соединения, но я не знаю пути или имени файла.


person Mark DeSpain    schedule 07.02.2019    source источник
comment
Возможно, посмотрите stackoverflow.com/questions/33040002/, чтобы посмотреть, поможет ли это   -  person owsega    schedule 07.02.2019
comment
Уточните, пожалуйста, нужно ли считывать изображение из кеша, если соединение недоступно, или вы хотите показать какое-то изображение по умолчанию, если в кеше нет нужного изображения и соединение недоступно?   -  person Igor Khvostenkov    schedule 13.02.2019
comment
@Igor Khvostenkov содержание содержит контент блога страницу, содержащую изображения ссылки, как это 1.bp.blogspot.com/-PhotHZJrpfQ/XEbV2_e_9YI/AAAAAAAAHLo/ imageanchor=1 style=margin-left: 1em; Маржа правый: 1em;> 1.bp.blogspot.com/-phothzjrpfq/xebv2_e_9yi/aaaaaaahlo/ /> Да я хочу кэшировать это изображения, если подключение недоступно   -  person Mark DeSpain    schedule 13.02.2019
comment
Перехватить свой HTTP и обрабатывать все запросы на изображение дополнительно.   -  person Fung LAM    schedule 14.02.2019


Ответы (1)


Вам нужно реализовать кеш Picasso на свой собственный. Это должно быть так:

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;
    }
}

Затем в вашем коде:

    @Override
    public Drawable getDrawable(String source) {

        BitmapDrawablePlaceHolder drawable = new BitmapDrawablePlaceHolder();
        PicassoCache.getPicassoInstance(getContext()).load(source).into(drawable);
        return drawable;

    }

OkHttp3Downloader установит кеш изображений в каталог кеша вашего приложения. Вы также можете использовать другой конструктор с вашим собственным каталогом public OkHttp3Downloader(final File cacheDir, final long maxSize)

В качестве альтернативы вы можете использовать Glide. Это похоже на Picasso, но также позволяет вам показывать гифы с анимацией и стратегией кэша ИМХО немного проще.

Glide.with(context)
     .load(source)
     .apply(RequestOptions().diskCacheStrategy(DiskCacheStrategy.ALL))
     .into(drawable)
person Igor Khvostenkov    schedule 13.02.2019
comment
спасибо, это работает хорошо, но некоторые изображения возвращают java.lang.NullPointerException: попытка вызвать виртуальный метод 'int android.graphics.drawable.Drawable.getIntrinsicWidth()', когда в методе setDrawable нет соединений. - person Mark DeSpain; 14.02.2019
comment
@MarkDeSpain Не могли бы вы опубликовать полную трассировку стека? - person Igor Khvostenkov; 14.02.2019
comment
E/AndroidRuntime: НЕИСПРАВНОЕ ИСКЛЮЧЕНИЕ: основной процесс: www.pro_cs_is.com, PID: 10595 java.lang.NullPointerException: попытка вызвать виртуальный метод 'int android.graphics.drawable.Drawable.getIntrinsicWidth()' для нулевой ссылки на объект в www.pro_cs_is.com.picassoImagegetter $ bitmapdrawablepactheer.setrawable (picassoimagegetter.java:49) на www.pro_cs_is.com.picassoimagegetter $ bitmapdrawabledholder.onbitmapfailed (picassoimagegetter.java:65) на com.squareup.picasso.targetaction.ru java:49) на com.squareup.picasso.Picasso.deliverAct - person Mark DeSpain; 14.02.2019
comment
@Markdepain Я могу объяснить, что, как в некотором случае вы пытаетесь загрузить без подключения и без изображения в кэше. Итак, мое предложение в этом случае будет заключаться в том, чтобы показать какое-то изображение-заполнитель с локального устройства: PicassoCache.getPicassoInstance(getContext()).load(source).placeholder(R.placeholder_image_on_local_device).into(drawable) - person Igor Khvostenkov; 14.02.2019
comment
@MarkDeSpain Должна быть ошибка, а не заполнитель, здесь все перепутано: PicassoCache.getPicassoInstance(getContext()).load(source).error(R.placeholder_image_on_local_device).into(drawable) - person Igor Khvostenkov; 14.02.2019
comment
@MarkDeSpain, если этот ответ решил ваш вопрос, рассмотрите возможность принятия его, нажав на галочку. Это показывает более широкому сообществу, что вы нашли решение, и повышает репутацию как отвечающего, так и вас самих. Нет никаких обязательств делать это. - person Igor Khvostenkov; 15.02.2019
comment
Хвостенко, не волнуйся, я сделаю это в последний день щедрости Если не будет новых ответов - person Mark DeSpain; 15.02.2019