关于android传感器的那点事儿

本文介绍了一种利用手机内置传感器(包括磁场传感器、速度传感器及距离传感器)实现自定义视图随手机旋转的方法,并详细解析了相关代码实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近做项目用到了传感器,需求是根据手机旋转的方向旋转自定义的view,用到的传感器有主要有两个 一个是磁场传感器,另一个是速度传感器,顺带着研究了一下手机的距离传感器,感觉手机的距离传感器比较坑啊,为啥这样说?等会儿就知道了。自定义view已经下好了,就不展示了,主要展示一下传感器的代码。

 public class SensorActivity extends Activity, implements SensorEventListener {
     private final SensorManager mSensorManager;
     private final Sensor mAccelerometer;
     private final Sensor magSensor ;
     float[] accValues = new float[3];
     float[] magValues = new float[3];
      /*
       android中有一个SensorManager来管理手机中的所有传感器,因此第一步先获取手机传感器manager
      */
     public SensorActivity() {
         mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
         mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
         magSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
     }


    /*
      注册一个监听回调
    */
     protected void onResume() {
         super.onResume();
         mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
         mSensorManager.registerListener(this, magSensor , SensorManager.SENSOR_DELAY_NORMAL);
     }

    /*
     接触监听的注册,防止内存溢出,程序崩溃
    */
     protected void onPause() {
         super.onPause();
         mSensorManager.unregisterListener(this);
     }

     /*
     接触监听的注册,防止内存溢出,程序崩溃
    */

     public void onAccuracyChanged(Sensor sensor, int accuracy) {
     }

     public void onSensorChanged(SensorEvent event) {
         //在这个方法里面可以获得传感器回调的值,返回的是一个长度为3的数组
        switch (event.sensor.getType()){
                case Sensor.TYPE_MAGNETIC_FIELD:
                    magValues = event.values;
                    break;
                case Sensor.TYPE_ACCELEROMETER:
                    accValues = event.values;
                    break;
            }
        //将磁场传感器和加速度传感器的值存储到定义后的数组中,然后计算方向精度
        getOrientionPrecision();
     }

    private void getOrientionPrecision() {
        float[] values = new float[3];
        float[] R = new float[9];
        //根据加速度传感器和磁场传感器获得旋转矩阵,只用经过这一步才能调用getOrientation()得到方向精度
        SensorManager.getRotationMatrix(R, null, accValues , magValues );
        //将经过计算后得到的方向精度存储到values中,这里我们取values[0] 这个值就是我们需要的经度
        SensorManager.getOrientation(R, values);
        // 要经过一次数据格式的转换,转换为度
        values[0] = (float) Math.toDegrees(values[0]);
        //正北为0度,正东为90 正南为180 ,正西为-90
        if(values[0]<0){
            //因为回调的方向精度是有0-180-(-180)-0这样的顺序,所以在这里要将方向精度转化为正数
            degree = 180+values[0]+180;
            tv_sensor_ori.setText("方向精度:" + degree);
        }else {
            degree =values[0];
            tv_sensor_ori.setText("方向精度:" + degree);
        }
        //每个0.2s和方向旋转超过2度将度数传递给自定义view,view开始旋转动画。
        if(isTime){
            currenttime = System.currentTimeMillis();
            isTime= false;
            currentDegree=degree;
//          customer.setAngle(degree,true,handler);
        }else {
            if(System.currentTimeMillis()-currenttime>200&&Math.abs(degree-currentDegree)>2){
                currenttime=System.currentTimeMillis();
                leidaLayout.setRotation(Math.abs(degree-currentDegree));
            }
        }
        if (values[0] >= -5 && values[0] < 5) {
            tv_sensor.setText("正北");
        } else if (values[0] >= 5 && values[0] < 85) {
            tv_sensor.setText("东北");
        } else if (values[0] >= 85 && values[0] <= 95) {
            tv_sensor.setText("正东");
        } else if (values[0] >= 95 && values[0] < 175) {
            tv_sensor.setText("东南");
        } else if ((values[0] >= 175 && values[0] <= 180) || (values[0]) >= -180 && values[0] < -175) {
            tv_sensor.setText("正南");
        } else if (values[0] >= -175 && values[0] < -95) {
            tv_sensor.setText("西南");
        } else if (values[0] >= -95 && values[0] < -85) {
            tv_sensor.setText("正西");
        } else if (values[0] >= -85 && values[0] < -5) {
            tv_sensor.setText("西北");
        }
    }
 }

在回调方向的时候有一个getRotationMatrix()方法 ,我们来解析一下。下面我们直接去api中找到谷歌的解释。

public static boolean getRotationMatrix (float[] R, float[] I, float[] gravity, float[] geomagnetic)
Added in API level 3

Computes the inclination matrix I as well as the rotation matrix R transforming a vector from the device coordinate system to the world’s coordinate system which is defined as a direct orthonormal basis, where:

X is defined as the vector product Y.Z (It is tangential to the ground at the device's current location and roughly points East).
Y is tangential to the ground at the device's current location and points towards the magnetic North Pole.
Z points towards the sky and is perpendicular to the ground.

World coordinate-system diagram.

Parameters
R is an array of 9 floats holding the rotation matrix R when this function returns. R can be null.

I is an array of 9 floats holding the rotation matrix I when this function returns. I can be null.

gravity is an array of 3 floats containing the gravity vector expressed in the device’s coordinate. You can simply use the values returned by a SensorEvent of a Sensor of type TYPE_ACCELEROMETER.

geomagnetic is an array of 3 floats containing the geomagnetic vector expressed in the device’s coordinate. You can simply use the values returned by a SensorEvent of a Sensor of type TYPE_MAGNETIC_FIELD.

从上面看出第一个参数是一个长度我9的数组,这个数组就是来存储这个方法的返回值的,第二个参数为单位矩阵可以为null,第三个参数是加速度回调的结果矩阵,第四个是磁场回调的结果矩阵。

public static float[] getOrientation (float[] R, float[] values)
Computes the device’s orientation based on the rotation matrix.
When it returns, the array values is filled with the result:
values[0]: azimuth, rotation around the -Z axis, i.e. the opposite direction of Z axis.
values[1]: pitch, rotation around the -X axis, i.e the opposite direction of X axis.
values[2]: roll, rotation around the Y axis.
Applying these three intrinsic rotations in azimuth, pitch and roll order transforms identity matrix to the rotation matrix given in input R. All three angles above are in radians and positive in the counter-clockwise direction. Range of output is: azimuth from -π to π, pitch from -π/2 to π/2 and roll from -π to π.
Parameters
**R rotation matrix see getRotationMatrix(float[], float[], float[], float[]).
values an array of 3 floats to hold the result**
我们来分析这个方法,第一我们可以知道的是这个方法的返回值依赖于getRotationMatrix()这个方法返回的矩阵,第二返回的值要想使用就要将弧度叫转化为角度。 第三个就是对两个参数做了个解释,第一个参数是getRotationMatrix()调用得到的矩阵,第二个是存储这个方法返回值的数组。value[0]就是我们要的数据。他是在地球坐标系中z轴与x轴的夹角。
最后说一下手机距离传感器的坑吧 ,手机距离传感器回调的值只有两个,一个是0,一个是1,只要你的手遮挡住手机头部他就会回掉0,认为手机是紧靠你的。我觉得这样也没法回调我们与手机之间的实际距离。也就是在做手机打电话的自动锁屏功能有点用吧。对于这个就不在写代码浪费之间了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值