APN,这东西对于刚接触的人来说并非那么好理解。对于3G移植上网不可缺少,这里记录一下。

撰写不易,转载请注明出处:http://blog.csdn.net/jscese/article/details/41248939

概念:

APN(Access Point Name),也就是 接入点 ,移动设备使用数据流量上网必须配置的一个參数,代表以何种方式来连接服务台开启数据流量功能.

一般有訪问WAP或者connect 因特网,国内的运营商2G,3G标识例如以下:

移动公司:2G:GSM、3G:TD-SCDMA

联通公司:2G:GSM、3G:WCDMA

电信公司:2G:CDMA、3G:CDMA2000

关于详细某个运营商的几G网络 的APN 是什么详细可參考/device/sample/etc/apns-full-conf.xml

这个xml文件里有google预置的多国经常使用的APN

使用:

apns-full-conf.xml

上面说道了apns-full-conf.xml 这个配置文件,这里面基本上是这种模块:

  <apn carrier="沃3G连接互联网 (China Unicom)"
mcc="460"
mnc="01"
apn="3gnet"
type="default,supl"
/>

其他选项都是网络參数,当中的apn就是我们最重要的接入点.也可自行加入apn属性模块.

移植3G时,就须要用到这个xml配置文件了。在android的device.mk 里面加个PRODUCT_COPY_FILES:

PRODUCT_COPY_FILES += \

     device/sample/etc/apns-full-conf.xml:system/etc/apns-conf.xml

telephony.db

这个文件被载入的地方可參考/packages/providers/TelephonyProvider/src/com/android/providers/telephony/TelephonyProvider.java:

    private static final String DATABASE_NAME = "telephony.db";  //数据库db文件

    private static final String PARTNER_APNS_PATH = "etc/apns-conf.xml";  //上面说到的copy到系统system/etc文件夹下

...

    private static class DatabaseHelper extends SQLiteOpenHelper {
// Context to access resources with
private Context mContext; /**
* DatabaseHelper helper class for loading apns into a database.
*
* @param context of the user.
*/
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, getVersion(context));
mContext = context;
} ...
        @Override
        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," +
                    "bearer INTEGER);");             initDatabase(db);
        }
private void initDatabase(SQLiteDatabase db) { ... // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
File confFile = new File(Environment.getRootDirectory(), PARTNER_APNS_PATH); //这里就是载入解析 load进db 了
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);
} ... } }

由于Content Provider採用的是懒载入机制,所以仅仅有检測load上sim卡的时候才会被创建这个db:

可使用sqlite3查看:

createAllApnList

在android中数据流量由/frameworks/opt/telephony/src/java/com/android/internal/telephony/DataConnectionTracker.java

以及它的子类GsmDataConnectionTracker.java(GSM模式) 或者 CdmaDataConnectionTracker.java(CDMA模式),(前者为移动,联通,后者为电信专用)

来控制,当中启动数据流量开关为onSetUserDataEnabled(boolean enabled).

这里单以GSM模式来说,在SIM 被load时调用:

    private void onRecordsLoaded() {
if (DBG) log("onRecordsLoaded: createAllApnList");
createAllApnList();
if(!mUserDataEnabled)
return;//jscese add judgement
if (mPhone.mCM.getRadioState().isOn()) {
if (DBG) log("onRecordsLoaded: notifying data availability");
notifyOffApnsOfAvailability(Phone.REASON_SIM_LOADED);
}
setupDataOnReadyApns(Phone.REASON_SIM_LOADED);
}

调用进createAllApnList

    /**
* Based on the sim operator numeric, create a list for all possible
* Data Connections and setup the preferredApn.
*/
private void createAllApnList() {
mAllApns = new ArrayList<ApnSetting>();
IccRecords r = mIccRecords.get();
String operator = (r != null) ? r.getOperatorNumeric() : "";
if (operator != null) {
String selection = "numeric = '" + operator + "'";
// query only enabled apn.
// carrier_enabled : 1 means enabled apn, 0 disabled apn.
selection += " and carrier_enabled = 1";
if (DBG) log("createAllApnList: selection=" + selection); Cursor cursor = mPhone.getContext().getContentResolver().query( //用当前SIM卡相应的运营商查询系统的全部APN。往下调用createApnList
Telephony.Carriers.CONTENT_URI, null, selection, null, null); if (cursor != null) {
if (cursor.getCount() > 0) {
mAllApns = createApnList(cursor);  //能够跟进去看查询Telephony.Carriers并返回一个Apn的list
}
cursor.close();
}
} if (mAllApns.isEmpty()) {
if (DBG) log("createAllApnList: No APN found for carrier: " + operator);
mPreferredApn = null;
// TODO: What is the right behaviour? //notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN);
} else {
mPreferredApn = getPreferredApn();
if (mPreferredApn != null && !mPreferredApn.numeric.equals(operator)) {
mPreferredApn = null;
setPreferredApn(-1);
}
if (DBG) log("createAllApnList: mPreferredApn=" + mPreferredApn);
}
if (DBG) log("createAllApnList: X mAllApns=" + mAllApns);
}

