Android 配置子Module混淆时遇到的错误,和一些零散技术点总结

概要说明:
1、子Module不能配置混淆,仅仅只能在主Module中配置混淆。
2、主Module配置了混淆,打包成apk后,其他Module的代码也会一起混淆。
3、所有Module中的res目录下的资源都会在打包时合并到主Module的res目录下对应文件位置。
4、所有被主Module直接或间接引用了的Module,在打包时,其AndroidManifest.xml文件都会合并到主Module的AndroidManifest.xml文件中。
5、手机横竖屏时寻找layout目录的规则。
6、手机横竖屏时的宽度dp值和高度dp值。
7、注意textView.setTextSize(size)函数的代码,size的单位



Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
> Compilation failed; see the compiler error output for details.
Android 配置子Module混淆时遇到的错误,和一些零散技术点总结
文章图片


上面错误导致的原因是所有子Module都不能配置混淆,即minifyEnabled true。如果需要,也只能在主Module中配置。


在主Module中配置了混淆,打包时会作用在所有的Module上,即其他的Module的代码也会被混淆。
所有Module下res目录中的内容也会合并到主Module的res对应目录和文件中。参考文章:http://blog.csdn.net/fesdgasdgasdg/article/details/78133821
所有被主Module直接或间接引用的子Module的AndroidManifest.xml文件,在打包时内容都会合并到主Module的AndroidManifest.xml文件中,
包括权限,注册的组件等






layout目录描述:
layout-port为竖屏时的布局目录。
layout-land为横屏时的布局目录。
layout为默认目录,即:
竖屏时,系统会首先寻找layout-port目录的布局,如果找不到则使用layout目录的布局;
横屏时,系统会首先寻找layout-land目录的布局,如果找不到则使用layout目录的布局。








我有个容器类的自定义控件ImageTextView,其内部包含了一个TextView。但是我想在容器级别上设置个自定义属性,获取字体大小imageTextSize,
1)、于是这么获取属性值:


imageTextSize = array.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, TEXT_SIZE, getResources().getDisplayMetrics()));

2)、然后这么设置
innerTextView.setTextSize(imageTextSize);

运行后看效果我就懵了,这么字体比普通的TextView字体大一倍?但是innerTextView.getTextSize()与普通的textView.getTextSize()值相等。奇葩。

分析发现:


imageTextSize = array.getDimensionPixelSize(attr,默认值);

看看默认值这个静态函数代码TypedValue.applyDimension():
public static float applyDimension(int unit, float value, DisplayMetrics metrics) { switch (unit) { case COMPLEX_UNIT_PX: return value; case COMPLEX_UNIT_DIP: return value * metrics.density; case COMPLEX_UNIT_SP: return value * metrics.scaledDensity; case COMPLEX_UNIT_PT: return value * metrics.xdpi * (1.0f/72); case COMPLEX_UNIT_IN: return value * metrics.xdpi; case COMPLEX_UNIT_MM: return value * metrics.xdpi * (1.0f/25.4f); } return 0; }


把TEXT_SIZE值当做sp单位,然后乘以了缩放比例。




在看看array.getDimensionPixelSize()函数代码:

public int getDimensionPixelSize(@StyleableRes int index, int defValue) { if (mRecycled) { throw new RuntimeException("Cannot make calls to a recycled instance!"); } final int attrIndex = index; index *= AssetManager.STYLE_NUM_ENTRIES; final int[] data = https://www.it610.com/article/mData; final int type = data[index+AssetManager.STYLE_TYPE]; if (type == TypedValue.TYPE_NULL) { return defValue; } else if (type == TypedValue.TYPE_DIMENSION) { return TypedValue.complexToDimensionPixelSize( data[index+AssetManager.STYLE_DATA], mMetrics); } else if (type == TypedValue.TYPE_ATTRIBUTE) { final TypedValue value = mValue; getValueAt(index, value); throw new UnsupportedOperationException("Failed to resolve attribute at index " + attrIndex + ": " + value); } throw new UnsupportedOperationException("Can't convert value at index " + attrIndex + " to dimension: type=0x" + Integer.toHexString(type)); }

【Android 配置子Module混淆时遇到的错误,和一些零散技术点总结】

调用了TypedValue.complexToDimensionPixelSize()函数,在深入看看这个函数代码:
public static int complexToDimensionPixelSize(int data, DisplayMetrics metrics) { final float value = https://www.it610.com/article/complexToFloat(data); final float f = applyDimension( (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK, value, metrics); final int res = (int)(f+0.5f); if (res != 0) return res; if (value =https://www.it610.com/article/= 0) return 0; if (value> 0) return 1; return -1; }


调用了TypedValue.applyDimension()代码,哈利路亚,这不又转回来了?乘以了缩放比例。

public static float applyDimension(int unit, float value, DisplayMetrics metrics) { switch (unit) { case COMPLEX_UNIT_PX: return value; case COMPLEX_UNIT_DIP: return value * metrics.density; case COMPLEX_UNIT_SP: return value * metrics.scaledDensity; case COMPLEX_UNIT_PT: return value * metrics.xdpi * (1.0f/72); case COMPLEX_UNIT_IN: return value * metrics.xdpi; case COMPLEX_UNIT_MM: return value * metrics.xdpi * (1.0f/25.4f); } return 0; }


也就是说(记住),我们通过array.getDimensionPixelSize(attr, 默认值)方式获取到的字体大小值,值经过转换后的pt值了,已经乘以了缩放比例。


我们在看看textView.setTextSize(size)函数代码:

public void setTextSize(float size) { setTextSize(TypedValue.COMPLEX_UNIT_SP, size); }


注意看两个参数,sp单位,系统认为size值是sp单位的,进入函数看:

public void setTextSize(int unit, float size) { Context c = getContext(); Resources r; if (c == null) r = Resources.getSystem(); else r = c.getResources(); setRawTextSize(TypedValue.applyDimension( unit, size, r.getDisplayMetrics())); }



最后一行调用了setRawTextSize()函数,括号内又调用了TypedValue.applyDimension()静态函数。shit,不多说了。是不是又把size当成sp值,再乘以了缩放比例?


进入setRawTextSize()函数看看系统拿到放大后的pt值怎么设置字体大小:


private void setRawTextSize(float size) { if (size != mTextPaint.getTextSize()) { mTextPaint.setTextSize(size); if (mLayout != null) { nullLayouts(); requestLayout(); invalidate(); } } }



搜迪斯嫩,设置到了画笔上(mTextPaint.setTextSize(size); ),然后重绘UI(requestLayout(); invalidate(); )立即生效。


总结这小节:
上例中,我们通过自定义属性获取到的字体值,已经是pt单位的了,此时要设置到textView上时,需要调用textView.getPaint().setTextSize()进行设置。
在自定义属性上获取到的字体大小和尺寸值都是乘以了缩放比例后的放大值。
textView.setTextSize()函数的单位是sp



































    推荐阅读