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

相关推荐
技术liul7 小时前
使用安卓平板,通过USB数据线(而不是Wi-Fi)来控制电脑(版本1)
android·stm32·电脑
_祝你今天愉快9 小时前
Android FrameWork - 开机启动 & Init 进程 初探
android
2501_916007479 小时前
iOS App 上架实战 从内测到应用商店发布的全周期流程解析
android·ios·小程序·https·uni-app·iphone·webview
TimeFine9 小时前
Android 邮件发送日志
android
杨过过儿9 小时前
【Task02】:四步构建简单rag(第一章3节)
android·java·数据库
Wgllss10 小时前
Kotlin 享元设计模式详解 和对象池及在内存优化中的几种案例和应用场景
android·架构·android jetpack
zzywxc78712 小时前
AI 行业应用:金融、医疗、教育、制造业领域的落地案例与技术实现
android·前端·人工智能·chrome·金融·rxjava
sTone8737512 小时前
android studio之外使用NDK编译生成android指定架构的动态库
android·c++
胖虎113 小时前
Android 入门到实战(三):ViewPager及ViewPager2多页面布局
android·viewpager·viewpager2
风往哪边走14 小时前
Media3在线本地视频播放器
android