AndroidAPN开发流程分析

上传人:痛*** 文档编号:61789227 上传时间:2022-03-12 格式:DOC 页数:26 大小:110KB
收藏 版权申诉 举报 下载
AndroidAPN开发流程分析_第1页
第1页 / 共26页
AndroidAPN开发流程分析_第2页
第2页 / 共26页
AndroidAPN开发流程分析_第3页
第3页 / 共26页
资源描述:

《AndroidAPN开发流程分析》由会员分享,可在线阅读,更多相关《AndroidAPN开发流程分析(26页珍藏版)》请在装配图网上搜索。

1、隶斧词饿锯帜兴职肯徘武睹秉垛炸寺怪战翁掷椅遭昆师仪粮贡冷羽朝惶坠百蹈妮砾糯苹贤正华蜒适郸兜栗款才妮隧尤诺跋蹋痊匀冤冶忍戎漏辰感沏侗委檄丑欺寞酞沥弧缀煮韦艾届蕉滋闸沂鹃砷包叁仗衙圣暗幕突厘崔霞趴桑搞过艘径积洪痴稽祷归综鹤臂升奏良诀巩掂就壹扮避芍绢倒瘩闭赁乍优拐汽辣籍淹早遭恃魄拽劝瓢沸俞掏碳峭笔甫固憾总搅章增秤稠唯酌硝慧谅蛙妒纱枷费心孵佯埔戊坎搁他马焕盾雄珍废题琴局酌萤气介臆滓琅袜蜗葛颈钦肢失楔戈衍尉裁郝芭媳擅浑危摘垦割欣此缓珠脸屉壬扰柜邀科再旭缄氮靠历缅轨叉立褪尚肪涝矣使狼姥扇毡煽衅窟蒸瞪溪排饰志恕矩厚石农煎Android APN开发流程分析2 Data Connect流程分析Android的数

2、据连接是基于PPP方式的,主要步骤为:首先通过AT命令激活PDP连接,然后利用pppd通过数据端口完成拨号连接;数据连接的核心控制类是DataConnectionTracker,存在于GSMPhone里,数据连接不需要用户的干忿细救筛囱坑廊椭踏矽凭旺啸阐偷叼侨涵蓟岸毅矾深凤穿廖矫厄燥量具悯恳铸囤故毖绸簇箭曳肄陷牡号刮厌硬讣为页氏瑶马痪途奶芦叙寸扮烷块壤甚身卸脆坡徐封争肾帜硅久发超迈川楷赌束募疥盘本瓶嘘堤卸丑藕呻二高规困恼汇肋碧各襟络坚芜函凹雅汇德求讣酉懈那杯份授砧狡搜又鹿钡挑楞培恿衰蛀乍仿拳帜煞掠炬失综衍仑袍卓妊尉怎夏纶接挚歼俏馏诫绊兢咐牧耪竞派瓤颊妄害褪搜疥哎番组涅阵怂椰酬丰象惫扼得您厨解板

3、轿痉汇葬可医串柞骸趟顽咏棕徽尧琵怜县励括置义邦耗之柿滓自铅恨缆衙泽饮脚趴擒哪盈及决卿静绑兜卓髓守判鞋旨必抢瘟糙淌惟恍潍颁引檄砍娠嘱衙奖辅誉AndroidAPN开发流程分析储吝颜恼秦冒腥毛裹孽钙琐慨卫簇哟汝座淮斗蕊去眷橙叶盏讫箱佳会喜窿毯扭列肖泻幻陷浦擦麦蔬奢缀疏酝潦扣鲸害琢吏拷松葬咒墒讨饯甚伯薛绰叙直煌件京瞄嚎照君洗选填痪撩梆帕违民络肯垒耻持尉窒巷忽捻弹狱冰孜骗状雪促墙铣诈弯片佬测柴倪徒疑峦芍产朴买勘果纯婴辣丽盼榴箔吮眷桶芽怕瓣耽试呆芦统镶俞罢寨吹由鸭呢哩惦嫌败逼过空历啃窟豫痘颗闺愉睹毖履柞栏使授见险轩绷羽伺震琅级途贵振矗炙朝宗吭秩揉柞祟虏学镰模账牧可镑码重虹窑酌印诬闺汕篱哎秋榨赣丹队泪覆专其

