【Android App】物联网中指南针、计步器、感光器、陀螺仪的讲解及实战演示(附源码 超详细必看)
创始人
2024-03-07 16:20:40

需要源码请点赞关注收藏后评论区留言~~~

一、指南针-磁场传感器

顾名思义,指南针只要找到朝南的方向就好了。 可是在App中并非使用一个方向传感器这么简单,事实上单独的方向传感器已经弃用,取而代之的是利用加速度传感器和磁场传感器。 获得加速度和磁场强度两个数值之后,再通过SensorManager的getRotationMatrix方法与getOrientation方法计算方向角度。

要想在手机上模拟指南针的效果,需要自己编写一个罗盘视图,然后在罗盘上绘制正南方向的指针效果如下  晃动手机头部即会显示不同方向

 

 代码如下

package com.example.iot;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.view.View;
import android.widget.TextView;import androidx.appcompat.app.AppCompatActivity;import com.example.iot.widget.CompassView;import java.util.List;public class DirectionActivity extends AppCompatActivity implements SensorEventListener {private TextView tv_direction; // 声明一个文本视图对象private CompassView cv_sourth; // 声明一个罗盘视图对象private SensorManager mSensorMgr;// 声明一个传感管理器对象private float[] mAcceValues; // 加速度变更值的数组private float[] mMagnValues; // 磁场强度变更值的数组@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_direction);tv_direction = findViewById(R.id.tv_direction);cv_sourth = findViewById(R.id.cv_sourth);// 从系统服务中获取传感管理器对象mSensorMgr = (SensorManager) getSystemService(Context.SENSOR_SERVICE);}@Overrideprotected void onPause() {super.onPause();mSensorMgr.unregisterListener(this); // 注销当前活动的传感监听器}@Overrideprotected void onResume() {super.onResume();int suitable = 0;// 获取当前设备支持的传感器列表List sensorList = mSensorMgr.getSensorList(Sensor.TYPE_ALL);for (Sensor sensor : sensorList) {if (sensor.getType() == Sensor.TYPE_ACCELEROMETER) { // 找到加速度传感器suitable += 1; // 找到加速度传感器} else if (sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { // 找到磁场传感器suitable += 10; // 找到磁场传感器}}if (suitable / 10 > 0 && suitable % 10 > 0) {// 给加速度传感器注册传感监听器mSensorMgr.registerListener(this,mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_NORMAL);// 给磁场传感器注册传感监听器mSensorMgr.registerListener(this,mSensorMgr.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),SensorManager.SENSOR_DELAY_NORMAL);} else {cv_sourth.setVisibility(View.GONE);tv_direction.setText("当前设备不支持指南针,请检查是否存在加速度和磁场传感器");}}@Overridepublic void onSensorChanged(SensorEvent event) {if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { // 加速度变更事件mAcceValues = event.values; // 加速度变更事件} else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { // 磁场强度变更事件mMagnValues = event.values; // 磁场强度变更事件}if (mAcceValues != null && mMagnValues != null) {calculateOrientation(); // 加速度和磁场强度两个都有了,才能计算磁极的方向}}//当传感器精度改变时回调该方法,一般无需处理@Overridepublic void onAccuracyChanged(Sensor sensor, int accuracy) {}// 计算指南针的方向private void calculateOrientation() {float[] values = new float[3];float[] R = new float[9];SensorManager.getRotationMatrix(R, null, mAcceValues, mMagnValues);SensorManager.getOrientation(R, values);values[0] = (float) Math.toDegrees(values[0]); // 计算手机上部与正北方向的夹角cv_sourth.setDirection((int) values[0]); // 设置罗盘视图中的指南针方向if (values[0] >= -10 && values[0] < 10) {tv_direction.setText("手机上部方向是正北");} else if (values[0] >= 10 && values[0] < 80) {tv_direction.setText("手机上部方向是东北");} else if (values[0] >= 80 && values[0] <= 100) {tv_direction.setText("手机上部方向是正东");} else if (values[0] >= 100 && values[0] < 170) {tv_direction.setText("手机上部方向是东南");} else if ((values[0] >= 170 && values[0] <= 180)|| (values[0]) >= -180 && values[0] < -170) {tv_direction.setText("手机上部方向是正南");} else if (values[0] >= -170 && values[0] < -100) {tv_direction.setText("手机上部方向是西南");} else if (values[0] >= -100 && values[0] < -80) {tv_direction.setText("手机上部方向是正西");} else if (values[0] >= -80 && values[0] < -10) {tv_direction.setText("手机上部方向是西北");}}
}

二、计步器

