Android Sensor Hand Wave Detection - android

I'm trying to implement a sensor that can detect a hand wave. I found an example that can do hand hover, but not hand wave.
The following code I used is from
How to controlandroid proximity sensor?
public class AndroidProximitySensorActivity extends Activity {
TextView ProximitySensor, ProximityMax, ProximityReading;
SensorManager mySensorManager;
Sensor myProximitySensor;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ProximitySensor = (TextView)findViewById(R.id.proximitySensor);
ProximityMax = (TextView)findViewById(R.id.proximityMax);
ProximityReading = (TextView)findViewById(R.id.proximityReading);
mySensorManager = (SensorManager)getSystemService(
Context.SENSOR_SERVICE);
myProximitySensor = mySensorManager.getDefaultSensor(
Sensor.TYPE_PROXIMITY);
if (myProximitySensor == null){
ProximitySensor.setText("No Proximity Sensor!");
}else{
ProximitySensor.setText(myProximitySensor.getName());
ProximityMax.setText("Maximum Range: "
+ String.valueOf(myProximitySensor.getMaximumRange()));
mySensorManager.registerListener(proximitySensorEventListener,
myProximitySensor,
SensorManager.SENSOR_DELAY_NORMAL);
}
}
SensorEventListener proximitySensorEventListener
= new SensorEventListener(){
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
#Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
if(event.sensor.getType()==Sensor.TYPE_PROXIMITY){
ProximityReading.setText("Proximity Sensor Reading:"
+ String.valueOf(event.values[0]));
}
}
};
}
In the above code, when the event.values[0] = 0, it means my hand is hover at the sensor. However, I need my sensor to detect a hand wave. How do I do it? Thanks.

Please try this code:
private SensorManager sensorManager;
private Sensor proximitySensor;
private final int WAVE_TIME = 2000;
private final int WAVE_NEEDED_MOVEMENTS = 3;
private long lastWaveTime = 0;
private float lastSensorValue;
private float maxSensorValue;
private float numOfMovements = 0;
public void onCreate() {
super.onCreate();
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
sensorManager.registerListener(proximitySensorEventListener, proximitySensor,SensorManager.SENSOR_DELAY_NORMAL);
maxSensorValue = proximitySensor.getMaximumRange();
}
#Override
public void onSensorChanged(SensorEvent event) {
if(lastWaveTime + WAVE_TIME > System.currentTimeMillis()) {
System.out.println("Reset timing...");
lastWaveTime = System.currentTimeMillis();
numOfMovements = 0;
lastSensorValue = event.values[0];
} else if((event.values[0] != maxSensorValue && lastSensorValue == maxSensorValue) || (event.values[0] == maxSensorValue && lastSensorValue != maxSensorValue) ){
numOfMovements++;
if(numOfMovements == WAVE_NEEDED_MOVEMENTS) {
System.out.println("WAVE EVENT");
lastWaveTime = System.currentTimeMillis();
numOfMovements = 0;
}
}
}

Related

Accelerometer coding not working in all the phones

I am in the process of developing an Android music player which will do the the following actions once a shake action is detected. Actions: 1. Do Nothing 2. Play or Pause 3. Next Song 4. Previous Song
I have created a Service class for the shaking action and it is as follows.
public class Shaker extends Service implements SensorEventListener {
SharedPreferences sharedPreferences;
private static final int MIN_TIME_BETWEEN_SHAKES_MILLISECS = 1000;
private long mLastShakeTime;
private SensorManager sensorManager;
private static final String SHAKE_ACTION_PREFERENCE = "shake_action_preference";
private static final String SHAKE_THRESHOLD_PREFERENCE = "shake_threshold_preference";
#Override
public IBinder onBind(Intent intent) {
return null;
}
public void onCreate() {
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
super.onCreate();
}
public void onDestroy() {
super.onDestroy();
sensorManager.unregisterListener(this);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
sensorManager.registerListener(this, sensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_UI);
return START_STICKY;
}
public void onStart(Intent intent, int startId) {
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
sensorManager.registerListener(this, sensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_UI);
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
#Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
long curTime = System.currentTimeMillis();
if ((curTime - mLastShakeTime) > MIN_TIME_BETWEEN_SHAKES_MILLISECS) {
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
double acceleration = Math.sqrt(Math.pow(x, 2) +
Math.pow(y, 2) +
Math.pow(z, 2)) - SensorManager.GRAVITY_EARTH;
Log.d("Acceleration", "Acceleration is " + acceleration + "m/s^2");
String threshold = sharedPreferences.getString(SHAKE_THRESHOLD_PREFERENCE, "medium");
float SHAKE_THRESHOLD;
if(threshold.equals("high"))
SHAKE_THRESHOLD = 40.5f;
else if(threshold.equals("low"))
SHAKE_THRESHOLD = 15.5f;
else
SHAKE_THRESHOLD = 25.5f;
if (acceleration > SHAKE_THRESHOLD) {
mLastShakeTime = curTime;
Log.d("Shake", "Shake, Rattle, and Roll");
String opt = sharedPreferences.getString(SHAKE_ACTION_PREFERENCE, "nothing");
Log.d("SharedPreference", opt);
Log.d("SharedPreference", threshold);
if(opt.equals("play")) {
MusicPlayer.playOrPause();
} else if(opt.equals("next")) {
MusicPlayer.next();
} else if(opt.equals("prev")) {
MusicPlayer.previous(getApplicationContext(), false);
}
}
}
}
}
}
But when I run the apk files in actual devices, the shaking function is working only on certain phones and not working for all the mobiles.
I have tried on different mobiles using same Android OS, but it is working in one and not working in the other.
I couldn't figure out why it is like this. Can anybody suggest a solution for this?
I had this problem. onSensorChanged method is called for any changes but in some devices, it is called more than once.It cause problem in logic of the code.
I solved this problem by adding a private static boolean variable. (It causes this method called once).Once this method executes,this variable becomes true.
#Override
public void onSensorChanged(SensorEvent event) {
if(!variable) {
variable=true;
...
...
variable=false;
}
}

