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

news2024/11/26 14:29:51

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

一、指南针-磁场传感器

顾名思义,指南针只要找到朝南的方向就好了。 可是在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) {}
}

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/51767.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

区块链工作原理(区块链治理系统、比特币、以太坊、智能合约)

文章目录Blockchain Governance SystemOn-Chain GovernanceOff-Chain GovernanceBitCoin BlockchainEthereum BlockchainProperties of Blockchain SystemSmart ContractsScalability Issues in Blockchain SystemsBlockchain Governance System 每个国家或者城市都有自己的一…

我的第一个网页之----使用HTML编辑器编写HTML文档

HTML篇_三、使用HTML编辑器编写HTML文档 为了满足使用HTML语言进行学习、开发需求我们还需要选择使用一款开发工具来使用。我们可以选择更专业的开发工具来使用&#xff0c;在这里简单介绍几款本人使用过的开发工具&#xff0c;选择你的趁手武器。 一、简述几款HTML编辑器 1…

Proxmox VE 彻底删除本地存储

作者&#xff1a;田逸&#xff08;formyz&#xff09; 问题描述 从Proxmox VE web管理后台添加本地存储&#xff0c;如LVM、LVM-Thin&#xff08;精简逻辑卷&#xff09;等&#xff0c;有时候可能需要删除这些存储&#xff0c;但其Web管理后台却没有提供菜单或者按钮。要删除这…

手把手教你写Linux线程池

手把手教你写Linux线程池 如果需要线程池源码&#xff0c;关注Linux兵工厂&#xff0c;并由大量Linux资料赠送。 线程池 顾名思义&#xff0c;存储线程的池子。线程池是线程的一种使用模式。在平常业务开发中常规的逻辑是遇到任务然后创建线程去执行。但是线程的频繁创建就类…

NR小区搜索(五)S准则

微信同步更新欢迎关注同名modem协议笔记 UE根据支持的频段进行小区搜索过程&#xff0c;检测PSS/SSS->PBCH&#xff0c;然后就可以读到MIB&#xff0c;根据MIB中的pdcch-ConfigSIB1&#xff0c;可以找到CORESET0 和SearchSpace0的信息&#xff0c;进而可以确定一块时频域资…

软件测试 -- 进阶 6 软件缺陷

上工治未病之病&#xff0c;中工治欲病之病&#xff0c;下工治已病之病。-- 孙思邈 .《千金方药方》 释译&#xff1a;未病之病&#xff1a;未病&#xff0c;未发之病&#xff08;及早干预&#xff0c;防止病发&#xff09;&#xff1b;欲病之病&#xff1a;小病&#xff0…

MIR7创建预制发票BAPI

1、事务代码MIR7 前台输入采购订单等相关字段进行开票 2、代码实现 调用BAPI&#xff1a;BAPI_INCOMINGINVOICE_PARK创建发票 "--------------------斌将军-------------------- DATA:ls_headerdata TYPE bapi_incinv_create_header,lv_invoicedocnumber LIKE ba…

桌面画图工具:Pointofix(fertig)

Pointofix桌面画图工具 Pointofix - der virtuelle Textmarker fr Ihren Bildschirm - Freeware 一、软件下载 官方网址https://www.pointofix.de/ 二、进入下载页面&#xff0c;需要下载安装文件和语言包两个文件 三、网站还提供了一个语言设置小程序&#xff0c;但我没用 …

JavaSE笔记——抽象类和接口

文章目录前言一、抽象类和方法二、接口创建1.默认方法2.多继承3.接口中的静态方法三、抽象类和接口四、完全解耦五、使用继承扩展接口六、接口适配七、接口字段八、接口和工厂方法模式总结前言 接口和抽象类提供了一种将接口与实现分离的更加结构化的方法。 一、抽象类和方法 …

传奇外网架设教程

外网架设前需准备&#xff1a; 准备工具:传奇版本源码&#xff0c;服务器&#xff0c;备案域名&#xff0c;DBC数据库&#xff0c;周年客户端 服务器和备案域名需要自备或者租用&#xff0c;这东西自己造不出来&#xff01;&#xff01;&#xff01; 其他的工具&#xff0c;…

