Android 传感器(一)— 使用加速度传感器实现摇一摇打开页面

大部分手机都内置了传感器,App可以使用这些传感器实现一些功能,例如统计步数、摇一摇打开页面(特指恶心的开屏广告)、根据光线调节屏幕亮度等。本文介绍如何使用加速度计传感器实现摇一摇打开页面。

传感器框架官方文档

传感器简介

大多数Android设备中都内置传感器,可以用于测量运动、环境条件以及屏幕方向等。同时Android提供了传感器框架API,可以通过此框架API访问多种类型的传感器。

坐标系

传感器通常使用标准的3轴坐标系来表示数据值,坐标系不会随设备的移动而改变。当设备处于默认屏幕方向时,x轴从左向右水平延伸,y轴从下往上垂直延伸,z轴垂直于屏幕向外延伸,如下图:

传感器简单使用

传感器可用性

使用传感器之前,可以先检测设备是否支持要使用的传感器。

  • 获取所有支持的传感器
kotlin 复制代码
class SensorExampleActivity : AppCompatActivity() {

    private lateinit var sensorManager: SensorManager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

        // 获取设备支持的所有类型的传感器
        val sensorList = sensorManager.getSensorList(Sensor.TYPE_ALL)
    }
}
  • 获取某个类型的传感器
kotlin 复制代码
class SensorExampleActivity : AppCompatActivity() {

    private lateinit var sensorManager: SensorManager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

        // 获取加速度计传感器
        val accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
        if (accelerometerSensor != null) {
            // 可以使用加速度计传感器
        } else {
            // 无法使用加速度计传感器
        }
    }
}

手机摇晃时打开新页面

可以使用加速度计传感器(Sensor.TYPE_ACCELEROMETER)来检测手机是否有摇晃,实现方案为通过加速度计传感器获取设备在3个轴上的加速度,每两次之间相减,当差值超过阈值时,代表在某个轴上发生了移动,可以判定为发生了摇晃,具体代码如下:

kotlin 复制代码
class SensorExampleActivity : AppCompatActivity() {

    private lateinit var binding: LayoutSensorExampleActivityBinding
    private lateinit var sensorManager: SensorManager
    private var accelerometerSensor: Sensor? = null

    private val accelerometerData = FloatArray(3)
    
    private val thresholds = 2
    
    private var enterNextPage = AtomicBoolean(false)

    private val sensorEventListener = object : SensorEventListener {
        override fun onSensorChanged(event: SensorEvent?) {
            // 传感器数据变化时回调此方法
            when (event?.sensor?.type) {
                Sensor.TYPE_ACCELEROMETER -> {
                    val oldX = accelerometerData[0]
                    val oldY = accelerometerData[1]
                    val oldZ = accelerometerData[2]

                    val currentX = event.values[0]
                    val currentY = event.values[1]
                    val currentZ = event.values[2]

                    // 判断3个轴的加速度变化是否超过阈值,超过则代表发生了移动
                    val xMove = oldX != 0f && currentX - oldX > thresholds
                    val yMove = oldY != 0f && currentY - oldY > thresholds
                    val zMove = oldZ != 0f && currentZ - oldZ > thresholds

                    accelerometerData[0] = currentX
                    accelerometerData[1] = currentY
                    accelerometerData[2] = currentZ

                    // 任意一个方向发生了位移,打开新页面
                    if (xMove || yMove || zMove) {
                        // 避免打开多个页面
                        if (!enterNextPage.get()) {
                            enterNextPage.set(true)
                            startActivity(Intent(this@SensorExampleActivity, CameraActivity::class.java))
                            finish()
                        }
                    }
                }
            }
        }

        override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
            // 传感器的精度发生变化时回调此方法,通常无需做处理
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = LayoutSensorExampleActivityBinding.inflate(layoutInflater)
        setContentView(binding.root)
        binding.includeTitle.tvTitle.text = "Sensor Example"

        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
        accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
    }

    override fun onResume() {
        super.onResume()
        accelerometerSensor?.let {
            // 注册传感器监听并且设置数据采样延迟
            // SensorManager.SENSOR_DELAY_FASTEST 延迟0微妙
            // SensorManager.SENSOR_DELAY_GAME 演示20000微妙
            // SensorManager.SENSOR_DELAY_UI 延迟60000微妙
            // SensorManager.SENSOR_DELAY_NORMAL 延迟200000微秒
            sensorManager.registerListener(sensorEventListener, it, 10 * 1000 * 1000)
        }
    }

    override fun onPause() {
        super.onPause()
        // 移除传感器监听
        sensorManager.unregisterListener(sensorEventListener)
    }
}

效果如图:

示例

演示代码已在示例Demo中添加。

ExampleDemo github

ExampleDemo gitee

相关推荐
服装学院的IT男1 小时前
【Android 13源码分析】WindowContainer窗口层级-4-Layer树
android
CCTV果冻爽2 小时前
Android 源码集成可卸载 APP
android
码农明明2 小时前
Android源码分析:从源头分析View事件的传递
android·操作系统·源码阅读
秋月霜风3 小时前
mariadb主从配置步骤
android·adb·mariadb
Python私教4 小时前
Python ORM 框架 SQLModel 快速入门教程
android·java·python
编程乐学5 小时前
基于Android Studio 蜜雪冰城(奶茶饮品点餐)—原创
android·gitee·android studio·大作业·安卓课设·奶茶点餐
problc6 小时前
Android中的引用类型:Weak Reference, Soft Reference, Phantom Reference 和 WeakHashMap
android
IH_LZH6 小时前
Broadcast:Android中实现组件及进程间通信
android·java·android studio·broadcast
去看全世界的云6 小时前
【Android】Handler用法及原理解析
android·java
机器之心7 小时前
o1 带火的 CoT 到底行不行?新论文引发了论战
android·人工智能