frameworks/base/core/res/res/xml/apns.xml文件内容:
<!-- If you edit this version, also edit the version in the partner-supplied apns-conf.xml configuration file --> <apns version="7"> </apns>
该文件被编译到res.apk中,通过android的资源管理器进行访问。
在Android源码build目录下,通过搜索apns-conf.xml可以找到在各个board中分别有配置:
在编译该product时会将device/generic/goldfish/data/etc/apns-conf.xml文件拷贝到system/etc/目录下,最后打包到system.img中。
packages/providers/TelephonyProvider/src/com/android/providers/telephony/TelephonyProvider.java文件中的内部类DatabaseHelper用于创建telephony.db数据库
public void onCreate(SQLiteDatabase db) { // Set up the database schema db.execSQL("CREATE TABLE " + CARRIERS_TABLE + "(_id INTEGER PRIMARY KEY," + "name TEXT," + "numeric TEXT," + "mcc TEXT," + "mnc TEXT," + "apn TEXT," + "user TEXT," + "server TEXT," + "password TEXT," + "proxy TEXT," + "port TEXT," + "mmsproxy TEXT," + "mmsport TEXT," + "mmsc TEXT," + "authtype INTEGER," + "type TEXT," + "current INTEGER," + "protocol TEXT," + "roaming_protocol TEXT," + "carrier_enabled BOOLEAN," + "preset BOOLEAN default false," + "bearer INTEGER);"); //从APN配置xml文件中读取APN配置,并存储到数据表carriers中 initDatabase(db); }APN配置信息加载分为两部分,首先从Android自带的内部APN配置文件中读取配置信息,然后在读取第三方提供的APN配置文件信息。
private void initDatabase(SQLiteDatabase db) { // Read internal APNS data Resources r = mContext.getResources(); //读取frameworks/base/core/res/res/xml/apns.xml文件 XmlResourceParser parser = r.getXml(com.android.internal.R.xml.apns); int publicversion = -1; try { XmlUtils.beginDocument(parser, "apns"); //读取APN配置版本信息 publicversion = Integer.parseInt(parser.getAttributeValue(null, "version")); //加载APN配置信息,并保存到数据表中 loadApns(db, parser); } catch (Exception e) { Log.e(TAG, "Got exception while loading APN database.", e); } finally { parser.close(); } // Read external APNS data (partner-provided) XmlPullParser confparser = null; // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system". //读取system/etc/apns-conf.xml文件 File confFile = new File(Environment.getRootDirectory(), PARTNER_APNS_PATH); FileReader confreader = null; try { confreader = new FileReader(confFile); confparser = Xml.newPullParser(); confparser.setInput(confreader); XmlUtils.beginDocument(confparser, "apns"); // 读取第三方提供的APN配置版本号 int confversion = Integer.parseInt(confparser.getAttributeValue(null, "version")); //判断第三方提供的APN配置版本号是否与Android自带的APN配置版本号相同 if (publicversion != confversion) { throw new IllegalStateException("Internal APNS file version doesn't match " + confFile.getAbsolutePath()); } //如果版本号相同,读取APN配置信息 loadApns(db, confparser); } catch (FileNotFoundException e) { // It's ok if the file isn't found. It means there isn't a confidential file // Log.e(TAG, "File not found: '" + confFile.getAbsolutePath() + "'"); } catch (Exception e) { Log.e(TAG, "Exception while parsing '" + confFile.getAbsolutePath() + "'", e); } finally { try { if (confreader != null) confreader.close(); } catch (IOException e) { } } }从APN信息加载源码中可以知道,第三方提供的APN配置信息版本必须与内部APN配置信息的版本相同。自此APN配置信息就存储在carriers表中了,并且通过TelephonyProvider向外提供访问接口。