Android Question Shake detecting Java code need to be converted into B4A, Can any one help please?

Rajesh kannan MJ

Member
Licensed User
Update 0.1 :

I have written a small code snippet here. http://www.basic4ppc.com/android/fo...based-shake-detection-code.47301/#post-292458
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

The following java code seems perfect for shake detection in accelerometer. Although I could understand the logic and algorithm in it, I am not able to convert it into B4A.

This code has force detection, minimum milliseconds of shakes happening and other properties.

Can some one convert this into B4A? Else, Can some one convert into library jar file please?

And here is the code,

B4X:
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;


/**
* Listener that detects shake gesture.
*/
public class ShakeEventListener implements SensorEventListener {


  /** Minimum movement force to consider. */
  private static final int MIN_FORCE = 10;

  /**
   * Minimum times in a shake gesture that the direction of movement needs to
   * change.
   */
  private static final int MIN_DIRECTION_CHANGE = 3;

  /** Maximum pause between movements. */
  private static final int MAX_PAUSE_BETHWEEN_DIRECTION_CHANGE = 200;

  /** Maximum allowed time for shake gesture. */
  private static final int MAX_TOTAL_DURATION_OF_SHAKE = 400;

  /** Time when the gesture started. */
  private long mFirstDirectionChangeTime = 0;

  /** Time when the last movement started. */
  private long mLastDirectionChangeTime;

  /** How many movements are considered so far. */
  private int mDirectionChangeCount = 0;

  /** The last x position. */
  private float lastX = 0;

  /** The last y position. */
  private float lastY = 0;

  /** The last z position. */
  private float lastZ = 0;

  /** OnShakeListener that is called when shake is detected. */
  private OnShakeListener mShakeListener;

  /**
   * Interface for shake gesture.
   */
  public interface OnShakeListener {

    /**
     * Called when shake gesture is detected.
     */
    void onShake();
  }

  public void setOnShakeListener(OnShakeListener listener) {
    mShakeListener = listener;
  }

  @Override
  public void onSensorChanged(SensorEvent se) {
    // get sensor data
    float x = se.values[SensorManager.DATA_X];
    float y = se.values[SensorManager.DATA_Y];
    float z = se.values[SensorManager.DATA_Z];

    // calculate movement
    float totalMovement = Math.abs(x + y + z - lastX - lastY - lastZ);

    if (totalMovement > MIN_FORCE) {

      // get time
      long now = System.currentTimeMillis();

      // store first movement time
      if (mFirstDirectionChangeTime == 0) {
        mFirstDirectionChangeTime = now;
        mLastDirectionChangeTime = now;
      }

      // check if the last movement was not long ago
      long lastChangeWasAgo = now - mLastDirectionChangeTime;
      if (lastChangeWasAgo < MAX_PAUSE_BETHWEEN_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
          long totalDuration = now - mFirstDirectionChangeTime;
          if (totalDuration < MAX_TOTAL_DURATION_OF_SHAKE) {
            mShakeListener.onShake();
            resetShakeParameters();
          }
        }

      } else {
        resetShakeParameters();
      }
    }
  }

  /**
   * Resets the shake parameters to their default values.
   */
  private void resetShakeParameters() {
    mFirstDirectionChangeTime = 0;
    mDirectionChangeCount = 0;
    mLastDirectionChangeTime = 0;
    lastX = 0;
    lastY = 0;
    lastZ = 0;
  }

  @Override
  public void onAccuracyChanged(Sensor sensor, int accuracy) {
  }

}
This is where I found the code http://stackoverflow.com/a/5117254

Thanks in advance,

Best Regards,

Rajeshkannan MJ
 
Last edited:

Rajesh kannan MJ

Member
Licensed User
Well, I searched the forum fully. Please see my question. I need "threshold" and "minimum amount of time shaken"

I have already seen those 2 links. One is a simple library that fires event on shake. Another is advanced one which explains and gives graph ability of x,y and z values.

So, I have searched the forum.

Moreover, I have even worked with AppInventor which has a library for shake sensor. This has a property called "sensitivity" where one can set your required values. You can see the beauty of the library http://ai2.appinventor.mit.edu/reference/components/sensors.html

This is what I want,

Thanks,
 

keirS

Well-Known Member
Licensed User
Which you can do using Erels tutorial and a simple bit of maths. The source you quoted above gives you all the maths required. The source code you quoted is not appropriate in any event as it uses deprecated properties.
 

Rajesh kannan MJ

Member
Licensed User
@keirS Yes, That is what I am going to if I do not get any guidance.

