Android学习笔记(十二)传感器

来源:互联网 发布:js怎么把数字变成汉字 编辑:程序博客网 时间:2024/05/18 05:43

12.1 简介

        手机内置传感器是一种微信物理设备,它能探测、感受到外界的物理信号,并按一定规律转换为我们所需要的信息。Android 手机通常都会支持多种类型的传感器,如光照传感右器、加速度传感器、地磁传感器、压力传感器、温度传感器等。

12.2 光照传感器

12.2.1 使用方法

每个传感器的用法都是类似的,如下所示:
/** * 1.传感器的用法都是类似的,首先要获取到SensorManager实例 */SensorManager sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);/** * 2.调用getDefaultSensor()方法来获取任意的传感器类型 * Sensor.TYPE_LIGHT:光照传感器的类型,同理还有其他类型<br> * 此时sensor就代表着一个光照传感器 */Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);/** * 3.对传感器输出的信号进行监听,借助SensorEventListener实现<br> * SensorEventListener是一个借口 */SensorEventListener listener = new SensorEventListener() {    @Override    public void onSensorChanged(SensorEvent event) {        //当传感器监测的数值发送变化时就会调用该方法        //param:参数中包含了一个values数组,所有传感器输出的信息都存放在这里    }    @Override    public void onAccuracyChanged(Sensor sensor, int accuracy) {        //当传感器的精度发送变化时就会调用该方法    }};/** * 4.调用SensorManager 的 registerListener()方法来注册监听 * param1:监听器的实例 * param2:传感器实例 * param3:传感器输出信息的更新速率,有以下几个值可选,速率依次递增: * SENSOR_DELAY_UI、SENSOR_DELAY_NORMAL、SENSOR_DELAY_GAME、SENSOR_DELAY_FASTEST */sensorManager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL);/** * 5.当程序退出或传感器使用完毕时,一定要将使用的资源释放掉 */sensorManager.unregisterListener(listener);

12.2.2 示例demo

以下示例实现手机监测外界光照强度并显示在界面上(UI代码省略):
public class MainActivity extends AppCompatActivity {    private TextView lightLevel;    private SensorManager sensorManager;    private SensorEventListener listener = new SensorEventListener() {        @Override        public void onSensorChanged(SensorEvent event) {            //数组中第一个下标的值就是光照强度            float value = event.values[0];            lightLevel.setText("now light level is :" + value);        }        @Override        public void onAccuracyChanged(Sensor sensor, int accuracy) {        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        lightLevel = (TextView) findViewById(R.id.light_level);        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);        Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);        sensorManager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL);    }    @Override    protected void onDestroy() {        super.onDestroy();        if (sensorManager != null) {            sensorManager.unregisterListener(listener);        }    }}

12.3 加速度传感器

12.3.1 使用方法

(1)加速度传感器的用法跟光照传感器的用法是一致的,只不过需要在获取Sensor实例的时候改变常量的值为:Sensor.TYPE_ACCELEROMETER
(2)加速度传感器输出的信息同样存放在values数组中,但是值有3个,分别代表X轴,Y轴,Z轴方向上的加速度信息。

注意:
        由于地心引力的存在,手机任何时候都会有重力加速度。当手机平放时,这个加速度作用在Z轴上;当竖立起来时,作用在Y轴上;当横立起来时,作用在X轴上。

12.3.2 示例demo

以下示例实现模拟微信摇一摇功能,并给出提示:
public class MainActivity extends AppCompatActivity {    private SensorManager sensorManager;    private SensorEventListener listener = new SensorEventListener() {        @Override        public void onSensorChanged(SensorEvent event) {            //因为加速度有可能是负的,所以要取绝对值            float xValue = Math.abs(event.values[0]);            float yValue = Math.abs(event.values[1]);            float zValue = Math.abs(event.values[2]);            //默认有重力加速度,所以比较的值要比重力加速度大,此处设为15            if (xValue > 15 || yValue > 15 || zValue > 15) {                Toast.makeText(MainActivity.this, "抱紧你女票,我要开始摇一摇了~", Toast.LENGTH_SHORT).show();            }        }        @Override        public void onAccuracyChanged(Sensor sensor, int accuracy) {        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);        Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);        sensorManager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL);    }    @Override    protected void onDestroy() {        super.onDestroy();        if (sensorManager != null) {            sensorManager.unregisterListener(listener);        }    }}

12.4 方向传感器

12.4.1 使用方法

        方向传感器与以上类似,获取Sensor时传入常量为Sensor.TYPE_ORIENTATION,但是!!!但是,Android已经废弃了这种传感器类型,代码仍然有效,但已经不推荐这么写了。
        事实上,Android 获取手机旋转的方向和角度是通过加速度传感器地磁传感器共同计算得出的,这也是 Android目前推荐使用的方式。


(1)首先需要分别获取加速度传感器和地磁传感器的实例,并给它们注册监听器
//加速度Sensor acceSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);//地磁Sensor magneticSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);//由于方向传感器精确度要求较高,所以设置为SENSOR_DELAY_GAMEsensorManager.registerListener(listener, acceSensor, SensorManager.SENSOR_DELAY_GAME);sensorManager.registerListener(listener, magneticSensor, SensorManager.SENSOR_DELAY_GAME);
(2)然后在 onSensorChanged()方法中获取到SensorEvent的values数组,分别记录着加速度和地磁传感器的值。然后将这两个值传入到 SensorManager 的getRotationMatrix()方法中就可以得到一个包含旋转矩阵的 R数组。
/** * param1:R是一个长度为9的float数组,该方法计算出的数据将会存放到这个数组中 * param2:是一个用于将地磁向量转换成重力坐标的旋转矩阵,通常指定为 null 即可 * param3:加速度传感器 输出的值 * param4:地磁传感器 输出的值 */SensorManager.getRotationMatrix(R, null, accelerometerValues, magneticValues);
(3)得到了 R 数组后,就可以调用 SensorManager 的 getOrientation()方法来计算手机的旋转数据了
/** * param1:R数组 * param2:长度为3的float数组,手机在各个方向上的旋转数据都会存放在该数组中 * values[0]:手机围绕如图Z轴的旋转弧度 * values[1]:手机围绕如图X轴的旋转弧度 * values[2]:手机围绕如图Y轴的旋转弧度 */SensorManager.getOrientation(R, values);/** * 以上得到的都是以弧度为单位,如果想将他们转换为角度还需要调用如下方法 */Math.toDegrees(values[0]);

12.4.2 示例demo

以下示例实现简易指南针的功能:
先给两张素材(分别为compass.pngarrow.png

【activity_main.xml】:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent">    <ImageView        android:id="@+id/compass_img"        android:layout_width="250dp"        android:layout_height="250dp"        android:layout_centerInParent="true"        android:src="@drawable/compass" />    <ImageView        android:id="@+id/arrow_img"        android:layout_width="60dp"        android:layout_height="110dp"        android:layout_centerInParent="true"        android:src="@drawable/arrow" /></RelativeLayout>
【MainActivity.java】:
public class MainActivity extends AppCompatActivity {    private SensorManager sensorManager;    private ImageView compassImg;    private SensorEventListener listener = new SensorEventListener() {        //记录加速度输出的数据        float[] acceValues = new float[3];        //记录地磁输出的数据        float[] magneticValues = new float[3];        float lastRotateDegree;        @Override        public void onSensorChanged(SensorEvent event) {            //判断当前是加速度还是地磁传感器            if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {                //注意赋值时要调用clone方法,不然acceValues和magneticValues将会指向同一个引用                acceValues = event.values.clone();            } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {                //注意赋值时要调用clone方法                magneticValues = event.values.clone();            }            float[] R = new float[9];            float[] values = new float[3];            //为R数组赋值            SensorManager.getRotationMatrix(R, null, acceValues, magneticValues);            //为values数组赋值            SensorManager.getOrientation(R, values);            /**             * 注意:<br>             * values[0]的取值范围是-180 度到 180 度,其中±180 度表示正南方向,0 度表示正北方向,-90 度表示正西方向,90 度表示正东方向。             */            Log.d("MainActivity", "values[0]:" + Math.toDegrees(values[0]));            //将计算出的角度取反,用于旋转指南针背景图            float rotateDegree = -(float) Math.toDegrees(values[0]);            if (Math.abs(rotateDegree - lastRotateDegree) > 1) {                /**                 * 使用旋转动画技术                 * param1:旋转的起始角度                 * param2:旋转的终止角度                 * param3、4、5、6:用于指定旋转的中心点                 *                 */                RotateAnimation animation = new RotateAnimation                        (lastRotateDegree, rotateDegree, Animation.RELATIVE_TO_SELF, 0.5f, Animation.                                RELATIVE_TO_SELF, 0.5f);                animation.setFillAfter(true);                compassImg.startAnimation(animation);                lastRotateDegree = rotateDegree;            }        }        @Override        public void onAccuracyChanged(Sensor sensor, int accuracy) {        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        compassImg = (ImageView) findViewById(R.id.compass_img);        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);        //传感器        Sensor acceSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);        Sensor magneticSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);        //注册监听        sensorManager.registerListener(listener, acceSensor, SensorManager.SENSOR_DELAY_GAME);        sensorManager.registerListener(listener, magneticSensor, SensorManager.SENSOR_DELAY_GAME);    }    @Override    protected void onDestroy() {        super.onDestroy();        if (sensorManager != null) {            sensorManager.unregisterListener(listener);        }    }}
效果图:


0 0