androidsvg: Invalid Layer Save Flag - only ALL_SAVE_FLAGS is allowed

I am getting the exception below occasionally when trying to execute the following code with compileSdkVersion 28 and Java 7. I am using com.caverock:androidsvg:1.2.1.

GlideApp.with(context)
                .as(PictureDrawable.class)
                .listener(new SvgSoftwareLayerSetter())
                .load("http://example.com/foo.svg")
                .into(target);
public class SvgDrawableTranscoder implements ResourceTranscoder<SVG, PictureDrawable> {
    @Nullable
    @Override
    public Resource<PictureDrawable> transcode(@NonNull Resource<SVG> toTranscode,
                                               @NonNull Options options) {
        SVG svg = toTranscode.get();
        Picture picture = svg.renderToPicture();
        PictureDrawable drawable = new PictureDrawable(picture);
        return new SimpleResource<>(drawable);
    }
}
public class SvgDecoder implements ResourceDecoder<InputStream, SVG> {

    @Override
    public boolean handles(@NonNull InputStream source, @NonNull Options options) {
        return true;
    }

    public Resource<SVG> decode(@NonNull InputStream source, int width, int height,
                                @NonNull Options options)
            throws IOException {
        try {
            SVG svg = SVG.getFromInputStream(source);
            return new SimpleResource<>(svg);
        } catch (SVGParseException ex) {
            throw new IOException("Cannot load SVG from stream", ex);
        }
    }
}

@GlideModule
public class SvgModule extends AppGlideModule {
    @Override
    public void registerComponents(@NonNull Context context, @NonNull Glide glide,
                                   @NonNull Registry registry) {
        registry.register(SVG.class, PictureDrawable.class, new SvgDrawableTranscoder())
                .append(InputStream.class, SVG.class, new SvgDecoder());
    }

    // Disable manifest parsing to avoid adding similar modules twice.
    @Override
    public boolean isManifestParsingEnabled() {
        return false;
    }
}

Exception:

07-12 22:20:14.474 10798-10847/com.example.n1try.myapp E/GlideExecutor: Request threw uncaught throwable
    java.lang.IllegalArgumentException: Invalid Layer Save Flag - only ALL_SAVE_FLAGS is allowed
        at android.graphics.Canvas.checkValidSaveFlags(Canvas.java:378)
        at android.graphics.Canvas.saveLayerAlpha(Canvas.java:555)
        at com.caverock.androidsvg.SVGAndroidRenderer.pushLayer(SVGAndroidRenderer.java:677)
        at com.caverock.androidsvg.SVGAndroidRenderer.render(SVGAndroidRenderer.java:982)
        at com.caverock.androidsvg.SVGAndroidRenderer.render(SVGAndroidRenderer.java:298)
        at com.caverock.androidsvg.SVGAndroidRenderer.renderChildren(SVGAndroidRenderer.java:330)
        at com.caverock.androidsvg.SVGAndroidRenderer.render(SVGAndroidRenderer.java:584)
        at com.caverock.androidsvg.SVGAndroidRenderer.renderDocument(SVGAndroidRenderer.java:267)
        at com.caverock.androidsvg.SVG.renderToPicture(SVG.java:306)
        at com.caverock.androidsvg.SVG.renderToPicture(SVG.java:286)
        at com.example.n1try.myapp.utils.svg.SvgDrawableTranscoder.transcode(SvgDrawableTranscoder.java:26)
        at com.bumptech.glide.load.engine.DecodePath.decode(DecodePath.java:47)
        at com.bumptech.glide.load.engine.LoadPath.loadWithExceptionList(LoadPath.java:58)
        at com.bumptech.glide.load.engine.LoadPath.load(LoadPath.java:43)
        at com.bumptech.glide.load.engine.DecodeJob.runLoadPath(DecodeJob.java:501)
        at com.bumptech.glide.load.engine.DecodeJob.decodeFromFetcher(DecodeJob.java:472)
        at com.bumptech.glide.load.engine.DecodeJob.decodeFromData(DecodeJob.java:458)
        at com.bumptech.glide.load.engine.DecodeJob.decodeFromRetrievedData(DecodeJob.java:410)
        at com.bumptech.glide.load.engine.DecodeJob.onDataFetcherReady(DecodeJob.java:379)
        at com.bumptech.glide.load.engine.DataCacheGenerator.onDataReady(DataCacheGenerator.java:95)
        at com.bumptech.glide.load.model.FileLoader$FileFetcher.loadData(FileLoader.java:76)
        at com.bumptech.glide.load.engine.DataCacheGenerator.startNext(DataCacheGenerator.java:75)
        at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:302)
        at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:269)
        at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:233)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)
        at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory$1.run(GlideExecutor.java:446)

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 19 (9 by maintainers)

Commits related to this issue

Most upvoted comments

AndroidSVG uses the method Canvas.save(int flags) to implement clip path support on pre-Kit Kat devices. It was previously used for all versions of Android, but I created a new implementation for clip paths in v1.3 that uses APIs that are only available since Kit Kat.

In Android 27 they deprecated the Canvas.save(int flags) method and most of the flag values. That was fair enough. The new versions of Skia (the underlying library that Android uses for 2D graphics), no longer support the version of save() that take flags.

Unfortunately, in Android 28, they seem to have taken the additional step of removing that save() method entirely. That means that the library cannot be compiled with compile/targetSdkVersion set to 28.

If this doesn’t change, I will either have to:

  • stick at SDK 27 and not take advantage of any new features that get added to Android in the future, or
  • remove the old code and drop support for pre-Kit Kat devices (around 5% of users still).

If you want to help get Android to reverse their decision, please take the time to star the following bug ticket. And maybe add a supporting comment about how it would affect you if they don’t. Please be polite.

https://issuetracker.google.com/issues/110856542

In the meantime, you can migrate to the upcoming version 1.3 of AndroidSVG. Instructions on how you can use the snapshot release of 1.3 can be found on the 1.3 release notes page as @devemux86 said.

Thanks, Paul