How to use sensor datas in another activity (Now it works well thanks to your help!)

(Now it works perfectly)I am new to android development and I have written an showActivity to show my result data from another class. In that class I implement a sensorEventListener and get sensor data. But when I want to display data in my showActivity, I get nothing to show. All the data is 0(or false) and I dont know what's wrong with my code. It's much appreciated if you can give me some advise on how to fix it. Thanks a lot.
This is my showActivity:
public class MapShowActivity extends AppCompatActivity {
public SensorUse mySensorUse ;
private TextView myText;
private Button myButton;
private Timer timer = new Timer();
private int count = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mySensorUse = new SensorUse(MapShowActivity.this);
setContentView(R.layout.activity_map_show);
myText = (TextView)findViewById(R.id.orientation);
}
public void startTimer(){
timer.scheduleAtFixedRate(detectNewOrientation, 100, 100);
}
TimerTask detectNewOrientation = new TimerTask(){
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
myText.setText(String.valueOf(mySensorUse.getOx()));
}
});
}
};
#Override
protected void onResume() {
super.onResume();
mySensorUse.sensorRegister(MapShowActivity.this);
startTimer();
}
#Override
protected void onPause() {
super.onPause();
mySensorUse.sensorUnregister();
}
}
And this is my Sensor class:
public class SensorUse implements SensorEventListener{
private float[] accValues = new float[3];
private float[] magValues = new float[3];
private float[] orientationValues = new float[4];
private float[] resultRotationMatrix = new float[16];
public float ax;
public float ay;
public float az;
public float sumAcc;
public float ox;
public static boolean flag = false;
public boolean rotationMatrixGenerated;
private SensorManager mySensorManager;
private Sensor accSencor, magSensor;
public SensorUse(Context context){
}
#Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION){
accValues = event.values.clone();
ax = accValues[0];
ay = accValues[1];
az = accValues[2];
sumAcc = (float) Math.sqrt(ax*ax + ay*ay + az*az);
flag = true;
}
else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD){
magValues = event.values.clone();
}
if (accValues != null && magValues != null){
rotationMatrixGenerated = SensorManager.getRotationMatrix(resultRotationMatrix,
null, accValues, magValues);
if(rotationMatrixGenerated) {
SensorManager.getOrientation(resultRotationMatrix, orientationValues);
ox = (float) Math.toDegrees(orientationValues[0]);
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public void sensorRegister(Context context){
mySensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
accSencor = mySensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
magSensor = mySensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
mySensorManager.registerListener(this, accSencor, SensorManager.SENSOR_DELAY_GAME);
mySensorManager.registerListener(this, magSensor, SensorManager.SENSOR_DELAY_GAME);
}
public void sensorUnregister(){
mySensorManager.unregisterListener(this, accSencor);
mySensorManager.unregisterListener(this, magSensor);
}
public float getAx(){
return ax;
}
public float getOx(){
return ox;
}
}
App doesn't know which class will be handling the sensor data.
You have to register your sensor class (SensorUse) object
to get accelerometer data.
Find example code below:
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
senAccelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorManager.registerListener(mySensorUse, senAccelerometer , SensorManager.SENSOR_DELAY_NORMAL);
sensorManger is object of SensorManager
mySensorUse is class that has implemented SensorEventListener

detect rotation around Y axis Android Java

How to detect rotation around Y axis of phone?
I am novice in android. I would like to detect 180 degrees rotation. I would like to detect for example if user flip phone which lies on a table or if user rotate his phone in his pocket.
I have read a lot of articles but I really don't understand how to get phone position and then compute angle between another position.
I have found for example this article but I don't know what to do with array named orientation:
Get device angle by using getOrientation() function
Thanks!
// Here is my solution. Not perfectly logical but works quite good:
public class FlipListener implements SensorEventListener {
SensorManager sensorMgr;
FlipEventReceiver receiver;
public FlipListener(Context context, FlipEventReceiver receiver) {
this.receiver = receiver;
sensorMgr = (SensorManager) context.getSystemService(Activity.SENSOR_SERVICE);
sensorMgr.registerListener(this, sensorMgr.getDefaultSensor(Sensor.TYPE_GYROSCOPE), SensorManager.SENSOR_DELAY_UI);
}
public void onResume() {
sensorMgr.registerListener(this, sensorMgr.getDefaultSensor(Sensor.TYPE_GYROSCOPE), SensorManager.SENSOR_DELAY_UI);
}
public void onPause() {
sensorMgr.unregisterListener(this);
clearStack();
}
private static final int IGNORE_FLIPS_AFTER_FLIP = 2500;
private static final int SAMPLING_INTERVAL = 60;
private static final int MINIMAL_STACK_SIZE_TO_FLIP = 2; // Shouldn't be lower than 2
private static final float FLIP_RADIANS = (float)Math.toRadians(140);
private static final int STACK_MAX_SIZE = 38;
private List<Float> stack = new ArrayList<Float>();
private long lastAdd = 0;
private long lastFlip = 0;
#Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_GYROSCOPE) {
rotationRateAroundYChanged((float)event.values[1]);
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
private void rotationRateAroundYChanged(float rotationRateAroundY) {
long currentTime = System.currentTimeMillis();
if (lastFlip != 0 && (currentTime - lastFlip) < IGNORE_FLIPS_AFTER_FLIP) {
return;
}
if( (currentTime - lastAdd) >= SAMPLING_INTERVAL ) {
if( Math.abs(rotationRateAroundY) > 0.3 ) { // Smaller values are unimportant. They can make only mess.
addToStack(rotationRateAroundY);
checkForFlip();
}
}
}
private void checkForFlip() {
int stackSize = stack.size();
if( stackSize < MINIMAL_STACK_SIZE_TO_FLIP ) return;
float approximateAngleSummary = 0;
float val;
for(int i = 0; i < stackSize; i++) {
val = Math.abs(stack.get(i).floatValue());
// "+ Math.pow(val/4.58, 2) )" don't have a sense. Simply it works better with it.
approximateAngleSummary += ( (val + Math.pow(val/4.58, 2) ) / 1000 ) * SAMPLING_INTERVAL;
if( approximateAngleSummary >= FLIP_RADIANS ) {
triggerFlipDetected();
clearStack();
return;
}
}
}
private void clearStack() {
stack.clear();
}
private void addToStack(float val) {
lastAdd = System.currentTimeMillis();
int stackSize = stack.size();
if( stackSize > 0 && ((stack.get(stackSize-1) > 0 ? 1 : -1) != (val>0?1:-1) || stackSize > STACK_MAX_SIZE) ) {
clearStack();
}
stack.add(val);
}
private void triggerFlipDetected() {
lastFlip = System.currentTimeMillis();
receiver.onFlipDetected();
}
public interface FlipEventReceiver {
public void onFlipDetected();
}
}
Usage:
public class FlipTestActivity extends Activity implements FlipEventReceiver {
FlipListener flipListener;
boolean flipListenerActive = true;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_flip_test);
flipListener = new FlipListener(this, this);
}
public void onFlipDetected() {
// What to do when flip detected
}
#Override
protected void onResume() {
super.onResume();
if( !flipListenerActive ) {
flipListener.onResume();
flipListenerActive = true;
}
}
#Override
protected void onPause() {
super.onPause();
if( flipListenerActive ) {
flipListener.onPause();
flipListenerActive = false;
}
}
}
SensorManager is a class that lets you access the device's sensors. Check here
Here is a nice tutorial about sensors