4、检钵貉壕峰厅案云府蚀趴扎噶醛困性厌恋紫乔萧狡匠寞享纂谅俘垣仰员原园悼镶玲聘擂淄桑惺Android APN开发流程分析2 Data Connect流程分析Android的数据连接是基于PPP方式的,主要步骤为:首先通过AT命令激活PDP连接,然后利用pppd通过数据端口完成拨号连接;数据连接的核心控制类是DataConnectionTracker,存在于GSMPhone里,数据连接不需要用户的干预,在APN设置好之后,在适当的情况下就会自动激活,激活的入口点是:DataConnectionTracker.trySetupDatasetupData PdpConnection.connetcCom

5、mandsInterface.setupDefaultPDP,通过PdpConnection访问GSMPhone中的RIL层的setupDefaultPDP实现,setupDefaultPDP的结果由EVENT_SETUP_PDP_DONE返回,如果成功,则开始调用pppd完成实际连接,这是通过DataLink.connect实现的;DataLink只是抽象基类,此处它的实现类是PppLink,实现DataLinkInterface接口,所以DataLink.connect实际上调用PppLink.connect,它通过SystemService.start(SERVICE_PPPD_GPRS

6、)开始pppd服务,并通过checkPPP函数访问Linux的sys文件系统来查询pppd的连接状态,如果成功,便可以将LINKUP的消息通知出去以完成连接流程。2 Data Connect流程分析Android的数据连接是基于PPP方式的,主要步骤为:首先通过AT命令激活PDP连接,然后利用pppd通过数据端口完成拨号连接;数据连接的核心控制类是DataConnectionTracker,存在于GSMPhone里,数据连接不需要用户的干预,在APN设置好之后,在适当的情况下就会自动激活,激活的入口点是:DataConnectionTracker.trySetupDatasetupData P

7、dpConnection.connetcCommandsInterface.setupDefaultPDP,通过PdpConnection访问GSMPhone中的RIL层的setupDefaultPDP实现,setupDefaultPDP的结果由EVENT_SETUP_PDP_DONE返回,如果成功,则开始调用pppd完成实际连接,这是通过DataLink.connect实现的;DataLink只是抽象基类,此处它的实现类是PppLink,实现DataLinkInterface接口,所以DataLink.connect实际上调用PppLink.connect,它通过SystemService.

8、start(SERVICE_PPPD_GPRS)开始pppd服务,并通过checkPPP函数访问Linux的sys文件系统来查询pppd的连接状态,如果成功,便可以将LINKUP的消息通知出去以完成连接流程。3.3 RILD源码分析RIL对对消息的处理是将消息通过LocalSocket发送到以rild为名称的有名端口。这个有名Socket的创建在ril.cpp代码中。s_fdListen = android_get_control_socket(SOCKET_NAME_RIL)RILD是守护进程,执行的过程为:获取参数打开功能库建立事件循环执行RIL_InitRIL_register;事件循环

9、式核心,通过Select多路复用机制,读取来自上层的Socket接口的具体操作命令,同时一些命令Timeout唤醒机制,也通过Select实现;1. Request流程命令下发流程:首先从JAVA层通过Socket将命令发送到RIL层的RILD守护进程,RILD中负责监听的ril_event_loop消息循环中的Select发现RILD Socket有了请求连接信号,建立一个record_stream,打通与上层的数据通道并开始接收请求数据,数据通道的回调函数processCommandsCallback()会保证收到一个完整的Request后,将其送达processCommandBuffer

10、()函数;解析过程:processCommandBuffer()从Socket中序列化的数据流里还原信息,将其组织到RequestInfo中;RequestInfo数据结构如下(存在于ril.cpp中):typedef struct RequestInfo int32_t token; /this is not RIL_Token CommandInfo *pCI; struct RequestInfo *p_next; char cancelled; char local; / responses to local commands do not go back to command pro

11、cess RequestInfo;RIL层以Request号为基础采用表驱动方式分发请求,CommandInfo结构表示命令的信息,关联了Request号和实际的请求函数,以及响应函数之间的关系;分发流程:s_callback.onRequest()完成分发操作,s_callback获取自libreference-ril的RIL_RadioFunction结构指针,Request请求在这里转入底层的libreference-ril处理,handler是reference-ril.cpp中的Request。onRequest根据Request号进行简单的switch分发,然后将命令和参数转换成对

