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 [email protected]
 * @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     @Override
10     public void onResume() {
11       super.onResume();
12       ApplicationContext.getInstance().getOrientationService().registerListener(this);
13     }
14
15     @Override
16     public void onOrientationChanged(float orientatoin) {
17         // TODO Auto-generated method stub
18         adapter.setOrientation(orientatoin);
19     }
20 }

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

时间: 2024-10-20 18:55:23

Android对方向感应器的封装调用的相关文章

PM撸代码之Android【武侠篇:封装、继承、多态】

80 PM撸代码之Android[武侠篇:封装.继承.多态] 这是Android系列的第六篇文章,在之前的一篇文章中,已经了解了面向对象的基础概念,这一篇将会通过武侠江湖的类比,讲解面向对象的更多内容,感谢小伙伴们一直以来的支持. 武林门派的三个特征 1 独门秘籍(封装) 2 传承的门派(继承) 3 看情况使功夫和换个姿势说明问题(多态) [封装] 1 门派独门秘籍(封装) 前一篇已经说到,当达摩上了嵩山以后,江湖就正式进入门派时代.每个门派区别于其他门派,肯定是因为这个门派拥有独门武功秘籍.举

如何在android平台上使用js直接调用Java方法[转]

转载自:http://www.cocos.com/docs/html5/v3/reflection/zh.html #如何在android平台上使用js直接调用Java方法 在cocos2d-js 3.0beta中加入了一个新特性,在android平台上我们可以通过反射直接在js中调用java的静态方法.它的使用方法很简单: var o = jsb.reflection.callStaticMethod(className, methodName, methodSignature, parame

android定义可以被其他程序调用的activity

在测试android调用其他应用的activity时,提示找不到对于的activity,经过检查发现在intent-filter的<category>中忘了写<category android:name="android.intent.category.DEFAULT"/>,自己定义的filter一定要写上这句,这是android默认添加的要求. android定义可以被其他程序调用的activity

android 横方向的Listview附带系统照相图库裁剪

※效果 ※介绍 效果模仿新浪微博发微博的界面,如果需要类似的功能拿来就可以直接:用图片最多选择6张,图片可以点击右上角按钮删除,点击图片可以查看放大图片: 照相和图库都是得到的原图,所以不会出现失真现象,分辨率为 480*480,代码中可以自己调整: ※Demo下载 http://download.csdn.net/detail/u010785585/7672677 android 横方向的Listview附带系统照相图库裁剪

Android 一个改进的okHttp封装库

一.概述 之前写了篇Android OkHttp完全解析 是时候来了解OkHttp了,其实主要是作为okhttp的普及文章,当然里面也简单封装了工具类,没想到关注和使用的人还挺多的,由于这股热情,该工具类中的方法也是剧增,各种重载方法,以致于使用起来极不方便,实在惭愧. 于是,在这个周末,抽点时间对该工具类,进行了重新的拆解与编写,顺便完善下功能,尽可能的提升其使用起来的方便性和易扩展性. 标题的改善,也是指的是对于我之前的代码进行改善. 如果你对okhttp不了解,可以通过Android Ok

Android 一个改善的okHttp封装库

转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/49734867: 本文出自:[张鸿洋的博客] 一.概述 之前写了篇Android OkHttp全然解析 是时候来了解OkHttp了,事实上主要是作为okhttp的普及文章,当然里面也简单封装了工具类,没想到关注和使用的人还挺多的,因为这股热情,该工具类中的方法也是剧增,各种重载方法,以致于使用起来极不方便.实在羞愧. 于是,在这个周末,抽点时间对该工具类,进行了又一次的拆解与编

Android 插件扩展系列之 -- 封装与应用

<---扩展插件最终是以“.jar”的形式提交到服务器,也要符合我们的命名规范,即plugin_+插/件名称.其中插件名称要和plugin.xml中的uexName一致.例如plugin_uexDemo.jar,和下载管理插件plugin_DownloaderMgr.jar等.---> 1.   开发环境搭建 Android的开发环境搭建主要包括JDK.Eclipse.Android SDK的安装. 您也可以直接安装好JDK后,去Android官网下载ADT套装(http://develope

Android图片系列(1)-------调用系统相册与相机获取图片

Android开发过程中,我们经常需要获取图片,你可以通过获取手机相册的图片,也可以调用相机拍照获取图片.这里主要讲这两个获取图片的方式,并记录其中遇到的小问题. 调用相册获取图片 这个功能非常简单,这里不多说了,这里贴出关键代码 Intent openAlbumIntent = new Intent(Intent.ACTION_GET_CONTENT); openAlbumIntent.setType("image/*"); startActivityForResult(openAl

【cocos2d-js官方文档】二十四、如何在android平台上使用js直接调用Java方法

在cocos2d-js 3.0beta中加入了一个新特性,在android平台上我们可以通过反射直接在js中调用java的静态方法.它的使用方法很简单: var o = jsb.reflection.callStaticMethod(className, methodName, methodSignature, parameters...) 在callStaticMethod方法中,我们通过传入Java的类名,方法名,方法签名,参数就可以直接调用Java的静态方法,并且可以获得Java方法的返回