onSetUserDataEnabled(true):

代表打开数据流量。终于调用到

private boolean trySetupData(ApnContext apnContext)

{

...

       if (apnContext.getState() == DctConstants.State.IDLE) {
ArrayList<ApnSetting> waitingApns = buildWaitingApns(apnContext.getApnType()); //使用用户设置的preferred APN构建一个可用于数据连接的备选APN列表,即waitingApns列表(当有preferred APN,该列表就仅仅有一个)。 //若用户没有设置preferred APN,则将全部类型匹配的APN加入到waitingApns列表(如default类型) if (waitingApns.isEmpty()) {
if (DBG) log("trySetupData: No APN found");
notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN, apnContext);
notifyOffApnsOfAvailability(apnContext.getReason());
return false;
} else {
apnContext.setWaitingApns(waitingApns);
if (DBG) {
log ("trySetupData: Create from mAllApns : " + apnListToString(mAllApns));
}
}
} if (DBG) {
log ("Setup watingApns : " + apnListToString(apnContext.getWaitingApns()));
}
// apnContext.setReason(apnContext.getReason());
boolean retValue = setupData(apnContext); // waitingApns列表中有可用的APN时,尝试建立连接
notifyOffApnsOfAvailability(apnContext.getReason());
return retValue; ... }

另外几个对apn操作的几个函数都在这个文件中面。分别的作用例如以下:

onApnChanged:当APN被用户更改时,将调用到此函数,又一次建立数据连接

setPreferredApn:当用户没有设置preferred APN时,将当前数据连接成功的那个APN设置为preferred APN。

能够去看onDataSetupComplete时的操作。

getPreferredApn:用户获取用户设置的preferred APN,这个在上面说到的createAllApnList时会去获取一次。看是否存在.

对于这个preferredApn会以xml的形式保存在:

shell@android:/data/data/com.android.providers.telephony/shared_prefs # cat preferred-apn.xml
ml <
<? xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<long name="apn_id" value="1124" />
</map>

这是代表打开数据流量成功之后保存的apn map。能够像上面一样去 telephony.db里面查查看看:

sqlite> select * from carriers where _id='1124';
1124|沃3G连接互联网 (China Unicom)|46001|460|01|3gnet|||||||||-1|default,supl|1|IP|IP|1|0

这里仅仅是分析了一下apn的由来以及在framework层的使用,终于是通过RIL.java 的setupDataCall通过一个rild 的socket发请求到hardware的ril.cpp:

public void
setupDataCall(String radioTechnology, String profile, String apn, /*上面传下来的apn*/
String user, String password, String authType, String protocol,
Message result) {
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_SETUP_DATA_CALL, result); rr.mp.writeInt(7); rr.mp.writeString(radioTechnology);
rr.mp.writeString(profile);
rr.mp.writeString(apn);
rr.mp.writeString(user);
rr.mp.writeString(password);
rr.mp.writeString(authType);
rr.mp.writeString(protocol); if (RILJ_LOGD) riljLog(rr.serialString() + "> "
+ requestToString(rr.mRequest) + " " + radioTechnology + " "
+ profile + " " + apn + " " + user + " "
+ password + " " + authType + " " + protocol); send(rr); //里面就是 socket了
}

再之后怎么获取到这个socket event处理而且交给reference-ril 发送这个apn接入网路可參考我前面的博客:

Android——RIL 机制源代码分析

Android——4.2 - 3G移植之路之 reference-ril .pppd 拨号上网 (三)

