Android实现摇晃手机的监听(摇一摇)
2018-11-28 本文已影响83人
蓝不蓝编程
背景
项目中,需要在某些界面监听用户摇晃动作做出相应的反应。下面分Kotlin和Java两种给出具体的代码。
实现方案(Kotlin)
- 新增SensorManagerHelper.kt
class SensorManagerHelper(private val context: Context) : SensorEventListener {
// 速度阈值,当摇晃速度达到这值后产生作用
private val SPEED_SHRESHOLD = 5000
// 两次检测的时间间隔
private val UPTATE_INTERVAL_TIME = 50
// 传感器管理器
private var sensorManager: SensorManager? = null
// 传感器
private var sensor: Sensor? = null
// 重力感应监听器
private var onShakeListener: OnShakeListener? = null
// 手机上一个位置时重力感应坐标
private var lastX: Float = 0.toFloat()
private var lastY: Float = 0.toFloat()
private var lastZ: Float = 0.toFloat()
// 上次检测时间
private var lastUpdateTime: Long = 0
init {
start()
}
/**
* 开始检测
*/
fun start() {
// 获得传感器管理器
sensorManager = context
.getSystemService(Context.SENSOR_SERVICE) as SensorManager
if (sensorManager != null) {
// 获得重力传感器
sensor = sensorManager!!.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
}
// 注册
if (sensor != null) {
sensorManager!!.registerListener(
this, sensor,
SensorManager.SENSOR_DELAY_GAME
)
}
}
/**
* 停止检测
*/
fun stop() {
sensorManager!!.unregisterListener(this)
}
// 摇晃监听接口
interface OnShakeListener {
fun onShake()
}
// 设置重力感应监听器
fun setOnShakeListener(listener: OnShakeListener) {
onShakeListener = listener
}
/**
* 重力感应器感应获得变化数据
* android.hardware.SensorEventListener#onSensorChanged(android.hardware
* .SensorEvent)
*/
override fun onSensorChanged(event: SensorEvent) {
// 现在检测时间
val currentUpdateTime = System.currentTimeMillis()
// 两次检测的时间间隔
val timeInterval = currentUpdateTime - lastUpdateTime
// 判断是否达到了检测时间间隔
if (timeInterval < UPTATE_INTERVAL_TIME) return
// 现在的时间变成last时间
lastUpdateTime = currentUpdateTime
// 获得x,y,z坐标
val x = event.values[0]
val y = event.values[1]
val z = event.values[2]
// 获得x,y,z的变化值
val deltaX = x - lastX
val deltaY = y - lastY
val deltaZ = z - lastZ
// 将现在的坐标变成last坐标
lastX = x
lastY = y
lastZ = z
val speed = Math.sqrt((deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ).toDouble()) / timeInterval * 10000
// 达到速度阀值,发出提示
if (speed >= SPEED_SHRESHOLD) {
onShakeListener!!.onShake()
}
}
override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}
}
- 调用
SensorManagerHelper sensorHelper = SensorManagerHelper(this)
sensorHelper.setOnShakeListener(object : SensorManagerHelper.OnShakeListener {
override fun onShake() {
Toast.makeText(this@MainActivity, "不要摇俺啦,好晕哦!", Toast.LENGTH_SHORT).show()
}
})
实现方案(Java)
- 新增SensorManagerHelper.java
public class SensorManagerHelper implements SensorEventListener {
// 速度阈值,当摇晃速度达到这值后产生作用
private final int SPEED_SHRESHOLD = 5000;
// 两次检测的时间间隔
private final int UPTATE_INTERVAL_TIME = 50;
// 传感器管理器
private SensorManager sensorManager;
// 传感器
private Sensor sensor;
// 重力感应监听器
private OnShakeListener onShakeListener;
// 上下文对象context
private Context context;
// 手机上一个位置时重力感应坐标
private float lastX;
private float lastY;
private float lastZ;
// 上次检测时间
private long lastUpdateTime;
public SensorManagerHelper(Context context) {
this.context = context;
start();
}
/**
* 开始检测
*/
public void start() {
// 获得传感器管理器
sensorManager = (SensorManager) context
.getSystemService(Context.SENSOR_SERVICE);
if (sensorManager != null) {
// 获得重力传感器
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
// 注册
if (sensor != null) {
sensorManager.registerListener(this, sensor,
SensorManager.SENSOR_DELAY_GAME);
}
}
/**
* 停止检测
*/
public void stop() {
sensorManager.unregisterListener(this);
}
/**
* 摇晃监听接口
*/
public interface OnShakeListener {
void onShake();
}
/**
* 设置重力感应监听器
*/
public void setOnShakeListener(OnShakeListener listener) {
onShakeListener = listener;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
/**
* 重力感应器感应获得变化数据
* android.hardware.SensorEventListener#onSensorChanged(android.hardware
* .SensorEvent)
*/
@Override
public void onSensorChanged(SensorEvent event) {
// 现在检测时间
long currentUpdateTime = System.currentTimeMillis();
// 两次检测的时间间隔
long timeInterval = currentUpdateTime - lastUpdateTime;
// 判断是否达到了检测时间间隔
if (timeInterval < UPTATE_INTERVAL_TIME) return;
// 现在的时间变成last时间
lastUpdateTime = currentUpdateTime;
// 获得x,y,z坐标
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
// 获得x,y,z的变化值
float deltaX = x - lastX;
float deltaY = y - lastY;
float deltaZ = z - lastZ;
// 将现在的坐标变成last坐标
lastX = x;
lastY = y;
lastZ = z;
double speed = Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ
* deltaZ)
/ timeInterval * 10000;
// 达到速度阀值,发出提示
if (speed >= SPEED_SHRESHOLD) {
onShakeListener.onShake();
}
}
}
- 调用
SensorManagerHelper sensorHelper = new SensorManagerHelper(this);
sensorHelper.setOnShakeListener(() -> ToastUtil.showToast(ContextUtil.get(), "不要摇俺啦,好晕哦!"));
onDestroy方法中停止监听
sensorHelper.stop()
如果只是某个界面监听摇晃,那就只在某个界面中增加;如果是整个app监听,建议在Application中添加监听(因app全生命周期监听,故不再需要增加停止监听方法)。
-
效果图(摇晃手机后)
image.png - demo代码(Kotlin)
https://gitee.com/cxyzy1/shakeMonitorDemo
安卓开发技术分享: https://www.jianshu.com/p/442339952f26