请选择 进入手机版 | 继续访问电脑版

石家庄老站长

点击联系客服
客服QQ:509006671 客服微信:mengfeiseo
 找回密码
 立即注册
查看: 26|回复: 0

肝!玩Android传感器

[复制链接]

1

主题

1

帖子

-7

积分

限制会员

积分
-7
发表于 2021-4-2 14:40:51 | 显示全部楼层 |阅读模式
提到手机上的传感器都不会陌生。例如方向传感器、陀螺、重力传感器、光线传感器等。目前手机的基本集成少了10多个传感器,未来人工智能的知识对我们也是必不可少的。

传感器分类

Android平台支持三种类型的传感器。

动态传感器

这些传感器测量三个轴方向的加速力和旋转力。包括加速度传感器、重力传感器、陀螺和旋转矢量传感器。环境传感器

这些传感器测量各种环境参数,如环境温度、气压、照度和湿度。这个类别包括气压计、光度计和温度计。位置传感器

这些传感器测量设备的物理位置。该类别包括屏幕方向传感器和磁力仪(电子罗盘)。传感器使用

Android平台上的Google已经为我们提供了一个非常方便的传感器框架,我们只需要在这个框架下定义我们要使用的传感器,并实现其逻辑即可。(约翰肯尼迪,北方执行部队)。

传感器框架是android.hardware软件包的一部分,在开发和使用过程中主要使用以下类和接口:

sensormanagersensorsensoreventlistenersensorevent  http://www  . Sina.com/

sensor  manager  msensormanager=(sensor  manager)getsystemservice(context  . sensor  _ service);

第一步:获取传感器管理对象

//获取传感器类型(TYPE  _ ACCELEROMETER:加速度传感器)

sensor  sensor=msensor  manager  . getdefaultsensor(sensor  . type  _ accelerometer);