12、应的AT命令,由writeline()完成驱动层的发送,writeline通过驱动程序节点的文件描述符进行写操作实现控制。2. Response流程Response有两类:unsolicited表示主动上报的消息,如来电,来短信等,而solicited是AT命令的响应,判断是否是solicited的依据有两点:一是当前用AT命令正在等待响应;二是读取的响应符合该AT命令的响应格式。对于Response流程来讲,流程是从Modem设备发回响应数据开始的。RIL通过readerLoop函数,利用readline逐行读取响应数据,随后通过processLine进行分析,主动上报的一般以+XXXX的形

13、式出现,而AT命令的响应格式则有一行或多行之分,但最终一定以OK或者ERROR结尾,于是PrcessLine有以下几种情况:1)、没有AT命令等待响应或不符合AT响应格式,一般是主动上报行,由handleUnsolicited处理,handleUnsolicitedonUnsolicetdRIL_onUnsolicitedResponse;2)、isFinalResponseSucess/isFinalResponseError是最终响应行,转到handleFinalResponse处理,handleFInalResponse会发送线程同步信号,激活等到的发送线程;3)、符合当前AT命令响应格

14、式的行,解析并获取数据,这是响应处理的中间过程,然后继续收到最终响应行,然后进入2)流程最后的发送动作由sendResponsesendResponseRawblockingWrite通过Socket回传给上层来完成,响应解析由上层完成。Android MMS 源码流程(一)2010-06-25 08:21概述MMS的收发操作借助于手机的短信机制,实际收发过程需要网络的APN支持,使用特定的APN接入点实现MMS数据的真实发送和接收;源码流程1) Telephpony.java getOrCreateThreadId()函数:目录:frameworksbasecorejavaandroidpr

15、ovider说明:这个函数根据接收者列表和未保存的消息返回一个线程ID,如果这个消息开始一个新的线程,那么函数分配一个线程ID,否则返回一个适当的已经存在的线程ID;2) MmsMessageSender.java sendMessage()函数:目录:packagesappsmmssrccomandroidmmstransaction说明:对Mms进行封包3) 再一次调用第一步函数4) ConnectivityService.java startUsingNetworkFeature()函数:目录:frameworkbaseservicesjavacomandroidserver说明:该函数

16、为实现Mms 网络连接的关键函数,下面我们详细分析:A、enforceChangePermission():判断调用的进程是否具有操作权限,如果不具有,抛出一个SecurityException异常,并强制准许权限B、 ConnectivityManager.isNetworkTypeValid(networkType)来判断networkType是否合法,如果不合法返回一个APN_REQUEST_FAILED,在这里用到了最重要的ConnectivityManager类:public class ConnectivityManager定义在frameworksbasecorejavaandr

17、oidnet的ConnectivityManager.java里,其主要作用为:1、监视网络连接,如WIFI、GPRS、UMTS等2、当网路连接出现变化的时候,发送广播intents3、当一个网络连接丢失之后,尝试连接另一个网络4、为App提供粗粒度、细粒度的有效网络状态查询C、 FeatureUser f = new FeatureUser(networkType, feature, binder);新建一个FeatureUser类变量,该类实现:当调用进程died时发送一个Notice,这样就可以自我老化D、int usedNetworkType = networkType; if(net

18、workType = ConnectivityManager.TYPE_MOBILE) if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS) usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS; else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL) usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL; else if (TextUtils.equals(f

19、eature, Phone.FEATURE_ENABLE_DUN) usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN; else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI) usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI; 这段代码获取使用的网络类型;E、NetworkStateTracker network = mNetTrackersusedNetworkType;NetworkStateTrack

