上周做了一个小小的需求,其中涉及到Android传感器的使用,恰好最近在看的一本书,也有对Android传感器的讲解,因此想总结一下Android传感器的使用。利用Android的传感器,我们可以实现很多有意思的功能。例如:利用加速度传感器可以实现“摇一摇”的功能。这篇博客,一起总结下Android各种传感器的使用。
一.Android传感器概述
Android支持的传感器有几十种,但是,并不是所有的设备都支持,具体可以看Android的Sensor类。比如我的小米max就不支持压力传感器,其他的一些传感器估计也不支持。我先列一下Android提供的主要的传感器:
1.加速度传感器(Sensor.TYPE_ACCELEROMETER)
2.磁场传感器(Sensor.TYPE_MAGNETIC_FIELD)
3.方向传感器(Sensor.TYPE_ORIENTATION)
4.陀螺仪传感器(Sensor.TYPE_GYROSCOPE)
5.重力传感器(Sensor.TYPE_GRAVITY)
6.线性加速度传感器(Sensor.TYPE_LINEAR_ACCELERATION)
7.温度传感器(Sensor.TYPE_TEMPERATURE)
8.光线传感器(Seneor.TYPE_LIGHT)
9.距离传感器(Sensor.TYPE_PROXIMITY)
10.压力传感器(Seneor.TYPE_PRESSURE)
11.计步传感器(Sensor.TYPE_STEP_DETECTOR和Sensor.TYPE_STEP_COUNTER)
二.Android传感器使用
1.加速度传感器
加速度传感器监听手机的加速度,我们可以利用加速度传感器实现类似微信摇一摇的功能。例如下面的代码,我们监听了重力加速度,然后根据x,y,z三个方向上的加速度去计算一个整体的加速度,通过设置两次检测间隔的时间,最后可以获取一个抽象的speed,我们可以根据这个speed去过滤数据,当达到某个值的时候,我们才响应摇动的监听:
package com.example.tuduzhao.tudusensordemo.accelerate;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import com.example.tuduzhao.tudusensordemo.R;
public class AccelerateActivity extends AppCompatActivity implements SensorEventListener {
private SensorManager mSensorManager;
private Sensor mSensor;
private PeriscopeLayout periscopeLayout;
private float lastX;
private float lastY;
private float lastZ;
public static void startActivity(Context context) {
Intent intent = new Intent();
intent.setClass(context, AccelerateActivity.class);
context.startActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_accelerate);
periscopeLayout = findViewById(R.id.periscope);
initSensorManager();
}
private void initSensorManager() {
//加速度
mSensorManager = (SensorManager) this.getSystemService(Context.SENSOR_SERVICE);
if (mSensorManager != null) {
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
if (mSensor != null) {
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
}
@Override
public void onSensorChanged(SensorEvent event) {
// 获得x,y,z坐标
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
// 获得x,y,z的变化值
float deltaX = x - lastX;
float deltaY = y - lastY;
float deltaZ = z - lastZ;
// 将现在的坐标变成last坐标
lastX = x;
lastY = y;
lastZ = z;
double delta = Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ);
if (delta >= 20) {
Log.d("TTTT","speed:"+delta);
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mSensorManager != null) {
mSensorManager.unregisterListener(this);
}
}
}
2.磁场传感器
磁场传感器可以检测手机所在位置x,y,z三个方向上的磁场强度。例如,当我们把手机靠近电脑的时候,可以看到手机磁场强度的变化。如下代码是获取磁场强度(如果我没记错的话,物理上磁场强度是有方向的,也就是最终的值可能是负的):
package com.example.tuduzhao.tudusensordemo.magnetic;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import com.example.tuduzhao.tudusensordemo.R;
public class MagneticActivity extends AppCompatActivity implements SensorEventListener{
private SensorManager mSensorManager;
private Sensor mSensor;
private TextView magneticX;
private TextView magneticY;
private TextView magneticZ;
public static void startActivity(Context context) {
Intent intent = new Intent();
intent.setClass(context, MagneticActivity.class);
context.startActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_magnetic);
magneticX = findViewById(R.id.x);
magneticY = findViewById(R.id.y);
magneticZ = findViewById(R.id.z);
initSensorManager();
}
private void initSensorManager() {
mSensorManager = (SensorManager) this.getSystemService(Context.SENSOR_SERVICE);
if (mSensorManager != null) {
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
}
if (mSensor != null) {
Log.d("TTTT", "mSensor");
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
}
@Override
public void onSensorChanged(SensorEvent event) {
float x = event.values[0];//x方向磁场
float y = event.values[1];//y方向磁场
float z = event.values[2];//z方向磁场
magneticX.setText("x方向磁场强度:"+x);
magneticY.setText("y方向磁场强度:"+y);
magneticZ.setText("z方向磁场强度:"+z);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
protected void onDestroy() {
super.onDestroy();
if(mSensorManager!=null){
mSensorManager.unregisterListener(this);
}
}
}
3.方向传感器
毫无疑问,方向传感器是使用手机获取方向的传感器。不过,我们并不能直接得到东西南北四个方向,需要经过一些简单的换算。获取到的三个值,分别是绕Z轴旋转的角度(0-360度),绕X轴旋转的角度(-90-90度),绕Y轴旋转的角度(-90-90度)。通过绕Z轴旋转的角度,我们可以获取方向:0或360是正北,90是正东,180是正南,270是正西。理论上,如果手机放在一个平面上,后两个值应该是接近0的。当手机头部或者尾部翘起的时候,第二个值会变化。当手机左右倾斜的时候,第三个值会变化。接下来,是我们利用方向传感器获取方向的代码:
package com.example.tuduzhao.tudusensordemo.orientation;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import com.example.tuduzhao.tudusensordemo.R;
public class OrientationActivity extends AppCompatActivity implements SensorEventListener {
private SensorManager mSensorManager;
private Sensor mSensor;
private TextView tv;
public static void startActivity(Context context) {
Intent intent = new Intent();
intent.setClass(context, OrientationActivity.class);
context.startActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_orientation);
tv = findViewById(R.id.tv);
initSensorManager();
}
private void initSensorManager() {
mSensorManager = (SensorManager) this.getSystemService(Context.SENSOR_SERVICE);
if (mSensorManager != null) {
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
}
if (mSensor != null) {
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
}
@Override
public void onSensorChanged(SensorEvent event) {
float zRotate = event.values[0];//方向
float xRotate = event.values[1];
float yRotate = event.values[2];
if ((zRotate >= 0 && zRotate <= 15) || (zRotate <= 360 && zRotate > 345)) {
tv.setText("北");
} else if (zRotate > 15 && zRotate <= 75) {
tv.setText("东北");
} else if (zRotate > 75 && zRotate <= 105) {
tv.setText("东");
} else if (zRotate > 105 && zRotate <= 165) {
tv.setText("东南");
} else if (zRotate > 165 && zRotate <= 195) {
tv.setText("南");
} else if (zRotate > 195 && zRotate <= 255) {
tv.setText("西南");
} else if (zRotate > 255 && zRotate <= 285) {
tv.setText("西");
} else if (zRotate > 285 && zRotate <= 345) {
tv.setText("西北");
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mSensorManager != null) {
mSensorManager.unregisterListener(this);
}
}
}
4.光线传感器
Android提供的光线传感器可以获取环境光照强度,注意:获取到的是环境的光照强度,而不是手机屏幕的光强,示例代码如下:
package com.example.tuduzhao.tudusensordemo.light;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import com.example.tuduzhao.tudusensordemo.R;
public class LightActivity extends AppCompatActivity implements SensorEventListener {
private SensorManager mSensorManager;
private Sensor mSensor;
private TextView tv;
public static void startActivity(Context context) {
Intent intent = new Intent();
intent.setClass(context, LightActivity.class);
context.startActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_light);
tv = findViewById(R.id.tv);
initSensorManager();
}
private void initSensorManager() {
mSensorManager = (SensorManager) this.getSystemService(Context.SENSOR_SERVICE);
if (mSensorManager != null) {
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
}
if (mSensor != null) {
Log.d("TTTT", "mSensor");
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
}
@Override
public void onSensorChanged(SensorEvent event) {
tv.setText("光照强度:" + event.values[0]);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mSensorManager != null) {
mSensorManager.unregisterListener(this);
}
}
}
5.距离传感器
准确来说,是近距离传感器,因为可监听到的距离很小。当身体的部位靠近和远离手机顶部的距离传感器时,会监听到一个数值,以我的小米手机为例,距离是0和5。在下面的示例代码中,我们手靠近和远离手机顶部时,改变下方布局的颜色,示例代码如下:
package com.example.tuduzhao.tudusensordemo.proximity;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import com.example.tuduzhao.tudusensordemo.R;
import com.example.tuduzhao.tudusensordemo.accelerate.AccelerateActivity;
public class ProximityActivity extends AppCompatActivity implements SensorEventListener {
private SensorManager mSensorManager;
private Sensor mSensor;
private TextView tv1;
private TextView tv2;
public static void startActivity(Context context) {
Intent intent = new Intent();
intent.setClass(context, ProximityActivity.class);
context.startActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_proximity);
tv1 = findViewById(R.id.top);
tv2 = findViewById(R.id.bottom);
initSensorManager();
}
private void initSensorManager() {
mSensorManager = (SensorManager) this.getSystemService(Context.SENSOR_SERVICE);
if (mSensorManager != null) {
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
}
if (mSensor != null) {
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
}
@Override
public void onSensorChanged(SensorEvent event) {
float proximity = event.values[0];
if (proximity <= 0) {
//贴近屏幕
tv2.setBackgroundColor(getResources().getColor(R.color.colorAccent));
} else {
//远离屏幕
tv2.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mSensorManager != null) {
mSensorManager.unregisterListener(this);
}
}
}
6.步数传感器
Android提供的步数传感器有两种,分别是Sensor.TYPE_STEP_DETECTOR和Sensor.TYPE_STEP_COUNTER,前者是监听单个步子是否有效,有效则加1,后者是获取计步器的总步数,示例代码如下:
package com.example.tuduzhao.tudusensordemo.step;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import com.example.tuduzhao.tudusensordemo.R;
public class StepActivity extends AppCompatActivity implements SensorEventListener {
private SensorManager mSensorManager;
private Sensor mSensor;
private TextView tvCount;
public static void startActivity(Context context) {
Intent intent = new Intent();
intent.setClass(context, StepActivity.class);
context.startActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_step);
tvCount = findViewById(R.id.step_count);
initSensorManager();
}
private void initSensorManager() {
mSensorManager = (SensorManager) this.getSystemService(Context.SENSOR_SERVICE);
if (mSensorManager != null) {
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
}
if (mSensor != null) {
Log.d("TTTT", "mSensor");
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
}
@Override
public void onSensorChanged(SensorEvent event) {
tvCount.setText("总步数:" + event.values[0]);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
对于加速度传感器,我只介绍了一种,其实还有线性加速度传感器和重力传感器。他们的区别其实就是Sensor种类的不同。另外,线性加速度=加速度-重力加速度。
最后,总结一下,上面总结了我手机支持的Android传感器的使用。我们可以发现,其实每种传感器的使用都是差不多的。区别主要有两点:(1)Sensor的种类(2)SensorEvent的值。像磁场强度这种,我们可以获取三个方向的磁场强度,而对于距离传感器这种,我们最终获取的只是一个值。利用Android传感器可以实现很多好玩的功能,大家可以慢慢地发掘。