Android——4.2 - 3G移植之路之 APN (五)的更多相关文章

  1. Android——4.2 - 3G移植之路之 AT 通信 (四)

    在前文Android--4.2 - 3G移植之路之 reference-ril .pppd 拨号上网 (三)中分析了3G连接网络的流程,当中有说道通过AT指令建立连接, 在这里记录一下3G中的AT通信 ...

  2. Android——4.2 - 3G移植之路之 reference-ril .pppd 拨号上网 (三)

    Android的RIL机制中的 reference-ril.c 即为厂商提供的驱动接口.这个驱动源代码各个厂商都是有提供的,网上也有下载.我如今用的就是huawei wcdma的.最后编译成libre ...

  3. 基于MT6752/32平台 Android L版本驱动移植步骤

    基于MT6752/32平台 Android L版本驱动移植步骤 根据MK官网所述,在Android L 版本上Turnkey ABS 架构将会phase out,而Mediatek Turnkey架构 ...

  4. Android Vector曲折的兼容之路

    Android Vector曲折的兼容之路 两年前写书的时候,就在研究Android L提出的Vector,可研究下来发现,完全不具备兼容性,相信这也是它没有被广泛使用的一个原因,经过Google的不 ...

  5. Android wifi驱动的移植 realtek 8188

    Android wifi驱动的移植 一般我们拿到的android源代码中wifi应用层部分是好的, 主要是wifi芯片的驱动要移植并添加进去. wifi驱动的移植, 以realtek的8188etv为 ...

  6. Android程序员的进阶之路

    本文主要论述的是Android程序员的进阶之路,博主本人就是一名android开发攻城狮,所以这里讲述的大多数是android开发攻城狮的技术进阶之路,如有问题请多指正. 大家都知道程序员之中有有菜鸟 ...

  7. Android安卓书籍推荐《Android驱动开发与移植实战详解》下载

    百度云下载地址:点我 Android凭借其开源性.优异的用户体验和极为方便的开发方式,赢得了广大用户和开发者的青睐,目前已经发展成为市场占有率很高的智能手机操作系统. <Android驱动开发与 ...

  8. Python之路【第五篇】:面向对象及相关

    Python之路[第五篇]:面向对象及相关   面向对象基础 基础内容介绍详见一下两篇博文: 面向对象初级篇 面向对象进阶篇 其他相关 一.isinstance(obj, cls) 检查是否obj是否 ...

  9. Python之路【第五篇】:面向对象和相关

    Python之路[第五篇]:面向对象及相关   面向对象基础 基础内容介绍详见一下两篇博文: 面向对象初级篇 面向对象进阶篇 其他相关 一.isinstance(obj, cls) 检查是否obj是否 ...

随机推荐

  1. RocketMQ学习笔记(7)----RocketMQ的整体架构

    1. RocketMQ主要的9个模块,如图: 2. 模块介绍 1. rocketmq-common:通用的常量枚举,基类方法或者数据结构,按描述的目标来分包,通俗易懂.报名有admin,consume ...

  2. tigergao

    互联网从业 6 年.前码农&DBA,现运维&电商创业者,也在做自媒体.终生学习者. 运营微信公众号:高哥咋么看 感兴趣的朋友们可以订阅.

  3. VBA 中Dim含义

    楼主是个初学者,在应用vba时遇到了dim方面的问题,查了很多资料后想把关于dim的这点儿知识简单整理出来 首先,从我遇到的问题作为切入点吧, (不得不承认我遇到的错误是很低级的) 具体的情境就不还原 ...

  4. 【codeforces 95C】Volleyball

    [题目链接]:http://codeforces.com/problemset/problem/95/C [题意] 给你n个点,m条边; 每个点有一辆出租车; 可以到达离这个点距离不超过u的点,且在这 ...

  5. String spilt时转义特殊字符【转】

    在使用String.split方法分隔字符串时,分隔符如果用到一些特殊字符,可能会得不到我们预期的结果. 我们经常使用public String[] split(String regex)方法来拆分一 ...

  6. 洛谷 P2049 魔术棋子

    P2049 魔术棋子 题目描述 在一个M*N的魔术棋盘中,每个格子中均有一个整数,当棋子走进这个格子中,则此棋子上的数会被乘以此格子中的数.一个棋子从左上角走到右下角,只能向右或向下行动,请问此棋子走 ...

  7. Android端通过HttpURLConnection上传文件到server

    Android端通过HttpURLConnection上传文件到server 一:实现原理 近期在做Androidclient的应用开发,涉及到要把图片上传到后台server中.自己选择了做Sprin ...

  8. Android开发学习之事件处理和Button具体解释

    Android的事件处理机制:  1.基于监听器的事件处理 --- 组件绑定特定的事件监听器   --- 重点   2.基于回调的事件处理   --- 主要做法是重写Android组件特定的回调函数, ...

  9. [Mobx] Using mobx to isolate a React component state

    React is great for diffing between Virtual-DOM and rendering it to the dom. It also offers a naïve s ...

  10. TextView超链接

    这里面涉及两个知识点--超链接和跳转.以下进行逐一解说: 1.实现超链接: 1.1形成超链接文本 public static SpannableString getUserlink(String us ...