计步器的原理是通过手机的前后摆动模拟步伐节奏的监测。Android中与计步器有关的传感器有两个。

(1)一个是步行检测(TYPE_STEP_DETECTOR) 步行检测的返回数值为1时,表示当前监测到一个步伐;

(2)另一个是步行计数(TYPE_STEP_ COUNTER) 步行计数的返回数值是累加后的数值,表示本次开机激活后的总步伐数。

效果如下  随着走路上面的计数会发生对应的变化

 代码如下

package com.example.iot;import android.annotation.SuppressLint;
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.widget.TextView;import androidx.appcompat.app.AppCompatActivity;import java.util.List;@SuppressLint("DefaultLocale")
public class StepActivity extends AppCompatActivity implements SensorEventListener {private TextView tv_step; // 声明一个文本视图对象private SensorManager mSensorMgr; // 声明一个传感管理器对象private int mStepDetector = 0; // 累加的步行检测次数private int mStepCounter = 0; // 计步器统计的步伐数目@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_step);tv_step = findViewById(R.id.tv_step);initStepSensor(); // 初始化步行传感器}// 初始化步行传感器private void initStepSensor() {// 从系统服务中获取传感管理器对象mSensorMgr = (SensorManager) getSystemService(Context.SENSOR_SERVICE);int suitable = 0;// 获取当前设备支持的传感器列表List sensorList = mSensorMgr.getSensorList(Sensor.TYPE_ALL);for (Sensor sensor : sensorList) {if (sensor.getType() == Sensor.TYPE_STEP_DETECTOR) { // 找到步行检测传感器suitable += 1;// 给步行检测传感器注册传感监听器mSensorMgr.registerListener(this,mSensorMgr.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR),SensorManager.SENSOR_DELAY_NORMAL);} else if (sensor.getType() == Sensor.TYPE_STEP_COUNTER) { // 找到计步器suitable += 10;// 给计步器注册传感监听器mSensorMgr.registerListener(this,mSensorMgr.getDefaultSensor(Sensor.TYPE_STEP_COUNTER),SensorManager.SENSOR_DELAY_NORMAL);}}if (suitable == 0) {tv_step.setText("当前设备不支持计步器,请检查是否存在步行检测传感器和计步器");}}@Overrideprotected void onDestroy() {super.onDestroy();mSensorMgr.unregisterListener(this); // 注销当前活动的传感监听器}@Overridepublic void onSensorChanged(SensorEvent event) {if (event.sensor.getType() == Sensor.TYPE_STEP_DETECTOR) { // 步行检测事件if (event.values[0] == 1.0f) {mStepDetector++; // 步行检测事件}} else if (event.sensor.getType() == Sensor.TYPE_STEP_COUNTER) { // 计步器事件mStepCounter = (int) event.values[0]; // 计步器事件}String desc = String.format("设备检测到您当前走了%d步,总计数为%d步",mStepDetector, mStepCounter);tv_step.setText(desc);}//当传感器精度改变时回调该方法,一般无需处理@Overridepublic void onAccuracyChanged(Sensor sensor, int accuracy) {}}

三、感光器

感光器也叫光线传感器,借助于前置摄像头的曝光,一旦遮住前置摄像头,传感器监测到的光线强度立马就会降低。 在实际开发中,光线传感器往往用于感应手机正面的光线强弱,从而自动调节屏幕亮度

摄像头没有被遮挡前数值如下

被遮挡后数值如下

