大部分手机都内置了传感器,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中添加。