打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
深入浅出

1.1  Sensor应用程序框架

这部分对于上层写应用的朋友来比较熟悉,我们通过一个简单的应用来分析框架层和底层的实现。

通常编写一个传感器的应用程序有以下步骤:

l  通过调用 Context.getSystemService(SENSOR_SERVICE)获得传感器服务,实现返回的是封装了SensorService的SensorManager对象

l  调用SensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION)来获得指定类型的传感器对象,方便获得传感器的数据

l  通过SensorManager.registerListener注册SensorEventListener监听器,监听获得的传感器对象,当传感器数据提交上来时,能被应用程序得到

l  实现监听器里传感器上报数据的具体操作

由编写应用程序的步骤可知,所有程序的操作都和SensorManager有关。在开始分析具体实现之前我们先来谈谈SensorManager概念。

1)    Android Manager机制

Manager中文直译是处理者,经理,管理人,总而言之,管事的人。用我的话说就是:有权有钱,屁事不干,指点江山,NB朝天。在Android的服务框架里Manager被安排作为经理人、领导,它负责自己管辖区的所有操作。类似于公司里的行政部门,它是一个纯粹非盈利服务部门,行政部门经理自己从来不干活,天天指挥别人干这干那,如果其它部门要想使用行政部门的服务,先要向行政经理提申请,申请通过了,安排具体人员为你服务。我们分析的是Sensor服务,Sensor服务用户程序不能直接访问,要通过SensorManager来访问,也就是说SensorManager是SensorService提供服务接口的封装。

通常在Android的Manager里都会维护对其管理Service的引用,用户程序提出Service操作申请,Manager将操作申请交由其管理的Service处理,然后将处理结果再交给用户程序或回调用户注册的监听接口。

 

总结:

1)      Manager是应用程序直接面对的接口

2)      Manager里维护对应的Service

3)      应用程序不能直接访问Service

为什么要这么设计??

使用Manager机制的好处是显而易见的:

l  Service是服务,服务是所有应用共享,不能属于某一个具体的进程,即:Android程序。

l  基于第一点,Android应用与Service在不同进程,它们之间必然要进行通信,要使用IPC,即:进程间通信,而框架的作用是让应用程序快速开发提供API,不可能让进程间通信的代码出现在Android应用中,这些所谓的后台操作不能让程序开发者感知到,即:隐藏通信手段与细节。

既然如此,那Google就给我们写一个Manager类,把共享服务隐藏起来,只暴露操作接口,操作细节,IPC细节统统后台去。

OK,理解了这个,可以看得出来,我们的之前写的LedHAL是如此的弱智,如此的没有规范,如此的不考虑框架设计,如此的不复用代码,如此…,太多了,没有办法,慢慢在后面再优化吧,差不多了,开始吧。

前面说了,使用Sensor服务要用SensorManager,让我们来看看一个简单应用的代码,再逐渐展开。

  1. public class SensorAppDemoActivity extends Activity implementsSensorEventListener{  
  2.   
  3.   private TextViewmTextView;  
  4.     /** Calledwhen the activity is first created. */  
  5.     @Override  
  6.     public voidonCreate(Bundle savedInstanceState) {  
  7.         super.onCreate(savedInstanceState);  
  8.         setContentView(R.layout.main);  
  9.         mTextView= (TextView) findViewById(R.id.mTextView);  
  10.   
  11.         // 得到SensorManager  
  12.        SensorManager sm = (SensorManager)this.getSystemService(SENSOR_SERVICE);  
  13.   
  14.         // 获得指定类型的传感器对象   
  15.         SensortempSensor = sm.getDefaultSensor(Sensor.TYPE_TEMPERATURE);  
  16.   
  17.         // 注册传感器对象的监听器  
  18.         sm.registerListener(this, tempSensor, SensorManager.SENSOR_DELAY_NORMAL);  
  19.     }   
  20.   
  21.   @Override  
  22.   
  23.   public voidonAccuracyChanged(Sensor sensor, int accuracy) {  
  24.            // TODOAuto-generated method stub  
  25.            // 未实现该方法  
  26.   }  
  27.   
  28.   @Override  
  29.   public void onSensorChanged(SensorEvent event) {  
  30.            // TODOAuto-generated method stub  
  31.            mTextView.setText("Currenttemperature is :" + event.values[0]);  
  32.   }  
  33. }  

上面代码很简单,得到温度传感器对象后,注册传感器事件监听器,当数据变化时在Activity上的TextView上显示温度。

现在我们分析每个步骤框架的实现:

先来看Context.getSystemService(SENSOR_SERVICE)。

2)    获得Sensor系统服务

上面代码里getSystemService(String)是在当前Activity里直接调用的,说明它不是Activity的方法就是其父类的方法,按照继承关系向上查找:

@frameworks/base/core/java/android/app/ContextImpl.java

  1. @Override  
  2. public Object getSystemService(String name) {  
  3.     ServiceFetcherfetcher = SYSTEM_SERVICE_MAP.get(name);  
  4.     returnfetcher == null ? null : fetcher.getService(this);  
  5. }  

