zoukankan      html  css  js  c++  java
  • Sensor与android Manager机制

    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,让我们来看看一个简单应用的代码,再逐渐展开。

    [java] view plaincopyprint?

    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) { 
          &nnbsp; 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

    [java] view plaincopyprint?

    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是什么东西,看样子像映射关系:

    [java] view plaincopyprint?

    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。

    [java] view plaincopyprint?

    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 
          nbsp;  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.      &nnbsp;         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。

  • 相关阅读:
    javaweb消息中间件——rabbitmq入门
    virtual box 桥接模式(bridge adapter)下无法获取ip(determine ip failed)的解决方法
    Apache Kylin本地启动
    git操作
    Java学习总结
    Java中同步的几种实现方式
    hibernate exception nested transactions not supported 解决方法
    vue 中解决移动端使用 js sdk 在ios 上一直报invalid signature 的问题解决
    cookie 的使用
    vue 专门为了解决修改微信标题而生的项目
  • 原文地址:https://www.cnblogs.com/banzhuan/p/6476122.html
Copyright © 2011-2022 走看看