1.APN簡介
APN(Access Point Name)是通過手機上網(wǎng)必須配置的一個參數(shù),用來決定手機通過哪種接入方式來訪問網(wǎng)絡(luò)侈贷。只要我們的手機插上sim卡之后就可以在手機的設(shè)置中查看當前sim卡內(nèi)置的默認apn參數(shù),一般的安卓智能機都可以在sim卡設(shè)置中找到“接入點名稱(APN)”并可以查看和新增apn。
下面我們看看apn到底是怎么使用的娄帖,在啟動Android手機或者啟動Android虛擬設(shè)備后,所有的APN配置信息都會保存在telephony.db的SQLite數(shù)據(jù)庫表名為carriers的表中昙楚。我們可以將此數(shù)據(jù)庫文件pull到本地近速,然后可以查看carriers表的結(jié)構(gòu)和其中的APN配置信息數(shù)據(jù),命令如下:
adb pull /data/user_de/0/com.android.providers.telephony
如上可以將mmssms.db和telephony.db等數(shù)據(jù)都pull出來。
在Android系統(tǒng)中APN配置文件的路徑:
1)vendor\qcom\proprietary\qrdplus\Extension\apps\etc\apns-config.xml
2)framework\base\core\res\xml\apn.xm
開機后削葱,啟動phone進程時奖亚,會加載運行在phone進程中的TelephonyProvider,TelephonyProvider負責解析apns-conf.xml文件析砸,將其中定義的APN參數(shù)寫入到數(shù)據(jù)庫中昔字。
1.1 APN配置關(guān)鍵字段
字段名稱 | 描述 |
---|---|
name | APN配置名稱,如CMNET |
numeric | 運營商編號首繁,如46000 |
mcc | 移動國家碼作郭,如460 |
mnc | 移動網(wǎng)絡(luò)碼,如00 |
apn | APN接入點蛮瞄,比如中國移動有兩個接入點:cmwap和cmnet |
user | 用戶名 |
server | 服務器地址 |
password | 密碼 |
proxy | 代理服務器地址所坯,如10.0.0.172 |
port | 端口號,如80 |
mmsproxy | 彩信代理服務器地址挂捅,如10.0.0.172 |
mmsport | 彩信代理服務器端口號,如80 |
mmsc | 彩信接入服務器地址堂湖,如http://mmsc.monternet.com |
type | APN接入類型,如default,net,supl,xcap,不同類型用","分隔 |
current | |
protocol | 連接該APN所用的協(xié)議闲先,如IPV4IPV6 |
roaming_protocol | 漫游時連接該APN所用的協(xié)議,如IPV4IPV6 |
carrier_enabled | 用于標識APN是否可用 |
bearer | 無線接入无蜂,如LTE和eHRPD |
bearer_bitmask | 無線接入技術(shù)位掩碼伺糠,用于標明當前APN可以包含的RAT |
network_type_bitmask | |
mvno_type | 移動虛擬網(wǎng)絡(luò)運營商(Mobile virtual network operator)的類型,可用的數(shù)據(jù)有spn,IMSI,GID(Group Identifier Level 1) |
mvno_match_data | MVNO_TYPE數(shù)據(jù)斥季,這個值是和MVNO_TYPE對應的训桶。例如:SPN:A MOBILE,BEN NL,IMSI:302720x94,2060188 GID:4E,33 |
sub_id | 用于表明這個APN屬于哪個subscription,此值從siminfo表獲取 |
profile_id | Profile id酣倾,profile是modem側(cè)存儲信息的方式舵揭,這個值將APN和modem側(cè)的profile聯(lián)系起來 |
modem_cognitive | 用于表明這個APN是否會在modem側(cè)設(shè)置 |
max_conns | APN支持的最大連接數(shù)量 |
wait_time | 使用該APN進行數(shù)據(jù)連接時,如果失敗躁锡,retry要等待的時間 |
max_conns_time | 限制APN最大連接的時間 |
mtu | 使用該APN建立的連接午绳,可以傳輸?shù)淖畲髥卧?/td> |
edited | 表明該APN是否被用戶或運營商添加、編譯或刪除的狀態(tài) |
user_visible | APN是否對用戶可見 |
user_editable | 用戶是否可以編輯APN |
owned_by | APN的擁有者映之,0或者1 |
apn_set_id | APN集合id拦焚,如果用戶或者框架選擇了一個apn作為首選APN,那么所有與選中apn相同集合id的APN擁有更高的優(yōu)先級 |
persistent | |
read_only | 是否只讀 |
ppp_number | |
sourcetype | |
csdnum | |
ipversion |
1.2 Android支持的APN類型
類型 | 描述 |
---|---|
default | 默認數(shù)據(jù)連接杠输、即瀏覽器赎败、Email等手機上網(wǎng)數(shù)據(jù)連接 |
mms | 發(fā)送和接收彩信使用的數(shù)據(jù)連接 |
supl | 支持AGPS的數(shù)據(jù)連接 |
dun(dial-up-network) | 撥號連接 |
hipri | 擴展 |
ims |
1.3 APN配置信息
apn配置在apns-conf.xml中,carriers表中的數(shù)據(jù)和此文件中的數(shù)據(jù)內(nèi)容一致蠢甲,在加載TelephonyProvider的時候僵刮,會調(diào)用其initDatabase方法,將apns-conf.xml配置文件內(nèi)容加載到carriers表中。
2妓笙、APN設(shè)置
2.1 重置APN
1若河、在ApnSettings界面點擊重置后,通過Uri: “content://telephony/carriers/restore"進行delete操作寞宫,刪除完成后會重新fillList萧福。
2、進行delete操作時辈赋,TelephonyProvider通過URL_RESTOREAPN進行刪除操作鲫忍,會刪除carriers表,同時刪除首選APN钥屈,獲取preferred-full-apn的SP悟民,如果SP包含version1,表示apn已經(jīng)存儲起來了篷就,刪除該subId對應的version1字段以及APN唯一字段與subId組合在一起的字段射亏,刪除完成,重新初始化加載carrier表竭业,
3智润、在ApnSettings界面查詢到APN后,會通過Uri:"content://telephony/carriers/
preferapn" 去設(shè)置首選APN未辆。
初始化完成后窟绷,DcTracker監(jiān)聽到數(shù)據(jù)庫變化執(zhí)行onApnChanged,然后會設(shè)置偏好APN咐柜,此時會將oldApnSettings設(shè)置成首選APN兼蜈,同時ApnSettings查詢到APN list檢測到如果沒有偏好APN,會將第一個APN設(shè)置成偏好APN拙友。APN如果配置了bearer_bitmask,且bearer_bitmask不為0为狸,如果插入的卡網(wǎng)絡(luò)類型識別的是unknown,查詢出來的APN則會被過濾掉不顯示献宫。
2.2切換APN
1钥平、在ApnSettings界面點擊onPreferenceChange,執(zhí)行setSelectedApnKey姊途,設(shè)置首選APN
通過URI:content://telephony/carriers/preferapn 和APN_ID為選中的id進行update涉瘾。
2、TelephonyProvider:獲取subId捷兰,檢查values中是否包含apn_id立叛,如果包含apn_id,獲取apn_id帶過來的id值贡茅,將對應的apn_id保存為該subId的首選APN
3秘蛇、DcTracker:監(jiān)聽到數(shù)據(jù)庫變化其做,ApnChangeObserver的onChange函數(shù)將被調(diào)用,觸發(fā)onApnChange函數(shù)赁还,onApnChange的時候妖泄,底層會清除掉所有的連接。
2.3 新建APN
1艘策、ApnEditor:布局初始化蹈胡,獲取相關(guān)控件,獲取subId等intent傳過來的參數(shù)朋蔫,插入一條僅有id的信息罚渐,并根據(jù)插入信息返回uri,根據(jù)uri查詢相應id的數(shù)據(jù)驯妄。
2荷并、根據(jù)查詢到的數(shù)據(jù)fillUi進行顯示,如果是新建的青扔,mvnoType顯示有差異源织,mvnoMatchData顯示有差異
3、移動定制版本微猖,APN協(xié)議和APN漫游協(xié)議默認為IpV4V6雀鹃、設(shè)置SIM卡相關(guān)的監(jiān)聽、APN變化的TextWatcher
4励两、在onResume中會注冊phone狀態(tài)、插拔卡等的監(jiān)聽
5囊颅、(1)點擊保存:內(nèi)置的APN則彈框提示是否保存当悔,非內(nèi)置的APN,直接驗證并保存踢代,如果APN相關(guān)有用信息為空盲憎,則toast提示,不保存返回胳挎,根據(jù)各項字段饼疙,通過uri更新數(shù)據(jù)庫中數(shù)據(jù)。
2.4 編輯APN
1慕爬、ApnEditor:布局初始化窑眯,獲取相關(guān)控件,獲取subId等intent傳過來的參數(shù)医窿,獲取傳遞過來的uri磅甩,uri以id結(jié)尾,如果uri為空或不滿足要求則返回姥卢,關(guān)閉界面卷要。
2渣聚、根據(jù)uri查詢相應id的數(shù)據(jù),根據(jù)查詢到的數(shù)據(jù)fillUi進行顯示僧叉,設(shè)置SIM卡相關(guān)的監(jiān)聽奕枝、APN變化的TextWatcher
3、在onResume中會注冊phone狀態(tài)瓶堕、插拔卡等的監(jiān)聽隘道,如果配置了ReadOnly字段喧半,則不可保存鞠抑、不可編輯preferene項
4冷溃、(1)點擊保存:name捏顺、APN腔丧、mcc闻坚、mnc 四項不能為空货岭,如果為空則返回不讓保存鲜漩,內(nèi)置的APN則彈框提示是否保存苍息,非內(nèi)置的APN缩幸,直接驗證并保存,如果APN相關(guān)有用信息為空竞思,則toast提示表谊,不保存返回,根據(jù)各項字段盖喷,通過uri更新數(shù)據(jù)庫中數(shù)據(jù)爆办。
(2)修改mcc,點擊保存课梳,此時發(fā)生沖突時距辆,更新舊的那條數(shù)據(jù),然后刪除掉要更新的這條數(shù)據(jù)暮刃,此時要更新這條APN就從數(shù)據(jù)庫中刪除了跨算,此時不會觸發(fā)onApnChange,不會導致DcTracker重新觸發(fā)連接的邏輯椭懊。重啟手機后诸蚕,此時通過numeric查詢APN是無法查到的,因為數(shù)據(jù)庫中的那條APN的mnc和numeric已經(jīng)相對應的被修改了氧猬。
3 TelephonyProvider
3.1 APN升級
APN升級在TelephonyProvider中實現(xiàn)背犯,先獲取首選APN保存,然后根據(jù)條件刪除數(shù)據(jù)庫狂窑。重新根據(jù)xml插入APN媳板,根據(jù)名稱、APN泉哈、numeric蛉幸、bearer四個屬性恢復首選APN破讨,若其中有屬性變更,則不恢復奕纫。
4提陶、 APN流程
4.1 卡加載后,監(jiān)聽APN數(shù)據(jù)庫變化
public DcTracker(Phone phone) {
.......
//每個Phone對象有自己DcTracker
//每個DcTracker加載各自卡可用的APN
mPhone = phone;
.......
//1匹层、監(jiān)聽卡載入
mUiccController = UiccController.getInstance();
mUiccController.registerForIccChanged(this, DctConstants.EVENT_ICC_CHANGED, null);
.......
//2隙笆、監(jiān)聽卡信息變化
mSubscriptionManager = SubscriptionManager.from(mPhone.getContext());
mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
.......
//監(jiān)聽APN數(shù)據(jù)庫變化
mApnObserver = new ApnChangeObserver();
phone.getContext().getContentResolver().registerContentObserver(
Telephony.Carriers.CONTENT_URI, true, mApnObserver);
.............
//初始化不同APN類型對應的網(wǎng)絡(luò)能力,后文介紹
initApnContexts();
.............
// Add Emergency APN to APN setting list by default to support EPDN in sim absent cases
initEmergencyApnSetting();
addEmergencyApnSetting();
...............
}
4)插卡或卡發(fā)生變化后升筏,就要創(chuàng)建當前卡可用的APN撑柔,同時設(shè)置初始時使用的APN
private void onRecordsLoadedOrSubIdChanged() {
..............
//1、創(chuàng)建當前卡可用的APN
createAllApnList();
//2您访、設(shè)置初始使用的APN
setInitialAttachApn();
if (mPhone.mCi.getRadioState().isOn()) {
if (DBG) log("onRecordsLoadedOrSubIdChanged: notifying data availability");
notifyOffApnsOfAvailability(Phone.REASON_SIM_LOADED);
}
//卡變化也會觸發(fā)撥號流程铅忿;不過若此時數(shù)據(jù)開關(guān)未開,那么撥號是不會成功的
setupDataOnConnectableApns(Phone.REASON_SIM_LOADED);
}
創(chuàng)建卡對應的APN的過程:
private void createAllApnList() {
//表示mvno是否匹配
//mvno也是APN的一種屬性灵汪,代表該APN適用于虛擬運營商檀训,目前用的比較少
mMvnoMatched = false;
//用于保存結(jié)果
mAllApnSettings = new ArrayList<ApnSetting>();
//得到當前卡的信息
IccRecords r = mIccRecords.get();
//得到卡對應的MCC/MNC
String operator = (r != null) ? r.getOperatorNumeric() : "";
if (operator != null) {
//構(gòu)造SQL語句
String selection = "numeric = '" + operator + "'";
String orderBy = "_id";
...............
//查詢MCC/MNC對應的APN
Cursor cursor = mPhone.getContext().getContentResolver().query(
Telephony.Carriers.CONTENT_URI, null, selection, null, orderBy);
if (cursor != null) {
if (cursor.getCount() > 0) {
//1、利用數(shù)據(jù)創(chuàng)建APN
mAllApnSettings = createApnList(cursor);
}
cursor.close();
}
}
//2享言、添加emergencyApnSettings
addEmergencyApnSetting();
//3峻凫、去除重復的APN
dedupeApnSettings();
if (mAllApnSettings.isEmpty()) {
mPreferredApn = null;
} else {
//4、得到用戶偏愛的APN (用戶在UI界面主動選擇的)
mPreferredApn = getPreferredApn();
if (mPreferredApn != null && !mPreferredApn.numeric.equals(operator) {
mPreferredApn = null;
//用戶偏愛的與當前卡不匹配览露,刪除數(shù)據(jù)庫中對應信息
setPreferredApn(-1);
}
}
//5荧琼、在需要的情況下,構(gòu)造APN文件發(fā)送給modem
setDataProfilesAsNeeded();
}
5.APN舉例
1)以中國移動舉例:其中carrier差牛、apn铭腕、mcc、mnc幾個字段是一個完整的apn一定要有的,不同的卡mnc會存在不同的情況如浩考,00夹孔、02,設(shè)置錯誤的情況下會無法上網(wǎng)析孽。
<apn carrier="China Mobile"
apn=""
mcc="460"
mnc="00"
type="ia"
protocol="IPV4V6"
roaming_protocol="IPV4V6"
/>
<apn carrier="CMCC DM"
apn=""
mcc="460"
mnc="00"
type="fota"
/>
<apn carrier="APN_NAME_CMNET"
apn="cmnet"
mcc="460"
mnc="00"
type="default,net,supl"
preferred="true"
protocol="IPV4V6"
roaming_protocol="IPV4V6"
/>
<apn carrier="APN_NAME_CMMMS"
apn="cmwap"
mcc="460"
mnc="00"
proxy="10.0.0.172"
port="80"
mmsproxy="10.0.0.172"
mmsport="80"
mmsc="http://mmsc.monternet.com"
type="mms"
protocol="IPV4V6"
roaming_protocol="IPV4V6"
/>
<apn carrier="APN_NAME_CMWAP"
apn="cmwap"
mcc="460"
mnc="00"
proxy="10.0.0.172"
port="80"
type="supl"
protocol="IPV4V6"
roaming_protocol="IPV4V6"
/>
<apn carrier="China Mobile (IMS)"
mcc="460"
mnc="00"
apn="ims"
type="ims"
protocol="IPV4V6"
roaming_protocol="IPV4V6"
profile_id="2"
modem_cognitive="true"
max_conns="1023"
max_conns_time="300"
/>
這里需要強調(diào)一下type和authtype搭伤,type字段可以有多個屬性值,依次用逗號隔開袜瞬,authtype在自己添加apn時可能給定的值是字符串怜俐,我們需要轉(zhuǎn)換為相應的值。具體關(guān)系如下:
屬性值 | 合入值 |
---|---|
None | 0 |
不寫(默認值) | -1 |
PAP | 1 |
CHAP | 2 |
PAP OR CHAP | 3 |
2)上網(wǎng)分為wap和net兩種方式邓尤,使用net手機就會直接連入互聯(lián)網(wǎng)拍鲤,而使用wap則會中間多了一個代理網(wǎng)關(guān)贴谎,移動聯(lián)通均是10.0.0.172,端口80季稳。
3)彩信APN
彩信apn中mmsproxy和mmsport兩個字段在發(fā)彩信的apn中是必須的
6.Android支持的apn類型
Android中支持的apn類型(”default, mms, supl, dun, hipri, fota, ims…….”)擅这,其功能如下所示:
類型 | 描述 |
---|---|
default | 默認數(shù)據(jù)連接,即瀏覽器景鼠、Email等普通連接(internet仲翎、wap、web) |
mms | 接收和發(fā)送彩信使用的數(shù)據(jù)連接 |
supl | 支持APGS的數(shù)據(jù)連接(gprs上網(wǎng)) |
dun | 撥號連接(wifi等上網(wǎng)類型铛漓,tethering) |
hipri | 擴展 |
此表中的數(shù)據(jù)優(yōu)先級是由低到高的溯香,即default數(shù)據(jù)連接的優(yōu)先級最低,而hipri數(shù)據(jù)連接的優(yōu)先級最高浓恶。比如在手機上網(wǎng)聊天時玫坛,將建立default數(shù)據(jù)連接;當手機收到一條彩信问顷,因為彩信的數(shù)據(jù)連接是mms昂秃,這時會斷開default數(shù)據(jù)連接而創(chuàng)建mms數(shù)據(jù)連接,從而能快速接收到此彩信杜窄,因為mms比default的數(shù)據(jù)連接優(yōu)先級高肠骆。因此,在發(fā)送和接收彩信的同時不能上網(wǎng)塞耕。
APN分類
1蚀腿、default
默認網(wǎng)絡(luò)連接,當激活時所有數(shù)據(jù)傳輸都使用該連接扫外,不能與其他網(wǎng)絡(luò)連接同時使用
適用場合:絕大部分正常上網(wǎng)時可以使用
2莉钙、mms
彩信專用連接,此連接與default類似筛谚,用于與載體的多媒體信息服務器對話的應用程序磁玉,此連接能與default連接同時使用
適用場合:使用彩信服務時,必須有mms類型的接入點驾讲,不必選中蚊伞,應用程序會自動使用此接入點
3、supl
是SecureUser Plane Location“安全用戶面定位”的簡寫吮铭,此連接與default類似时迫,用于幫助定位設(shè)備與載體的安全用戶面定位服務器對話的應用程序,此連接能與default連接同時使用
4谓晌、dun
Dial UpNetworking撥號網(wǎng)絡(luò)的簡稱掠拳,此連接與default連接類似,用于執(zhí)行一個撥號網(wǎng)絡(luò)網(wǎng)橋纸肉,使載體能知道撥號網(wǎng)絡(luò)流量的應用程序溺欧,此連接能與default連接同時使用
適用場合:當我們使用自己的手機給別人做熱點時使用喊熟,不管是USB 熱點,wifi熱點或則bluetooth熱點胧奔。將他與default區(qū)別開來的主要目的一般是方面計費逊移,國外很多運營商手機自己上網(wǎng)和做熱點計費不同的。目前在國內(nèi)三大運營商都沒有區(qū)分龙填,所以也就沒有dun這個apn
5胳泉、hipri
高優(yōu)先級網(wǎng)絡(luò),與default類似岩遗,但路由設(shè)置不同扇商。使用較少。
6宿礁、ims
當ims發(fā)起激活請求時會使用這個apn連建立ims的專用承載.
7案铺、FOTA
手機FOTA升級的時候使用
8.IA
IA的apn專用于LTE attach使用,在手機檢測到sim卡后梆靖,便會加載這個attach apn. 不過很多運營商并沒有嚴格規(guī)定attach apn控汉,所以常常復用default類型的apn。 在attachapn 加載的時候它有一個優(yōu)先級順序返吻,如下:
IaApn > PreferredApn > DefaultApn>FirstApn
IaApn : 類型為ia的apn姑子,優(yōu)先級最高。
PreferredApn :選中的apn测僵。比如在手機setting里面設(shè)置的那個apn
DefaultApn :從apnlist里面查詢到的第一個類型為“default”的apn
FirstApn :apnlist中的第一個apn街佑。
APN加載和過濾
在每次開機的時候系統(tǒng)回自動檢查telephony.db是否存在,如果不存在則會創(chuàng)建數(shù)據(jù)庫telephony.db捍靠,并利用apns-conf.xml中的內(nèi)容生成表carriers,以后所有對apn的操作都會是直接針對表carriers沐旨,包括查詢,創(chuàng)建榨婆,修改磁携,刪除等。
當插入一張卡后系統(tǒng)會根據(jù)卡的相關(guān)信息來匹配相應的apn良风,在apn list中主要涉及匹配的項有:mcc颜武,mnc,mvno_type, mvno_match_data拖吼。mvno_type值決定mvno_match_data的值,android原生代碼里mvno_type會有4個值这吻,他們分別是“spn”,“imsi”,“gid”, “iccid”吊档。所以,在apn 讀取的時候唾糯,會先根據(jù)sim卡的mcc怠硼,mnc讀取出相應的apn list鬼贱,接著會判斷apn list 中的每一個apn的mvno_type 的值,如果不為空香璃,則會根據(jù)mvno_type 和mvno_match_data再一次對apn list進行過濾这难,一般情況下,mvno_type,mvno_match_data為空葡秒。
7姻乓、常見的APN問題
7.1 重置APN,顯示為默認的APN接入點后又變?yōu)槭謩痈牡慕尤朦c
D ApnSettings: --restoreDefaultApn-- ——開始重置
D TelephonyProvider: restoreDefaultAPN: where: owned_by!=0
D TelephonyProvider: deletePreferredApn: for subId 1
D TelephonyProvider: deletePreferredApn: apn is stored. Deleting it now for subId 1
D TelephonyProvider: dbh.initDatabase:+ db=SQLiteDatabase: /data/user_de/0/com.android.providers.telephony/databases/telephony.db ——重新創(chuàng)建
D TelephonyProvider: dbh.initDatabase:- db=SQLiteDatabase: /data/user_de/0/com.android.providers.telephony/databases/telephony.db ——插入數(shù)據(jù)庫完成
D TelephonyProvider: setPreferredApn: _id 2965 subId 1 ————設(shè)置偏好APN
DCT : [ApnContext:default] getApnSetting: apnSetting=[ApnSettingV5] CUWAP, 2966, 46001, 3gwap, 10.0.0.172, http://mmsc.myuni.com.cn, 10.0.0.172, 80, 80, -1, default | mms, IPV4V6, IPV4V6, true, 0, 0, 0, false, 0, 0, 0, 0, , , false, 0, 0
DCT : [ApnContext:default] getApnSetting: apnSetting=[ApnSettingV5] CUWAP, 2966, 46001, 3gwap, 10.0.0.172, http://mmsc.myuni.com.cn, 10.0.0.172, 80, 80, -1, default | mms, IPV4V6, IPV4V6, true, 0, 0, 0, false, 0, 0, 0, 0, , , false, 0, 0
QtiDCT : [0]buildWaitingApns: reset preferred APN to [ApnSettingV5] CUWAP, 2966, 46001, 3gwap, 10.0.0.172, http://mmsc.myuni.com.cn, 10.0.0.172, 80, 80, -1, default | mms, IPV4V6, IPV4V6, true, 0, 0, 0, false, 0, 0, 0, 0, , , false, 0, 0 ——設(shè)置偏好APN失敗眯牧,重置到2966了
從log可知蹋岩,上層設(shè)置2965 APN時未設(shè)置成功,底層重新設(shè)置了2966
//上層設(shè)置偏好APN 2965
Line 58117: 06-21 14:43:07.940 2883 3252 D TelephonyProvider: setPreferredApn: _id 2965 subId 1
//framework設(shè)置偏好APN 2966
Line 4405: 06-21 14:43:07.939 2883 2883 D QtiDCT : [0]buildWaitingApns: reset preferred APN to [ApnSettingV5] CUWAP, 2966, 46001, 3gwap, 10.0.0.172, http://mmsc.myuni.com.cn, 10.0.0.172, 80, 80, -1, default | mms, IPV4V6, IPV4V6, true, 0, 0, 0, false, 0, 0, 0, 0, , , false, 0, 0 ——設(shè)置偏好APN失敗学少,重置到2966了
//framerok調(diào)用刪除
Line 4406: 06-21 14:43:07.939 2883 2883 D QtiDCT : [0]setPreferredApn: delete
//OS寫入完成剪个,數(shù)據(jù)庫執(zhí)行完打印的log
Line 58119: 06-21 14:43:07.943 5337 5337 D _ApnSettings: set key to 2965
//framework開始寫入偏好APN
Line 4407: 06-21 14:43:07.967 2883 2883 D QtiDCT : [0]setPreferredApn: insert
//響應framework的操作,寫入偏好APN 2966
Line 58161: 06-21 14:43:07.967 2883 2883 D TelephonyProvider: delete:match=12
Line 58162: 06-21 14:43:07.967 2883 2883 D TelephonyProvider: subIdString = 1 subId = 1
Line 58163: 06-21 14:43:07.967 2883 2883 D TelephonyProvider: deletePreferredApn: for subId 1
Line 58164: 06-21 14:43:07.967 2883 2883 D TelephonyProvider: deletePreferredApn: apn is stored. Deleting it now for subId 1
Line 58170: 06-21 14:43:07.972 2883 2883 D TelephonyProvider: subIdString = 1 subId = 1 ——此處log只有對應URL_PREFERAPN_NO_UPDATE_USING_SUBID 或者URL_PREFERAPN_USING_SUBID URI才會打印出來
Line 58171: 06-21 14:43:07.973 2883 2883 D TelephonyProvider: setPreferredApn: _id 2966 subId 1
//從上面流程可以看出版确,最后執(zhí)行的是響應 framework的寫入2966的操作
分析:在buildWaitingAPN()中增加的reset preferred APN的邏輯和上層沖突扣囊,導致preferred APN值不對,這段已經(jīng)不需要绒疗。上層在restore APN時會設(shè)置default preferred APN
方案:刪除reset prefered APN邏輯
7.2 升級后侵歇,SIM2的APN需要重新選擇
分析:
(1)從log來看,卡2沒有選擇默認的APN忌堂,故會彈框通知設(shè)置APN
(2)對比升級前后的apn可知盒至,升級后由于名稱改變了,相當于APN變更了士修,故需要重新設(shè)置APN
7.3 手動配置APN
手動配置APN需要配置的元素枷遂,例如:
(1)name:ims
(2)APN:ims
(3)type:ims
(4)APN protocol & APN roaming protocol:IPV4V6