Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Nougat cannot show certain vector files (Resources$NotFoundException)

I have been working on an app that contains a number of vector graphics. Recently I started testing it on Nougat and found it crashing immediately. The logcat shows a Resources$NotFoundException while loading a vector which is reminiscent of all the AppCompat errors in earlier versions of Android with vector graphics. However, it runs fine on KitKat, Lollipop, and Marshmallow. It is only on Nougat that I am getting this error.

I have narrowed it down to a certain number of vector files that cause the exception, but I cannot see why they are different than the others I am using. All were generated from fairly simple SVGs from: http://inloop.github.io/svg2android/

My guess is that something has changed in the way they are creating drawables from vectors and for some reason these files are now causing an error so that the drawable is not created. When the library gets to putting the drawable on screen it cannot "find" the missing drawable because it has not been created. I am not sure what the extra check/restriction is on the vector file in Nougat.

Has anyone else experienced this? Any idea why? What has changed with Nougat's vector handling?

After experiencing the error and searching through other Vector errors, I updated my gradle settings to:

  • buildToolsVersion '25.0.3'
  • vectorDrawables.useSupportLibrary = true
  • compile 'com.android.support:appcompat-v7:25.4.0'
  • compile 'com.android.support:preference-v14:25.4.0'
  • compile 'com.android.support:recyclerview-v7:25.4.0'
  • compile 'com.android.support:design:25.4.0'

I have also included in the main class:

static {
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
    }

The logcat:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.MyApp.Application.MyAppApplication, PID: 4957
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.MyApp.Application.MyAppApplication/com.MyApp.Application.MyAppApplication.MyApp}: android.content.res.Resources$NotFoundException: Drawable com.MyApp.Application.MyAppApplication:drawable/icon_month with resource ID #0x7f0800da
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2646)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
    at android.app.ActivityThread.-wrap12(ActivityThread.java)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6077)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
                   Caused by: android.content.res.Resources$NotFoundException: Drawable com.MyApp.Application.MyAppApplication:drawable/icon_month with resource ID #0x7f0800da
                   Caused by: android.content.res.Resources$NotFoundException: File res/drawable/icon_month.xml from drawable resource ID #0x7f0800da
    at android.content.res.ResourcesImpl.loadDrawableForCookie(ResourcesImpl.java:725)
    at android.content.res.ResourcesImpl.loadDrawable(ResourcesImpl.java:571)
    at android.content.res.Resources.getDrawable(Resources.java:767)
    at android.content.Context.getDrawable(Context.java:525)
    at android.support.v4.content.ContextCompatApi21.getDrawable(ContextCompatApi21.java:30)
    at android.support.v4.content.ContextCompat.getDrawable(ContextCompat.java:372)
    at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:202)
    at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:190)
    at android.support.v7.content.res.AppCompatResources.getDrawable(AppCompatResources.java:100)
    at android.support.v7.widget.AppCompatImageHelper.setImageResource(AppCompatImageHelper.java:85)
    at android.support.v7.widget.AppCompatImageView.setImageResource(AppCompatImageView.java:92)
    at com.MyApp.Application.MyAppApplication.MyApp.onCreate(MyApp.java:233)
    at android.app.Activity.performCreate(Activity.java:6662)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2599)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
    at android.app.ActivityThread.-wrap12(ActivityThread.java)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6077)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
                   Caused by: java.lang.IllegalArgumentException: Path string cannot be empty.
    at android.util.PathParser.nCreatePathDataFromString(Native Method)
    at android.util.PathParser.-wrap1(PathParser.java)
    at android.util.PathParser$PathData.<init>(PathParser.java:74)
    at android.graphics.drawable.VectorDrawable$VFullPath.updateStateFromTypedArray(VectorDrawable.java:1556)
    at android.graphics.drawable.VectorDrawable$VFullPath.inflate(VectorDrawable.java:1507)
    at android.graphics.drawable.VectorDrawable.inflateChildElements(VectorDrawable.java:693)
    at android.graphics.drawable.VectorDrawable.inflate(VectorDrawable.java:598)
    at android.graphics.drawable.DrawableInflater.inflateFromXml(DrawableInflater.java:130)
    at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:1224)
    at android.graphics.drawable.Drawable.createFromXml(Drawable.java:1197)
