频道栏目
首页 > 资讯 > Android > 正文

一个ResourceNotFound Exception引发的思考

17-06-20        来源:[db:作者]  
收藏   我要投稿

一个ResourceNotFound Exception引发的思考

问题背景:在大模式下启动相机,直接crash报了ResourceNotFound Exception。
在启动相机的过程中有一个资源Id没有找到,直接导致相机crash了。通过检查代码,发现该资源id在values-sw480dp目录下面已设置了,但是没有在values目录下面设置默认值,而我们产品默认取的资源就是在values-sw480dp-hdpi目录下面,那为什么没有找到该资源呢?屏幕的宽度是800,density为1.75,计算得出最小宽度值是457dp。计算公式如下所示:
sw(N)dp = 屏幕的宽度 / density
按照Android资源优先匹配规则,只会找小于等于457dp的资源目录,奇怪的是6月5号之前的版本为什么又可以呢,看来只能去源码中查看真相,在WindowManagerService类中找到计算尺寸大小和屏幕布局的方法。

private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated,
                  int dw, int dh, float density, Configuration outConfig) {
        // TODO: Multidisplay: for now only use with default display.

        // We need to determine the smallest width that will occur under normal
        // operation.  To this, start with the base screen size and compute the
        // width under the different possible rotations.  We need to un-rotate
        // the current screen dimensions before doing this.
        int unrotDw, unrotDh;
        if (rotated) {
            unrotDw = dh;
            unrotDh = dw;
        } else {
            unrotDw = dw;
            unrotDh = dh;
        }
        displayInfo.smallestNominalAppWidth = 1<<30;
        displayInfo.smallestNominalAppHeight = 1<<30;
        displayInfo.largestNominalAppWidth = 0;
        displayInfo.largestNominalAppHeight = 0;
        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh);
        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw);
        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh);
        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw);
        int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
        sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh);
        sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw);
        sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh);
        sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw);
**//计算最小宽度值**
        outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
        outConfig.screenLayout = sl;

跟踪代码发现在Configuration类里面,对smallestScreenWidthDp进一步做了处理:

//在产品属性里面设置ro.config.***值为true,是否锁定资源dpi,true表示锁定,false表示不锁定
Boolean isLockResMultiDpi = SystemProperties.getBoolean("ro.config.***",false);
if((isLockResMultiDpi && isMultiWhiteList()) || !isLockResMultiDpi){
    **//计算新的smallestNominalAppWidth**
    smallestNominalAppWidth = (smallestNominalAppWidth*dstDensity+srcDensity-1)/srcDensity;
}

在方法isMulitWhiteList()里面发现相机应用不在白名单里面,真相终于找到了。如果产品属性设置为false,无论显示模式为大中小,smallestNominalAppWidth都会被锁定为中间值;如果产品属性设置为true,另还要判断该应用是否加入白名单,如果加入白名单则锁定为中间值,否则就不会锁定,就会取默认值。
遇到问题不能仅从应用层资源适配的角度去思考,还要从根源上找原因,从底层源码里找真相。

相关TAG标签
上一篇:RunLoop总结:RunLoop的应用场景(四)
下一篇:AndroidStudio第一次新建项目时报错
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站