【Android App】物联网中指南针、计步器、感光器、陀螺仪的讲解及实战演示(附源码 超详细必看)

简介: 【Android App】物联网中指南针、计步器、感光器、陀螺仪的讲解及实战演示(附源码 超详细必看)

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

一、指南针-磁场传感器

顾名思义,指南针只要找到朝南的方向就好了。 可是在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; // 磁场强度变更值的数组
    @Override
    protected 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);
    }
    @Override
    protected void onPause() {
        super.onPause();
        mSensorMgr.unregisterListener(this); // 注销当前活动的传感监听器
    }
    @Override
    protected void onResume() {
        super.onResume();
        int suitable = 0;
        // 获取当前设备支持的传感器列表
        List<Sensor> 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("当前设备不支持指南针,请检查是否存在加速度和磁场传感器");
        }
    }
    @Override
    public 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(); // 加速度和磁场强度两个都有了,才能计算磁极的方向
        }
    }
    //当传感器精度改变时回调该方法,一般无需处理
    @Override
    public 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; // 计步器统计的步伐数目
    @Override
    protected 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<Sensor> 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("当前设备不支持计步器,请检查是否存在步行检测传感器和计步器");
        }
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        mSensorMgr.unregisterListener(this); // 注销当前活动的传感监听器
    }
    @Override
    public 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);
    }
    //当传感器精度改变时回调该方法,一般无需处理
    @Override
    public 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; // 声明一个传感管理器对象
    @Override
    protected 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);
    }
    @Override
    protected void onPause() {
        super.onPause();
        mSensorMgr.unregisterListener(this); // 注销当前活动的传感监听器
    }
    @Override
    protected void onResume() {
        super.onResume();
        // 给光线传感器注册传感监听器
        mSensorMgr.registerListener(this, mSensorMgr.getDefaultSensor(Sensor.TYPE_LIGHT),
                SensorManager.SENSOR_DELAY_NORMAL);
    }
    @Override
    public void onSensorChanged(SensorEvent event) {
        if (event.sensor.getType() == Sensor.TYPE_LIGHT) { // 光线强度变更事件
            float light_strength = event.values[0];
            tv_light.setText(DateUtil.getNowTime() + " 当前光线强度为" + light_strength);
        }
    }
    //当传感器精度改变时回调该方法,一般无需处理
    @Override
    public 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三个方向上的旋转角度
    @Override
    protected 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);
    }
    @Override
    protected void onPause() {
        super.onPause();
        mSensorMgr.unregisterListener(this); // 注销当前活动的传感监听器
    }
    @Override
    protected void onResume() {
        super.onResume();
        // 获取当前设备支持的传感器列表
        List<Sensor> 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("当前设备不支持陀螺仪,请检查是否存在陀螺仪传感器");
        }
    }
    @Override
    public 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;
        }
    }
    //当传感器精度改变时回调该方法,一般无需处理
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {}
}

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

