APN 源码分析 --- 增删改查过程分析

5.3 查询/增加/删除/修改 APN

在手机的设置里,每一张SIM卡对应一个APN界面,这个界面包含了APN信息,并且可以增加,修改,删除等操作。

例如,电信卡对应的APN界面如下,


第一个就是当前默认的APN或者已经连接的APN,第三个APN专门用于发送彩信的。

3.1查询

查询当前默认的APN信息,也就是查询telephony.db数据库的siminfo表

Uri curi = Uri.parse("content://telephony/carriers/preferapn");  
Cursor ccr = mContext.getContentResolver().query(curi, null, null, null, null); 
ccr.moveToFirst();        
String idd = ccr.getString(ccr.getColumnIndex("_id"));       
String named = ccr.getString(ccr.getColumnIndex("name"));
String apnd = ccr.getString(ccr.getColumnIndex("apn"));
		 
String usercurrent = ccr.getString(ccr.getColumnIndex("user"));
String passwordcurrent = ccr.getString(ccr.getColumnIndex("password"));
String authtypecurrent = ccr.getString(ccr.getColumnIndex("authtype"));
String typecurrent = ccr.getString(ccr.getColumnIndex("type"));

查询当期SIM卡对应的APN信息,查询telephony.db数据库的carriers表单,