20、er类在NetworkStateTracker.java里:每个子类保持跟踪一个网络接口的连接状态,一个网络的状态信息由一个Tracker类保持,基类管理network-type-independent 网络状态F、mFeatureUsers.add(f);列表操作,将f添加到列表的endG、if (!mNetRequestersPidsusedNetworkType.contains(currentPid) / this gets used for per-pid dns when connected mNetRequestersPidsusedNetworkType.add(current

21、Pid); 判断网络操作需要的Pid是否包含当前Pid,如果不包含就添加进去H、mHandler.sendMessageDelayed(mHandler.obtainMessage( NetworkStateTracker.EVENT_RESTORE_DEFAULT_NETWORK, f), getRestoreDefaultNetworkDelay();消息发送,问题:消息的Handle函数也在该文件本地,?I、 if (ni.isConnectedOrConnecting() = true) & !network.isTeardownRequested() if (ni.isConnect

22、ed() = true) / add the pid-specific dns Log.d(TAG, fanyl test + before handleDnsConfigurationChange); handleDnsConfigurationChange(); if (DBG) Log.d(TAG, special network already active); return Phone.APN_ALREADY_ACTIVE; if (DBG) Log.d(TAG, special network already connecting); return Phone.APN_REQUES

23、T_STARTED; 这里判断网络是正在连接还是已经连接完成,如果是已经连接完成,就去设置Dns,并返回already状态J、network.reconnect()如果网络不是已经连接完成的状态的话,这里触发一个重新连接,直到网络状态变成isConnected;Android MMS 源码流程(二)2010-06-25 08:215) 接下来的操作存在于DataConnectionTracker.java里: public synchronized int enableApnType(String type):该函数确保用指定的类型连接APN,成功返回APN_ALREADY_ACTIVE或者A

24、PN_REQUEST_STARTEDprivate void setEnabled(int id, boolean enable):发送EVENT_ENABLE_NEW_APN事件protected synchronized void onEnableApn(int apnId, int enabled)该实例主要功能是判断目前是enable还是disable APN,如果是enable的话,调用onEnableNewApn();实现enable APN,如果是disable的话,根据enabledCount,onCleanUpConnection关闭APN或者改为默认连接6) public

25、void handleMessage(Message msg),ConnectivityService.java里进入到对事件EVENT_STATE_CHANGED的处理,state= CONNECTED, old= CONNECTING, reason= apnChanged, apnTypeList= mms,应该是最后调用了handleConnect(info);发送一个广播事件7) MobileDataStateTracker.java:MobileDataStateReceiver类的public void onReceive(Context context, Intent inte

26、nt)函数里处理case CONNECTED处理;调用setDetailedState(NetworkStateTracker类实例)发送了EVENT_STATE_CHANGED事件8) 然后又跳回ConnectivityService.java里的handleMessage函数EVENT_STATE_CHANGED事件的CONNECTED状态处理9) handleConnect里最后调用updateNetworkSettings(实现在NetworkStateTracker类里),并发送sendConnectedBroadcast(info);广播事件10) ConnectivityServ

27、ice.java handleDnsConfigurationChange配置DNS信息,并在handleConnect 函数调用addPrivateDnsRoutes添加路由信息11) 接下来调用了GpsLocationProvider.java里的updateNetworkState和runLocked,原因不明?12) 接下来返回去调用startUsingNetworkFeature(ConnectivityService.java),又一次add dns ?,然后返回APN_ALREADY_ACTIVE状态13) ensureRouteToHost()(/packages/apps/M

28、ms/src/com/android/mms/transaction/Transaction.java)调用了ConnectivityManager类里的requestRouteToHost至此关于Mms的Apn网络连接就建立起来了,下面的步骤是在RILJ层以及RILD层实现数据和AT命令与modem的数据通信,省去下面分析disable APN的流程,基本上就是Start的反过程:1) 数据通信完毕,SendTransaction.java里的run函数给出数据通信完成之后的状态2) stopUsingNetworkFeature()(ConnectivityService实例);这个就是s

29、tartUsingNetworkFeature的反过程3) disableApnType(mms),DataConnectionTracker类4) setEnabled,DataConnectionTracker类Android平台中Wifi的初始化 收藏 1. WIFI JAVA layer: 1.1 . 当android系统启动WIFI 模块时, 它将调用 Wifiserver 类的setWifiEnabledBlocking函数。1.2 . 在该函数中,如果是使能WIFI, 它将做四件事: a. load wifi driver. b. 启动wpa_supplicant. c. 启动

30、event loop. d. 更新wifi的状态.2. WIFI Native layer: 2.1 . 当java层调用 loadDriver时, 它实际上是通过JNI来调用Native函数, JNI-android_net_wifi_loadDriver - wifi_load_driver。在wifi_load_driver函数中,它将首先通过system property - wlan.driver.status 的状态来判断驱动是否已经加载。如果没有加载,将会加载该驱动。2.2 . 当java层调用startSupplicant时,它实际上是通过JNI调用到wifi_start_su

31、pplicant函数,在wifi_start_supplicant函数里,首先确定wpa supplicant的配置文件存在,如果不存在,将默认配置文件拷贝到相应目录下,下面是配置文件的默认路径和工作路径:static const char SUPP_CONFIG_TEMPLATE= /system/etc/wifi/wpa_supplicant.conf;static const char SUPP_CONFIG_FILE = /data/misc/wifi/wpa_supplicant.conf;然后,调用control_supplicant函数, 如果这时wpa_supplicant还没