此处指定的传感器类型有多种
,这里暂且列举一些最常用的传感器:

  • Sensor.TYPE_ACCELEROMETER: 三轴加速度传感器
  • Sensor.TYPE_ORIENTATION:方向传感器
  • Sensor.TYPE_GYROSCOPE:陀螺仪传感器
  • Sensor.TYPE_MAGNETIC_FIELD:磁力传感器
  • Sensor.TYPE_GRAVITY:重力传感器
  • Sensor.TYPE_LINEAR_ACCELERATION:线性加速度传感器
  • Sensor.TYPE_AMBIENT_TEMPERATURE:温度传感器
  • Sensor.TYPE_LIGHT:光传感器
  • Sensor.TYPE_PRESSURE:压力传感器
  • Sensor.TYPE_ALL:所有类型的传感器,通过getSensorList返回所有支持的传感器列表。
    第三步:注册传感器监听

    SensorEventListener mListener = new SensorEventListener() {
        // 当传感器的值改变的时候回调该方法
        @Override
        public void onSensorChanged(SensorEvent event) {
            // Do something with this sensor value.
            // The light sensor returns a single value.
            // Many sensors return 3 values, one for each axis.
        }
        // 当传感器精度发生改变时回调该方法
        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
            // Do something here if sensor accuracy changes.
        }
    }
    mSensorManager.registerListener(mListener, mSensor, SensorManager.SENSOR_DELAY_GAME);

    其中registerListener最后一个参数是指定传感器获取数据的频率,有以下四种形式:

    [ol]
  • SensorManager.SENSOR_DELAY_NORMAL,正常频率,一般对实时性要求不高的应用适合使用这种频率。
  • SensorManager.SENSOR_DELAY_FASTEST,最快,延迟最小,同时也最消耗资源,一般只有特别依赖传感器的应用使用该频率,否则不推荐。
  • SensorManager.SENSOR_DELAY_GAME,适合游戏的频率,一般有实时性要求的应用适合使用这种频率。
  • SensorManager.SENSOR_DELAY_UI,适合普通应用的频率,这种模式比较省电,而且系统开销小,但延迟大,因此只适合普通小程序使用。[/ol]
    一旦传感器监测到环境数据变化,便会回调两个实现方法:

  • onSensorChanged(SensorEvent event):传感器报告了新值。
    内部的SensorEvent 对象包含关于新传感器数据的信息,包括:数据的准确度、生成数据的传感器、生成数据的时间戳以及传感器记录的新数据,系统可能会频繁调用,切记请勿阻塞 onSensorChanged() 方法
  • onAccuracyChanged(Sensor sensor, int accuracy):传感器的准确度发生了变化。
    当传感器精度发生变化时onAccuracyChanged被触发。第一参数是发生变化的sensor对象,第二个参数是传感器的新精度(准确度)。精度有以下四种:

      
  • SENSOR_STATUS_ACCURACY_LOW:低精度值
  • SENSOR_STATUS_ACCURACY_MEDIUM:平均精度值
  • SENSOR_STATUS_ACCURACY_HIGH:高精度值
  • SENSOR_STATUS_UNRELIABLE:精度值不可靠
    第四步:解注册传感器监听

    mSensorManager.unregisterListener(mListener)

    传感器几乎是非常消耗资源的,最佳的做法是始终停用不需要的传感器,特别是在活动处于暂停状态时。如果不这样做,可能会在几小时内将电池电量耗尽。

    第三步和第四步开发过程中一般是相呼应的,我们常常在onResume中进行注册,在onPause中进行解注册,也可根据业务需要自行确定时机。

    运行时检测传感器
    有时我们不能确定当前设备是否包含我们所需的传感器,所以在运行时我们需要做一个判断:

    Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE);
    if(sensor != null){
        // Success! There's a pressure sensor.
    }else{
        // Failure! No pressure sensor.
    }

    如果您要在 Google Play 上发布应用,您可以在清单文件中使用 元素,以对不具备适合您应用的传感器配置的设备屏蔽您的应用,以下清单示例条目会对没有加速度计的设备屏蔽应用:

    uses-feature android:name="android.hardware.sensor.accelerometer"
                    android:required="true" />

    传感器坐标系
    大部分传感器都是以三轴坐标来表示数据值。对于大多数传感器,当设备处于默认屏幕方向(平板和手机就有可能不一样)时,会相对于设备屏幕来定义坐标系,如下图:



    以下传感器使用此坐标系:

  • 加速度传感器
  • 重力传感器
  • 陀螺仪
  • 线性加速度传感器
  • 地磁场传感器
    记着,传感器的坐标系是始终跟随设备的。

    小栗子
    下边就是通过三轴加速度传感器实现一个计步器功能,代码来源于网络,个人稍加注释:

    public class StepDetector implements SensorEventListener{
        private final static String TAG = "StepDetector";
        private float   mLimit = 10;
        private float   mLastValues[] = new float[3*2];
        private float   mScale[] = new float[2];
        private float   mYOffset;

        private float   mLastDirections[] = new float[3*2];
        private float   mLastExtremes[][] = { new float[3*2], new float[3*2] };
        private float   mLastDiff[] = new float[3*2];
        private int     mLastMatch = -1;
       
        private ArrayListStepListener> mStepListeners = new ArrayListStepListener>();
       
        public StepDetector() {
            // 手机屏幕的高
            int h = 480;
            // 中心点,y轴的偏移量
            mYOffset = h * 0.5f;
            // 获取重力相关参数
            mScale[0] = - (h * 0.5f * (1.0f / (SensorManager.STANDARD_GRAVITY * 2)));
            mScale[1] = - (h * 0.5f * (1.0f / (SensorManager.MAGNETIC_FIELD_EARTH_MAX)));
        }
         
        public void setSensitivity(float sensitivity) {
            //灵敏度 1.97  2.96  4.44  6.66  10.00  15.00  22.50  33.75  50.62
            mLimit = sensitivity;
        }
         
        public void addStepListener(StepListener sl) {
            mStepListeners.add(sl);
        }
         
        //public void onSensorChanged(int sensor, float[] values) {
        public void onSensorChanged(SensorEvent event) {
            Sensor sensor = event.sensor;
            synchronized (this) {
                int j = (sensor.getType() == Sensor.TYPE_ACCELEROMETER) ? 1 : 0;
                if (j == 1) {
                    //三个方向上的速度和
                    float vSum = 0;
                    for (int i=0 ; i3 ; i++) {
                        final float v = mYOffset + event.values * mScale[j];
                        vSum += v;
                    }
                    int k = 0;
                    //平均速度
                    float v = vSum / 3;
                   
                    float direction = (v > mLastValues[k] ? 1 : (v  mLastValues[k] ? -1 : 0));
                    if (direction == - mLastDirections[k]) {
                        // Direction changed
                        int extType = (direction > 0 ? 0 : 1); // minumum or maximum?
                        mLastExtremes[extType][k] = mLastValues[k];
                        float diff = Math.abs(mLastExtremes[extType][k] - mLastExtremes[1 - extType][k]);
                        //运动太慢,忽略
                        if (diff > mLimit) {
                            
                            boolean isAlmostAsLargeAsPrevious = diff > (mLastDiff[k]*2/3);
                            boolean isPreviousLargeEnough = mLastDiff[k] > (diff/3);
                            boolean isNotContra = (mLastMatch != 1 - extType);
                            //判断有效的一步
                            if (isAlmostAsLargeAsPrevious && isPreviousLargeEnough && isNotContra) {
                                Log.i(TAG, "step");
                                for (StepListener stepListener : mStepListeners) {
                                    stepListener.onStep();
                                }
                                mLastMatch = extType;
                            }
                            else {
                                mLastMatch = -1;
                            }
                        }
                        mLastDiff[k] = diff;
                    }
                    mLastDirections[k] = direction;
                    mLastValues[k] = v;
                }
            }
        }
         
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
            // TODO Auto-generated method stub
        }
    }

    参考
  • https://developer.android.com/guide/topics/sensors/sensors_overview
  • 回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|无图版|手机版|小黑屋|石家庄@IT精英团

    GMT+8, 2021-5-10 16:20 , Processed in 0.060521 second(s), 25 queries .

    Powered by Discuz! X3.4

    © 2001-2021 Comsenz Inc.

    快速回复 返回顶部 返回列表