accelerometer sensor and mediaplayer

with your help and some guides on the internet, i'm managed to knock out this code. But I find myself with several problems, the application, according to my idea, it should start the media player at the time the phone is shaken, and start it once, but now the media player is started every time the phone is shaken . Furthermore, I would like that, the application worked and the screen off when the phone is shaken starts the media player and the screen is turned on
public class SensorTestActivity extends Activity implements SensorEventListener {
private SensorManager sensorManager;
private boolean color = false;
private View view;
private long lastUpdate;
MediaPlayer mMediaPlayer;
#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.main);
view = findViewById(R.id.textView);
view.setBackgroundColor(Color.BLUE);
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL);
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];
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", Toast.LENGTH_SHORT).show();
if (color) {
view.setBackgroundColor(Color.GREEN);
try {
mMediaPlayer = MediaPlayer.create(getBaseContext(), R.raw.mymusic);
mMediaPlayer.setLooping(false);
mMediaPlayer.start();
mMediaPlayer.setOnCompletionListener(new
OnCompletionListener() {
public void onCompletion(MediaPlayer arg0) {
// if (mMediaPlayer != null) {
// mMediaPlayer.release();
// mMediaPlayer = null;
// }
}
});
} catch (Exception e) {
if (mMediaPlayer != null) {
mMediaPlayer.release();
mMediaPlayer = null;
}
}
}
} 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);
}
}
To start something just once, add a boolean.
boolean startOnce = true;
if (startOnce) {
....
startOnce = false;
}

