Android实现摇晃手机的监听(摇一摇)

版权声明:本文为程序园中猿原创文章,转载请注明出处 https://blog.csdn.net/yinxing2008/article/details/84585305

背景

项目中,需要在某些界面监听用户摇晃动作做出相应的反应。下面分Kotlin和Java两种给出具体的代码。

实现方案(Kotlin)

  1. 新增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) {}

}
  1. 调用
SensorManagerHelper sensorHelper = SensorManagerHelper(this)
    sensorHelper.setOnShakeListener(object : SensorManagerHelper.OnShakeListener {
        override fun onShake() {
            Toast.makeText(this@MainActivity, "不要摇俺啦,好晕哦!", Toast.LENGTH_SHORT).show()
        }
    })

实现方案(Java)

  1. 新增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();
        }
    }
}
  1. 调用
SensorManagerHelper sensorHelper = new SensorManagerHelper(this);
sensorHelper.setOnShakeListener(() -> ToastUtil.showToast(ContextUtil.get(), "不要摇俺啦,好晕哦!"));

onDestroy方法中停止监听
sensorHelper.stop()

如果只是某个界面监听摇晃,那就只在某个界面中增加;如果是整个app监听,建议在Application中添加监听(因app全生命周期监听,故不再需要增加停止监听方法)。

  1. 效果图(摇晃手机后)
    image.png
  2. demo代码(Kotlin)
    https://gitee.com/cxyzy1/shakeMonitorDemo

安卓开发技术分享: https://blog.csdn.net/yinxing2008/article/details/84555061

猜你喜欢

转载自blog.csdn.net/yinxing2008/article/details/84585305