相关实践学习
钉钉群中如何接收IoT温控器数据告警通知
本实验主要介绍如何将温控器设备以MQTT协议接入IoT物联网平台,通过云产品流转到函数计算FC,调用钉钉群机器人API,实时推送温湿度消息到钉钉群。
阿里云AIoT物联网开发实战
本课程将由物联网专家带你熟悉阿里云AIoT物联网领域全套云产品,7天轻松搭建基于Arduino的端到端物联网场景应用。 开始学习前,请先开通下方两个云产品,让学习更流畅: IoT物联网平台:https://iot.console.aliyun.com/ LinkWAN物联网络管理平台:https://linkwan.console.aliyun.com/service-open
相关文章
|
9天前
|
Web App开发 前端开发 安全
语音交友app系统源码功能及技术研发流程剖析
语音交友App核心功能包括语音聊天(一对一、群聊、语音消息)、语音房间(直播、主题房、管理)、社交互动(好友、关注、打赏)、内容发现、音效美化、通知提醒及安全隐私等。开发流程涵盖需求分析、技术选型(前端、后端、数据库、实时通信)、UI/UX设计、前后端开发、实时通信集成、音效处理、测试优化、部署上线及运营维护,确保稳定高效运行并持续优化用户体验。
|
6天前
|
安全 JavaScript 前端开发
小游戏源码开发之可跨app软件对接是如何设计和开发的
小游戏开发团队常需应对跨平台需求,为此设计了成熟的解决方案。流程涵盖游戏设计、技术选型、接口设计等。首先明确游戏功能与特性,选择合适的技术架构和引擎(如Unity或Cocos2d-x)。接着设计通用接口,确保与不同App的无缝对接,并制定接口规范。开发过程中实现游戏逻辑和界面,完成登录、分享及数据对接功能。最后进行测试优化,确保兼容性和性能,发布后持续维护更新。
|
8天前
|
前端开发 Java 测试技术
语音app系统软件源码开发搭建新手启蒙篇
在移动互联网时代,语音App已成为生活和工作的重要工具。本文为新手开发者提供语音App系统软件源码开发的启蒙指南,涵盖需求分析、技术选型、界面设计、编码实现、测试部署等关键环节。通过明确需求、选择合适的技术框架、优化用户体验、严格测试及持续维护更新,帮助开发者掌握开发流程,快速搭建功能完善的语音App。
|
1月前
|
移动开发 开发框架 小程序
轻松搭建婚恋交友系统源码,H5/小程序/APP自动适配,智能匹配恋爱交友平台快速落地
婚恋交友系统涵盖在线交友、线下活动、专业服务、社交娱乐等,满足用户多样化需求。系统设计简洁易用,提供实名认证、多注册方式及安全保护,确保用户隐私和数据安全。功能丰富,支持图文展示、筛选匹配、聊天互动、虚拟礼物等,提升互动趣味性。平台可分类管理用户、审核信息、智能推荐,优化用户体验。基于TP6+Uni-app框架,实现跨平台同步,支持二次开发,适应不同市场需求。 [了解更多](https://gitee.com/multi-customer-software/jy)
|
30天前
|
小程序 IDE PHP
圈子源码如何打包生成App小程序/开发一个圈子系统软件所需要的费用体现在哪里?
将PHP源码打包成App的过程涉及多个步骤和技术选择。以圈子源码为例,首先明确需求,确定App功能和目标用户群体,并根据需求开发小程序页面,如用户注册、圈子列表等。源码准备阶段确保源码适用于小程序开发,环境配置需安装IDE(如微信开发者工具)及依赖库。最后在IDE中打包小程序并上传至管理平台,通过审核后发布。费用方面,模板开发成本较低,定制开发则更高,具体取决于需求复杂度和第三方服务费用。
73 0
|
2月前
|
开发框架 小程序 前端开发
圈子社交app前端+后端源码,uniapp社交兴趣圈子开发,框架php圈子小程序安装搭建
本文介绍了圈子社交APP的源码获取、分析与定制,PHP实现的圈子框架设计及代码编写,以及圈子小程序的安装搭建。涵盖环境配置、数据库设计、前后端开发与接口对接等内容,确保平台的安全性、性能和功能完整性。通过详细指导,帮助开发者快速搭建稳定可靠的圈子社交平台。
|
2月前
|
前端开发 算法 安全
一站式搭建相亲交友APP丨交友系统源码丨语音视频聊天社交软件平台系统丨开发流程步骤
本文详细介绍了一站式搭建相亲交友APP的开发流程,涵盖需求分析、技术选型、系统设计、编码实现、测试、部署上线及后期维护等环节。通过市场调研明确平台定位与功能需求,选择适合的技术栈(如React、Node.js、MySQL等),设计系统架构和数据库结构,开发核心功能如用户注册、匹配算法、音视频聊天等,并进行严格的测试和优化,确保系统的稳定性和安全性。最终,通过云服务部署上线,并持续维护和迭代,提供一个功能完善、安全可靠的社交平台。
172 6
|
28天前
|
移动开发 小程序
thinkphp+uniapp开发的多端商城系统源码/H5/小程序/APP支持DIY模板直播分销
thinkphp+uniapp开发的多端商城系统源码/H5/小程序/APP支持DIY模板直播分销
26 0
|
2月前
|
移动开发 小程序 前端开发
使用php开发圈子系统特点,如何获取圈子系统源码,社交圈子运营以及圈子系统的功能特点,圈子系统,允许二开,免费源码,APP 小程序 H5
开发一个圈子系统(也称为社交网络或社群系统)可以是一个复杂但非常有趣的项目。以下是一些关键特点和步骤,帮助你理解如何开发、获取源码以及运营一个圈子系统。
167 4
|
2月前
|
前端开发 搜索推荐 PHP
大开眼界!uniapp秀操作,陪玩系统新功能,陪玩app源码,可实时互动随心优化!
多客游戏陪玩系统采用前端uniapp与PHP语言,实现全开源、易改造,RTC传输协议确保低延迟语音连麦,分布式部署应对高并发。功能创新包括游戏约单、多人语音聊天室、动态广场、私信聊天等,提供高端社交和个性化服务,满足各类需求,让玩家畅享游戏乐趣。

热门文章

最新文章

  • 1
    如何修复 Android 和 Windows 不支持视频编解码器的问题?
  • 2
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
  • 3
    Android经典面试题之Kotlin中Lambda表达式和匿名函数的区别
  • 4
    MNN-LLM App:在手机上离线运行大模型,阿里巴巴开源基于 MNN-LLM 框架开发的手机 AI 助手应用
  • 5
    【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 6
    微信小程序 app.json 配置文件解析与应用
  • 7
    【Azure App Service】基于Linux创建的App Service是否可以主动升级内置的Nginx版本呢?
  • 8
    【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
  • 9
    【Azure Function】Function App出现System.IO.FileNotFoundException异常
  • 10
    原生鸿蒙版小艺APP接入DeepSeek-R1,为HarmonyOS应用开发注入新活力