《Framework中的TelephonyManager分析.docx》由会员分享,可在线阅读,更多相关《Framework中的TelephonyManager分析.docx(11页珍藏版)》请在三一办公上搜索。
1、Framework中的TelephonyManager分析Framework中的TelephonyManager分析 目录(?)- 一TelephonyManager的作用 二TelephonyManager方法的实现 得到SystemService的过程 Atelephonyregistry服务 Biphonesubinfo服务 Cphone服务 TelephonyManager方法的具体实现 Atelephonyregistry扩展的方法 Biphonesubinfo扩展的方法 Cphone扩展的方法 三TelephonyManager自身的注册 TelephonyManager的注册过程
2、 如何得到TelephonyManager对象 TelephonyManager的注册本质 四TelephonyManager存在的意义 五为什么TelephonyManager只整合了3个SystemService 一、TelephonyManager的作用 我们先来谈谈TelephonyManager的作用。 对于这个问题,我们看TelephonyManager提供的几个重要接口就可以知道: javaview plaincopy /得到软件版本 getDeviceSoftwareVersion /得到设备的ID,IMEI或者MEID getDeviceId /得到位置信息,主要是当前注册小
3、区的位置码 getCellLocation /得到附近小区信息 getNeighboringCellInfo /得到当前Phone的类型,GSM/CDMA getCurrentPhoneType /得到/proc/cmdline文件当前的内容 getProcCmdLine /得到运营商名字 getNetworkOperatorName /得到MCC+MNC getNetworkOperator /得到是否漫游的状态 isNetworkRoaming /得到网络状态,NETWORK_TYPE_GPRS、NETWORK_TYPE_EDGE、NETWORK_TYPE_CDMA等等 getNetwor
4、kType /得到SIM卡状态 getSimState /得到SIM卡MCC+MNC getSimOperator /得到SIM卡SPN getSimOperatorName /得到SIM卡串号 getSimSerialNumber /得到MSISDN getMsisdn /得到语音信箱号码 getVoiceMailNumber /得到语音信箱短信条数 getVoiceMessageCount /得到语音信箱名称 getVoiceMailAlphaTag /得到数据连接状态:DATA_DISCONNECTED、DATA_CONNECTING、DATA_CONNECTED、DATA_SUSPEN
5、DED等 getDataState /注册监听器监听Phone状态 listen /得到所有Phone的信息 getAllCellInfo 从以上提供的接口可以看出,TelephonyManager作为一个“Manager”,主要提供Phone模块各种信息的查询和监听服务。这些信息既包括设备的状态,也包括SIM卡的状态,还包括网络的状态,这都是上层应用比较关心的信息。 那么他是如何实现这些功能的呢?我们接下来介绍。 二、TelephonyManager方法的实现 准确的讲,TelephonyManager并不是一个标准的服务,因为他既没有继承自任何其他的Service,也没有把自己注册给 Sy
6、stemService,他只是一个普通的类,没有继承任何父类或接口。那么他是如何实现上面提到的方法呢? 原因说起来也简单,TelephonyManager在自己内部同时申请了三个SystemService的代理对象,当我们向TelephonyManager查询状态或注册监听时,TelephonyManager间接的将相应的请求发给系统服务,从而实现相应的功能。 下面我们先来介绍如何得到的SystemService,再来看如何通过这些SystemService实现TelephonyManager的接口。 2.1、得到SystemService的过程 在TelephonyManager内部注册了一
7、下3个SystemService: A:telephony.registry服务;TelephonyRegistry.java B:iphonesubinfo服务;PhoneSubInfoProxy.java C:phone服务;PhoneInterfaceManager.java 我们分别来看一下如何得到的这些Service A、telephony.registry服务 这个服务是在TelephonyManager构造函数中得到的,他的主要作用就是对信号、呼叫转移、位置改变、数据连接状态等信息的监听。 javaview plaincopy public TelephonyManager(Co
8、ntext context) if (sContext = null) Context appContext = context.getApplicationContext; if (appContext != null) sContext = appContext; else sContext = context; sRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(telephony.registry); B、iphonesubinfo服务 这个服务是在getSubscriberInfo接口中得
9、到的,通过这个服务可以得到软件版本、设备ID、SIM卡串号、语音信箱等信息。 javaview plaincopy private IPhoneSubInfo getSubscriberInfo return IPhoneSubInfo.Stub.asInterface(ServiceManager.getService(iphonesubinfo); C、phone服务 这个服务很特殊,是在Phone模块中注册给系统的,主要功能是Phone模块相关状态的查询和处理,包括位置服务、小区注册信息、当前网络状态、是否有SIM卡插入、以及SIM卡状态等信息。在TelephonyManager中是通过
10、getITelephony接口得到的这个服务: javaview plaincopy private ITelephony getITelephony return ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE); 通过以上3个接口,就得到了3个SystemService。下面我们分析,如何在TelephonyManager中通过这3个SystemService扩展其他的方法。 2.2、TelephonyManager方法的具体实现 我们知道,TelephonyManager的方法
11、是通过3个SystemService去扩展的,那么我们顺着SystemService去分析,看通过这3个SystemService可以扩展出哪些方法。 A、telephony.registry扩展的方法 首先来看利用sRegistry对象扩展的方法,其实就是telephony.registry服务的扩展功能: javaview plaincopy public void listen(PhoneStateListener listener, int events) String pkgForDebug = sContext != null ? sContext.getPackageName :
12、 ; try Boolean notifyNow = (getITelephony != null); /通过TelephonyRegistry注册监听器 sRegistry.listen(pkgForDebug, listener.callback, events, notifyNow); catch (RemoteException ex) catch (NullPointerException ex) 通过telephony.registry扩展的功能只有这一个,这个listen方法的作用就是去注册Phone状态的监听器。我们在 TelephonyRegistry服务的介绍中讲到,客户端
13、在得到这个服务后,可以通过listen的方法去注册某个事件的监听器,当这个事件发生时, 就会调用所有曾经注册的客户端的回调函数,通知客户端。 B、iphonesubinfo扩展的方法 上面说道,通过这个服务可以得到软件版本、设备ID、SIM卡串号、语音信箱等信息,具体来说主要的方法有: javaview plaincopy /得到软件版本信息 public String getDeviceSoftwareVersion return getSubscriberInfo.getDeviceSvn; /得到设备ID public String getDeviceId return getSubsc
14、riberInfo.getDeviceId; /得到SIM卡串号 public String getSimSerialNumber return getSubscriberInfo.getIccSerialNumber; /得到语音信箱 public String getVoiceMailNumber return getSubscriberInfo.getVoiceMailNumber; C、phone扩展的方法 通过这个SystemService得到的方法主要有: javaview plaincopy /得到位置信息 public CellLocation getCellLocation
15、Bundle bundle = getITelephony.getCellLocation; if (bundle.isEmpty) return null; CellLocation cl = CellLocation.newFromBundle(bundle); return cl; /得到附近小区信息 public List getNeighboringCellInfo return getITelephony.getNeighboringCellInfo; /得到当前Phone状态 public int getCurrentPhoneType ITelephony telephony
16、= getITelephony; if (telephony != null) return telephony.getActivePhoneType; else return getPhoneTypeFromProperty; /判断是否有SIM卡插入 public boolean hasIccCard return getITelephony.hasIccCard; 三、TelephonyManager自身的注册 上面的第二节中介绍了TelephonyManager内部实现原理,那么面对如此好用又强大的信息提供者,我们如何去使用呢? 在介绍使用方法之前,我们先来看看这个类的“注册”过程,了
17、解了他的“注册”方法,我们自然就会明白如何使用他。 3.1、TelephonyManager的“注册”过程 在第二节开始的地方我们讲过,TelephonyManager既不是服务,也没有注册给SystemService,他甚至没有继承自任何父类或接口。因此他的“注册”过程并不是严格意义上的“注册”。 javaview plaincopy ContextImpl.java registerService(TELEPHONY_SERVICE, new ServiceFetcher public Object createService(ContextImpl ctx) return new Tel
18、ephonyManager(ctx.getOuterContext); ); 我们继续看registerService: javaview plaincopy private static void registerService(String serviceName, ServiceFetcher fetcher) if (!(fetcher instanceof StaticServiceFetcher) fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex+; SYSTEM_SERVICE_MAP.put(servic
19、eName, fetcher); 以及TELEPHONY_SERVICE: javaview plaincopy private static final HashMap SYSTEM_SERVICE_MAP = new HashMap; 上面三段代码说明这样一个事实:在ContextImpl中,我们new了一个TelephonyManager对象,并把这个对象通过registerService的方法放到了一个SYSTEM_SERVICE_MAP的HashMap中。这个过程,就是TelephonyManager所谓的“注册”过程。 那么我们如何得到TelephonyManager对象呢? 3.
20、2、如何得到TelephonyManager对象 javaview plaincopy public Object getSystemService(String name) ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name); return fetcher = null ? null : fetcher.getService(this); 这个过程也很容易理解,就是通过getSystemService接口从SYSTEM_SERVICE_MAP中找到TelephonyManager的对象,并返回出来。 3.3、TelephonyManag
21、er的注册本质 从TelephonyManager的注册和得到的过程我们看出,其实所谓的“注册”,就是在ContextImpl中new一个TelephonyManager的对象,并保存在HashMap中。 我们可以通过Context的getSystemService方法去得到这个对象,也就是TelephonyManager这个“服务”。 四、TelephonyManager存在的意义 此时我们再来谈谈TelephonyManager存在的意义,也就是说,为什么需要构建这么一个东西来同时注册3个SystemService? 假如现在有3个模块A、B、C,都需要做一些Phone有关的操作,他么的需
22、求如下: A模块:需要用到TelephonyRegistry和PhoneSubInfoProxy的服务,那么他就要去分别申请这两个服务的代理对象; B模块:需要用到TelephonyRegistry和PhoneInterfaceManager服务,他也需要分别申请代理对象。 C模块:需要用到上面的3个服务,那么就需要申请3个代理对象。 对于这样的情况,我们当然可以在每个需要的模块内部分别调用系统接口去得到相应的代理对象。这种情况下我们需要调用7次getService方法得到7个SystemService的远程对象。 如果通过TelephonyRegistry的方式去实现呢? 此时我们只需要在3
23、个模块中,分别调用Context的getSystemService方法就能同时得到3个SystemService远程代理对象。 而且我们得到的3个TelephonyManager对象是同一个对象,3个模块公用了同一个SystemService。因此,我们实际上只调用了3此 getService方法,得到了3个SystemService远程对象。 这个例子说明,TelephonyManager整合3个SystemService的意义就在于减轻系统负担,特别是一些SystemService的负担,同时提高了访问效率。 五、为什么TelephonyManager只整合了3个SystemService
24、? 既然TelephonyManager大大减轻了一些SystemService的负担,为什么只整合了3个SystemService呢?或者说,为什么选中了这3个SystemService来整合呢? 我们再来梳理以下TelephonyManager的运行原理。经过TelephonyManager的整合,当我们通过Context去得到 TelephonyManager对象时,得到的是同一个TelephonyManager对象,那么我们进一步得到的SystemService也是同 一个,此时我们调用TelephonyManager中的方法时,得到的返回值也是完全相同的。 这就说明了,TelephonyManager整合的SystemService,有一个共同特点:这些服务无论谁去调用,方法的返回值都是相同的。比如SIM卡的状态、当前的运营商信息、设备的ID号等。 而对于存在差异的SystemService,由于对于不同的客户端需要返回不同的值,当然就无法放到TelephonyManager中处理了。