Android传感器

时间:2020-02-23 14:29:15  来源:igfitidea点击:

在本教程中,我们将深入研究Android传感器的世界。
我们的智能手机不仅限于速度,UI和动画。

Android传感器

Android Sensors包含可检测环境变化的属性,例如光线,接近度,旋转,运动,磁场等。

从广义上讲,Android传感器属于以下类别:

  • 环境传感器
  • 运动传感器
  • 方向和位置传感器

要访问Android中的各种Sensor,必须使用SensorManager类。

以下代码显示了如何初始化SensorManager

SensorManager sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);

接下来,您可以使用Sensor类来实例化特定的Sensor。

Sensor lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);

接下来,您可以使用以下代码注册传感器:

sensorManager.registerListener(this, lightSensor,
              SensorManager.SENSOR_DELAY_NORMAL);

建议您在onResume()方法中注册侦听器,并在onPause方法中取消注册侦听器,以节省电池电量。

为了监听传感器事件,您可以在活动中实现SensorEventListener接口。

您需要为此重写以下方法:

@Override
  public void onSensorChanged(SensorEvent event) {
      
  }

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

  }

要获取设备上所有可用传感器的列表,请使用以下代码:

List<Sensor> sensorList = sensorManager.getSensorList(Sensor.TYPE_ALL);

String sensorInfo = "";
for (Sensor s : sensorList){
  sensorInfo= sensorInfo + s.getName()+ "\n";
}

在下一节中,我们将讨论一些常见的传感器类型。

Android传感器类型

  • 光度计用于感应和控制亮度。
    此外,还有压力,湿度和温度传感器。

  • 对于运动,加速度计用于检测摇动/倾斜手势。

  • 接近传感器用于检测物体与设备的距离。
    它通常出现在"呼叫应用程序"中。
    当您将手机靠近耳朵时,借助此传感器,屏幕会变黑。
    虽然最大接近范围是5厘米。

  • 陀螺仪用于测量旋转/自旋。
    重力传感器用于测量重力。

  • 磁力仪用于获取设备位置。

  • 计步器用于检测用户执行的步数。

下图描绘了几种传感器类型及其事件数据值以及相应的格式。

如何检查Android Sensor是否可用?

某些设备不支持某些传感器。
因此,您只需在列表文件中添加权限。
Google确保Play商店中的应用程序对于不支持设备的用户不可见。

<uses-feature android:name="android.hardware.accelerometer"
  android:required="true" 

<uses-feature android:name="android.hardware.sensor.proximity"
  android:required="true" 

<uses-feature android:name="android.hardware.sensor.gyroscope"
  android:required="true" 

加速度计在Android模拟器上不可用。

在下一节中,我们将在Android应用程序中实现某些传感器。

Android传感器示例代码

下面给出了" activity_main.xml"的代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
  xmlns:app="https://schemas.android.com/apk/res-auto"
  xmlns:tools="https://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:layout_gravity="center"
  android:layout_margin="16dp"
  android:gravity="center"
  android:orientation="vertical"
  tools:context=".MainActivity">

  <Button
      android:id="@+id/btnAccelerometer"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:onClick="accelerometerSensorOnClick"
      android:text="Accelerometer" 

  <Button
      android:id="@+id/btnProximity"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:onClick="proximitySensorOnClick"
      android:text="Proximity Sensor" 

  <Button
      android:id="@+id/btnGyro"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:onClick="gyroscopeSensorOnClick"
      android:text="Gyroscope" 

  <Button
      android:id="@+id/btnLightSensor"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:onClick="lightSensorOnClick"
      android:text="Light Sensor" 

  <Button
      android:id="@+id/btnStepCounterOnClick"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:onClick="stepCounterOnClick"
      android:text="Step Counter Sensor" 

  <Button
      android:id="@+id/btnAmbientTemp"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:onClick="ambientTempSensorOnClick"
      android:text="Ambient Temperature Sensor" 

  <TextView
      android:id="@+id/tvResult"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginTop="8dp"
      android:text="Values would be entered here..." 

</LinearLayout>

MainActivity.java的代码如下:

package com.theitroad.androidsensors;

