Search code examples
androidimagepicasso

Using Picasso with Image Getter


I ma building a chat application and I am attempting to append an image to an EditText, through use of Picasso to get the image from a URL and the append and ImageGetter to attach the image to the EditText. However, what I have implemented below does not work, as appending messages when using the app displays nothing (but the message does show up in the database).

I have tested without using Picasso, as simply just using the ImageGetter with an image resource within the app works just fine, only it's not from a URL as is required.

What is the proper way to configure the ImageGetter and/or the append method so that this functionality will work with Picasso? Or is there a simpler way?

Append method:

public void appendToMessageHistory(final String username,
            final String message) {
        if (username != null && message != null) {

            Picasso.with(getBaseContext())
                    .load("http://localhost:3000/uploads/campaign/image/2/2.jpg")
                    .into(new Target() {

                        @Override
                        public void onPrepareLoad(Drawable arg0) {

                        }

                        @Override
                        public void onBitmapLoaded(Bitmap bitmap,
                                LoadedFrom arg1) {
                            Drawable drawImage = new BitmapDrawable(
                                    getBaseContext().getResources(), bitmap);

                            drawImage.setBounds(0, 0,
                                    drawImage.getIntrinsicHeight(),
                                    drawImage.getIntrinsicWidth());
                            messageHistoryText.append(Html.fromHtml("<b>"
                                    + username + ":" + "</b>" + "<br>"));
                            messageHistoryText.append(Html.fromHtml(message
                                    + "<hr>" + "<br>")
                                    + System.getProperty("line.separator") + "");

                            messageHistoryText.append(Html
                                    .fromHtml("<img src = '" + drawImage
                                            + "'/>",
                            imageGetter,
                            null));
                        }

                        @Override
                        public void onBitmapFailed(Drawable arg0) {

                        }
                    });

        }
    }

ImageGetter:

ImageGetter imageGetter = new ImageGetter() {
        Drawable imageUsed=null;

        @Override
        public Drawable getDrawable(String source) {

            Picasso.with(getBaseContext())
                    .load("http://localhost:3000/uploads/campaign/image/2/2.jpg")
                    .into(new Target() {

                        @Override
                        public void onPrepareLoad(Drawable arg0) {

                        }

                        @Override
                        public void onBitmapLoaded(Bitmap bitmap,
                                LoadedFrom arg1) {
                            Drawable drawImage = new BitmapDrawable(
                                    getBaseContext().getResources(), bitmap);

                            drawImage.setBounds(0, 0,
                                    drawImage.getIntrinsicHeight(),
                                    drawImage.getIntrinsicWidth());

                            imageUsed=drawImage;

                        }

                        @Override
                        public void onBitmapFailed(Drawable arg0) {

                        }
                    });

            return imageUsed;
        }

    };

Solution

  • I couldn't get it to work with using Picasso's Target...

    My workaround is:

    • use an AsyncTask for concurrency
    • use Picasso's get() method to load the image synchronously in the AsyncTask's background method

    Like this:

    public class PicassoImageGetter implements Html.ImageGetter {
    
    final Resources resources;
    
    final Picasso pablo;
    
    final TextView textView;
    
    public PicassoImageGetter(final TextView textView, final Resources resources, final Picasso pablo) {
        this.textView  = textView;
        this.resources = resources;
        this.pablo     = pablo;
    }
    
    @Override public Drawable getDrawable(final String source) {
        final BitmapDrawablePlaceHolder result = new BitmapDrawablePlaceHolder();
    
        new AsyncTask<Void, Void, Bitmap>() {
    
            @Override
            protected Bitmap doInBackground(final Void... meh) {
                try {
                    return pablo.load(source).get();
                } catch (Exception e) {
                    return null;
                }
            }
    
            @Override
            protected void onPostExecute(final Bitmap bitmap) {
                try {
                    final BitmapDrawable drawable = new BitmapDrawable(resources, bitmap);
    
                    drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
    
                    result.setDrawable(drawable);
                    result.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
    
                    textView.setText(textView.getText()); // invalidate() doesn't work correctly...
                } catch (Exception e) {
                    /* nom nom nom*/
                }
            }
    
        }.execute((Void) null);
    
        return result;
    }
    
    static class BitmapDrawablePlaceHolder extends BitmapDrawable {
    
        protected Drawable drawable;
    
        @Override
        public void draw(final Canvas canvas) {
            if (drawable != null) {
                drawable.draw(canvas);
            }
        }
    
        public void setDrawable(Drawable drawable) {
            this.drawable = drawable;
        }
    
    }
    

    Hope this is useful.