TelephonyManager iPhoneManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
Uri APN_URI = Uri.parse("content://telephony/carriers/");
String iNumeric = iPhoneManager.getSimOperator();
•••
Cursor apnCursor = mContext.getContentResolver().query(APN_URI, new String[] { "_id", "name", "numeric", "apn", "mcc", "mnc", "user", "password", "authtype", "type"}, "numeric=?", new String[]{iNumeric}, null);
if (apnCursor != null && apnCursor.moveToFirst()) {
	while (!apnCursor.isAfterLast()) {
		StringBuilder builder = new StringBuilder();
		String user = apnCursor.getString(apnCursor.getColumnIndex("user"));
		String password = apnCursor.getString(apnCursor.getColumnIndex("password"));
		String authtype = apnCursor.getString(apnCursor.getColumnIndex("authtype"));
		String type = apnCursor.getString(apnCursor.getColumnIndex("type"));
•••
      apnCursor.moveToNext();
•••
apnCursor.close();

3.2增加

增加一个APN首先会往telephony.db数据库的carriers表单中插入一条APN数据,然后phone进程监听到数据库的改变之后,

会利用添加的APN发起拨号请求。往数据库里面添加一个APN主要逻辑如下,

1,将需要添加的APN信息封装成ContentValues 对象,

String[] strArray = strCommand.split("/"); //APN信息
ContentValues apnValues = new ContentValues();
apnValues.put("name",strArray[1]);
apnValues.put("apn",strArray[2]);
apnValues.put("mcc",iNumeric.substring(0,3));
apnValues.put("mnc",iNumeric.substring(3,5));
apnValues.put("user",strArray[3]);
apnValues.put("password",strArray[4]);
apnValues.put("authtype",strArray[5]);
apnValues.put("type",strArray[6]);
apnValues.put("numeric",iNumeric);

2,然后插入数据库,并更新

Uri APN_URI = Uri.parse("content://telephony/carriers/");
String PREFERAPN_NO_UPDATE_URI_USING_SUBID =
     "content://telephony/carriers/preferapn/subId/";
int subId = SubscriptionManager.getSubId(0)[0];
Uri uri = Uri.parse(PREFERAPN_NO_UPDATE_URI_USING_SUBID + subId);
TelephonyManager iPhoneManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
String iNumeric = iPhoneManager.getSimOperator();
Uri k = mContext.getContentResolver().insert(APN_URI, apnValues);
Cursor c = mContext.getContentResolver().query(k, new String[]{"_id"},null,null,null);
Log.d(TAG, "apn add c = " + c);
if (c!=null && c.moveToFirst()) {
	String id = c.getString(c.getColumnIndex("_id"));
	Log.d(TAG, "apn add id = " + id);
	ContentValues values = new ContentValues();
	values.put("apn_id",id);
	int kkk = mContext.getContentResolver().update(uri, values, null,null);
•••
c.close();

3.3更改默认APN

更改默认APN其实就是对telephony.db数据库的siminfo表单进行更新,

并且,只需要APN的id就可以,

String PREFERAPN_NO_UPDATE_URI_USING_SUBID =
                        "content://telephony/carriers/preferapn/subId/";
String apnid = ***; // APN的id
ContentResolver resolver = mContext.getContentResolver();
String APN_ID = "apn_id";
int subId = SubscriptionManager.getSubId(0)[0];
Uri uri = Uri.parse(PREFERAPN_NO_UPDATE_URI_USING_SUBID + subId);
ContentValues values = new ContentValues();
values.put(APN_ID, apnid);
resolver.update(uri, values, null, null); //更新

3.4重置(删除)

设置的APN界面有个重置的功能,重置具体流程如下,

1,首先删除数据库中的所有APN,然后重新解析加载apns-conf.xml 文件里面的APN信息。

2,然后重新发起拨号请求,设置默认的APN。

因此,重置就相当于删除非apns-conf.xml 文件里面定义的APN,也就是在设置界面手动添加上去的APN。

和前面的方法一样,重置是调用数据库的delete方法完成的,

TelephonyProvider的delete方法对重置操作处理如下,

case URL_RESTOREAPN: {
    count = 1;
    restoreDefaultAPN(subId);
    break;
}

restoreDefaultAPN方法处理流程如下,

try {
   db.delete(CARRIERS_TABLE, where, null); //删除数据库中的所有APN信息
} catch (SQLException e) {
  loge("got exception when deleting to restore: " + e);
}
setPreferredApnId((long)-1, subId); //设置默认的APN
mOpenHelper.initDatabase(db); //重新加载apns-conf.xml 文件里面定义的APN

TelephonyProvider的四个方法, insert/delete/update/query 除了query方法不改变数据库之外,

其他三种方法最后都会引起数据库的改变,因此一般都会调用notifyChange方法进行通知,

getContext().getContentResolver().notifyChange(Telephony.Carriers.CONTENT_URI, null,
                    true, UserHandle.USER_ALL);

5.4 APN changed

根据5.2 小节的分析, 一旦telephony.db数据库发生变化,就会调用DcTracker的onApnChanged方法。

onApnChanged方法如下,

private void onApnChanged() {
   if(DBG) log("onApnChanged: tryRestartDataConnections");
   tryRestartDataConnections(Phone.REASON_APN_CHANGED); //原因:APN改变
}

tryRestartDataConnections方法主要逻辑如下,

1,调用createAllApnList方法创建当前SIM卡的APN,

createAllApnList(); 

2,调用setInitialAttachApn方法设置初始使用的APN,

setInitialAttachApn();

3,调用cleanUpConnectionsOnUpdatedApns方法断开当前的数据连接,

if (reason.equalsIgnoreCase(Phone.REASON_APN_CHANGED)) {
    cleanUpConnectionsOnUpdatedApns(!isDisconnected);
} else {
    cleanUpAllConnections(!isDisconnected, reason);
}

4,调用setupDataOnConnectableApns方法发起拨号请求,

setupDataOnConnectableApns(Phone.REASON_SIM_LOADED);

其中,第3个方法是清理并且断开网络连接的,第1,2,4个方法在5.2 章节中已经论述过了,在此就不赘述了。

还有一些其他原因导致调用setupDataOnConnectableApns方法重新发起拨号上网请求。

1,当数据注册状态变化时,rild守护进程会向RIL.java上报RIL_REQUEST_SETUP_DATA_CALL消息,

最后会调用DcTracker的handleMessage方法,如下,

case DctConstants.EVENT_DATA_RAT_CHANGED:
    // When data rat changes we might need to load different
    // set of apns (example, LTE->1x)
    if (onUpdateIcc()) {
  log("onUpdateIcc: tryRestartDataConnections " + Phone.REASON_NW_TYPE_CHANGED);
      tryRestartDataConnections(Phone.REASON_NW_TYPE_CHANGED);
     } else if (isNvSubscription()){
         // If cdma subscription source changed to NV or data rat changed to cdma
         // (while subscription source was NV) - we need to trigger NV ready
         onNvReady();
    } else {
          //May new Network allow setupData, so try it here
          setupDataOnConnectableApns(Phone.REASON_NW_TYPE_CHANGED,
                            RetryFailures.ONLY_ON_CHANGE);
    }
break;

这几个判断最后都会调用setupDataOnConnectableApns方法。

2,打开关闭飞行模式/数据业务时 也会发起拨号请求。

3,通话之前会断开数据业务,通话完成之后会重新发起拨号请求。

这些都可以在DcTracker中找到对应的方法。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值