import android.content.Context;
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.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements SensorEventListener {

  private TextView textView;

  private SensorManager sensorManager;

  private Sensor accelerometerSensor;
  private Sensor proximitySensor;
  private Sensor lightSensor;
  private Sensor stepCounterSensor;
  private Sensor tempSensor;
  private Sensor gyroscopeSensor;

  private int currentSensor;

  private long lastUpdate = 0;
  private float last_x, last_y, last_z;
  private static final int SHAKE_THRESHOLD = 600;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      textView = findViewById(R.id.tvResult);

      sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);

      accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
      proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
      lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
      stepCounterSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
      gyroscopeSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
      tempSensor = sensorManager.getDefaultSensor(Sensor.TYPE_AMBIENT_TEMPERATURE);
  }

  public boolean checkSensorAvailability(int sensorType) {
      boolean isSensor = false;
      if (sensorManager.getDefaultSensor(sensorType) != null) {
          isSensor = true;
      }
      return isSensor;
  }

  @Override
  public void onSensorChanged(SensorEvent event) {

      if (event.sensor.getType() == currentSensor) {

          if (currentSensor == Sensor.TYPE_LIGHT) {
              float valueZ = event.values[0];
              textView.setText("Brightness " + valueZ);
          } else if (currentSensor == Sensor.TYPE_PROXIMITY) {
              float distance = event.values[0];
              textView.setText("Proximity " + distance);
          } else if (currentSensor == Sensor.TYPE_STEP_DETECTOR) {
              float steps = event.values[0];
              textView.setText("Steps : " + steps);
          } else if (currentSensor == Sensor.TYPE_ACCELEROMETER) {
              float x = event.values[0];
              float y = event.values[1];
              float z = event.values[2];

              long curTime = System.currentTimeMillis();

              if ((curTime - lastUpdate) > 100) {
                  long diffTime = (curTime - lastUpdate);
                  lastUpdate = curTime;

                  float speed = Math.abs(x + y + z - last_x - last_y - last_z)/diffTime * 10000;

                  if (speed > SHAKE_THRESHOLD) {
                      Toast.makeText(getApplicationContext(), "Your phone just shook", Toast.LENGTH_LONG).show();
                  }

                  last_x = x;
                  last_y = y;
                  last_z = z;
              }
          } else if (currentSensor == Sensor.TYPE_GYROSCOPE) {
              if (event.values[2] > 0.5f) {
                  textView.setText("Anti Clock");
              } else if (event.values[2] < -0.5f) {
                  textView.setText("Clock");
              }
          } else if (currentSensor == Sensor.TYPE_AMBIENT_TEMPERATURE) {
              textView.setText("Ambient Temp in Celsius :" + event.values[0]);
          }

      }

  }

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

  }

  public void accelerometerSensorOnClick(View view) {
      if (checkSensorAvailability(Sensor.TYPE_ACCELEROMETER)) {
          currentSensor = Sensor.TYPE_ACCELEROMETER;
      }
      textView.setText("Accelerometer not available");
  }

  public void proximitySensorOnClick(View view) {
      if (checkSensorAvailability(Sensor.TYPE_PROXIMITY)) {
          currentSensor = Sensor.TYPE_PROXIMITY;
      }
      textView.setText("Proximity Sensor not available");
  }

  public void gyroscopeSensorOnClick(View view) {
      if (checkSensorAvailability(Sensor.TYPE_GYROSCOPE)) {
          currentSensor = Sensor.TYPE_GYROSCOPE;
      } else {
          textView.setText("Gyroscope Sensor not available");
      }
  }

  public void lightSensorOnClick(View view) {
      if (checkSensorAvailability(Sensor.TYPE_LIGHT)) {
          currentSensor = Sensor.TYPE_LIGHT;
      } else {
          textView.setText("Light Sensor not available");
      }
  }

  public void stepCounterOnClick(View view) {
      if (checkSensorAvailability(Sensor.TYPE_STEP_DETECTOR)) {
          currentSensor = Sensor.TYPE_STEP_DETECTOR;
      } else {
          textView.setText("Step Counter Sensor not available");
      }
  }

  public void ambientTempSensorOnClick(View view) {
      if (checkSensorAvailability(Sensor.TYPE_AMBIENT_TEMPERATURE)) {
          currentSensor = Sensor.TYPE_AMBIENT_TEMPERATURE;
      } else {
          textView.setText("Ambient Temperature Sensor not available");
      }
  }

  @Override
  protected void onResume() {
      super.onResume();

      sensorManager.registerListener(this, accelerometerSensor,
              SensorManager.SENSOR_DELAY_NORMAL);
      sensorManager.registerListener(this, lightSensor,
              SensorManager.SENSOR_DELAY_NORMAL);
      sensorManager.registerListener(this, proximitySensor,
              SensorManager.SENSOR_DELAY_NORMAL);
      sensorManager.registerListener(this, stepCounterSensor,
              SensorManager.SENSOR_DELAY_NORMAL);
      sensorManager.registerListener(this, tempSensor,
              SensorManager.SENSOR_DELAY_NORMAL);
      sensorManager.registerListener(this, gyroscopeSensor,
              SensorManager.SENSOR_DELAY_NORMAL);
  }

  @Override
  protected void onPause() {
      super.onPause();
      sensorManager.unregisterListener(this);
  }

}

对于加速度计,我们需要从三个轴中的每个轴获取所有三个坐标的位置。
加速度计非常灵敏,因此会不断更新这些点。

为了检测是否晃动,我们采用给定时间范围内的点差来检测它们移动的速度。

陀螺仪检测手机在z平面中是逆时针方向还是顺时针方向旋转。

光线感应器的硬件位于手机顶部,位于前置摄像头镜头的右侧。