一、概述
近段时间有个项目需求,在欧洲的时候SIM卡无法识别,但是在国内可以。很明显这是APN设置的问题。于是想在android系统中添加默认的APN配置
二、APN默认配置文件位置
Android系统的APN配置存储在telephony.db这个数据库中,数据库生成后路径在/data/data/com.android.providers.Telephony。注意手机第一次开机如果没有插卡的话是不会生成这个数据库的,一定要识别到一次插卡以后这个数据库才存在。
分析源码数据库生成源码packages/providers/TelephonyProvider/src/com/android/providers/telephony/TelephonyProvider.java
private static int getVersion(Context context) {
// Get the database version, combining a static schema version and the XML version
Resources r = context.getResources();
XmlResourceParser parser = r.getXml(com.android.internal.R.xml.apns);
try {
XmlUtils.beginDocument(parser, "apns");
int publicversion = Integer.parseInt(parser.getAttributeValue(null, "version"));
return DATABASE_VERSION | publicversion;
} catch (Exception e) {
Log.e(TAG, "Can't get version of APN database", e);
return DATABASE_VERSION;
} finally {
parser.close();
}
}
这是数据库创建的helper类中获取数据库版本的方法,可以看到这里取的文件是com.android.internal.R.xml.apns,这个文件在frameworks/base/core/res/apns.xml下。可是打开发现里面是空的,就一个版本号,这是google Android默认的数据库配置文件,我们一般不在这里改。
继续往下,是数据库onCreate()回调方法,创建了表和各个字段,最后调用initDatabase()方法。
private void initDatabase(SQLiteDatabase db) {
// Read internal APNS data
Resources r = mContext.getResources();
XmlResourceParser parser = r.getXml(com.android.internal.R.xml.apns);//上面已经分析了这里是空的没有配置数据
int publicversion = -1;
try {
XmlUtils.beginDocument(parser, "apns");
publicversion = Integer.parseInt(parser.getAttributeValue(null, "version"));
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".
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");
// Sanity check. Force internal version and confidential versions to agree
int confversion = Integer.parseInt(confparser.getAttributeValue(null, "version"));
if (publicversion != confversion) {
throw new IllegalStateException("Internal APNS file version doesn't match "
+ confFile.getAbsolutePath());
}
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默认的配置其实是来自于system/etc/apns-conf.xml这个文件,这个目录是out目录下的,生成它的地方在device/目录下的apns-conf.xml中,找不到的用find命令找一下,根据项目的不同路径不同。然后在apns-conf.xml中可以看到许多已经存在的apn信息,在末尾添加上你需要配置的新的APN即可。
三、默认选中配置好的APN
任务还没有结束,我们配置好以后,重烧系统开机,插入欧洲卡Vodaphone卡,发现APN列表中的确是有我们新添加的APN了,可是它没有被默认选中,依旧得我们手动选中它才行,这显然不人性化。 而其他的例如移动和联通卡却有默认选上的功能,这应该是Vodaphone卡在大陆本身的问题吧。不过没有关系,我们在代码中加两句话即可
packages/apps/Settings/src/com/android/settings/ApnSettings.java中,找到fillList()方法,该方法中定位到
if (selectable) {
if ((mSelectedKey != null) && mSelectedKey.equals(key)) {
pref.setChecked();
}
apnList.addPreference(pref);
} else {
mmsApnList.add(pref);
}
可以在这儿添加判断,如果name和apn和numeric满足自己配置的条件,就直接给它setChceked。
if ((mSelectedKey != null) && mSelectedKey.equals(key))
例如我的是这样添加
//add by zhiming.su start
if("Vodaphone".equals(name) && "internetd.gdsp".equals(apn) && where.contains("20404")){
pref.setChecked();
apnList.addPreference(pref);
Log.v("szm","Vodaphone");
}else{//add by zhiming.su end
if (selectable) {
if ((mSelectedKey != null) && mSelectedKey.equals(key)) {
pref.setChecked();
}
apnList.addPreference(pref);
} else {
mmsApnList.add(pref);
}
}
---------------------
作者:Smoyan_
来源:CSDN
原文:https://blog.csdn.net/u012761076/article/details/79062118
版权声明:本文为博主原创文章,转载请附上博文链接!