这是什么?我恨Android新版本的代码,没有老版本的看着简单。先来看下SYSTEM_SERVICE_MAP是什么东西,看样子像映射关系:

  1. private static final HashMap<String,ServiceFetcher> SYSTEM_SERVICE_MAP =  
  2.             newHashMap<String, ServiceFetcher>();  

SYSTEM_SERVICE_MAP其实是一个哈希键值映射表,其Key为String类型,Value为ServiceFetcher类型,而我们获得服务时通过服务名来查找一个ServiceFetcher类型,并返回ServiceFetcher.getService()的结果作为SensorManager。

  1. static class ServiceFetcher {  
  2.         intmContextCacheIndex = -1;   
  3.   
  4.         publicObject getService(ContextImpl ctx) {  
  5.             // mServiceCache是ArrayList<Object>类型对象  
  6.               ArrayList<Object> cache =ctx.mServiceCache;   
  7.             Object service;  
  8.             synchronized (cache) {  
  9.             // 对于新创建的Activity mServiceCache里没有元素,所以size为0  
  10.                 if (cache.size() == 0) {           
  11.                      // Initialize the cache vector on first access.  
  12.                      // At this point sNextPerContextServiceCacheIndex  
  13.                      // is the number of potential services that are  
  14.                      // cached per-Context.  
  15.                      // sNextPerContextServiceCacheIndex为每个Android服务的索引值  
  16.                        for (int i = 0; i < sNextPerContextServiceCacheIndex; i++) {  
  17.                        cache.add(null);  // 添加null对象  
  18.                        }  
  19.                 }else {     // size不为0的时候,即,之前已经调用过getSystemService  
  20.                      service = cache.get(mContextCacheIndex);  
  21.                      if (service != null) {  
  22.                          return service;  // 直接拿到之前添加的对象返回  
  23.                         }  
  24.                 }  
  25.                 service = createService(ctx);  // cache.size=0并且已经添加了一个null对象到cache里  
  26.                   cache.set(mContextCacheIndex, service); // 设置新创建的服务添加到cache里  
  27.                   return service;            // 返回该服务  
  28.              }  
  29.         }  
  30.   
  31.         publicObject createService(ContextImpl ctx) { // 必须实现的方法  
  32.             thrownew RuntimeException("Not implemented");  
  33.         }  
  34. }  
  35.   
  36. 通过分析代码可知,在ContextImpl类里维护了一个ArrayList<Object>对象,其里面保存着所有注册的Service对象,并且Service对象的获得和创建由ServiceFether来封装,该类就两个方法:createService和getService,而createService是未实现的方法。createSerive的实现在后面:  
  37. private static int sNextPerContextServiceCacheIndex =0;  
  38. private static void registerService(String serviceName, ServiceFetcher fetcher){  
  39.         if(!(fetcher instanceof StaticServiceFetcher)) {   //是否为StaticServiceFetcher的对象  
  40.             fetcher.mContextCacheIndex =sNextPerContextServiceCacheIndex++;  
  41.         }  
  42.        SYSTEM_SERVICE_MAP.put(serviceName, fetcher);  // 添加到SYSTEM_SERVICE_MAP键值表里  
  43. }  
  44.   
  45. static {  
  46.      …  
  47.         registerService(POWER_SERVICE, new ServiceFetcher() {  
  48.                public Object createService(ContextImpl ctx) {  
  49.                    IBinder b = ServiceManager.getService(POWER_SERVICE);  
  50.                    IPowerManager service = IPowerManager.Stub.asInterface(b);  
  51.                    return new PowerManager(service, ctx.mMainThread.getHandler());  
  52.                 }});  
  53.          …  
  54.         registerService (SENSOR_SERVICE,new ServiceFetcher() {  
  55.                public Object createService(ContextImpl ctx) {  
  56.                   return new SensorManager(ctx.mMainThread.getHandler().getLooper());  
  57.                }});  
  58.              …  
  59. }  

好家伙,一下子在静态初始化语句块里通过私有方法registerService注册了30多个服务,其第二个参数为ServiceFetcher类型,每个注册的服务都是匿名内部类,都实现了createService方法,在createService方法里创建了SensorManager对象,该对象和Activity的Looper共享消息队列。

总结下吧:

用户程序调用getSystemService(SENSOR_SERVICE),其实现在ContextImpl.java中,在其实实现中从SYSTEM_SERVICE_MAP键值表查找与SENSOR_SERVICE键对应的对象ServiceFetcher,调用ServiceFetcher.getService方法得到SensorManager对象,而ContextImpl对象里还维护着一个ServiceCache,如果某个服务被get过一次,就会被记录在这个所谓缓存里,ServiceFetcher.getService先查找缓存里有没有Cache的Object,如果没有,则调用自己的createService方法创建这个Object,而createService没有实现,其在registerService注册服务时创建ServiceFetcher匿名内部类时实现,并且将注册的服务添加到SYSTEM_SERVICE_MAP中,在创建SensorManager对象时,它和Activity共享了一个Looper。


总而言之,言而总之,在getSystemService(SENSOR_SERVICE)里,创建了SensorManager对象并且和Activity共享Looper。





本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
getSystemService() in Android
Alarm机制与Binder交互
android 传感器类 sensor
Android之传感器系统(Gsensor)
getSystemService原理
深入理解Android Sensor系统 (4.0)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服