i am using glide with androidsvg lib as shown in the sample code , i have a .svg file on the server and this file is having image tag like this -
image x="185" y="83" width="1139" height="98" xlink:href="https://s3-a-1.amazonaws.com/*************/*****/1/img/1.png" /
i have many image tags like this in this .svg file from server , i am able to see this .svg file with all the images filled and in perfect condition in any web browser and even in the android browser or a android web view too , but i want to render this .svg in my imageview using glide as shown in the sample but anyhow i am able to render text in the .svg without any problem with missing images
my code looks like this --->
requestBuilder = Glide.with(this)
.using(Glide.buildStreamModelLoader(Uri.class, this), InputStream.class)
.from(Uri.class)
.as(SVG.class)
.transcode(new SvgDrawableTranscoder(), PictureDrawable.class)
.sourceEncoder(new StreamEncoder())
.cacheDecoder(new FileToStreamDecoder<SVG>(new SvgDecoder()))
.decoder(new SvgDecoder())
.placeholder(R.drawable.image_loading)
.error(R.drawable.image_error)
.animate(android.R.anim.fade_in)
.listener(new SvgSoftwareLayerSetter<Uri>());
Uri uri = Uri.parse("https://s3-ap-southeast-1.amazonaws.com/*******/#######/1.svg");
requestBuilder
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
// SVG cannot be serialized so it's not worth to cache it
.load(uri)
.into(imageViewNet);
and one more thing i want to specify is that i am using this image view in list item to render multiple .svg files which have been converted from .pdf and let me tell that these .svg's converted are working fine on web.
any help would be appreciated , i am pretty messed up ;)
thanks ,
Vinay
I think that's a problem with AndroidSVG, Glide doesn't know anything about SVG files, that's why you need to write your own decoder/transcoder/etc...
In the documention it says:
<image>Embed an image 1.0 Fully supported for bitmaps only (including data URLs). Embedding of external SVG documents is not supported.
I think this means that if you embed those png files with data:image/png;base64,... it'll work, but AndroidSVG is not capable of fetching any external HTTP(S) Uri images.
@BigBadaboom can you weigh in please?
AndroidSVG handles DataURIs itself, but if your <image> element points to anything outside of the SVG file, you need to give it some assistance.
You do that by creating an implementation of the SVGExternalFileResolver class and register your class with AndroidSVG using SVG.registerExternalFileResolver().
When any <image> element is encountered, AndroidSVG calls the resolveImage() method with the image URL. You will need to use whichever HTTP client library you prefer to fetch and return the image data as a Bitmap.
@BigBadaboom Ah, cool, thank you very much!
@hashtaag-vinay-sasalatti you can try to implement that resolver with sync Glide loading if you want:
Glide.with(context).load(url).asBitmap().diskCacheStrategy(SOURCE).into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL).get();
thanks for the update guys , really appreciate this concern , i will try this approach and keep you guys posted .
Cheers,
Vinay
thanks guys @TWiStErRob , @BigBadaboom
i used SVGExternalFileResolver class with SVG.registerExternalFileResolver() and i got my solution and am able to render the whole .svg with embedded image http(s) urls now .
PS - Appreciate all the help ;)
cheers,
Vinay
If you can, I think it would be a good idea to share your resolver (or the core of it) in case someone finds this issue facing the same problem.
Sure @TWiStErRob , this below is my working solution and i am sharing it ;P
I have created a requestBuilder in my android Activity like below.
private GenericRequestBuilder<Uri, InputStream, SVG, PictureDrawable> requestBuilder;
requestBuilder = Glide
.with(this)
.using(Glide.buildStreamModelLoader(Uri.class, this), InputStream.class)
.from(Uri.class)
.as(SVG.class)
.transcode(new SvgDrawableTranscoder(), PictureDrawable.class)
.sourceEncoder(new StreamEncoder())
.cacheDecoder(new FileToStreamDecoder<SVG>(new **SvgDecoder**()))
.decoder(new SvgDecoder())
.placeholder(R.drawable.image_loading)
.error(R.drawable.image_error)
.animate(android.R.anim.fade_in)
.listener(new SvgSoftwareLayerSetter<Uri>());
Uri uri = Uri.parse("https://s3-ap-southeast-1.amazonaws.com/*******/*****/1.svg");
requestBuilder
// SVG cannot be serialized so it's not worth to cache it
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.load(uri)
.into(imageViewNet);
I have a custom SvgDecoder as shown below which is referring to my implementation of SVGExternalFileResolver (which is SvgFileResolver below).
public class SvgDecoder implements ResourceDecoder<InputStream, SVG> {
private SvgFileResolver svgFileResolver;
public Resource<SVG> decode(InputStream source, int width, int height) throws IOException {
svgFileResolver = new SvgFileResolver();
try {
SVG svg = SVG.getFromInputStream(source);
svg.registerExternalFileResolver(svgFileResolver);
return new SimpleResource<SVG>(svg);
} catch (SVGParseException ex) {
throw new IOException("Cannot load SVG from stream", ex);
}
}
@Override
public String getId() {
return "SvgDecoder.com.bumptech.svgsample.app";
}
}
and this is my implementation of SVGExternalFileResolver:
public class SvgFileResolver extends SVGExternalFileResolver {
@Override public Bitmap resolveImage(String filename) {
return getBitmapFromURL(filename);
}
public static Bitmap getBitmapFromURL(String src) {
try {
URL url = new URL(src);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return myBitmap;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
Here in the above class filename is the http(s) remote path for the image and i am getting a bitmap object from this method here getBitmapFromURL and returning it from resolveImage method.
This is the magical code to render the image tag referring to a remote image source in the .svg source file.
This is a basic implementation in above code and I am using a similar implementation for have a list of svg's in my recycler view.
All thanks to @TWiStErRob and @BigBadaboom who helped me out.
Cheers,
Vinay Sasalatti
Thanks for sharing! I formatted it for you.
Note to future readers: This is a very basic implementation, it's worth considering using some proper networking (OkHttp, Volley, etc) to be able to cache those images, because every time an SVG is displayed these images are retrieved through the network, the asBitmap().....get() above is another option.
I am not able to resolve it
GenericRequestBuilder
even i added the libraries
implementation files('libs/androidsvg-1.2.1.jar')
compile 'com.github.bumptech.glide:glide:4.2.0'
can someone please help me..please.......
@DaminiBansal the answers here are for Glide v3. You need v3.8.0 or you need to adapt the solution here for Glide v4 (should be relatively straight forward).
Most helpful comment
Thanks for sharing! I formatted it for you.
Note to future readers: This is a very basic implementation, it's worth considering using some proper networking (OkHttp, Volley, etc) to be able to cache those images, because every time an SVG is displayed these images are retrieved through the network, the
asBitmap().....get()above is another option.