我需要添加一个摇功能,将刷新我的Android应用程序。
我所找到的所有文档都涉及实现SensorListener,但Eclipse告诉我它已被弃用,并建议使用SensorEventListener。
有人知道如何创建这个震动控制器吗?
我需要添加一个摇功能,将刷新我的Android应用程序。
我所找到的所有文档都涉及实现SensorListener,但Eclipse告诉我它已被弃用,并建议使用SensorEventListener。
有人知道如何创建这个震动控制器吗?
当前回答
我修改了@peceps的答案,并使它的kotlin版本。我还添加了LifecycleOwner参数,使其能够感知生命周期。
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import kotlin.math.abs
/**
* Listener that detects shake gesture.
*/
class ShakeEventListener(
lifecycleOwner: LifecycleOwner,
private val sensorManager: SensorManager,
private val onShake: () -> Unit = {}
) : SensorEventListener, DefaultLifecycleObserver {
/** Time when the gesture started. */
private var mFirstDirectionChangeTime: Long = 0
/** Time when the last movement started. */
private var mLastDirectionChangeTime: Long = 0
/** How many movements are considered so far. */
private var mDirectionChangeCount = 0
/** The last x position. */
private var lastX = 0f
/** The last y position. */
private var lastY = 0f
/** The last z position. */
private var lastZ = 0f
init {
sensorManager.registerListener(
this,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_UI
)
// observe lifecycle state
lifecycleOwner.lifecycle.addObserver(this)
}
override fun onResume(owner: LifecycleOwner) {
sensorManager.registerListener(
this,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_UI
)
}
override fun onPause(owner: LifecycleOwner) {
sensorManager.unregisterListener(this)
}
override fun onSensorChanged(se: SensorEvent) {
// get sensor data
val x = se.values[0]
val y = se.values[1]
val z = se.values[2]
// calculate movement
val totalMovement = abs(x + y + z - lastX - lastY - lastZ)
if (totalMovement > MIN_FORCE) {
// get time
val now = System.currentTimeMillis()
// store first movement time
if (mFirstDirectionChangeTime == 0L) {
mFirstDirectionChangeTime = now
mLastDirectionChangeTime = now
}
// check if the last movement was not long ago
val lastChangeWasAgo = now - mLastDirectionChangeTime
if (lastChangeWasAgo < MAX_PAUSE_BETWEEN_DIRECTION_CHANGE) {
// store movement data
mLastDirectionChangeTime = now
mDirectionChangeCount++
// store last sensor data
lastX = x
lastY = y
lastZ = z
// check how many movements are so far
if (mDirectionChangeCount >= MIN_DIRECTION_CHANGE) {
// check total duration
val totalDuration = now - mFirstDirectionChangeTime
if (totalDuration < MAX_TOTAL_DURATION_OF_SHAKE) {
onShake()
resetShakeParameters()
}
}
} else {
resetShakeParameters()
}
}
}
/**
* Resets the shake parameters to their default values.
*/
private fun resetShakeParameters() {
mFirstDirectionChangeTime = 0
mDirectionChangeCount = 0
mLastDirectionChangeTime = 0
lastX = 0f
lastY = 0f
lastZ = 0f
}
override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}
companion object {
/** Minimum movement force to consider. */
private const val MIN_FORCE = 10
/**
* Minimum times in a shake gesture that the direction of movement needs to
* change.
*/
private const val MIN_DIRECTION_CHANGE = 3
/** Maximum pause between movements. */
private const val MAX_PAUSE_BETWEEN_DIRECTION_CHANGE = 200
/** Maximum allowed time for shake gesture. */
private const val MAX_TOTAL_DURATION_OF_SHAKE = 400
}
}
在您的活动中,添加以下代码,使其检测震动事件:
ShakeEventListener(this, sensorManager){
// onShake logic
}
其他回答
我正在为我的大学项目开发一个运动检测和震动检测应用程序。
除了应用程序的原始目标之外,我还从应用程序中分离了库部分(负责运动和震动检测)。该代码是免费的,可在SourceForge上获得,项目名称为“BenderCatch”。我正在制作的文件将在9月中旬左右准备好。 http://sf.net/projects/bendercatch
它使用了一种更精确的方法来检测震动:当你执行震动时,既观察SensorEvents之间的力差,也观察X轴和Y轴上的振动。它甚至可以在每次震动时发出声音(或振动)。
欢迎通过电子邮件raffaele [at] terzigno [dot] com向我询问更多信息
我已经尝试了几种实现,但我想分享一下我自己的实现。 它以g力为单位进行阈值计算。这让我们更容易理解发生了什么,同时也设置了一个好的阈值。
它只是记录G力的增加,如果超过阈值就触发侦听器。它不使用任何方向阈值,因为如果你只是想记录一个好的震动,你真的不需要这个。
当然,您需要在Activity中对这个侦听器进行标准的注册和un -注册。
此外,为了检查您需要的阈值,我推荐以下应用程序(我没有以任何方式连接到该应用程序)
public class UmitoShakeEventListener implements SensorEventListener {
/**
* The gforce that is necessary to register as shake. (Must include 1G
* gravity)
*/
private final float shakeThresholdInGForce = 2.25F;
private final float gravityEarth = SensorManager.GRAVITY_EARTH;
private OnShakeListener listener;
public void setOnShakeListener(OnShakeListener listener) {
this.listener = listener;
}
public interface OnShakeListener {
public void onShake();
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// ignore
}
@Override
public void onSensorChanged(SensorEvent event) {
if (listener != null) {
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
float gX = x / gravityEarth;
float gY = y / gravityEarth;
float gZ = z / gravityEarth;
//G-Force will be 1 when there is no movement. (gravity)
float gForce = FloatMath.sqrt(gX * gX + gY * gY + gZ * gZ);
if (gForce > shakeThresholdInGForce) {
listener.onShake();
}
}
}
}
package com.example.shakingapp;
import android.app.Activity;
import android.graphics.Color;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;
public class MainActivity extends Activity implements SensorEventListener {
private SensorManager sensorManager;
private boolean color = false;
private View view;
private long lastUpdate;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
view = findViewById(R.id.textView);
view.setBackgroundColor(Color.GREEN);
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
lastUpdate = System.currentTimeMillis();
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
getAccelerometer(event);
}
}
private void getAccelerometer(SensorEvent event) {
float[] values = event.values;
// Movement
float x = values[0];
float y = values[1];
float z = values[2];
System.out.println(x);
System.out.println(y);
System.out.println(z);
System.out.println(SensorManager.GRAVITY_EARTH );
float accelationSquareRoot = (x * x + y * y + z * z)
/ (SensorManager.GRAVITY_EARTH * SensorManager.GRAVITY_EARTH);
long actualTime = System.currentTimeMillis();
if (accelationSquareRoot >= 2) //
{
if (actualTime - lastUpdate < 200) {
return;
}
lastUpdate = actualTime;
Toast.makeText(this, "Device was shuffed "+accelationSquareRoot, Toast.LENGTH_SHORT)
.show();
if (color) {
view.setBackgroundColor(Color.GREEN);
} else {
view.setBackgroundColor(Color.RED);
}
color = !color;
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
protected void onResume() {
super.onResume();
// register this class as a listener for the orientation and
// accelerometer sensors
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
protected void onPause() {
// unregister listener
super.onPause();
sensorManager.unregisterListener(this);
}
}
下面是一个示例代码。 把这些放到你的活动课上:
/* put this into your activity class */
private SensorManager mSensorManager;
private float mAccel; // acceleration apart from gravity
private float mAccelCurrent; // current acceleration including gravity
private float mAccelLast; // last acceleration including gravity
private final SensorEventListener mSensorListener = new SensorEventListener() {
public void onSensorChanged(SensorEvent se) {
float x = se.values[0];
float y = se.values[1];
float z = se.values[2];
mAccelLast = mAccelCurrent;
mAccelCurrent = (float) Math.sqrt((double) (x*x + y*y + z*z));
float delta = mAccelCurrent - mAccelLast;
mAccel = mAccel * 0.9f + delta; // perform low-cut filter
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
@Override
protected void onResume() {
super.onResume();
mSensorManager.registerListener(mSensorListener, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
protected void onPause() {
mSensorManager.unregisterListener(mSensorListener);
super.onPause();
}
把这个添加到你的onCreate方法中:
/* do this in onCreate */
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensorManager.registerListener(mSensorListener, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
mAccel = 0.00f;
mAccelCurrent = SensorManager.GRAVITY_EARTH;
mAccelLast = SensorManager.GRAVITY_EARTH;
然后你可以在你的应用程序中任何你想要的地方询问“mAccel”当前加速度,独立于轴,并从静态加速度(如重力)中清除。 大概是。如果没有移动,则为0,如果设备震动,则为>2。
根据评论-测试这一点:
if (mAccel > 12) {
Toast toast = Toast.makeText(getApplicationContext(), "Device has shaken.", Toast.LENGTH_LONG);
toast.show();
}
注:
The accelometer should be deactivated onPause and activated onResume to save resources (CPU, Battery). The code assumes we are on planet Earth ;-) and initializes the acceleration to earth gravity. Otherwise you would get a strong "shake" when the application starts and "hits" the ground from free-fall. However, the code gets used to the gravitation due to the low-cut filter and would work also on other planets or in free space, once it is initialized. (you never know how long your application will be in use...;-)
你可能想试试开源tinybus。有了它,震动检测就像这样简单。
public class MainActivity extends Activity {
private Bus mBus;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
// Create a bus and attach it to activity
mBus = TinyBus.from(this).wire(new ShakeEventWire());
}
@Subscribe
public void onShakeEvent(ShakeEvent event) {
Toast.makeText(this, "Device has been shaken",
Toast.LENGTH_SHORT).show();
}
@Override
protected void onStart() {
super.onStart();
mBus.register(this);
}
@Override
protected void onStop() {
mBus.unregister(this);
super.onStop();
}
}
它采用地震仪进行振动检测。