Android實現搖晃手機的監聽(搖一搖)
阿新 • • 發佈:2018-12-13
背景
專案中,需要在某些介面監聽使用者搖晃動作做出相應的反應。下面分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([email protected], "不要搖俺啦,好暈哦!", 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全生命週期監聽,故不再需要增加停止監聽方法)。
- 效果圖(搖晃手機後)
- demo程式碼(Kotlin)
https://gitee.com/cxyzy1/shakeMonitorDemo
安卓開發技術分享: https://blog.csdn.net/yinxing2008/article/details/84555061