我正在尝试开发一个应用程序,用户可以使用手机的动作击中隐形鼓。因此,当手机向下轻弹时,在轻弹结束时会响起鼓声。
通过检测大型快速移动突然停止的时间,我已经成功完成了90%的工作。但是虽然在轻弹(好)之后鼓声响起,但是在拉动结束时也会发出声音(不理想)。
通过轻弹我的意思是手机正在向前和向下轻弹,好像你用它敲击鼓,而拉我的意思是你将手臂放回到起始位置。
有没有人知道确定何时发生轻弹而不是推动的有效方法?
任何想法都将被感激不尽。
由于
现有代码:
package com.example.testaccelerometer;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.view.Menu;
import android.widget.TextView;
public class MainActivity extends Activity implements SensorEventListener{
public static TextView results;
public static TextView clickresults;
StringBuilder builder = new StringBuilder();
private float mAccelNoGrav;
private float mAccelWithGrav;
private float mLastAccelWithGrav;
public static boolean shakeIsHappening;
public static int beatnumber = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
results = (TextView) findViewById(R.id.results);
clickresults = (TextView) findViewById(R.id.clickresults);
SensorManager manager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
Sensor accelerometer = manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
if(!manager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_FASTEST)){
builder.append("Problem with Accelerometer - Shaking will not work");
};
mAccelNoGrav = 0.00f;
mAccelWithGrav = SensorManager.GRAVITY_EARTH;
mLastAccelWithGrav = SensorManager.GRAVITY_EARTH;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
@Override
public void onSensorChanged(SensorEvent event) {
builder.setLength(0);
builder.append("X " + event.values[0] + "\nY " + event.values[1] + "\nZ " + event.values[2]);
results.setText(builder.toString());
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
mLastAccelWithGrav = mAccelWithGrav;
mAccelWithGrav = android.util.FloatMath.sqrt(x*x + y*y + z*z);
float delta = mAccelWithGrav - mLastAccelWithGrav;
mAccelNoGrav = mAccelNoGrav * 0.9f + delta;
if (mAccelNoGrav >8.5) {
shakeIsHappening = true;
//clickresults.append(" click " + mAccel);
}
if (shakeIsHappening == true && mAccelNoGrav <2) {
beatnumber++;
clickresults.append(" click number: " + beatnumber + "\n" + "PA: " + mLastAccelWithGrav + " CA:" + mAccelNoGrav + "\n ");
shakeIsHappening = false;
}
}
@Override
protected void onResume() {
super.onResume();
// YOU DO NEED TO TRY AND REREGISTER IT NOW
}
@Override
protected void onPause() {
// YOU DO NEED TO TRY AND UNREGISTER IT NOW
super.onPause();
}
}
答案 0 :(得分:1)
您可以将地磁传感器与加速计传感器结合使用,以确定设备的哪个边缘朝向地面,然后排除任何相反方向的加速度事件
http://developer.android.com/reference/android/hardware/SensorManager.html#getOrientation(love [],float [])
答案 1 :(得分:0)
我最终想出了如何解决这个问题,只需使用z轴来确定运动是否朝向地面。
z轴数据被送入z阵列(减去重力)。当加速度超过一定水平时,我们记录最高数字,highZ和最低数字,lowZ。这些标出了高点和低点之间的手部运动范围。当加速度低于2时,我们检查Z阵列中的最新数据位是否等于高点或低点,这告诉我们这个动作是轻弹还是拉动。
这可能不是最有效的解决方法,但它现在正在工作,所以我很开心。感谢大家的帮助。
这是我完成的代码:
public class MainActivity extends Activity implements SensorEventListener {
private float mAccelNoGrav;
private float mAccelWithGrav;
private float mLastAccelWithGrav;
ArrayList<Float> z = new ArrayList<Float>();
public static float finalZ;
public static boolean shakeIsHappening;
public static int beatnumber = 0;
public static float highZ;
public static float lowZ;
public static boolean flick;
public static boolean pull;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
results = (TextView) findViewById(R.id.results);
clickresults = (TextView) findViewById(R.id.clickresults);
SensorManager manager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
Sensor accelerometer = manager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
if (!manager.registerListener(this, accelerometer,
SensorManager.SENSOR_DELAY_FASTEST)) {
builder.append("Problem with Accelerometer - Shaking will not work");
}
;
mAccelNoGrav = 0.00f;
mAccelWithGrav = SensorManager.GRAVITY_EARTH;
mLastAccelWithGrav = SensorManager.GRAVITY_EARTH;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
@Override
public void onSensorChanged(SensorEvent event) {
float x = event.values[0];
float y = event.values[1];
z.add((event.values[2])-SensorManager.GRAVITY_EARTH);
mLastAccelWithGrav = mAccelWithGrav;
mAccelWithGrav = android.util.FloatMath.sqrt(x * x + y * y + z.indexOf(z.size()-1) * z.indexOf(z.size()-1));
float delta = mAccelWithGrav - mLastAccelWithGrav;
mAccelNoGrav = mAccelNoGrav * 0.9f + delta; // Low-cut filter
if (mAccelNoGrav > 8.5) {
shakeIsHappening = true;
z.clear();
if (z.indexOf(z.size()-2) > z.indexOf(z.size()-1)) {
clickresults.append(" Z shrinking" + z);
} else if (z.indexOf(z.size()-2) < z.indexOf(z.size()-1)) {
clickresults.append(" Z growing" + z);
}
}
if (shakeIsHappening == true && mAccelNoGrav < 2) {
finalZ = z.get(z.size()-1);
highZ= z.get(z.size()-1);
lowZ= z.get(z.size()-1);
for (int i = 0; i < z.size(); i++) {
if (z.get(i) > highZ) {
highZ = z.get(i);
} else if ((z.get(i) < lowZ)) {
lowZ = z.get(i);
}
if (highZ==finalZ) {
flick = true;
pull = false;
} else if (lowZ==finalZ) {
flick = false;
pull = true;
}
if (flick) {
beatnumber++;
clickresults.append(" click number: " + beatnumber + "\n" + "PA: "
+ mLastAccelWithGrav + " CA:" + mAccelNoGrav + "\n " + "Lz " + z.indexOf(z.size()-2) +"z " + z.indexOf(z.size()-1) + "\n" + "\n");
shakeIsHappening = false;
}
z.clear();
} }
}
@Override
protected void onResume() {
super.onResume();
// YOU DO NEED TO TRY AND REREGISTER IT NOW
}
@Override
protected void onPause() {
// YOU DO NEED TO TRY AND UNREGISTER IT NOW
super.onPause();
}
}