Binary XML file line #17<vector> tag requires viewportWidth >0
来源:互联网 发布:曙光 hadoop大数据平台 编辑:程序博客网 时间:2024/06/06 01:48
- 前言
- 问题
- 原因
- 日志1
- 日志2
- 解决方案
- 方案1
- 方案2
- 方案3
- 方案4
- 总结
前言
近期把项目中的support包升级到了26.1.0,看起来在手机上运行的稳稳的,没翻船!之后提交,测试就报了一个bug说5.0以下的手机都不能运行了!因此就排查了问题原因。
问题
首先我们复现一下问题,看看崩溃日志,崩溃日志主要有以下两个:
E/VdcInflateDelegate: Exception while inflating <vector>org.xmlpull.v1.XmlPullParserException: Binary XML file line #17<vector> tag requires viewportWidth > 0 at android.support.graphics.drawable.VectorDrawableCompat.updateStateFromTypedArray(VectorDrawableCompat.java:690) at android.support.graphics.drawable.VectorDrawableCompat.inflate(VectorDrawableCompat.java:623) at android.support.graphics.drawable.VectorDrawableCompat.createFromXmlInner(VectorDrawableCompat.java:586) at android.support.v7.widget.AppCompatDrawableManager$VdcInflateDelegate.createFromXmlInner(AppCompatDrawableManager.java:777) at android.support.v7.widget.AppCompatDrawableManager.loadDrawableFromDelegates(AppCompatDrawableManager.java:365) at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:195) at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:188) at android.support.v7.widget.AppCompatDrawableManager.checkVectorDrawableSetup(AppCompatDrawableManager.java:755) at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:193) at android.support.v7.widget.TintTypedArray.getDrawableIfKnown(TintTypedArray.java:87) at android.support.v7.app.AppCompatDelegateImplBase.<init>(AppCompatDelegateImplBase.java:128) at android.support.v7.app.AppCompatDelegateImplV9.<init>(AppCompatDelegateImplV9.java:149) at android.support.v7.app.AppCompatDelegateImplV11.<init>(AppCompatDelegateImplV11.java:29) at android.support.v7.app.AppCompatDelegateImplV14.<init>(AppCompatDelegateImplV14.java:54) at android.support.v7.app.AppCompatDelegate.create(AppCompatDelegate.java:202) at android.support.v7.app.AppCompatDelegate.create(AppCompatDelegate.java:183) at android.support.v7.app.AppCompatActivity.getDelegate(AppCompatActivity.java:519) at com.xxx.common.activity.BaseActionBarActivity.installInflaterFactory(BaseActionBarActivity.java:192) at com.xxx.common.activity.BaseActionBarActivity.onCreate(BaseActionBarActivity.java:156) at com.xxx.activity.login.EntranceActivity.onCreate(EntranceActivity.java:64) at android.app.Activity.performCreate(Activity.java:5356) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1089) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2151) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2236) at android.app.ActivityThread.access$800(ActivityThread.java:138) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1199) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5122) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602) at dalvik.system.NativeStart.main(Native Method)
以及如下的错误,如下的错误会导致系统崩溃不能运行。
E/AndroidRuntime: FATAL EXCEPTION: mainProcess: com.xxx.debug, PID: 3565java.lang.RuntimeException: Unable to start activity ComponentInfo{com.xxx.debug/com.xxx.activity.login.EntranceActivity}: android.content.res.Resources$NotFoundException: File res/drawable/abc_vector_test.xml from drawable resource ID #0x7f020052at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2187)at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2236)at android.app.ActivityThread.access$800(ActivityThread.java:138)at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1199)at android.os.Handler.dispatchMessage(Handler.java:102)at android.os.Looper.loop(Looper.java:136)at android.app.ActivityThread.main(ActivityThread.java:5122)at java.lang.reflect.Method.invokeNative(Native Method)at java.lang.reflect.Method.invoke(Method.java:515)at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)at dalvik.system.NativeStart.main(Native Method)Caused by: android.content.res.Resources$NotFoundException: File res/drawable/abc_vector_test.xml from drawable resource ID #0x7f020052at android.content.res.Resources.loadDrawable(Resources.java:2124)at android.content.res.Resources.getDrawable(Resources.java:704)at android.support.v7.widget.VectorEnabledTintResources.superGetDrawable(VectorEnabledTintResources.java:74)at android.support.v7.widget.AppCompatDrawableManager.onDrawableLoadedFromResources(AppCompatDrawableManager.java:435)at android.support.v7.widget.VectorEnabledTintResources.getDrawable(VectorEnabledTintResources.java:67)at android.support.v4.content.ContextCompat.getDrawable(ContextCompat.java:353)at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:200)at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:188)at android.support.v7.widget.AppCompatDrawableManager.checkVectorDrawableSetup(AppCompatDrawableManager.java:755)at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:193)at android.support.v7.widget.TintTypedArray.getDrawableIfKnown(TintTypedArray.java:87)at android.support.v7.app.AppCompatDelegateImplBase.<init>(AppCompatDelegateImplBase.java:128)at android.support.v7.app.AppCompatDelegateImplV9.<init>(AppCompatDelegateImplV9.java:149)at android.support.v7.app.AppCompatDelegateImplV11.<init>(AppCompatDelegateImplV11.java:29)at android.support.v7.app.AppCompatDelegateImplV14.<init>(AppCompatDelegateImplV14.java:54)at android.support.v7.app.AppCompatDelegate.create(AppCompatDelegate.java:202)at android.support.v7.app.AppCompatDelegate.create(AppCompatDelegate.java:183)at android.support.v7.app.AppCompatActivity.getDelegate(AppCompatActivity.java:519)at com.xxx.common.activity.BaseActionBarActivity.installInflaterFactory(BaseActionBarActivity.java:192)at com.xxx.common.activity.BaseActionBarActivity.onCreate(BaseActionBarActivity.java:156)at com.xxx.activity.login.EntranceActivity.onCreate(EntranceActivity.java:64)at android.app.Activity.performCreate(Activity.java:5356)at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1089)at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2151)at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2236) at android.app.ActivityThread.access$800(ActivityThread.java:138) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1199) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5122) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602) at dalvik.system.NativeStart.main(Native Method) Caused by: org.xmlpull.v1.XmlPullParserException: Binary XML file line #17: invalid drawable tag vectorat android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:933)at android.graphics.drawable.Drawable.createFromXml(Drawable.java:877)at android.content.res.Resources.loadDrawable(Resources.java:2120)at android.content.res.Resources.getDrawable(Resources.java:704) at android.support.v7.widget.VectorEnabledTintResources.superGetDrawable(VectorEnabledTintResources.java:74) at android.support.v7.widget.AppCompatDrawableManager.onDrawableLoadedFromResources(AppCompatDrawableManager.java:435) at android.support.v7.widget.VectorEnabledTintResources.getDrawable(VectorEnabledTintResources.java:67) at android.support.v4.content.ContextCompat.getDrawable(ContextCompat.java:353) at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:200) at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:188) at android.support.v7.widget.AppCompatDrawableManager.checkVectorDrawableSetup(AppCompatDrawableManager.java:755) at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:193) at android.support.v7.widget.TintTypedArray.getDrawableIfKnown(TintTypedArray.java:87) at android.support.v7.app.AppCompatDelegateImplBase.<init>(AppCompatDelegateImplBase.java:128) at android.support.v7.app.AppCompatDelegateImplV9.<init>(AppCompatDelegateImplV9.java:149) at android.support.v7.app.AppCompatDelegateImplV11.<init>(AppCompatDelegateImplV11.java:29) at android.support.v7.app.AppCompatDelegateImplV14.<init>(AppCompatDelegateImplV14.java:54) at android.support.v7.app.AppCompatDelegate.create(AppCompatDelegate.java:202) at android.support.v7.app.AppCompatDelegate.create(AppCompatDelegate.java:183) at android.support.v7.app.AppCompatActivity.getDelegate(AppCompatActivity.java:519) at com.xxx.common.activity.BaseActionBarActivity.installInflaterFactory(BaseActionBarActivity.java:192) at com.xxx.common.activity.BaseActionBarActivity.onCreate(BaseActionBarActivity.java:156) at com.xxx.activity.login.EntranceActivity.onCreate(EntranceActivity.java:64) at android.app.Activity.performCreate(Activity.java:5356) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1089) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2151) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2236) at android.app.ActivityThread.access$800(ActivityThread.java:138) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1199) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5122) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602) at dalvik.system.NativeStart.main(Native Method)
原因
由于历史原因,以前做了很多分包的操作,因此gradle版本一直是1.2.3,不是当前最新的版本,因此写了一个Demo发现采用最新的版本不会出现崩溃。因此根据代码我们可以看到有如下执行路径:
日志1
Activity继承自AppCompatActivity,在Activity加载的时候会调用到getDelegate()函数:
@NonNullpublic AppCompatDelegate getDelegate() { if (mDelegate == null) { mDelegate = AppCompatDelegate.create(this, this); } return mDelegate;}
最终会调用到create函数:
private static AppCompatDelegate create(Context context, Window window, AppCompatCallback callback) { if (Build.VERSION.SDK_INT >= 24) { return new AppCompatDelegateImplN(context, window, callback); } else if (Build.VERSION.SDK_INT >= 23) { return new AppCompatDelegateImplV23(context, window, callback); } else if (Build.VERSION.SDK_INT >= 14) { return new AppCompatDelegateImplV14(context, window, callback); } else if (Build.VERSION.SDK_INT >= 11) { return new AppCompatDelegateImplV11(context, window, callback); } else { return new AppCompatDelegateImplV9(context, window, callback); }}
这里我们主要是5.0以下版本会崩溃,因此我们需要查看AppCompatDelegateImplV14,里面我们一直跟踪调用父类,最终会调用到如下的代码:
final TintTypedArray a = TintTypedArray.obtainStyledAttributes(context, null, sWindowBackgroundStyleable);final Drawable winBg = a.getDrawableIfKnown(0);
这里先解析是否有windowbackground属性,并且获取对应的drawable:
public Drawable getDrawableIfKnown(int index) { if (mWrapped.hasValue(index)) { final int resourceId = mWrapped.getResourceId(index, 0); if (resourceId != 0) { return AppCompatDrawableManager.get().getDrawable(mContext, resourceId, true); } } return null;}
这里recouseId不等于0,进入到AppCompatDrawableManager.中的getDrawable函数:
Drawable getDrawable(@NonNull Context context, @DrawableRes int resId, boolean failIfNotKnown) { checkVectorDrawableSetup(context); Drawable drawable = loadDrawableFromDelegates(context, resId); if (drawable == null) { drawable = createDrawableIfNeeded(context, resId); } if (drawable == null) { drawable = ContextCompat.getDrawable(context, resId); } if (drawable != null) { // Tint it if needed drawable = tintDrawable(context, resId, failIfNotKnown, drawable); } if (drawable != null) { // See if we need to 'fix' the drawable DrawableUtils.fixDrawable(drawable); } return drawable;}
getDrawable函数中首先调用了checkVectorDrawableSetup(context)函数:
private void checkVectorDrawableSetup(@NonNull Context context) { if (mHasCheckedVectorDrawableSetup) { // We've already checked so return now... return; } // Here we will check that a known Vector drawable resource inside AppCompat can be // correctly decoded mHasCheckedVectorDrawableSetup = true; final Drawable d = getDrawable(context, R.drawable.abc_vector_test); if (d == null || !isVectorDrawable(d)) { mHasCheckedVectorDrawableSetup = false; throw new IllegalStateException("This app has been built with an incorrect " + "configuration. Please configure your build for VectorDrawableCompat."); }}
我们发现上面有一个资源R.drawable.abc_vector_test,这个系统support包里的Vector资源,我们先来看看他的xml:
<?xml version="1.0" encoding="utf-8"?><vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportHeight="24.0" android:viewportWidth="24.0"> <path android:fillColor="@android:color/white" android:pathData="M20,11L7.8,11l5.6,-5.6L12,4l-8,8l8,8l1.4,-1.4L7.8,13L20,13L20,11z"/></vector>
我们继续往下看,这里初始状态为false,因此会继续往下执行,首先改为了true,并且继续调用了上面的getDrawable函数,因为这里改为了true,因此会进入的到getDrawable函数中的loadDrawableFromDelegates:
private Drawable loadDrawableFromDelegates(@NonNull Context context, @DrawableRes int resId) { if (mDelegates != null && !mDelegates.isEmpty()) { ............................ if (tv.string != null && tv.string.toString().endsWith(".xml")) { // If the resource is an XML file, let's try and parse it try { final XmlPullParser parser = res.getXml(resId); final AttributeSet attrs = Xml.asAttributeSet(parser); int type; while ((type = parser.next()) != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) { // Empty loop } if (type != XmlPullParser.START_TAG) { throw new XmlPullParserException("No start tag found"); } final String tagName = parser.getName(); // Add the tag name to the cache mKnownDrawableIdTags.append(resId, tagName); // Now try and find a delegate for the tag name and inflate if found final InflateDelegate delegate = mDelegates.get(tagName); if (delegate != null) { dr = delegate.createFromXmlInner(context, parser, attrs, context.getTheme()); } if (dr != null) { // Add it to the drawable cache dr.setChangingConfigurations(tv.changingConfigurations); if (addDrawableToCache(context, key, dr) && DEBUG) { Log.i(TAG, "[loadDrawableFromDelegates] Saved drawable to cache: " + context.getResources().getResourceName(resId)); } } } catch (Exception e) { Log.e(TAG, "Exception while inflating drawable", e); } } ............. return dr; } return null;}
这里我们先删除了部分代码,只看最重要的部分,那就是delegate.createFromXmlInner,实际调用的是VectorDrawableCompat
.createFromXmlInner(context.getResources(), parser, attrs, theme),继续调用createFromXmlInner中的inflate函数,inflate中继续调用到updateStateFromTypedArray:
private void updateStateFromTypedArray(TypedArray a, XmlPullParser parser) throws XmlPullParserException { final VectorDrawableCompatState state = mVectorState; final VPathRenderer pathRenderer = state.mVPathRenderer; // Account for any configuration changes. // state.mChangingConfigurations |= Utils.getChangingConfigurations(a); final int mode = TypedArrayUtils.getNamedInt(a, parser, "tintMode", AndroidResources.STYLEABLE_VECTOR_DRAWABLE_TINT_MODE, -1); state.mTintMode = parseTintModeCompat(mode, Mode.SRC_IN); final ColorStateList tint = a.getColorStateList(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_TINT); if (tint != null) { state.mTint = tint; } state.mAutoMirrored = TypedArrayUtils.getNamedBoolean(a, parser, "autoMirrored", AndroidResources.STYLEABLE_VECTOR_DRAWABLE_AUTO_MIRRORED, state.mAutoMirrored); pathRenderer.mViewportWidth = TypedArrayUtils.getNamedFloat(a, parser, "viewportWidth", AndroidResources.STYLEABLE_VECTOR_DRAWABLE_VIEWPORT_WIDTH, pathRenderer.mViewportWidth); pathRenderer.mViewportHeight = TypedArrayUtils.getNamedFloat(a, parser, "viewportHeight", AndroidResources.STYLEABLE_VECTOR_DRAWABLE_VIEWPORT_HEIGHT, pathRenderer.mViewportHeight); if (pathRenderer.mViewportWidth <= 0) { throw new XmlPullParserException(a.getPositionDescription() + "<vector> tag requires viewportWidth > 0"); } else if (pathRenderer.mViewportHeight <= 0) { throw new XmlPullParserException(a.getPositionDescription() + "<vector> tag requires viewportHeight > 0"); } pathRenderer.mBaseWidth = a.getDimension( AndroidResources.STYLEABLE_VECTOR_DRAWABLE_WIDTH, pathRenderer.mBaseWidth); pathRenderer.mBaseHeight = a.getDimension( AndroidResources.STYLEABLE_VECTOR_DRAWABLE_HEIGHT, pathRenderer.mBaseHeight); if (pathRenderer.mBaseWidth <= 0) { throw new XmlPullParserException(a.getPositionDescription() + "<vector> tag requires width > 0"); } else if (pathRenderer.mBaseHeight <= 0) { throw new XmlPullParserException(a.getPositionDescription() + "<vector> tag requires height > 0"); } // shown up from API 11. final float alphaInFloat = TypedArrayUtils.getNamedFloat(a, parser, "alpha", AndroidResources.STYLEABLE_VECTOR_DRAWABLE_ALPHA, pathRenderer.getAlpha()); pathRenderer.setAlpha(alphaInFloat); final String name = a.getString(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_NAME); if (name != null) { pathRenderer.mRootName = name; pathRenderer.mVGTargetsMap.put(name, pathRenderer); }}
这里调用TypedArrayUtils.getNamedFloat会去解析viewportWidth与viewportHeight:
public static float getNamedFloat(@NonNull TypedArray a, @NonNull XmlPullParser parser, @NonNull String attrName, @StyleableRes int resId, float defaultValue) { final boolean hasAttr = hasAttribute(parser, attrName); if (!hasAttr) { return defaultValue; } else { return a.getFloat(resId, defaultValue); }} public static boolean hasAttribute(@NonNull XmlPullParser parser, @NonNull String attrName) { return parser.getAttributeValue(NAMESPACE, attrName) != null;}
这里会发现viewportHeight与viewportWidth不存在,但是我们上面的xml里明明有这两个属性,为什么到这个地方就没有了?
gradle 1.2.3调用aapt编译资源,因为VectorDrawable是21才加入的,因此他不认识这两个属性,被优化掉了,同时优化掉的还有path中的内容
由于上面的原因,xml在编译后viewportWidth与viewportHeight会移除了,因此在解析的时候返回了0,系统检测该值,抛出了异常!
- 为什么23的版本不崩溃
23版本的内容未做检查,不会调用checkVectorDrawableSetup函数
日志2
上面有两个日志,第一个日志我们已经清楚了,只是抛出了异常,而不会导致崩溃,那为什么系统会崩溃,我们看到上面日志的下半部分与日志1相同,所以原因也是一样的,我们继续往下看loadDrawableFromDelegates解析失败后drawable为空,会继续执行createDrawableIfNeeded,这里只是对想要资源做了检查,因此最终会调用到ContextCompat.getDrawable中:
public static final Drawable getDrawable(Context context, @DrawableRes int id) { if (Build.VERSION.SDK_INT >= 21) { return context.getDrawable(id); } else if (Build.VERSION.SDK_INT >= 16) { return context.getResources().getDrawable(id); } else { // Prior to JELLY_BEAN, Resources.getDrawable() would not correctly // retrieve the final configuration density when the resource ID // is a reference another Drawable resource. As a workaround, try // to resolve the drawable reference manually. final int resolvedId; synchronized (sLock) { if (sTempValue == null) { sTempValue = new TypedValue(); } context.getResources().getValue(id, sTempValue, true); resolvedId = sTempValue.resourceId; } return context.getResources().getDrawable(resolvedId); }}
这里我们调用到context.getResources().getDrawable(id), 而5.0以上的版本会调用 context.getDrawable(id),这里的Resources是什么?我们在AppCompatActivity中有一个如下函数:
@Overridepublic Resources getResources() { if (mResources == null && VectorEnabledTintResources.shouldBeUsed()) { mResources = new VectorEnabledTintResources(this, super.getResources()); } return mResources == null ? super.getResources() : mResources;}
如果这里VectorEnabledTintResources.shouldBeUsed是true因此会进入到VectorEnabledTintResources, 如果为false调用系统,5.0以下的系统是不能解析Vector的因此这里我们需要让上面的条件为true,shouldBeUsed的代码如下 :
public static boolean shouldBeUsed() { return AppCompatDelegate.isCompatVectorFromResourcesEnabled() && Build.VERSION.SDK_INT <= MAX_SDK_WHERE_REQUIRED;}
这里条件2已经满足了,因此我们需要满足条件1,那条件1怎么满足,AppCompatDelegate有一个静态函数,我们可以再系统初始化的时候进行调用:
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
如果这里条件不满足,系统rescoures不认识该资源,系统崩溃,如果这里条件满足,那就会调用VectorEnabledTintResources的getDrawable函数:
@Overridepublic Drawable getDrawable(int id) throws NotFoundException { final Context context = mContextRef.get(); if (context != null) { return AppCompatDrawableManager.get().onDrawableLoadedFromResources(context, this, id); } else { return super.getDrawable(id);
这里context不为空,如果为空调用下面崩溃。这里继续调用AppCompatDrawableManager的onDrawableLoadedFromResources函数:
Drawable onDrawableLoadedFromResources(@NonNull Context context, @NonNull VectorEnabledTintResources resources, @DrawableRes final int resId) { Drawable drawable = loadDrawableFromDelegates(context, resId); if (drawable == null) { drawable = resources.superGetDrawable(resId); } if (drawable != null) { return tintDrawable(context, resId, false, drawable); } return null;}
这里我们看到了一个熟悉的函数,loadDrawableFromDelegates,这里下面就跟日志1一样,因为viewportWidth与viewportHeight不存在,导致出现日志2下班部分的异常,这里返回drawable为空,继续调用resources.superGetDrawable,进入系统resources调用,由于5.0以下版本解析不了vector TAG,具体调用代码如下:
public static Drawable createFromXmlInner(Resources r, XmlPullParser parser, AttributeSet attrs)throws XmlPullParserException, IOException { Drawable drawable; final String name = parser.getName(); if (name.equals("selector")) { drawable = new StateListDrawable(); } else if (name.equals("level-list")) { drawable = new LevelListDrawable(); } else if (name.equals("layer-list")) { drawable = new LayerDrawable(); } else if (name.equals("transition")) { drawable = new TransitionDrawable(); } else if (name.equals("color")) { drawable = new ColorDrawable(); } else if (name.equals("shape")) { drawable = new GradientDrawable(); } else if (name.equals("scale")) { drawable = new ScaleDrawable(); } else if (name.equals("clip")) { drawable = new ClipDrawable(); } else if (name.equals("rotate")) { drawable = new RotateDrawable(); } else if (name.equals("animated-rotate")) { drawable = new AnimatedRotateDrawable(); } else if (name.equals("animation-list")) { drawable = new AnimationDrawable(); } else if (name.equals("inset")) { drawable = new InsetDrawable(); } else if (name.equals("bitmap")) { //noinspection deprecation drawable = new BitmapDrawable(r); if (r != null) { ((BitmapDrawable) drawable).setTargetDensity(r.getDisplayMetrics()); } } else if (name.equals("nine-patch")) { drawable = new NinePatchDrawable(); if (r != null) { ((NinePatchDrawable) drawable).setTargetDensity(r.getDisplayMetrics()); } } else { throw new XmlPullParserException(parser.getPositionDescription() + ": invalid drawable tag " + name); } drawable.inflate(r, parser, attrs); return drawable;}
未解析vector标签,抛出异常,大于fileNotFound,该异常未被捕获,因此系统崩溃。
5.0以上版本,虽然viewportWidth与viewportHeight被擦除,但是可以解析vector标签,因此会生成对应的vectordrawable。
解决方案
上面的出现的种种问题怎么解决?主要有以下几种方案:
方案1
最正确的解法还是需要升级gradle,将gradle升级最新版本就可以了,只要能大于1.2.3就有解,首先在调用如下代码:
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
如果是1.5版本如下:
// Gradle Plugin 1.5 android { defaultConfig { generatedDensities = [] } // This is handled for you by the 2.0+ Gradle Plugin aaptOptions { additionalParameters "--no-version-vectors" } }
2.0版本如下:
// Gradle Plugin 2.0+ android { defaultConfig { vectorDrawables.useSupportLibrary = true } }
更新的版本啥都不用做。
方案2
如果因为种种原因不能升级gradle怎么办?也可以,我们可以用高版本打包,将Vector编译的资源拷贝出来,在低版本打包的时候进行覆盖。
该方案工作量太大,每次打包都必须覆盖,并且需要找到所有的vector资源
方案3
该方案是一个取巧的方案那就是不升级support包,只要在24以下,都未做检查,因此不会崩溃。
该方案的前提是自生应用中不能包含Vector资源,如有该方案行不通
如果必须升级support包,该方案也行不通
方案4
我们知道资源是在aapt中被移除的,怎么才能不移除,添加方案1中的参数,然而gradle1.2.3不识别该参数,怎么办?我们可以采用级联调用,我们在build-tool中新建aapt,重命名掉系统的aapt,由我们的aapt调用系统的aapt在调用时,添加对应的参数:
#!/bin/sh#ashap=$*#echo "input $*"#echo "xxx-test $*" >> /Users/asha/Library/Android/sdk/build-tools/25.0.2/cmd.txt/Users/xxxxx/Library/Android/sdk/build-tools/25.0.2/aapt-x $* "--no-version-vectors"exit $?#exit 0
这样就将对应的参数传递给了对应的aapt。
该方案必须要新建appt,让系统先调用到自己的,再调用到系统
总结
这次是因为系统的recyclerview有bug,必须升级所以才引发了这一系列的问题。总之升级gradle是王道。
- Binary XML file line #17<vector> tag requires viewportWidth >0
- org.xmlpull.v1.XmlPullParserException: Binary XML file line #17 tag requires viewportWidth > 0
- XmlPullParserException:<vector> tag requires viewportWidth > 0
- org.xmlpull.v1.XmlPullParserException: Binary XML file line #17<vector> tag requires vi
- 使用SDK23报错:Binary XML file line #17: invalid drawable tag vector
- 使用Material Design报错:Binary XML file line #17: invalid drawable tag vector
- org.xmlpull.v1.XmlPullParserException: Binary XML file line #19<gradient> tag requires 'gradientRadi
- Binary XML file line #4: <item> tag requires a 'drawable' attribute or child tag defining a drawable
- Binary XML file line #3: <item> tag requires a 'drawable' attribute or child tag defining a drawable
- Caused by: org.xmlpull.v1.XmlPullParserException: Binary XML file line #17: invalid drawable tag vec
- Caused by: org.xmlpull.v1.XmlPullParserException: Binary XML file line #17: invalid drawable tag vec
- Binary XML file line #13: Duplicate id 0x7f070055, tag null, or parent id 0x7f070054 with another fr
- android.view.InflateException: Binary XML file line #17: Binary XML file line #17: Error inflating c
- binary xml file line错误
- Binary XML file line #34
- Exception raised during rendering: Binary XML file line #-1: No start tag found!
- Binary XML file line #0: Error inflating class TextView
- android.view.InflateException: Binary XML file line
- 在CentOS7上安装docker
- thinkPHP5 表单提交接收数据验证
- Sublime Text 3 安装插件管理 Package Control
- 迁移oracle数据文件
- 设计模式17-责任链模式
- Binary XML file line #17<vector> tag requires viewportWidth >0
- 征信明明很好,贷款却栽在综合评分上,这货从哪里冒出来的?
- Android Gradle 插件 3.0 挖坑日记
- 集合
- VC++动态链接库编程之MFC DLL
- Struts2中,三种获取ServletAPI的方法
- python 列表,字典 ,集合推导
- kafka
- vi02