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

相关推荐
*才华有限公司*1 小时前
安卓前后端连接教程
android
氦客2 小时前
Android Compose中的附带效应
android·compose·effect·jetpack·composable·附带效应·side effect
雨白2 小时前
Kotlin 协程的灵魂:结构化并发详解
android·kotlin
我命由我123452 小时前
Android 开发问题:getLeft、getRight、getTop、getBottom 方法返回的值都为 0
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
Modu_MrLiu2 小时前
Android实战进阶 - 用户闲置超时自动退出登录功能详解
android·超时保护·实战进阶·长时间未操作超时保护·闲置超时
Jeled3 小时前
Android 网络层最佳实践:Retrofit + OkHttp 封装与实战
android·okhttp·kotlin·android studio·retrofit
信田君95273 小时前
瑞莎星瑞(Radxa Orion O6) 基于 Android OS 使用 NPU的图片模糊查找APP 开发
android·人工智能·深度学习·神经网络
tangweiguo030519873 小时前
Kotlin 实现 Android 网络状态检测工具类
android·网络·kotlin
nvvas4 小时前
Android Studio JAVA开发按钮跳转功能
android·java·android studio