首页 > 代码库 > Android对方向感应器的封装调用

Android对方向感应器的封装调用

 Android自动的SensorManager使用起来已经很方便,但由于一些情况我们希望对其中的功能进行封装:

  • 只使用个别的sensor,功能相对单一
  • 要对sensor返回的raw data进行算法处理方可使用
  • 程序中多处频繁调用禁用sensor的数据

由于项目需要在很多页面调用手机的方向信息,故而对sensor的方向感应器进行简单的封装,源码如下:

package com.weicheche.android.service;import java.util.ArrayList;import com.****.android.bean.ApplicationContext;import android.hardware.Sensor;import android.hardware.SensorEvent;import android.hardware.SensorEventListener;import android.hardware.SensorManager;import android.os.Handler;import android.os.SystemClock;/** *  * @ClassName: OrientationService  * @Description: TODO(对android SDk自带的方向感应器进行封装)  * @author xuyong yxy8023@gmail.com    * @date  2014年7月14日  上午2:24:10 */public class OrientationService implements SensorEventListener {    /*     * 对于想要监听方向变化的类,需要继承实现这个接口     */    public static abstract interface OrientationListener{        public abstract void onOrientationChanged(float orientatoin);    }        protected final Handler mHandler = new Handler();    private SensorManager sensorManager;    private Sensor mOrientationSensor;    private float mTargetDirection = 0;    private ArrayList<OrientationListener> listenerList = new ArrayList<OrientationListener>();    private long delayMillis = 20;        public OrientationService() {        // TODO Auto-generated constructor stub         init();    }    /**     *      * @Title: registerListener      * @Description: TODO(将需要监听方向变化的类注册到OrientationService里,service中的sensor自动打开)      * @param listener     * @throws      * @date  2014年7月14日  上午2:29:26      * Xuyong     */    public void registerListener(OrientationListener listener){        listenerList.add(listener);        if(1 == listenerList.size()){            // 刚刚有新的listener加入的时候打开方向感应器并启动更新线程            startService();            mHandler.postDelayed(mCompassViewUpdater, delayMillis);  // delayMillis毫秒执行一次方向更新        }    }        /**     * @Title: unregisterListener      * @Description: TODO(再activity pause或者销毁时,讲listener从service移除,service会根据情况自动停止方向感应器的工作)      * @param listener     * @throws      * @date  2014年7月14日  上午2:30:45      * Xuyong     */    public void unregisterListener(OrientationListener listener){        if((listenerList.remove(listener)) && 0 == listenerList.size()){            // 如果成功移除listener后导致没有任何listener监听方向变化,暂停方向感应器            stopService();        }    }        /**     * @Title: setDelayMillis      * @Description: TODO(设置更新时间间隔,不得低于10ms)      * @param delayMillis     * @throws      * @date  2014年7月14日  上午2:34:10      * Xuyong     */    public void setDelayMillis(long delayMillis){        if(delayMillis>10){            this.delayMillis = delayMillis;        }    }        /**     * @Title: onDestory      * @Description: TODO(移除所有的监听类,并停止方向感应器)      * @throws      * @date  2014年7月14日  上午2:34:46      * Xuyong     */    public void onDestory(){        listenerList.clear();        stopService();    }        /**     * @Title: init      * @Description: TODO(初始化方向感应器)      * @throws      * @date  2014年7月14日  上午12:36:53      * Xuyong     */    @SuppressWarnings("deprecation")    private void init(){        sensorManager = (SensorManager) ApplicationContext.getInstance().getContext().getSystemService(android.content.Context.SENSOR_SERVICE);        try {            mOrientationSensor = sensorManager.getSensorList(                    Sensor.TYPE_ORIENTATION).get(0);        } catch (Exception e) {            // TODO: handle exception            mOrientationSensor = null;        }            }        private void stopService(){        if (mOrientationSensor != null && sensorManager != null) {            sensorManager.unregisterListener(this);        }    }        private void startService(){        if (mOrientationSensor != null && sensorManager != null) {            sensorManager.registerListener(this, mOrientationSensor, SensorManager.SENSOR_DELAY_GAME);        }    }        /**     * 这个是更新指南针旋转的线程,handler的灵活使用,每delayMillis毫秒检测方向变化值(这样的机制不太好,可能会出现线程阻滞)     */    protected Runnable mCompassViewUpdater = new Runnable() {        @Override        public void run() {                    if (listenerList.size() > 0) {// 有监听的时候,传递下去,并且注意传入顺序为倒序,保证最近的层最先响应。                long startTime = SystemClock.uptimeMillis();                for(int i = listenerList.size()-1; i>=0; i--){                    ((OrientationListener) listenerList.get(i)).onOrientationChanged(mTargetDirection);                }                // 由于线程阻滞,可能带来延时,通过时间控制来弥补                long endTime = SystemClock.uptimeMillis();                long delayTime = endTime - startTime;                delayTime = (delayTime > delayMillis)? 2:(delayMillis-delayTime);                mHandler.postDelayed(mCompassViewUpdater, delayTime);    // 比定时器好            }                    }    };    /*     * no use currently     */    @Override    public void onAccuracyChanged(Sensor arg0, int arg1) {        // TODO Auto-generated method stub    }        /**     * @Title: onSensorChanged      * @Description: TODO(直接调用SDK自带的API获取方向信息,以后需要修改为根据加速度和地磁数据的方向计算)      * @param event     * @throws      * @date  2014年7月11日  下午4:52:36      * Xuyong     */    @SuppressWarnings("deprecation")    @Override    public void onSensorChanged(SensorEvent event) {        // TODO Auto-generated method stub        switch (event.sensor.getType()) {            // Note:改方法已经不鼓励使用,考虑在此处修改数据获取方向重新计算方向值        case Sensor.TYPE_ORIENTATION:            float direction = event.values[SensorManager.DATA_X] * -1.0f;            mTargetDirection = (direction + 720) % 360; // 赋值给全局变量,让指南针旋转            break;        default:            break;        }    }}

 

调用方法:

 对任意activity,继承实现OrientationListener,在onResume和onPause中分别注册和注下销listener,代码如下:

 1 public class xxxxActivity  implements  OrientationListener { 2  3     @Override 4     protected void onPause() { 5        super.onPause(); 6     ApplicationContext.getInstance().getOrientationService().unregisterListener(this); 7     } 8      9     @Override10     public void onResume() {11       super.onResume();12       ApplicationContext.getInstance().getOrientationService().registerListener(this);13     }14 15     @Override16     public void onOrientationChanged(float orientatoin) {17         // TODO Auto-generated method stub18         adapter.setOrientation(orientatoin);19     } 20 }