How can I access the accelerometer properly in Android 1.5?

I have seen a few code examples of 1.0 / 1.1 but since a lot of that is deprecated now I was hoping to find a nice 1.5+ example. I have some code here that I wrote but it doesn't really work properly. Any help would be great, thanks!
public class collectAccel extends Activity implements SensorEventListener,
OnClickListener{
private SensorManager sensorMgr;
private TextView xLabel, yLabel, zLabel;
private Button StartBtn;
private List<Sensor> sensorList;
private float x, y, z;
private long lastUpdate = -1;
// deltas for calibration
private float cx, cy, cz;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
xLabel = (TextView) findViewById(R.id.x_label);
yLabel = (TextView) findViewById(R.id.y_label);
zLabel = (TextView) findViewById(R.id.z_label);
StartBtn = (Button) findViewById(R.id.Button1);
StartBtn.setOnClickListener(this);
}
#Override
public void onClick(View arg0) {
if (xLabel.getVisibility() != 1)
xLabel.setVisibility(1);
if (yLabel.getVisibility() != 1)
yLabel.setVisibility(1);
if (zLabel.getVisibility() != 1)
zLabel.setVisibility(1);
}
#Override
protected void onPause() {
super.onPause();
sensorMgr.unregisterListener((SensorEventListener)this, sensorList.get(0));
sensorMgr = null;
cx = 0;
cy = 0;
cz = 0;
}
#Override
protected void onResume() {
super.onResume();
sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);
sensorList = sensorMgr.getSensorList(Sensor.TYPE_ACCELEROMETER);
boolean accelSupported = sensorMgr.registerListener((SensorEventListener)this,
sensorList.get(0),
SENSOR_DELAY_UI);
if (!accelSupported) {
// on accelerometer on this device
sensorMgr.unregisterListener((SensorEventListener)this, sensorList.get(0));
}
}
#Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
cx = 0;
cy = 0;
cz = 0;
}
#Override
public void onSensorChanged(SensorEvent arg0) {
if (arg0.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
long curTime = System.currentTimeMillis();
// only allow one update every 100ms, otherwise updates
// come way too fast and the phone gets bogged down
// with garbage collection
if (lastUpdate == -1 || (curTime - lastUpdate) > 100) {
lastUpdate = curTime;
x = arg0.values[0];
y = arg0.values[1];
z = arg0.values[2];
xLabel.setText(String.format("X: %+2.5f (%+2.5f)", (x+cx), cx));
yLabel.setText(String.format("Y: %+2.5f (%+2.5f)", (y+cy), cy));
zLabel.setText(String.format("Z: %+2.5f (%+2.5f)", (z+cz), cz));
}
}
}
}
You can look it up in the Android Reference but It looks like you'll need
SensorManager mgr = Context.getSystemService(SENSOR_SERVICE);
IList<Sensor> sensorList = mgr.getSensorList(SensorManager.SENSOR_ACCELEROMETER);
If you really want the list, but I think you are actually meant to use SensorManager.RegisterListener(SensorListener listener, int sensors, int rate) or another version of that method.

Categories

Resources