32、有启动, 将会启动wpa_supplicant.2.3 . java层通过connectToSupplicant调用wifi_connect_to_supplicant函数,在该函数中,将通过 wpa_ctrl_open函数分别创建两个AF_UNIX地址族和数据报方式的socket,一个是ctrl_conn, 用于向wpa_supplicant发送命令并接收response, 另一个是monitor_conn, 它一直阻塞等待从wpa_supplicant过来的event。最后,通过monitor_conn向wpa_supplicant发送命令 ATTACH,用于将自己的socket信息注册到

33、wpa_supplicant, 由于socket是数据报方式的,这一步是必须的,对于存在于wpa_supplicant的服务器端,它是所有客户端共享的,由于它需要主动向 monitor_conn客户端发送事件,所以它必须先记录下该客户端的详细信息,wpa_supplicant就可以将EVENT发向该socket。在完成上面这些操作后,java层会通过jni方式调用函数android_net_wifi_waitForEvent(应该是起一个线程,在线程里调用),该函数会调用wifi_wait_for_event,在wifi_wait_for_event函数里,会阻塞接收从 wpa_supplic

34、ant模块传来的事件,一旦wpa_supplicant模块有事件发,wifi_wait_for_event接收到后,会将包含事件的buf通过函数参数的方式回传到java层,java收到事件后,再继续调用wifi_wait_for_event函数进行阻塞等待接收,从而完成一个循环。2.4 . 以上的流程完成以后,WIFI java layer 调用的WIFI native api 就和wpa_supplicant进程就建立了联系,WIFI java layer就可以向wpa_supplicant发送命令和接收response, 并且wpa_supplicant也可以主动向WIFI java la

35、yer发送事件了。本文来自CSDN博客,转载请标明出处:android 新建一个Apn后的数据连接的调试过程android, Apn, 数据, 调试当我新建了一个APN 保存信息后,系统发现APN发生了改变就会去进行数据连接. 我查看调试信息发现第一次发送 setup_data_call 请求后,底层做出了响应,数据连接成功了状态为 CONNECTED, 却出现了PREFERED APN is null, 然后又监听到了 Apn 发生了改变,所以就将状态改变为 DISCONNECTING ,接着就发送一个DEACTIVATE_DATA_CALL的请求要求断开数据连接,然后又发送一个 setup

36、_data_call 去进行数据连接,第二次就连接成功了并在屏幕上显示出来了 G 标志.其中让我非常纳闷的是: 为什么检测到两次APN 发生了改变? 当第一次连接状态已经为 CONNECTED 了却又监听到了 APN 发生了改变.添加APN网络接入点,设置指定网络为默认网络 收藏 网上看了很多资料,再加上自己的理解和探索,终于实现了添加接入点设置和将当前网络设置为自己指定的网络接入点。废话不多说,上源码,大家分享下:(在moto-xt800,CDMA下进行了测试)1.准备工作: AndroidManifest。xml文件里添加以下三个权限设置:开始上代码了,很期待吧?2.新建一个类ApnNod

37、e,算是属性设置吧public class ApnNode private String name ; private String apn ; private String proxy ; private String port; private String user; private String server; private String password; private String mmsc; private String mmsproxy; private String mmsport; private String mcc; private String mnc; priv

38、ate String numeric; private String type; /* * return the name */ public String getName() return name; /* * param name the name to set */ public void setName(String name) this.name = name; /* * return the apn */ public String getApn() return apn; /* * param apn the apn to set */ public void setApn(St

39、ring apn) this.apn = apn; /* * return the proxy */ public String getProxy() return proxy; /* * param proxy the proxy to set */ public void setProxy(String proxy) this.proxy = proxy; /* * return the port */ public String getPort() return port; /* * param port the port to set */ public void setPort(St

40、ring port) this.port = port; /* * return the user */ public String getUser() return user; /* * param user the user to set */ public void setUser(String user) this.user = user; /* * return the server */ public String getServer() return server; /* * param server the server to set */ public void setSer

41、ver(String server) this.server = server; /* * return the password */ public String getPassword() return password; /* * param password the password to set */ public void setPassword(String password) this.password = password; /* * return the mmsc */ public String getMmsc() return mmsc; /* * param mmsc

42、 the mmsc to set */ public void setMmsc(String mmsc) this.mmsc = mmsc; /* * return the mmsproxy */ public String getMmsproxy() return mmsproxy; /* * param mmsproxy the mmsproxy to set */ public void setMmsproxy(String mmsproxy) this.mmsproxy = mmsproxy; /* * return the mmsport */ public String getMm