 代码如下

package com.example.iot;import android.annotation.SuppressLint;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Build;
import android.os.Bundle;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.TextView;import androidx.appcompat.app.AppCompatActivity;import com.example.iot.util.DateUtil;
import com.example.iot.util.SwitchUtil;@SuppressLint(value={"DefaultLocale","SetTextI18n"})
public class LightActivity extends AppCompatActivity implements SensorEventListener {private TextView tv_light; // 声明一个文本视图对象private SensorManager mSensorMgr; // 声明一个传感管理器对象@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_light);CheckBox ck_bright = findViewById(R.id.ck_bright);// 检查屏幕亮度是否为自动调节if (SwitchUtil.getAutoBrightStatus(this)) {ck_bright.setChecked(true);}// Android8.0之后普通应用不允许修改系统设置if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {ck_bright.setOnCheckedChangeListener((buttonView, isChecked) -> {// 设置是否开启屏幕亮度的自动调节SwitchUtil.setAutoBrightStatus(this, isChecked);});} else {ck_bright.setEnabled(false);}tv_light = findViewById(R.id.tv_light);// 从系统服务中获取传感管理器对象mSensorMgr = (SensorManager) getSystemService(Context.SENSOR_SERVICE);}@Overrideprotected void onPause() {super.onPause();mSensorMgr.unregisterListener(this); // 注销当前活动的传感监听器}@Overrideprotected void onResume() {super.onResume();// 给光线传感器注册传感监听器mSensorMgr.registerListener(this, mSensorMgr.getDefaultSensor(Sensor.TYPE_LIGHT),SensorManager.SENSOR_DELAY_NORMAL);}@Overridepublic void onSensorChanged(SensorEvent event) {if (event.sensor.getType() == Sensor.TYPE_LIGHT) { // 光线强度变更事件float light_strength = event.values[0];tv_light.setText(DateUtil.getNowTime() + " 当前光线强度为" + light_strength);}}//当传感器精度改变时回调该方法,一般无需处理@Overridepublic void onAccuracyChanged(Sensor sensor, int accuracy) {}}

四、陀螺仪

陀螺仪是测量平衡的仪器,它的测量结果为当前与上次位置之间的倾斜角度,这个角度描述的是三维空间上的夹角,因而其数值由x、y、z三个坐标轴上的角度偏移组成。 由于陀螺仪具备三维角度的测量功能,因此它又被称作角速度传感器。 加速度传感器只能检测线性距离的大小,而陀螺仪能够检测旋转角度的大小,所以利用陀螺仪可以还原三维物体的转动行为。

运行测试效果如下 随着手机的转动示数会跟着变化

 代码如下

package com.example.iot;import android.annotation.SuppressLint;
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.widget.TextView;import androidx.appcompat.app.AppCompatActivity;import com.example.iot.util.DateUtil;import java.util.List;@SuppressLint("DefaultLocale")
public class GyroscopeActivity extends AppCompatActivity implements SensorEventListener {private static final float NS2S = 1.0f / 1000000000.0f; // 将纳秒转化为秒private TextView tv_gyroscope; // 声明一个文本视图对象private SensorManager mSensorMgr; // 声明一个传感管理器对象private float mTimestamp; // 记录上次的时间戳private float mAngle[] = new float[3]; // 记录xyz三个方向上的旋转角度@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_gyroscope);tv_gyroscope = findViewById(R.id.tv_gyroscope);// 从系统服务中获取传感管理器对象mSensorMgr = (SensorManager) getSystemService(Context.SENSOR_SERVICE);}@Overrideprotected void onPause() {super.onPause();mSensorMgr.unregisterListener(this); // 注销当前活动的传感监听器}@Overrideprotected void onResume() {super.onResume();// 获取当前设备支持的传感器列表List sensorList = mSensorMgr.getSensorList(Sensor.TYPE_ALL);boolean isSuitable = false;for (Sensor sensor : sensorList) {if (sensor.getType() == Sensor.TYPE_GYROSCOPE) { // 找到陀螺仪isSuitable = true;break;}}if (isSuitable) { // 找到了陀螺仪// 给陀螺仪传感器注册传感监听器mSensorMgr.registerListener(this,mSensorMgr.getDefaultSensor(Sensor.TYPE_GYROSCOPE),SensorManager.SENSOR_DELAY_FASTEST);} else { // 未找到陀螺仪tv_gyroscope.setText("当前设备不支持陀螺仪,请检查是否存在陀螺仪传感器");}}@Overridepublic void onSensorChanged(SensorEvent event) {if (event.sensor.getType() == Sensor.TYPE_GYROSCOPE) { // 陀螺仪角度变更事件if (mTimestamp != 0) {final float dT = (event.timestamp - mTimestamp) * NS2S;mAngle[0] += event.values[0] * dT;mAngle[1] += event.values[1] * dT;mAngle[2] += event.values[2] * dT;// x轴的旋转角度,手机平放桌上,然后绕侧边转动float angleX = (float) Math.toDegrees(mAngle[0]);// y轴的旋转角度,手机平放桌上,然后绕底边转动float angleY = (float) Math.toDegrees(mAngle[1]);// z轴的旋转角度,手机平放桌上,然后水平旋转float angleZ = (float) Math.toDegrees(mAngle[2]);String desc = String.format("%s 陀螺仪检测到当前位置为:\n" +"x轴方向的转动角度为%.6f,\n" +"y轴方向的转动角度为%.6f,\n" +"z轴方向的转动角度为%.6f。",DateUtil.getNowTime(), angleX, angleY, angleZ);tv_gyroscope.setText(desc);}mTimestamp = event.timestamp;}}//当传感器精度改变时回调该方法,一般无需处理@Overridepublic void onAccuracyChanged(Sensor sensor, int accuracy) {}
}

创作不易 觉得有帮助请点赞关注收藏~~~

相关内容

热门资讯

猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...