1

I'm trying to use Glide to get a SVG resource from a URL, but I don't know how to get a Bitmap object instead of loading it in into a View.
The reason for that is that I need to load some SVG files on a Widget.

I used this example: https://stackoverflow.com/a/30938082/3346625

UPDATE 1: Setup GenericRequestBuilder

            final RemoteViews fViews = views;
            final int fViewId = viewId;

            Runnable myRunnable = new Runnable() {
                @Override
                public void run() {

                    GenericRequestBuilder<Uri, InputStream, SVG, Bitmap> requestBuilder;

                    requestBuilder = Glide.with(mContext)
                            .using(Glide.buildStreamModelLoader(Uri.class, mContext), InputStream.class)
                            .from(Uri.class)
                            .as(SVG.class)
                            .transcode(new SvgBitmapTranscoder(), Bitmap.class)
                            .sourceEncoder(new StreamEncoder())
                            .cacheDecoder(new FileToStreamDecoder<SVG>(new SvgDecoder()))
                            .decoder(new SvgDecoder())
                            .placeholder(R.drawable.ic_launcher)
                            .error(R.drawable.no_icon)
                            .diskCacheStrategy(DiskCacheStrategy.SOURCE)
                            .load(Uri.parse(url));

                    requestBuilder.into(new SimpleTarget<Bitmap>() {
                                @Override
                                public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
                                    fViews.setImageViewBitmap(fViewId, resource);
                                }
                            });
                }
            };
            mainHandler.post(myRunnable);
  • I had to use a Runnable as requestBuilder.into needs to run on the main thread.

How can I get a Bitmap to later use it with a RemoteView?

Community
  • 1
  • 1
Carlos Jimenez
  • 114
  • 1
  • 14
  • Wait a moment, if you're already off main, why do you want to use Glide? It's probably easier to just get a network stream and decode the SVG yourself. Or if you're already on main, why do you post to main? – TWiStErRob Oct 01 '15 at 21:18
  • I also did it, ran an AsyncTask, got the svg file and then used the SVG parser but came to the same issue, images are not displayed. Don't know if it's because i have to use RemoveViews as final. – Carlos Jimenez Oct 01 '15 at 21:22
  • Then it sounds like you have a totally different problem. The key is that you have to have `views.setImageViewBitmap` execute sooner than `manager.updateAppWidget(ids, views)`. Currently it looks like you fire off the Runnable which then fires off an async Glide load, and immediately after that you call `updateAppWidget`, not even giving a chance for either the Runnable nor the Glide request to complete. Which means the `manager` receives the views without the Bitmap set, updates the widget(s) and then sometime later the real Bitmap is set to RemoteViews, but that'll be just garbage collected. – TWiStErRob Oct 01 '15 at 21:39
  • You might be right but I have PNG images which are loaded correctly via Glide and setImageViewBitmap, in that case i assume Glide is also coming back with the resources after updateAppWidget is called. – Carlos Jimenez Oct 01 '15 at 21:57
  • Maybe, but that can be just luck, or a memory cache hit, which is like an immediate load. Try putting a `.skipMemoryCache(true).diskCacheStrategy(NONE)` to that Glide load to prove that it'll work in all cases, most importantly the first one after install. As another check for SVG, you can try to save the Bitmap to disk (`bmp.compress(Bitmap.CompressFormat.PNG, 100, new FileOutputStream(filename))`) to see if it has any content at all, what you'd expect. – TWiStErRob Oct 01 '15 at 22:03
  • When using skipMemoryCache and diskCacheStrategy NONE, it loads fine but it shows some IBinder null pointer exceptions sometimes. Also validated that the code i'm using saves the bitmap correctly to disk, all images are downloaded fine but not shown on the collection widget. – Carlos Jimenez Oct 02 '15 at 12:51
  • I just noticed you said "collection widget", if you're referring to [this](https://developer.android.com/guide/topics/appwidgets/index.html#collections) then still the above should apply, that is `setImageViewBitmap` must be called before returning the `RemoteViews` from `getViewAt()`, which may be problematic. – TWiStErRob Oct 02 '15 at 16:12
  • An idea on how to deliver Bitmaps to collection widget: Create a model class that holds the Url and the image Bitmap and make loading the images part of populating the collection, that is don't tell the widget the adapter data is ready until all Bitmaps are loaded. This means that you need to fill the model's image field by the time `getViewAt` is called, so that Bitmap can be set simply synchronously inside the method. – TWiStErRob Oct 02 '15 at 16:31

1 Answers1

1

Try this:

.transcode(new SvgBitmapTranscoder(), Bitmap.class)

.into(new SimpleTarget<Bitmap>(sizeW, sizeH) {
    @Override public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
        // update RemoteViews with resource
    }
})

SvgBitmapTranscoder should be fairly trivial if there's an svg.renderToBitmap() method.

TWiStErRob
  • 44,762
  • 26
  • 170
  • 254
  • It doesn't work, I updated the original question with the code i used according to your suggestion. – Carlos Jimenez Oct 01 '15 at 21:04
  • 2
    To whom it may concern: based on the comments above this solution is workable in general ("Also validated that the code i'm using saves the bitmap correctly to disk"), the problem seems to be delivering the resulting Bitmap to an app widget. – TWiStErRob Oct 02 '15 at 16:18