BTW, Can you please tell me how to handle this

B4X:
float totalMovement = Math.abs(x + y + z - lastX - lastY - lastZ);
in B4A

Thanks in advance,
 

keirS

Well-Known Member
Licensed User
B4X:
dim totalMovement as Double
totalMovement  =  abs(x + y + z - lastX - lastY - lastZ)
 

Rajesh kannan MJ

Member
Licensed User
@keirS the "abs" is totally different from Math.abs. So, I created a java libraray just for Math.abs :) and imported it. But there is another way too, I think, the java.lang.math can be imported directly through objects.

Anyways, I found solution for my program.

Actually, I wanted to create an App that makes some bell sounds when the phone shakes. When the phone stops shaking, the bell sound stops. We are humans and we cannot provide exact shakings. So, I added some shaking corrections in the code. It means the code confirms the "non shake" mode when it received a minimum of two 0 values.

The basic algorithm I have written is here, I hope it is useful to somebody. Please enhance or fix any bugs if any one sees it,

B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Dim Accelerometer As PhoneAccelerometer
    
    Dim lastX As Float
    Dim lastY As Float
    Dim lastZ As Float
    Dim myMaths As FirstLib
    Dim MIN_FORCE As Int
    Dim totalMovement As Int
    Dim shakingCorrection As Int
   
End Sub

Sub Globals
    MIN_FORCE = 2
End Sub

Sub Activity_Create(FirstTime As Boolean)
    
End Sub

Sub Accelerometer_AccelerometerChanged (X As Float, Y As Float, Z As Float)
    totalMovement = myMaths.Myabs( X + Y + Z  - lastX - lastY - lastZ )
   
    If (totalMovement > MIN_FORCE) Then    
        Log("shaking")
        'do all things here when you wanted the phone to shake
        'reset shaking correction
        shakingCorrection = 0
    Else
        shakingCorrection = shakingCorrection + 1
        If shakingCorrection > 2 Then
            Log("not shaking, do not do anything")
            shakingCorrection = 0
        End If
    End If
   
    'Assign new values
    lastX = X
    lastY = Y
    lastZ = Z 
End Sub
Sub Activity_Resume
    Accelerometer.StartListening("Accelerometer")
End Sub

Sub Activity_Pause (UserClosed As Boolean)
     Accelerometer.StopListening
End Sub
In the code, the MIN_FORCE stands for the distance you move the phone. 2 is minimum and sensitive. But If you add 5 or 10, it means the phone has to be shaken more distance.

Also, note that the myMaths.Myabs is my function written in library. There may be some other better ways to do it, But I am using it to get value,

B4X:
totalMovement = myMaths.Myabs( X + Y + Z  - lastX - lastY - lastZ )
Thank you,
 

moster67

Expert
Licensed User
Might be a good idea to attach your library too o_O
In this way, we can try your code.
 

Rajesh kannan MJ

Member
Licensed User
@moster67 I have changed the code by avoiding library. I used Java Object concept to use the function "abs"

Please see this updated code. This code does not need any external library. It requires basically Java Object Library and Phone Library.

I shall better start a new thread at "code snippets" so users can see it first,

B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Dim Accelerometer As PhoneAccelerometer
    
    Dim lastX As Float
    Dim lastY As Float
    Dim lastZ As Float
    Dim MIN_FORCE As Int
    Dim totalMovement As Int
    Dim jo As JavaObject
    jo.InitializeStatic("java.lang.Math")
    Dim shakingCorrection As Int
End Sub

Sub Globals
    MIN_FORCE = 2
End Sub

Sub Activity_Create(FirstTime As Boolean)
    
End Sub

Sub Accelerometer_AccelerometerChanged (X As Float, Y As Float, Z As Float)
    'totalMovement = myMaths.Myabs( )
    totalMovement = jo.RunMethod("abs", Array As Object( X + Y + Z  - lastX - lastY - lastZ))
    If (totalMovement > MIN_FORCE) Then    
        Log("shaking")
        'do all things here when you wanted the phone to shake
        'reset shaking correction
        shakingCorrection = 0
    Else
        shakingCorrection = shakingCorrection + 1
        If shakingCorrection > 2 Then
            Log("not shaking, do not do anything")
            shakingCorrection = 0
        End If
    End If
   
    'Assign new values
    lastX = X
    lastY = Y
    lastZ = Z 
End Sub
Sub Activity_Resume
    Accelerometer.StartListening("Accelerometer")
End Sub

Sub Activity_Pause (UserClosed As Boolean)
     Accelerometer.StopListening
End Sub
 
Top