记录Resource获取资源时不同设备的优先级。
之前心里一直在打鼓,Android资源文件可以定义在不同分辨率,density,屏幕方向,最小宽度,当我们的程序需要找一个资源,但是他在多个文件下面都存在,那么Android系统的查找顺序是怎样的?最近在适配公司的项目,这些问题就深刻的站到面前了,抽时间查看了Android这部分的源代码,下面是ResTable_config类,此类是framework在native层的代码,用来记录系统的一些运行环境参数,比如屏幕方向,density,语言等等,需要详细了解的自行google。1
bool ResTable_config::match(const ResTable_config& settings) const {
if (imsi != 0) {
if (mcc != 0 && mcc != settings.mcc) {
return false;
}
if (mnc != 0 && mnc != settings.mnc) {
return false;
}
}
if (locale != 0) {
// Don't consider the script & variants when deciding matches.
//
// If we two configs differ only in their script or language, they
// can be weeded out in the isMoreSpecificThan test.
if (language[0] != 0
&& (language[0] != settings.language[0]
|| language[1] != settings.language[1])) {
return false;
}
if (country[0] != 0
&& (country[0] != settings.country[0]
|| country[1] != settings.country[1])) {
return false;
}
}
if (screenConfig != 0) {
const int layoutDir = screenLayout&MASK_LAYOUTDIR;
const int setLayoutDir = settings.screenLayout&MASK_LAYOUTDIR;
if (layoutDir != 0 && layoutDir != setLayoutDir) {
return false;
}
const int screenSize = screenLayout&MASK_SCREENSIZE;
const int setScreenSize = settings.screenLayout&MASK_SCREENSIZE;
// Any screen sizes for larger screens than the setting do not
// match.
if (screenSize != 0 && screenSize > setScreenSize) {
return false;
}
const int screenLong = screenLayout&MASK_SCREENLONG;
const int setScreenLong = settings.screenLayout&MASK_SCREENLONG;
if (screenLong != 0 && screenLong != setScreenLong) {
return false;
}
const int uiModeType = uiMode&MASK_UI_MODE_TYPE;
const int setUiModeType = settings.uiMode&MASK_UI_MODE_TYPE;
if (uiModeType != 0 && uiModeType != setUiModeType) {
return false;
}
const int uiModeNight = uiMode&MASK_UI_MODE_NIGHT;
const int setUiModeNight = settings.uiMode&MASK_UI_MODE_NIGHT;
if (uiModeNight != 0 && uiModeNight != setUiModeNight) {
return false;
}
if (smallestScreenWidthDp != 0
&& smallestScreenWidthDp > settings.smallestScreenWidthDp) {
return false;
}
}
if (screenSizeDp != 0) {
if (screenWidthDp != 0 && screenWidthDp > settings.screenWidthDp) {
//ALOGI("Filtering out width %d in requested %d", screenWidthDp, settings.screenWidthDp);
return false;
}
if (screenHeightDp != 0 && screenHeightDp > settings.screenHeightDp) {
//ALOGI("Filtering out height %d in requested %d", screenHeightDp, settings.screenHeightDp);
return false;
}
}
if (screenType != 0) {
if (orientation != 0 && orientation != settings.orientation) {
return false;
}
// density always matches - we can scale it. See isBetterThan
if (touchscreen != 0 && touchscreen != settings.touchscreen) {
return false;
}
}
if (input != 0) {
const int keysHidden = inputFlags&MASK_KEYSHIDDEN;
const int setKeysHidden = settings.inputFlags&MASK_KEYSHIDDEN;
if (keysHidden != 0 && keysHidden != setKeysHidden) {
// For compatibility, we count a request for KEYSHIDDEN_NO as also
// matching the more recent KEYSHIDDEN_SOFT. Basically
// KEYSHIDDEN_NO means there is some kind of keyboard available.
//ALOGI("Matching keysHidden: have=%d, config=%d\n", keysHidden, setKeysHidden);
if (keysHidden != KEYSHIDDEN_NO || setKeysHidden != KEYSHIDDEN_SOFT) {
//ALOGI("No match!");
return false;
}
}
const int navHidden = inputFlags&MASK_NAVHIDDEN;
const int setNavHidden = settings.inputFlags&MASK_NAVHIDDEN;
if (navHidden != 0 && navHidden != setNavHidden) {
return false;
}
if (keyboard != 0 && keyboard != settings.keyboard) {
return false;
}
if (navigation != 0 && navigation != settings.navigation) {
return false;
}
}
if (screenSize != 0) {
if (screenWidth != 0 && screenWidth > settings.screenWidth) {
return false;
}
if (screenHeight != 0 && screenHeight > settings.screenHeight) {
return false;
}
}
if (version != 0) {
if (sdkVersion != 0 && sdkVersion > settings.sdkVersion) {
return false;
}
if (minorVersion != 0 && minorVersion != settings.minorVersion) {
return false;
}
}
return true;
}
代码位于framework/base/libs/androidfw/ResourceTypes.cpp
优先级
- IMSI
- 语言
- 国家
- UI mode(白天or黑夜)
- 屏幕大小
- 最小宽度DPI
- 屏幕密度
- 屏幕方向
- 系统version
IMSI
由MCC、MNC、MSIN组成,其中MCC为移动国家号码,由3位数字组成,* 唯一地识别移动客户所属的国家,我国为460;MNC为网络id,由2位数字组成, * 用于识别移动客户所归属的移动网络,中国移动为00,中国联通为01,中国电信为03;MSIN为移动客户识别码,采用等长11位数字构成。 * 唯一地识别国内GSM移动通信网中移动客户。所以要区分是移动还是联通,只需取得SIM卡中的MNC字段即可
1 String imsi = telManager.getSubscriberId(); if(imsi!=null){ if(imsi.startsWith("46000") || imsi.startsWith("46002")){//因为移动网络编号46000下的IMSI已经用完,所以虚拟了一个46002编号,134/159号段使用了此编号 //中国移动 }else if(imsi.startsWith("46001")){ //中国联通 }else if(imsi.startsWith("46003")){ //中国电信 } }IMSI:国际移动用户识别码(唯一标识),IMSI = MCC + MNC + MSIN,其中MCC是指移动台国家代码(3 位,中国460),MNC是指移动网代码(2 位中国00),MSIN是指移动用户识别号码 (10 位 )
IMSI共有15位,其结构如下:
MCC+MNC+MSIN ,(MNC+MSIN=NMSI)
MCC:Mobile Country Code,移动国家码,MCC的资源由国际电联(ITU)统一分配和管理,唯一识别移动用户所属的国家,共3位,中国为460;
MNC:Mobile Network Code,移动网络码,共2位,中国移动TD系统使用00,中国联通GSM系统使用01,中国移动GSM系统使用02,中国电信CDMA系统使用03,一个典型的IMSI号码为460030912121001;
MSIN:Mobile Subscriber Identification Number共有10位,其结构如下:
09+M0M1M2M3+ABCD
其中的M0M1M2M3和MDN号码中的H0H1H2H3可存在对应关系,ABCD四位为自由分配。
可以看出IMSI在MSIN号码前加了MCC即NMSI,可以区别出每个用户的来自的国家,因此可以实现国际漫游。在同一个国家内,如果有多个移动网络运营商,可以通过MNC来进行区别.