Flink被阿里收购4年,最开心的却是Spark背后的Databricks

最近&#xff0c;Flink Forward Asia&#xff08;FFA&#xff09;峰会成功举行&#xff0c;有关Flink的讨论&#xff0c;又开始在国内热闹起来。 2022 年&#xff0c;Apache Flink 社区保持快速发展&#xff1a;GitHub Star 数突破 2 万&#xff0c;单月下载量突破 1400 万次&…

学习总结 | 下一代人工智能

文章目录 一、前言二、底层逻辑三、六大维度今后发展的方向是第三代人工智能,最主要的措施就是把第一代人工智能知识驱动的方法和第二代人工智能数据驱动的方法结合起来,发展安全、可信、可靠和可扩展的人工智能技术,从而推动人工智能的创新应用。 一、前言 中国科学院院士…

iTOP3A5000开发板多路PCIE、SATA、USB3.0等

iTOP3A5000开发板多路PCIE、SATA、USB3.0等 桥片&#xff1a;支持PCIE3.0、USB3.0、SATA3.0、显示接口2路、HDMI和1路VGA、可直接连显示器&#xff0c;另外内置一个网络PHY&#xff0c;片内集成了自研GPU、搭配32位DDR4显存接口&#xff0c;支持16GB显存容量。 底板引出多路PCI…

第3关:添加数据、删除数据、删除表

为了完成本关任务&#xff0c;你需要掌握&#xff1a;1.如何使用HBase shell命令添加数据、2.如何使用命令删除表。 首先启动HBASE 启动HBASEshell 添加数据 我们来给上一关创建的test表的列data添加一些数据&#xff1a; hbase(main):002:0> create test,data Created t…

在 Python 中构建一体化音频分析工具包,在一个地方分析您的音频文件

语言构成了人类之间每次对话的基础。因此,自然语言处理(或简称 NLP)领域无疑在帮助人类日常生活方面具有巨大潜力。 简而言之,NLP 领域包含一组旨在理解人类语言数据并完成下游任务的技术。 NLP 技术涵盖许多领域,例如问答 (QA)、命名实体识别 (NER)、文本摘要、自然语言…

0111 栈与队列Day1

剑指offer09.用两个栈实现队列 用两个栈实现一个队列。队列的声明如下&#xff0c;请实现它的两个函数 appendTail 和 deleteHead &#xff0c;分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素&#xff0c;deleteHead 操作返回 -1 ) 示例 1&#x…

音视频开发入门小知识

什么是视频 视频就是由一系列图片构成的&#xff0c;当画面快速切换时&#xff0c;人眼看起来就感觉是连贯的动作。 视频帧 帧&#xff0c;表示一张画面&#xff0c;就是一帧。一个视频就是由许许多多帧组成的。 帧率 帧率&#xff0c;表示单位时间内帧的数量&#xff0c;…

KingbaseES数据库 kdb_schedule 自动定时任务

KingbaseES数据库 kdb_schedule 自动定时任务 文章目录KingbaseES数据库 kdb_schedule 自动定时任务前言一 安装插件 kdb_schedule1. 添加kdb_schedule2. 修改kdb_schedule所需参数&#xff1a;3. 重启数据库4. 加载kdb_schedule插件二 dbms_scheduler2.1 创建program创建progr…

(四) 共享模型之管程【Monitor 概念】

一、Java 对象头&#xff08;P75&#xff09; 二、原理之 Monitor(锁) Monitor 被翻译为监视器或管程。 每个 Java 对象都可以关联一个 Monitor 对象&#xff0c;如果使用 synchronized 给对象上锁&#xff08;重量级&#xff09;之后&#xff0c;该对象头的 Mark Word 中就被设…

Cookie Session JSP

这里写目录标题1 Cookie1.1 会话介绍1.2 Cookie 介绍1.3 Cookie 属性1.4 Cookie 方法1.4.1 Cookie 添加和获取1.5 Cookie 的使用1.6 Cookie 的细节2 Session2.1 HttpSession 介绍2.2 HttpSession 常用方法2.3 HttpSession 获取2.4 HttpSession 的使用2.5 HttpSession 的细节3 J…