1. 程式人生 > >Android實現搖晃手機的監聽(搖一搖)

Android實現搖晃手機的監聽(搖一搖)

背景

專案中,需要在某些介面監聽使用者搖晃動作做出相應的反應。下面分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([email protected], "不要搖俺啦,好暈哦!", 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