E/AndroidRuntime:     at android.content.res.ResourcesImpl.loadDrawableForCookie(ResourcesImpl.java:715)
        ... 23 more

The beginning of the XML vector file (unable to post whole file):

    <?xml version="1.0" encoding="utf-8"?>
    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="100.000000dp"
        android:height="75.666667dp"
        android:viewportWidth="100.000000"
        android:viewportHeight="75.666667">

        <group
                android:translateY="75.666667"
                android:scaleX="0.003333"
                android:scaleY="-0.003333">
            <path
                android:fillColor="#000000"
                android:strokeWidth="1"
                android:pathData="M28898 22695 c-7 -7 -376 -19 -491 -16 -69 2 -113 -1 -122 -9 -14 -12 -296 -34
    -330 -26 -18 4 -170 7 -235 4 -14 0 -47 3 -75 7 -61 9 -223 9 -265 0 -19 -4 -36 -2
    -46 6 -12 10 -20 9 -39 -1 -20 -11 -35 -11 -77 -1 -38 9 -151 11 -404 8 -192 -2
    -354 -6 -360 -9 -5 -3 -103 -4 -217 -3 -115 1 -210 -2 -213 -7 -3 -5 -18 -6 -34 -3
    -23 5 -126 7 -310 5 -14 -1 -185 -1 -380 -1 -280 0 -567 -3 -705 -8 -5 -1 -35 1
    -65 3 -100 8 -183 7 -324 -2 -77 -5 -148 -7 -158 -4 -10 2 -18 -1 -18 -7 0 -14 -35
    -14 -76 1 -25 9 -39 9 -56 0 -13 -6 -81 -14 -153 -17 -71 -3 -195 -9 -275 -14 -80
    -5 -152 -10 -160 -10 -138 -6 -171 -10 -184 -24 -9 -9 -16 -20 -16 -26 0 -6 -4 -11
    -10 -11 -15 0 -12 21 7 42 16 18 14 19 -68 19 -121 0 -114 0 -234 -5 -113 -6 -236
    -11 -550 -22 -221 -8 -229 -9 -243 -18 -7 -4 -80 -7 -162 -8 -85 0 -153 -4 -156 -9
    -4 -6 -10 -6 -18 0 -6 5 -68 11 -136 11 -114 1 -181 -1 -371 -14 -36 -3 

....

Thanks!

Edit It seems like the issue is vector files with longer "pathData" entries (Number of paths does not seem to be the issue). The error seems to happen when the native JNI function GetStringUTFChars is called on a longer pathData entry and it returns an empty string which the parser cannot draw. I do not know if this is just a length thing nor why this works fine in the AppCompat libraries.

Current workarounds are 1) to use bitmaps for any vectors with long pathData or 2) to modify the xml files and split the pathData up into multiple paths (Thanks Lewis McGreary for the suggestion!).

Both require testing every vector graphic to determine which work and then individually modifying the drawables. This is not-ideal, especially for this particular app which chooses images from a large pool. Moving wholly to pngs is an option, but results in a larger apk and poorer scaling :(

Android source related to crash:

PathParser Java

PathParser JNI - here is the call to GetStringUTFChars

PathParser JNI Hwui - here is where the crash happens

like image 334
Emilie Avatar asked Jun 22 '17 23:06

Emilie


2 Answers

I found a workaround! It seems the problem is in AAPT2.

Adding:

android.enableAapt2 = false

To

gradle.properties
like image 195
Emilie Avatar answered Oct 24 '22 09:10

Emilie


In my case, the vector drawable xml file had path entries with empty pathData string. I removed these path entries and it is working.

Android Studio generated this faulty xml while importing from external svg file.

Open the vector drawable xml and remove / comment following lines.

<path
        android:pathData=""
        android:fillColor="#000000"/>
like image 45
Pawan Avatar answered Oct 24 '22 09:10

Pawan