阅读郭霖《第一行代码》的笔记——第12章 Android特色开发,使用传感器

1、传感器简介

手机中内置的传感器是一种微型的物理设备,它能够探测、感受到外界的信号,并按一定规律转换成我们所需要的信息。Android手机通常都会支持多种类型的传感器,如光照传感右器、加速度传感器、地磁传感器、压力传感器、温度传感器等。
当然,Android系统只是负责将这些传感器所输出的信息传递给我们,至于具体如何去利用这些信息就要充分发挥开发者的想象力了。目前市场上很多的程序都有使用到传感器的功能,比如最常见的赛车游戏,玩家可以通过旋转设备来控制赛车的前进方向,就像是在操作方向盘一样。除此之外,微信的摇一摇功能,手机指南针等软件也都是借助传感器来完成的。

2、光照传感器

光照传感器在Android中的应用还是比较常见的,比如系统就有个自动调整屏幕亮度的功能。它会检测手机周围环境的光照强度,然后对手机屏幕的亮度进行相应地调整,以此保证不管是在强光还是弱光下,手机屏幕都能够看得清。
例子:
布局:

<?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">

    <TextView
        android:id="@+id/txt_light_lever"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="1"
        android:textSize="20sp" />

</RelativeLayout>

代码:

package com.example.test.sensor;

import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.widget.TextView;

import com.example.test.R;

/**
* Created by Administrator on 2016/6/4.
*/
public class LightSensorActivity extends Activity {
    private TextView txtLevel;
    //SensorManager是系统所有传感器的管理器,有了它的实例之后就可以调用getDefaultSensor()方法来得到任意的传感器类型了
    private SensorManager sensorManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sensor_light);
        txtLevel = (TextView) findViewById(R.id.txt_light_lever);
        sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        //这里使用Sensor.TYPE_LIGHT常量来指定传感器类型,此时的Sensor实例就代表着一个光照传感器
        Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
        /**
        *调用SensorManager的registerListener()方法来注册SensorEventListener才能使其生效,registerListener()方法接收三个参数
        * 第一个参数就是SensorEventListener的实例,
        * 第二个参数是Sensor的实例,
        * 第三个参数是用于表示传感器输出信息的更新速率,共有SENSOR_DELAY_UI、SENSOR_DELAY_NORMAL、
        *        SENSOR_DELAY_GAME和SENSOR_DELAY_FASTEST这四种值可选,它们的更新速率是依次递增的。
        */
        sensorManager.registerListener(listener, sensor, sensorManager.SENSOR_DELAY_NORMAL);
    }

    /**
    * 调用unregisterListener()方法来释放使用的资源
    */
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (null != sensorManager) {
            sensorManager.unregisterListener(listener);
        }
    }

    //SensorEventListener是对传感器输出的信号进行监听,SensorEventListener是一个接口,其中定义了onSensorChanged()和onAccuracyChanged()这两个方法
    private SensorEventListener listener = new SensorEventListener() {
        /**
        * 当传感器的精度发生变化时就会调用onAccuracyChanged()方法
        * @param event SensorEvent参数里又包含了一个values数组,所有传感器输出的信息都是存放在这里的。
        */
        @Override
        public void onSensorChanged(SensorEvent event) {
            //values数组中第一个下标的值就是当前的光照强度
            float value = event.values[0];
            txtLevel.setText("Current light level is " + value + " lx.");
        }

        /**
        * 当传感器监测到的数值发生变化时就会调用onSensorChanged()方法
        * @param sensor 传感器
        * @param accuracy 变化后的值
        */
        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {

        }
    };

}

3、加速度传感器

Android中的加速度传感器则是提供了一种机制,使得我们能够在应用程序中获取到手机当前的加速度信息,合理利用这些信息就可以开发出一些比较好玩的功能。
接下来我们尝试利用加速度传感器来模仿一下微信的摇一摇功能。其实主体逻辑也非常简单,只需要检测手机在X轴、Y轴和Z轴上的加速度,当达到了预定值的时候就可以认为用户摇动了手机,从而触发摇一摇的逻辑。那么现在问题在于,这个预定值应该设定为多少呢?由于重力加速度的存在,即使手机在静止的情况下,某一个轴上的加速度也有可能达到9.8m/s2,因此这个预定值必定是要大于9.8m/s2的,这里我们就设定为15m/s2吧。
例子:
布局:什么都没有,

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

</LinearLayout>

代码:

package com.example.test.sensor;

import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.widget.Toast;

import com.example.test.R;

