2017-06-22 47 views
6

Pracuję nad aplikacją zawierającą wiele grafiki wektorowej. Niedawno zacząłem testować go na Nougat i natychmiast znalazłem awarię. Logcat pokazuje wyjątek Resources $ NotFoundException podczas ładowania wektora, który przypomina wszystkie błędy AppCompat we wcześniejszych wersjach Androida z grafiką wektorową. Jednak działa dobrze na KitKat, Lollipop i Marshmallow. Tylko na Nougacie dostaję ten błąd.

Zawęziłem go do pewnej liczby plików wektorowych, które powodują wyjątek, ale nie widzę, dlaczego są inne niż inne, których używam. Wszystkie zostały wygenerowane z dość prostych plików SVG z: http://inloop.github.io/svg2android/

Domyślam się, że coś się zmieniło w sposobie, w jaki tworzą rysunki z wektorów iz jakiegoś powodu pliki te powodują teraz błąd, więc nie można utworzyć wyciągu. Gdy biblioteka pobiera nakładkę na ekranie, nie może "znaleźć" brakującego szuflady, ponieważ nie została ona utworzona. Nie jestem pewien, jakie dodatkowe kontrole/ograniczenia dotyczą pliku wektorowego w Nougat.

Czy ktoś jeszcze tego doświadczył? Każdy pomysł, dlaczego? Co się zmieniło w obsłudze wektorowej Nougat?

Po doświadczeniu błąd i przeszukując innych błędów Wektor, zaktualizowałem moje ustawienia do Gradle:

  • buildToolsVersion '25 .0.3'
  • vectorDrawables.useSupportLibrary = true
  • kompilacji „com.android Wspomóż: AppCompat-v7: 25.4.0'
  • kompilacji 'com.android.support:preference-v14:25.4.0'
  • kompilacji 'com.android.support:recyclerview-v7:25.4.0'
  • kompilacji 'com.android.support:design:25.4.0'

Mam również w głównej klasie:

static { 
     AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); 
    } 

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 

Początek pliku wektorowego XML (nie można opublikować całego pliku):

<?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 

.... 

Dzięki!

Edit Wydaje się, że problem jest wektorowe z dłuższymi „pathData” zgłoszeń (liczba ścieżek nie wydaje się być problem). Wydaje się, że błąd występuje, gdy natywna funkcja JNI funkcji GetStringUTFChars jest wywoływana na dłuższym wpisie pathData i zwraca pusty ciąg, którego parser nie może narysować. Nie wiem, czy to jest tylko kwestia długości i dlaczego to działa dobrze w bibliotekach AppCompat.

Obecne obejścia: 1) użycie bitmap dla dowolnych wektorów z długimi pathData lub 2) w celu zmodyfikowania plików xml i podzielenia pathData na wiele ścieżek (dziękuję Lewisowi McGreary za sugestię!).

Obie wymagają przetestowania każdej grafiki wektorowej w celu określenia, która praca, a następnie indywidualnie modyfikując rysunki. To nie jest idealne, szczególnie w przypadku tej konkretnej aplikacji, która wybiera zdjęcia z dużej puli.Przeniesienie całości do PNG jest opcją, ale wyniki w większej apk i gorszą skalowania :(

Android źródło związane z katastrofą:

PathParser Java

PathParser JNI - here is the call to GetStringUTFChars

PathParser JNI Hwui - here is where the crash happens

+1

Nie wiem, co rzeczywistą przyczyną jest tutaj, ale mogę powiedzieć, że podczas korzystania z biblioteki Support - Nougat (API 24) i w górę to deleguje do ramowej wersji VectorDrawable, a dla API 23 w dół używa wersji biblioteki wsparcia. –

+0

To pomaga. Więcej kopania i wydaje się, że 24+ Api dławi na dłuższych ciągach pathData, podając powyższy błąd "Ciąg znaków nie może być pusty". Nie mogłem znaleźć odpowiedniego źródła dla renderowania wektorowego. Dotyczy to również grafiki wektorowej utworzonej w Android Studio przy użyciu wbudowanego Vector Studio. Stworzyłem tylko nowy Nougat, bez biblioteki wsparcia, projekt z takim samym wynikiem. Najwyraźniej biblioteka pomocnicza wykonuje lepszą pracę renderowania wektorów z długimi ścieżkami, ale co robić pratycznie? Przetestuj wszystkie wektory na nougacie? Czy mogę zmusić Nougat do korzystania z biblioteki wsparcia? – Emilie

+2

Nie jestem pewien, czy możesz wymusić użycie biblioteki pomocy technicznej. Jeśli problemem jest dłuższy pathData, a w zależności od konkretnego obrazu, rozdzielenie pojedynczej ścieżki na wiele krótszych elementów '' może być rozwiązaniem. Dlatego szczególnie, jeśli obraz ma wiele elementów w jednej ścieżce, polecenie "M" na części będzie dobrym miejscem do wycinania/wklejania do nowej ścieżki. –

Odpowiedz

2

Znalazłem obejście! Wygląda na to, że problem dotyczy AAPT2.

dodania:

android.enableAapt2 = false 

Aby

gradle.properties 
+0

Czy ma to jakieś skutki uboczne? – thailey01

+0

Powyższe rozwiązanie nie działa dla mnie, ponieważ pojawia się błąd, gdy następuje 'gradle sync'. Domyślam się, że najlepszym rozwiązaniem byłoby zoptymalizowanie twojego wektorowego losowania. Prawdopodobnie SVGO mógłby w pewnym stopniu pomóc https://github.com/svg/svgo – karthikk

0

mam nie ma innego rozwiązania niż te 2 wspomniane przez Ciebie. Wydaje się jednak, że ten problem został naprawiony w systemie Android 7.1