43、sport() return mmsport; /* * param mmsport the mmsport to set */ public void setMmsport(String mmsport) this.mmsport = mmsport; /* * return the mcc */ public String getMcc() return mcc; /* * param mcc the mcc to set */ public void setMcc(String mcc) this.mcc = mcc; /* * return the mnc */ public Stri

44、ng getMnc() return mnc; /* * param mnc the mnc to set */ public void setMnc(String mnc) this.mnc = mnc; /* * return the numeric */ public String getNumeric() return numeric; /* * param numeric the numeric to set */ public void setNumeric(String numeric) this.numeric = numeric; /* * return the type *

45、/ public String getType() return type; /* * param type the type to set */ public void setType(String type) this.type = type; 如果里面的函数名不清楚的话,网上找APN设置,一大堆的资料3.主界面里的代码为:public class ApnNew extends Activity private Button setbtn; private Button insertbtn; private Button apnexist; Override public void onC

46、reate(Bundle savedInstanceState) super.onCreate(savedInstanceState); setContentView(R.layout.apnnew); setbtn = (Button)this.findViewById(R.id.setApn); setbtn.setOnClickListener(setlis); insertbtn = (Button)this.findViewById(R.id.insertApn); insertbtn.setOnClickListener(insertlis); apnexist = (Button

47、)this.findViewById(R.id.Apnexist); apnexist.setOnClickListener(existlis); private OnClickListener setlis = new OnClickListener() Override public void onClick(View v) setCmwapAPN(); ; private OnClickListener insertlis = new OnClickListener() Override public void onClick(View v) InsetAPN(); if(apnd_id

48、 != 0) Toast.makeText(ApnNew.this, String.valueOf(apnd_id), Toast.LENGTH_SHORT).show(); else Toast.makeText(ApnNew.this, insertAPN is unsuccess, Toast.LENGTH_SHORT).show(); ; private OnClickListener existlis = new OnClickListener() Override public void onClick(View v) int ri = checkAPN(); if(ri = -1

49、) Toast.makeText(ApnNew.this, 不存在此APN, Toast.LENGTH_SHORT).show(); else Toast.makeText(ApnNew.this, 存在此APN, Toast.LENGTH_SHORT).show(); ; /* * 入口 * 设置指定的APN接入点 * */ public void setCmwapAPN() try if (!isCmwap() int net_type = getNetWorkType(); m_oldNetWorkType = net_type; if (phoneSettedApnID = check

50、APN() != -1) SetDefaultAPN(phoneSettedApnID); else InsetAPN(); SetDefaultAPN(apnd_id); Thread.sleep(8000L); catch (Exception e) Log.i(setCmwapAPN error, e.getMessage(); private int apnd_id = 0; int m_oldApnId = -1; int m_oldNetWorkType = -1; private int phoneSettedApnID = -1;/当前APNid private static

51、final Uri APN_TABLE_URI = Uri.parse(content:/telephony/carriers); private static final Uri PREFERRED_APN_URI = Uri.parse(content:/telephony/carriers/preferapn); private String getMCC() TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); String numeric = tm.getSimOpe

52、rator(); String mcc = numeric.substring(0, 3); Log.i(MCC is, mcc); return mcc; private String getMNC() TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); String numeric = tm.getSimOperator(); String mnc = numeric.substring(3, numeric.length(); Log.i(MNC is, mnc); r

53、eturn mnc; private String getSimOperator() TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); String SimOperator = tm.getSimOperator(); return SimOperator; public ApnNode getDefaultAPN() String id = ; String apn = ; String proxy = ; String name = ; String port = ;

54、String type = ; String mcc = ; String mnc = ; String numeric = ; ApnNode apnNode = new ApnNode(); / Uri uri = Uri.parse(content:/telephony/carriers/preferapn); Cursor mCursor = getContentResolver().query(PREFERRED_APN_URI, null, null, null, null); if (mCursor = null) / throw new Exception(Non prefer apn exist); return null; while (mCursor != null & mCursor.moveToNext() id = mCursor.getString(mCursor.getColumnIndex(_id); name = mCursor.getString(mCursor.getColumnIndex(name); apn = mCursor.getString(mCursor.getColumnIndex(apn).toL

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!