Android——4.2 - 3G移植之路之 APN (五)

Android APN加载流程 1、Android的APN(Access Point Name)数据预置在/system/etc/apns-conf.xml中: 2、源码:apns-conf.xml来自apns-full-conf.xml,编译系统的时候Copy到/system/etc/目录下: 3、检索APN,根据MCC、MNC的值组合(46001)来查询telephony.db数据库: 阅读详情

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


                                              撰写不易,转载请注明出处:http://blog.youkuaiyun.com/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 carrier_list.textpb 和apns-conf.xml 配置文件参考 apns-conf.xml和apns-full-conf.xml有什么区别? 阅读详情

相关推荐

apns-full-conf.xml

vendor/rockchip/common/phone/etc apn 电信、联通,移动

4G拨号上网 之 APN的XML文件解析

将存放APN的XML文档进行解析

qq_54593609的博客 2671

apns-conf.xml

网络上很多的APN文件,看了许多,没有带电信参数的,花费一晚上的时间,通宵写成了这个,确切的说是改成了这个集成了中国电信相关参数的apns-conf.xml文件,借阅请说明出处,谢谢

android:apn相关资料

APN全称是Access Point Name,中文即接入点,是通过手机上网时必须配置的一个参数,它决定了手机通过哪种接入方式来访问网络。 android系统把所有的APN都保存在数据库中,数据库绝对路径:/data/data/com.android.providers.telephony/databases/telephony.db。 使用adb命令可以把该数据库导出查看: adb ...

daibalusu 218

Easy APNs Provider.app

这是一款为iOS、Mac app提供推送测试的小工具。 您可以使用该工具为您的App发送Apple提供的推送信息,您可以使用便利构造器构造简易Payload,也可以使用原始方法手动写入Json字典来构造Payload。 为了发送推送,您需要加入一个或多个待推送设备的令牌(Token),一共有三种加入方式:手动输入、文件读取、网络发送。添加令牌时记得为您刚刚添加的令牌命名(可随意起名)。

EG25-G的so库和apn-config.xml

EG25-G的so库和apn-config.xml

Android 3G通信

原创Android——4.2 - 3G移植之路之 APN (五) APN(Access Point Name),也就是 接入点 ,移动设备使用数据流量上网必须配置的一个参数,代表以何种方式来连接服务台开启数据流量功能. 一般有访问WAP或者connect 因特网,国内的运营商2G,3G标识如下: 移动公司:2G:GSM、3G:TD-SCDMA 联通公司:2G:GSM、3G:WCDMA 电信公司:2G:CDMA、3G:CDMA2000 关于具体某个运营商的几G网络 的APN 是什么具体可参考/dev...

linuxarmsummary的专栏 243

xxl-conf-admin gradle项目源码+postgresql改造

该资源是改自xxl-conf-admin 将原本用于maven构建的改为gradle构建的,数据库改为postgresql以及做了对应修改,详情可以参考:https://blog.csdn.net/cdnight/article/details/86437673 注意,原本作者是许雪里大神,网址是: https://www.cnblogs.com/xuxueli/p/4777808.html

Android MID 3G 移植

分类: 3G android2012-05-31 11:26 2796人阅读 评论(2) 收藏 举报 android华为symlinkstream中兴filter 市面上大多数MID使用的3G模块一般都是使用中兴、华为的, 在项目中本人调试过中兴的MU301 TD模块、华为的EM770w WCDMA模块。 本文基于华为的EM770w WCDMA模块进行讲述。

kerson的专栏 1828

BookSim2.0 教程

本文是yz关于BookSim2.0的个人学习经验与教程。 1.介绍 什么是BookSim2.0 BookSim2.0 是周期正确的互联网络模拟器(A Cycle-Accurate Interconnection Network Simulator),被设计用来伴随William James Dally 等人出版的的书籍 Principles and Practices of INterconnection on Networks使用。 此后其功能不断得到扩展。当前的主要版本 BookSim 2.0 支持广泛

更新一些计算机体系架构NoC,GEM5, AXI4,还有machine learning 的日常 5736

ROS下UR+Realsense相机进行手眼标定

手眼标定主要是用来确定相机坐标系和机械臂坐标系之间的转换关系,从而实现后续的抓取等任务。

weixin_42157689的博客 7573

android 3G功能移植

曾几何时在Android2.1下调试3G模块,曾几何时模块厂商提供的库不能用,曾几何时只能用自己的库痛苦地调试...这一切的一切都已成往事,昔日的成功在毫无保留下成为浮云,该忘了忘记了,该记得也跟着忘记了。现如今再次调3G模块,却不知道以前如何调试,看来还是要记下来。 我采用的是华为EM770W模块,支持WCDMA网络,由于华为提供的库只支持Android2.2,所以用Android2.1就需要

sunnywalden 4353

FastAPI 极简教程(偏实战,一篇搞定)

本文是一篇FastAPI实战教程,通过最少的概念讲解快速掌握FastAPI的核心功能。文章首先介绍FastAPI是基于Starlette和Pydantic的高性能Python API框架,具有自动生成文档、类型驱动校验、异步支持和依赖注入等优势。教程从安装环境开始,演示了如何创建最小项目并编写第一个"Hello World"接口。接着详细讲解了路由参数处理(Path/Query/Body)、Pydantic数据模型校验、响应模型控制、状态码设置等核心功能。在高级功能方面,重点介绍了错误处

AI天才研究院 814

Android平台开发-3G function porting-3G功能移植

Android平台开发-3G function porting-3G功能移植 2012-03-19 00:33:00 分类: LINUX 曾几何时在Android2.1下调试3G模块,曾几何时模块厂商提供的库不能用,曾几何时只能用自己的库痛苦地调试...这一切的一切都已成往事,昔日的成功在毫无保留下成为浮云,该忘了忘记了,该记得也跟着忘记了。现如今再次调3G模块

Sam 的专栏 1760

华为OD机试2025C卷真题题库目录|机考题库 + 算法考点详解

本文整理华为OD 2025C卷 机试(机考)题库,提供高频考点精析与详细题目内容,提供Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解

qq_45776114的博客 3988

vue3 - 详细实现用户收货地址识别解析“姓名/手机号/省市区/街道/乡镇村庄“关键字,用户复制粘贴一段含有姓名电话/详细地址的文字文本信息,vue3自动识别拆分并填入到对应表单字段中,详细示例代码

vue3,nuxt3,快递地址读取,收货地址解析、快递地址解析、物流地址解析自动识别,收货地址解析,从发货地址中拆出姓名电话地址,根据粘贴的字符串提取姓名地址,vue3地址信息自动识别,ts,vue3智能识别地址,提取姓名电话地址信息,自动识别出省市区街道姓名手机号等,根据文本自动解析出收货信息,怎么识别文本中的手机号,粘贴板地址识别,地址智能识别,如何识别收货地址中的关键字,粘贴一段文字后,自动识别到姓名/手机号/收货地址,vue3仿淘宝地址智能识别解析实现,省市区街道智能解析,vue3收货地址,识别地址

✅ 精选推荐文章 5501
上一篇: Android——4.2 - 3G移植之路之 AT 通信 (四)
下一篇: Android——4.2 蓝牙 BlueTooth 初探入门 (一)
南丶烟
博客等级 码龄14年 569粉丝 98原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值