/**
* Created by Administrator on 2016/6/4.
*/
public class AccelerometerSensorActivity extends Activity {
    private SensorManager sensorManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sensor_accelerometer);
        sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        sensorManager.registerListener(listener, sensor, sensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (null != sensorManager) {
            sensorManager.unregisterListener(listener);
        }
    }

    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]);
            if (xValue > 15 || yValue > 15 || zValue > 15) {
                //认为用户摇动了手机,触发摇一摇逻辑
                Toast.makeText(AccelerometerSensorActivity.this, "摇一摇", Toast.LENGTH_SHORT).show();
            }
        }

        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {

        }
    };

}

#4、方向传感器

要说Android中另外一个比较常用的传感器应该就是方向传感器了。方向传感器的使用场景要比其他的传感器更为广泛,它能够准确地判断出手机在各个方向的旋转角度,利用这些角度就可以编写出像指南针、地平仪等有用的工具。另外,在本章开始时介绍的通过旋转设备来控制方向的赛车游戏,也是使用方向传感器来完成的。Android获取手机旋转的方向和角度是通过加速度传感器和地磁传感器共同计算得出的,这也是Android目前推荐使用的方式。
例子:制作简易指南针
布局文件:

<?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/img_compass"
        android:layout_width="250dp"
        android:layout_height="250dp"
        android:layout_centerInParent="true"
        android:src="@drawable/compass" />

    <ImageView
        android:layout_width="60dp"
        android:layout_height="110dp"
        android:layout_centerInParent="true"
        android:src="@drawable/arrow" />

</RelativeLayout>

主界面:

package com.example.compasstest;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    private SensorManager sensorManager;
    //指南针的背景图
    private ImageView imgCompass;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imgCompass = (ImageView) findViewById(R.id.img_compass);

        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        //获取加速传感器,并为它注册监听器
        Sensor accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        sensorManager.registerListener(listener, accelerometerSensor, SensorManager.SENSOR_DELAY_GAME);
        //获取地磁传感器,并为它注册监听器
        Sensor magneticSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
        sensorManager.registerListener(listener, magneticSensor, SensorManager.SENSOR_DELAY_GAME);
        //注:SensorManager.SENSOR_DELAY_GAME为传感器输出信息的更新速度
    }

    private SensorEventListener listener = new SensorEventListener() {

        float[] accelerometerValues = new float[3];
        float[] magneticValues = new float[3];
        private float lastRotateDegree;

        @Override
        public void onSensorChanged(SensorEvent event) {
            //判断当前是加速传感器还是地磁传感器
            if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
                //注意赋值的时候要调用close方法
                accelerometerValues = event.values.clone();
            } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
                magneticValues = event.values.clone();
            }
            float[] R = new float[9];
            float[] values = new float[3];
            SensorManager.getRotationMatrix(R, null, accelerometerValues, magneticValues);
            SensorManager.getOrientation(R, values);
            //values[0]表示是手机围绕Z轴旋转的弧度,Math.toDegrees()方法是将弧度转化成角度
//            Log.i(TAG, "values[0] is " + Math.toDegrees(values[0]));
            //values[0]的取值范围是-180度到180度,其中±180度表示正南方向,0度表示正北方向,90度表示正西方向,90度表示正东方向。
            //将计算出的旋转角度取反,用于旋转指南针背景图
            float rotateDegree = -(float) Math.toDegrees(values[0]);
            if (Math.abs(rotateDegree - lastRotateDegree) > 1) {
                //创建一个动画的实例,参数:旋转的起始角度、旋转的终止角度、后面四个参数用于指定旋转的中心店
                RotateAnimation animation = new RotateAnimation(
                        lastRotateDegree, rotateDegree,
                        Animation.RELATIVE_TO_SELF, 0.5f,
                        Animation.RELATIVE_TO_SELF, 0.5f);
                animation.setFillAfter(true);
                //执行旋转动画
                imgCompass.startAnimation(animation);
                lastRotateDegree = rotateDegree;
            }
        }

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

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (null!=sensorManager){
            sensorManager.unregisterListener(listener);
        }
    }

}

主题设置:
在AndroidManifest文件里面种application里面的属性theme设置值为@style/AppTheme,而AppTheme里面设置

   <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="android:windowActionBar">false</item>
        <!--<item name="windowActionBar">false</item>-->
    </style>

效果图:
指南针
当然了,Android中支持的传感器远远不只这些,还有压力传感器、温度传感器、陀螺仪传感器等,不过由于这些传感器都不太常用,而且不少Android手机中都没有嵌入这些传感器。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值