I am a beginner in android programming. Below is the program which is updating current position of the object using accelerometer and gyroscope readings.My objective is to update the object's position on the screen. Currently the output of the program is it just displays the object and it doesn't update it's position. Can you please suggest me where i am going wrong.
Mainactivity.java
public class MainActivity extends Activity implements SensorEventListener {
CustomDrawableView mCustomDrawableView = null;
ShapeDrawable mDrawable = new ShapeDrawable();
int UPDATE_THRESHOLD=20;
Sensor accelerometer,gyroscope;
SensorManager sm,sm1;
TextView acceleration,rotation,c_x,c_y;
long mLastUpdate;
public static int x;
public static int y;
double GRAVITY_THRESH = 12;
double one_step_freeze = 0;
double SENSOR_INTERVAL = 0.02;
double STEP_INTERVAL_THRESH = 0.4;
double init_x = 1;
double init_y = 0;
double init_theta = 0;
static int ACCE_FILTER_DATA_MIN_TIME = 20; // 1000ms
long lastSaved = System.currentTimeMillis();
double step_counter = 0;
double current_x,current_y;
double one_step_happend = 0;
double accumulated_rad = 0;
double trace_x = init_x;
double trace_x_particle = init_x;
double trace_y = init_y;
double trace_y_particle = init_y;
double last_x = init_x;
double last_y = init_y;
double last_theta = init_theta;
double z_gy;
float acc_z,acc_x,acc_y;
SensorEventListener mSensorListenerAcc,mSensorListenerGyro;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
sm=(SensorManager)getSystemService(SENSOR_SERVICE);
sm1=(SensorManager)getSystemService(SENSOR_SERVICE);
mCustomDrawableView = new CustomDrawableView(this);
setContentView(mCustomDrawableView);
accelerometer=sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
gyroscope=sm1.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
sm.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL );
sm1.registerListener(this,gyroscope,SensorManager.SENSOR_DELAY_NORMAL);
//acceleration=(TextView)findViewById(R.id.acceleration);
//rotation=(TextView)findViewById(R.id.rotation);
// c_x=(TextView)findViewById(R.id.c_x);
//c_y=(TextView)findViewById(R.id.c_y);
}
/*#Override
protected void onResume()
{
super.onResume();
//sm.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_FASTEST);
sm.registerListener(mSensorListenerAcc, accelerometer, SensorManager.SENSOR_DELAY_FASTEST);
sm1.registerListener(mSensorListenerGyro, gyroscope,SensorManager.SENSOR_DELAY_FASTEST);
//mLastUpdate=System.currentTimeMillis();
}
#Override
protected void onPause()
{
sm.unregisterListener(this);
}*/
#Override
public void onSensorChanged(SensorEvent event) {
/* long actualTime = System.currentTimeMillis();
if(actualTime-mLastUpdate > UPDATE_THRESHOLD){
mLastUpdate=actualTime;
}*/
if (event.sensor.getType() == Sensor.TYPE_GYROSCOPE) {
/*rotation.setText("Xg: " + event.values[0] +
"\nYg: " + event.values[1] +
"\nZg: " + event.values[2]);*/
z_gy= event.values[2];
}
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
/* acceleration.setText("X: " + event.values[0] +
"\nY: " + event.values[1] +
"\nZ: " + event.values[2]);*/
acc_x=event.values[1];
acc_y=event.values[2];
acc_z = event.values[2];
System.out.println("acc_z:" + Float.toString(acc_z));
if (acc_z > GRAVITY_THRESH && one_step_freeze == 0) {
System.out.println("entering1oop1");
one_step_happend = 1;
step_counter = step_counter + 1;
System.out.println("stepcounter: " + Double.toString(step_counter) + "==========================");
one_step_freeze = STEP_INTERVAL_THRESH / SENSOR_INTERVAL;
/*System.out.println("onestepfreeze_in_firstloop_aft_div: " + Double.toString(one_step_freeze));
System.out.println("exitingloop1");*/
}
if (one_step_freeze > 0) {
System.out.println("stepcounterin 2 loop: " + Double.toString(step_counter) + "==========================");
if ((System.currentTimeMillis() - lastSaved) > ACCE_FILTER_DATA_MIN_TIME) {
lastSaved = System.currentTimeMillis();
one_step_freeze = one_step_freeze - 1;
/* System.out.println("onestepfreeze2:" + Double.toString(one_step_freeze));
System.out.println("exitin 2loop");*/
}
}
if(one_step_happend==1){
// System.out.println("entered 3 loop:");
last_theta=accumulated_rad+last_theta;
// System.out.println("last_theta value: "+last_theta);
current_x=last_x+STRIDE_LENGTH*Math.cos(last_theta);
System.out.println("current_x value: " + current_x);
current_y=last_y+STRIDE_LENGTH*Math.sin(last_theta);
//System.out.println("current_y value: " + current_y);
// System.out.println("processing c_x");
//c_x.setText("c_x:" + current_x);
// System.out.println("processing c_y");
//c_y.setText("c_y:" + current_y);
last_x = current_x;
// System.out.println("last_x value: " + last_x);
last_y = current_y;
// System.out.println("last_y value: "+last_y);
accumulated_rad = 0;
one_step_happend = 0;
}else{
accumulated_rad= accumulated_rad + z_gy * SENSOR_INTERVAL;
System.out.println("accumulatedrad: "+accumulated_rad);
}
}
/*if ((acc_z > GRAVITY_THRESH) && (one_step_freeze == 0)) {
one_step_happend = 1;
step_counter = step_counter + 1;
System.out.println("stepcounter: " + Double.toString(step_counter) + "==========================");
one_step_freeze = STEP_INTERVAL_THRESH / SENSOR_INTERVAL;
//System.out.println("onestepfreeze2:"+Double.toString(one_step_freeze)+"==========================");
/*spcounter.setText((int) step_counter);
}*/
/*if (one_step_freeze > 0) {
if ((System.currentTimeMillis() - lastSaved) > ACCE_FILTER_DATA_MIN_TIME) {
lastSaved = System.currentTimeMillis();
one_step_freeze = one_step_freeze - 1;
System.out.println("onestepfreeze2:" + Double.toString(one_step_freeze));
}
}
if (one_step_happend == 1) {
last_theta = accumulated_rad + last_theta;
double current_x = last_x + STRIDE_LENGTH * Math.cos(last_theta);
double current_y = last_y + STRIDE_LENGTH * Math.sin(last_theta);
c_x.setText((int) current_x);
c_y.setText((int)current_y);
/*trace_x = [trace_x current_x];
trace_y = [trace_y current_y];
last_x = current_x;
//System.out.println("last_x"+last_x);
last_y = current_y;
//System.out.println("last_y"+last_y);
accumulated_rad = 0;
one_step_happend = 0;
} *//*else {
accumulated_rad = accumulated_rad + z_gy * SENSOR_INTERVAL;
//System.out.println(accumulated_rad);
/* calculate(accumulated_rad);
}
}
*/
}
#Override
protected void onResume()
{
super.onResume();
// Register this class as a listener for the accelerometer sensor
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL);
// ...and the orientation sensor
sm1.registerListener(this, sm1.getDefaultSensor(Sensor.TYPE_ORIENTATION),
SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
protected void onStop()
{
// Unregister the listener
sm.unregisterListener(this);
super.onStop();
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public class CustomDrawableView extends View
{
static final int width = 50;
static final int height = 50;
public CustomDrawableView(Context context)
{
super(context);
mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xff74AC23);
mDrawable.setBounds((int) current_x, (int) current_y, (int) current_x + width, (int) current_y + height);
//mDrawable.setBounds((int)acc_x, (int)acc_y, (int)acc_x + width,(int) acc_y + height);
}
protected void onDraw(Canvas canvas)
{
/* x= (int)current_x;
y= (int)current_y;*/
RectF oval = new RectF(MainActivity.x, MainActivity.y, MainActivity.x + width, MainActivity.y
+ height); // set bounds of rectangle
Paint p = new Paint(); // set some paint options
p.setColor(Color.BLUE);
canvas.drawOval(oval, p);
invalidate();
}
}
}
Related
Due to the power consuming GPS data, I would like to calculate the device speed with only the accelerometer x,y and z data. I have read a lot of questions about this topic and I tried many set-ups to find a satisfactory solution to calculate the speed when my device is in my car.
It seems so simple but nothing works, which drives me crazy.
Been trying the Sensor.TYPE_LINEAR_ACCELERATION and the Sensor.TYPE_ACCELEROMETER with removed gravity. Tried a Low Pass Filter on the Linear acceleration data. Unfortunately all with no succes.
Looks like the calculated speed is correct but testing in my car the calculated speed doesn't get higher then about 2 m/s.
below a code snip
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
public void onSensorChanged(SensorEvent event) {
if (event.sensor == mAccelerometer) {
if (timestamp != 0) {
final float dT = (event.timestamp - timestamp) * NS2S;
lax = event.values[0];
lay = event.values[1];
laz = event.values[2];
vx = vxo + lax * dT ;
vy = vyo + lay * dT ;
vz = vzo + laz * dT ;
speed = (float) (Math.sqrt(vx*vx + vy*vy + vz*vz)) ;
if (speed < 0.01) {speed = 0 ; }
tv_speed.setText(String.valueOf(speed));
}
timestamp = event.timestamp;
}
}
Hope someone can help, thanks a lot.
It's possible to compute distance and speed using only accelerometer, but with three conditions:
1. Linear movement - trajectory must be straight.
2. Slope of the road must be constant.
3. You must perform calibration procedure before start.
Where can you use this method with such restrictions - it's up to you... Now, how to do it:
We need something, implementing SensorEventListener interface. For the future use, let's add following abstract class:
public abstract class Accelerometer implements SensorEventListener {
protected float lastX;
protected float lastY;
protected float lastZ;
public abstract Point getPoint();
public void onAccuracyChanged(Sensor arg0, int arg1) {
}
}
and this will be our SensorEventListener:
public class XYZAccelerometer extends Accelerometer {
private static final int BUFFER_SIZE = 500;
// calibration
private float dX = 0;
private float dY = 0;
private float dZ = 0;
// buffer variables
private float X;
private float Y;
private float Z;
private int cnt = 0;
// returns last SenorEvent parameters
public Point getLastPoint(){
return new Point(lastX, lastY, lastZ, 1);
}
// returrns parameters, using buffer: average acceleration
// since last call of getPoint().
public Point getPoint(){
if (cnt == 0){
return new Point(lastX, lastY, lastZ, 1);
}
Point p = new Point(X, Y, Z, cnt);
reset();
return p;
}
// resets buffer
public void reset(){
cnt = 0;
X = 0;
Y = 0;
Z = 0;
}
public void onSensorChanged(SensorEvent se) {
float x = se.values[SensorManager.DATA_X] + dX;
float y = se.values[SensorManager.DATA_Y] + dY;
float z = se.values[SensorManager.DATA_Z] + dZ;
lastX = x;
lastY = y;
lastZ = z;
X+= x;
Y+= y;
Z+= z;
if (cnt < BUFFER_SIZE-1) {
cnt++;
} else
{
reset();
}
}
public int getCnt(){
return cnt;
}
public void setdX(float dX) {
this.dX = dX;
}
public void setdY(float dY) {
this.dY = dY;
}
public void setdZ(float dZ) {
this.dZ = dZ;
}
}
Calibrating accelerometer must be called before each experiment. Phone orientation must not be changed while measuring.
To calibrate accelerometer, i use this class:
public class Calibrator {
final static int UPDATE_INTERVAL = 400;
final static int ITERATIONS = 5;
Handler hRefresh;
XYZAccelerometer acc;
int eventNumber;
private LinkedList calData;
public Calibrator(Handler hRefresh, XYZAccelerometer acc, int eventNumber) {
this.hRefresh = hRefresh;
this.acc = acc;
this.eventNumber = eventNumber;
}
public void calibrate() {
final Timer calTimer = new Timer();
calData = new LinkedList();
acc.setdX(0);
acc.setdY(0);
acc.setdZ(0);
calTimer.scheduleAtFixedRate(
new TimerTask() {
public void run() {
addCalData(calData);
if (calData.size() > ITERATIONS) {
calTimer.cancel();
try {
calSensor(calData);
} catch (Exception ex) {
try {
throw ex;
} catch (Exception ex1) {
hRefresh.sendEmptyMessage(5);
}
}
hRefresh.sendEmptyMessage(eventNumber);
}
}
},
0,
UPDATE_INTERVAL);
}
private void addCalData(LinkedList cD) {
Point p = acc.getPoint();
cD.add(p);
acc.reset();
}
private void calSensor(LinkedList cD) throws Exception {
if (cD.size() < ITERATIONS-1) {
throw new Exception("not enough data to calibrate");
}
float x = 0;
float y = 0;
float z = 0;
// Don't use first measure
for (int i = 1; i < cD.size(); ++i) {
x += cD.get(i).getX();
y += cD.get(i).getY();
z += cD.get(i).getZ();
}
x = x / (cD.size() - 1);
y = y / (cD.size() - 1);
z = z / (cD.size() - 1);
acc.setdX(-x);
acc.setdY(-y);
acc.setdZ(-z);
}
}
maintenance class to keep data of one measure
public class Point {
private float x = 0;
private float y = 0;
private float z = 0;
private int cnt = 1;
public float getX() {
return x/(float)cnt;
}
public float getY() {
return y/(float)cnt;
}
public float getZ() {
return z/(float)cnt;
}
public Point(float x, float y, float z, int cnt) {
this.x = x;
this.y = y;
this.z = z;
this.cnt = cnt;
}
public float getForce(){
return getX()*getX()+getY()*getY()+getZ()*getZ();
}
}
And class to process data of measure
public class MeasurePoint {
private float x;
private float y;
private float z;
private float speedBefore;
private float speedAfter;
private float distance;
private float acceleration;
private long interval;
private Point averagePoint;
public MeasurePoint(float x, float y, float z, float speedBefore, long interval, Point averagePoint) {
this.x = x;
this.y = y;
this.z = z;
this.speedBefore = speedBefore;
this.interval = interval;
this.averagePoint = averagePoint;
speedAfter = 0;
calc();
}
private void calc(){
//Acceleration as projection of current vector on average
acceleration = this.x*averagePoint.getX() +
this.y*averagePoint.getY() +
this.z*averagePoint.getZ();
acceleration = acceleration / ((float)Math.sqrt(averagePoint.getForce()));
float t = ((float)interval / 1000f);
speedAfter = speedBefore + acceleration * t;
distance = speedBefore*t + acceleration*t*t/2;
}
public String getStoreString(){
String s = "write here whatever you want";
return s;
}
// add getters
}
This one - to store and save data array
public class MeasureData {
// points from accelerometr
private LinkedList accData;
private LinkedList data;
// timer interval of generating points
private long interval;
public MeasureData(long interval) {
this.interval = interval;
accData = new LinkedList ();
data = new LinkedList ();
}
public void addPoint(Point p){
accData.add(p);
}
public void process(){
for(int i = 0; i < accData.size(); ++i){
Point p = accData.get(i);
float speed = 0;
if(i > 0){
speed = data.get(i-1).getSpeedAfter();
}
data.add(new MeasurePoint(p.getX(), p.getY(), p.getZ(), speed, interval, getAveragePoint()));
}
}
public boolean saveExt(Context con, String fname) throws Throwable {
try {
File file = new File(con.getExternalFilesDir(null), fname);
FileOutputStream os = new FileOutputStream(file);
OutputStreamWriter out = new OutputStreamWriter(os);
for (int i = 0; i < data.size(); ++i) {
MeasurePoint m = data.get(i);
out.write(m.getStoreString());
}
out.close();
} catch (Throwable t) {
throw (t);
}
return true;
}
private Point getAveragePoint() {
float x = 0;
float y = 0;
float z = 0;
for(int i = 0; i < accData.size(); ++i){
Point p = accData.get(i);
x += p.getX();
y += p.getY();
z += p.getZ();
}
return new Point(x, y, z, 1);
}
public float getLastSpeed(){
return data.getLast().getSpeedAfter();
}
public float getLastSpeedKm(){
float ms = getLastSpeed();
return ms*3.6f;
}
}
And, finally, how to use all this in your activity(I cleaned it up a lot, sorry if it will not complie - fill free to write it in comments:
public class TestActivity extends Activity {
static final int TIMER_DONE = 2;
static final int START = 3;
static final int CAL_TIMER_DONE = 4;
static final int ERROR = 5;
private StartCatcher mStartListener;
private XYZAccelerometer xyzAcc;
private SensorManager mSensorManager;
private static final long UPDATE_INTERVAL = 500;
private static final long MEASURE_TIMES = 20;
private Timer timer;
private TextView tv;
private Button testBtn;
int counter;
private MeasureData mdXYZ;
/** handler for async events*/
Handler hRefresh = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case TIMER_DONE:
onMeasureDone();
String es1 = Float.toString(Math.round(mdXYZ.getLastSpeedKm()*100)/100f);
tv.append(" END SPEED " + es1 + " " + es2 + " \n");
enableButtons();
break;
case START:
tv.append(" START");
timer = new Timer();
timer.scheduleAtFixedRate(
new TimerTask() {
public void run() {
dumpSensor();
}
},
0,
UPDATE_INTERVAL);
break;
case ERROR:
Toast.makeText(getApplicationContext(), "ERROR", Toast.LENGTH_SHORT).show();
break;
}
}
};
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tv = (TextView) findViewById(R.id.txt);
testBtn = (Button) findViewById(R.id.btn);
}
#Override
protected void onResume() {
super.onResume();
tv.append("\n ..");
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
setAccelerometer();
setStartCatcher();
mSensorManager.registerListener(xyzAcc,
mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_GAME);
}
#Override
protected void onPause() {
mSensorManager.unregisterListener(xyzAcc);
super.onPause();
}
public void onButtonTest(View v) {
disableButtons();
mdXYZ = new MeasureData(UPDATE_INTERVAL);
counter = 0;
tv.setText("");
tv.append("Calibrating");
Calibrator cal = new Calibrator(hRefresh, xyzAcc, START);
cal.calibrate();
}
void dumpSensor() {
++counter;
mdXYZ.addPoint(xyzAcc.getPoint());
hRefresh.sendEmptyMessage(TICK);
if (counter > MEASURE_TIMES) {
timer.cancel();
hRefresh.sendEmptyMessage(TIMER_DONE);
}
}
private void enableButtons() {
testBtn.setEnabled(true);
}
private void setAccelerometer() {
xyzAcc = new XYZAccelerometer();
mSensorManager.registerListener(xyzAcc,
mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_UI);
}
private void disableButtons() {
testBtn.setEnabled(false);
}
private void onMeasureDone() {
try {
mdXYZ.process();
long now = System.currentTimeMillis();
mdXYZ.saveExt(this, Long.toString(now) + ".csv");
} catch (Throwable ex) {
Toast.makeText(this, ex.getMessage().toString(), Toast.LENGTH_SHORT);
}
}
}
<serviceLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<serviceButton
android:id="#+id/btn"
android:text="TEST"
android:layout_width="300px"
android:layout_height="200px"
android:onClick="onButtonTest" />
<serviceTextView
android:id = "#+id/txt"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text=":"
/>
<service/LinearLayout>
Although at the developer.android.com site it is stated clearly that
you could use the linear accelerometer to see how fast your car is going"
But I did not find anything (in testing or in examples or code) that showed this is really true.
Now, unfortunately, I am convinced that it is not possible to calculate the speed of a car with the linear accelerometer.
Please see the below code to get the velocity using accelerometer
public class SensorTestActivity extends Activity implements SensorEventListener {
double calibration = Double.NaN;
private SensorManager sensorManager;
private boolean color = false;
private TextView view;
private long lastUpdate;
float appliedAcceleration = 0;
float currentAcceleration = 0;
float velocity = 0;
Date lastUpdatedate;
/** 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_main2);
view = findViewById(R.id.textView);
// view.setBackgroundColor(Color.GREEN);
lastUpdatedate = new Date(System.currentTimeMillis());
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
lastUpdate = System.currentTimeMillis();
}
#Override
public void onSensorChanged(SensorEvent event) {
// if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
// getAccelerometer(event);
// }
double x = event.values[0];
double y = event.values[1];
double z = event.values[2];
double a = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2));
if (calibration == Double.NaN)
calibration = a;
else {
updateVelocity();
currentAcceleration = (float)a;
}
}
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 = event.timestamp;
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);
} else {
view.setBackgroundColor(Color.RED);
}
color = !color;
view.setText("SPEEDDDDD=== "+accelationSquareRoot);
// Log.i("SensorTestActivity","SPEEDDDDD=== "+accelationSquareRoot+" ");
}
}
private void updateVelocity() {
// Calculate how long this acceleration has been applied.
Date timeNow = new Date(System.currentTimeMillis());
long timeDelta = timeNow.getTime()-lastUpdatedate.getTime();
lastUpdatedate.setTime(timeNow.getTime());
// Calculate the change in velocity at the
// current acceleration since the last update.
float deltaVelocity = appliedAcceleration * (timeDelta/1000);
appliedAcceleration = currentAcceleration;
// Add the velocity change to the current velocity.
velocity += deltaVelocity;
final double mph = (Math.round(100*velocity / 1.6 * 3.6))/100;
Log.i("SensorTestActivity","SPEEDDDDD=== "+mph+" "+velocity);
}
#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);
}
}
I am having a WaveFormView on which I want to change the color of it while playing Audio file and as the Audio is paused it should be stopped coloring at that certain point and when resumed it should continue forward with coloring. I am not getting how to do it in my code..
This is the screen shot of my generated waveform. Now when I will click on Play button it should change the color of waveform gradually with red color (from start to end slowly).
Here is my code to draw waveform view.
WaveFormView.class
public class WaveformView extends View {
public interface WaveformListener {
public void waveformFling(float x);
public void waveformDraw();
}
;
// Colors
private Paint mGridPaint;
private Paint mSelectedLinePaint;
private Paint mUnselectedLinePaint;
private Paint mUnselectedBkgndLinePaint;
private Paint mBorderLinePaint;
private Paint mPlaybackLinePaint;
private Paint mTimecodePaint;
private SoundFile mSoundFile;
private int[] mLenByZoomLevel;
private double[][] mValuesByZoomLevel;
private double[] mZoomFactorByZoomLevel;
private int[] mHeightsAtThisZoomLevel;
private int mZoomLevel;
private int mNumZoomLevels;
private int mSampleRate;
private int mSamplesPerFrame;
private int mOffset;
private int mSelectionStart;
private int mSelectionEnd;
private int mPlaybackPos;
private float mDensity;
private float mInitialScaleSpan;
private WaveformListener mListener;
private GestureDetector mGestureDetector;
private ScaleGestureDetector mScaleGestureDetector;
private boolean mInitialized;
Color color;
public WaveformView(Context context, AttributeSet attrs) {
super(context, attrs);
// We don't want keys, the markers get these
setFocusable(false);
mGridPaint = new Paint();
mGridPaint.setAntiAlias(false);
mGridPaint.setColor(
getResources().getColor(R.color.grid_line));
mSelectedLinePaint = new Paint();
mSelectedLinePaint.setAntiAlias(false);
mSelectedLinePaint.setColor(
getResources().getColor(R.color.waveform_selected));
mUnselectedLinePaint = new Paint();
mUnselectedLinePaint.setAntiAlias(false);
mUnselectedLinePaint.setColor(
getResources().getColor(R.color.waveform_unselected));
mUnselectedBkgndLinePaint = new Paint();
mUnselectedBkgndLinePaint.setAntiAlias(false);
mUnselectedBkgndLinePaint.setColor(
getResources().getColor(
R.color.selection_border));
mBorderLinePaint = new Paint();
mBorderLinePaint.setAntiAlias(true);
mBorderLinePaint.setStrokeWidth(1.5f);
mBorderLinePaint.setPathEffect(
new DashPathEffect(new float[]{3.0f, 2.0f}, 0.0f));
mBorderLinePaint.setColor(
getResources().getColor(R.color.selection_border));
mPlaybackLinePaint = new Paint();
mPlaybackLinePaint.setAntiAlias(false);
mPlaybackLinePaint.setColor(
getResources().getColor(R.color.playback_indicator));
mTimecodePaint = new Paint();
mTimecodePaint.setTextSize(12);
mTimecodePaint.setAntiAlias(true);
mTimecodePaint.setColor(
getResources().getColor(R.color.timecode));
mTimecodePaint.setShadowLayer(
2, 1, 1,
getResources().getColor(R.color.timecode_shadow));
mGestureDetector = new GestureDetector(
context,
new GestureDetector.SimpleOnGestureListener() {
public boolean onFling(
MotionEvent e1, MotionEvent e2, float vx, float vy) {
mListener.waveformFling(vx);
return true;
}
});
mSoundFile = null;
mLenByZoomLevel = null;
mValuesByZoomLevel = null;
mHeightsAtThisZoomLevel = null;
mOffset = 0;
mPlaybackPos = -1;
mSelectionStart = 0;
mSelectionEnd = 0;
mDensity = 1.0f;
mInitialized = false;
}
public boolean hasSoundFile() {
return mSoundFile != null;
}
public void setSoundFile(SoundFile soundFile) {
mSoundFile = soundFile;
mSampleRate = mSoundFile.getSampleRate();
mSamplesPerFrame = mSoundFile.getSamplesPerFrame();
computeDoublesForAllZoomLevels();
mHeightsAtThisZoomLevel = null;
}
/**
* Called once when a new sound file is added
*/
private void computeDoublesForAllZoomLevels() {
int numFrames = mSoundFile.getNumFrames();
int[] frameGains = mSoundFile.getFrameGains();
double[] smoothedGains = new double[numFrames];
if (numFrames == 1) {
smoothedGains[0] = frameGains[0];
} else if (numFrames == 2) {
smoothedGains[0] = frameGains[0];
smoothedGains[1] = frameGains[1];
} else if (numFrames > 2) {
smoothedGains[0] = (double)(
(frameGains[0] / 2.0) +
(frameGains[1] / 2.0));
for (int i = 1; i < numFrames - 1; i++) {
smoothedGains[i] = (double)(
(frameGains[i - 1] / 3.0) +
(frameGains[i ] / 3.0) +
(frameGains[i + 1] / 3.0));
}
smoothedGains[numFrames - 1] = (double)(
(frameGains[numFrames - 2] / 2.0) +
(frameGains[numFrames - 1] / 2.0));
}
// Make sure the range is no more than 0 - 255
double maxGain = 1.0;
for (int i = 0; i < numFrames; i++) {
if (smoothedGains[i] > maxGain) {
maxGain = smoothedGains[i];
}
}
double scaleFactor = 1.0;
if (maxGain > 255.0) {
scaleFactor = 255 / maxGain;
}
// Build histogram of 256 bins and figure out the new scaled max
maxGain = 0;
int gainHist[] = new int[256];
for (int i = 0; i < numFrames; i++) {
int smoothedGain = (int)(smoothedGains[i] * scaleFactor);
if (smoothedGain < 0)
smoothedGain = 0;
if (smoothedGain > 255)
smoothedGain = 255;
if (smoothedGain > maxGain)
maxGain = smoothedGain;
gainHist[smoothedGain]++;
}
// Re-calibrate the min to be 5%
double minGain = 0;
int sum = 0;
while (minGain < 255 && sum < numFrames / 20) {
sum += gainHist[(int)minGain];
minGain++;
}
// Re-calibrate the max to be 99%
sum = 0;
while (maxGain > 2 && sum < numFrames / 100) {
sum += gainHist[(int)maxGain];
maxGain--;
}
// Compute the heights
double[] heights = new double[numFrames];
double range = maxGain - minGain;
for (int i = 0; i < numFrames; i++) {
double value = (smoothedGains[i] * scaleFactor - minGain) / range;
if (value < 0.0)
value = 0.0;
if (value > 1.0)
value = 1.0;
heights[i] = value * value;
}
mNumZoomLevels = 5;
mLenByZoomLevel = new int[5];
mZoomFactorByZoomLevel = new double[5];
mValuesByZoomLevel = new double[5][];
// Level 0 is doubled, with interpolated values
mLenByZoomLevel[0] = numFrames * 2;
mZoomFactorByZoomLevel[0] = 2.0;
mValuesByZoomLevel[0] = new double[mLenByZoomLevel[0]];
if (numFrames > 0) {
mValuesByZoomLevel[0][0] = 0.5 * heights[0];
mValuesByZoomLevel[0][1] = heights[0];
}
for (int i = 1; i < numFrames; i++) {
mValuesByZoomLevel[0][2 * i] = 0.5 * (heights[i - 1] + heights[i]);
mValuesByZoomLevel[0][2 * i + 1] = heights[i];
}
// Level 1 is normal
mLenByZoomLevel[1] = numFrames;
mValuesByZoomLevel[1] = new double[mLenByZoomLevel[1]];
mZoomFactorByZoomLevel[1] = 1.0;
for (int i = 0; i < mLenByZoomLevel[1]; i++) {
mValuesByZoomLevel[1][i] = heights[i];
}
// 3 more levels are each halved
for (int j = 2; j < 5; j++) {
mLenByZoomLevel[j] = mLenByZoomLevel[j - 1] / 2;
mValuesByZoomLevel[j] = new double[mLenByZoomLevel[j]];
mZoomFactorByZoomLevel[j] = mZoomFactorByZoomLevel[j - 1] / 2.0;
for (int i = 0; i < mLenByZoomLevel[j]; i++) {
mValuesByZoomLevel[j][i] =
0.5 * (mValuesByZoomLevel[j - 1][2 * i] +
mValuesByZoomLevel[j - 1][2 * i + 1]);
}
}
if (numFrames > 5000) {
mZoomLevel = 3;
} else if (numFrames > 1000) {
mZoomLevel = 2;
} else if (numFrames > 300) {
mZoomLevel = 1;
} else {
mZoomLevel = 0;
}
mInitialized = true;
}
public boolean canZoomIn() {
return (mZoomLevel > 0);
}
public void zoomIn() {
if (canZoomIn()) {
mZoomLevel--;
mSelectionStart *= 2;
mSelectionEnd *= 2;
mHeightsAtThisZoomLevel = null;
int offsetCenter = mOffset + getMeasuredWidth() / 2;
offsetCenter *= 2;
mOffset = offsetCenter - getMeasuredWidth() / 2;
if (mOffset < 0)
mOffset = 0;
invalidate();
}
}
public boolean canZoomOut() {
return (mZoomLevel < mNumZoomLevels - 1);
}
public void zoomOut() {
if (canZoomOut()) {
mZoomLevel++;
mSelectionStart /= 2;
mSelectionEnd /= 2;
int offsetCenter = mOffset + getMeasuredWidth() / 2;
offsetCenter /= 2;
mOffset = offsetCenter - getMeasuredWidth() / 2;
if (mOffset < 0)
mOffset = 0;
mHeightsAtThisZoomLevel = null;
invalidate();
}
}
public double pixelsToSeconds(int pixels) {
double z = mZoomFactorByZoomLevel[mZoomLevel];
return (pixels * (double)mSamplesPerFrame / (mSampleRate * z));
}
public void setListener(WaveformListener listener) {
mListener = listener;
}
public void recomputeHeights(float density) {
mHeightsAtThisZoomLevel = null;
mDensity = density;
mTimecodePaint.setTextSize((int)(12 * density));
invalidate();
}
protected void drawWaveformLine(Canvas canvas,
int x, int y0, int y1,
Paint paint) {
canvas.drawLine(x, y0, x, y1, paint);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mSoundFile == null)
return;
if (mHeightsAtThisZoomLevel == null)
computeIntsForThisZoomLevel();
DisplayMetrics displaymetrics = getContext().getResources().getDisplayMetrics();
int height = displaymetrics.heightPixels;
int widths = displaymetrics.widthPixels;
// Draw waveform
int measuredWidth = getMeasuredWidth();
int measuredHeight = getMeasuredHeight();
int start = mOffset;
int width = mHeightsAtThisZoomLevel.length - start;
int ctr = measuredHeight / 2;
Log.e("wid",String.valueOf(width));
Log.e("widCal",String.valueOf(mHeightsAtThisZoomLevel.length));
Log.e("widstart",String.valueOf(start));
if (width > measuredWidth)
width = measuredWidth;
Log.e("measured",String.valueOf(measuredWidth));
// Draw grid
double onePixelInSecs = pixelsToSeconds(1);
boolean onlyEveryFiveSecs = (onePixelInSecs > 1.0 / 50.0);
double fractionalSecs = mOffset * onePixelInSecs;
int integerSecs = (int) fractionalSecs;
int i = 0;
while (i < width) {
i++;
fractionalSecs += onePixelInSecs;
int integerSecsNew = (int) fractionalSecs;
if (integerSecsNew != integerSecs) {
integerSecs = integerSecsNew;
if (!onlyEveryFiveSecs || 0 == (integerSecs % 5)) {
canvas.drawLine(i, 0, i, measuredHeight, mGridPaint);
}
}
}
// Draw waveform
for ( i = 0; i < width; i++) {
Paint paint;
if (i + start >= mSelectionStart &&
i + start < mSelectionEnd) {
paint = mSelectedLinePaint;
// paint.setColor(color);
} else {
drawWaveformLine(canvas, ((widths/width)*i), 0, measuredHeight,
mUnselectedBkgndLinePaint);
paint = mUnselectedLinePaint;
}
drawWaveformLine(
canvas, ((widths/width)*i),
ctr - mHeightsAtThisZoomLevel[start + i],
ctr + 1 + mHeightsAtThisZoomLevel[start + i],
paint);
if (i + start == mPlaybackPos) {
canvas.drawLine(i, 0, i, measuredHeight, mPlaybackLinePaint);
}
}
if (mListener != null) {
mListener.waveformDraw();
}
}
private void computeIntsForThisZoomLevel() {
int halfHeight = (getMeasuredHeight() / 2) - 1;
mHeightsAtThisZoomLevel = new int[mLenByZoomLevel[mZoomLevel]];
for (int i = 0; i < mLenByZoomLevel[mZoomLevel]; i++) {
mHeightsAtThisZoomLevel[i] =
(int)(mValuesByZoomLevel[mZoomLevel][i] * halfHeight);
}
}
}
MainActivity.class
public class MainActivity extends AppCompatActivity implements WaveformView.WaveformListener {
WaveformView mWaveformView;
SoundFile mSoundFile;
private float mDensity;
private File mFile;
private String mFilename;
private long mLoadingLastUpdateTime;
boolean mLoadingKeepGoing;
boolean mFinishActivity;
private ProgressDialog mProgressDialog;
String mTitle,mArtist;
private Thread mLoadSoundFileThread;
private Thread mRecordAudioThread;
private Thread mSaveSoundFileThread;
private boolean mIsPlaying;
private SamplePlayer mPlayer;
private String mInfoContent;
private int mWidth;
private int mMaxPos;
private int mStartPos;
private int mEndPos;
private boolean mStartVisible;
private boolean mEndVisible;
private int mLastDisplayedStartPos;
private int mLastDisplayedEndPos;
private int mOffset;
private int mOffsetGoal;
private int mFlingVelocity;
private int mPlayStartMsec;
private int mPlayEndMsec;
private Handler mHandler;
Button pla;
MediaPlayer mediaPlayer;
boolean ismIsPlaying;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pla = (Button)findViewById(R.id.play);
mWaveformView = (WaveformView)findViewById(R.id.waveform);
mWaveformView.setListener(this);
mHandler = new Handler();
Uri uri = Uri.parse("/sdcard/audio_file.mp3");
mediaPlayer = new MediaPlayer();
mediaPlayer = MediaPlayer.create(getApplicationContext(),uri);
loadGui();
loadFromFile();
}
/**
* Called from both onCreate and onConfigurationChanged
* (if the user switched layouts)
*/
private void loadGui() {
// Inflate our UI from its XML layout description.
setContentView(R.layout.activity_main);
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
mDensity = metrics.density;
mWaveformView = (WaveformView)findViewById(R.id.waveform);
mWaveformView.setListener(this);
if (mSoundFile != null && !mWaveformView.hasSoundFile()) {
mWaveformView.setSoundFile(mSoundFile);
mWaveformView.recomputeHeights(mDensity);
}
}
private void loadFromFile() {
mFilename = "/sdcard/audio_file.mp3";
mFile = new File(mFilename);
SongMetadataReader metadataReader = new SongMetadataReader(
this, mFilename);
mTitle = metadataReader.mTitle;
mArtist = metadataReader.mArtist;
String titleLabel = mTitle;
if (mArtist != null && mArtist.length() > 0) {
titleLabel += " - " + mArtist;
}
setTitle(titleLabel);
mLoadingLastUpdateTime = getCurrentTime();
mLoadingKeepGoing = true;
mFinishActivity = false;
mProgressDialog = new ProgressDialog(MainActivity.this);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setTitle("Loading...");
mProgressDialog.setCancelable(true);
mProgressDialog.setOnCancelListener(
new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
mLoadingKeepGoing = false;
mFinishActivity = true;
}
});
mProgressDialog.show();
final SoundFile.ProgressListener listener =
new SoundFile.ProgressListener() {
public boolean reportProgress(double fractionComplete) {
long now = getCurrentTime();
if (now - mLoadingLastUpdateTime > 100) {
mProgressDialog.setProgress(
(int) (mProgressDialog.getMax() * fractionComplete));
mLoadingLastUpdateTime = now;
}
return mLoadingKeepGoing;
}
};
// Load the sound file in a background thread
mLoadSoundFileThread = new Thread() {
public void run() {
try {
mSoundFile = SoundFile.create(mFile.getAbsolutePath(), listener);
if (mSoundFile == null) {
mProgressDialog.dismiss();
String name = mFile.getName().toLowerCase();
String[] components = name.split("\\.");
String err;
if (components.length < 2) {
err = getResources().getString(
R.string.no_extension_error);
} else {
err = getResources().getString(
R.string.bad_extension_error) + " " +
components[components.length - 1];
}
final String finalErr = err;
Runnable runnable = new Runnable() {
public void run() {
showFinalAlert(new Exception(), finalErr);
}
};
mHandler.post(runnable);
return;
}
mPlayer = new SamplePlayer(mSoundFile);
} catch (final Exception e) {
mProgressDialog.dismiss();
e.printStackTrace();
mInfoContent = e.toString();
runOnUiThread(new Runnable() {
public void run() {
}
});
Runnable runnable = new Runnable() {
public void run() {
showFinalAlert(e, getResources().getText(R.string.read_error));
}
};
mHandler.post(runnable);
return;
}
mProgressDialog.dismiss();
if (mLoadingKeepGoing) {
Runnable runnable = new Runnable() {
public void run() {
finishOpeningSoundFile();
}
};
mHandler.post(runnable);
} else if (mFinishActivity){
MainActivity.this.finish();
}
}
};
mLoadSoundFileThread.start();
}
private void finishOpeningSoundFile() {
mWaveformView.setSoundFile(mSoundFile);
mWaveformView.recomputeHeights(mDensity);
Log.e("sound file",mFilename);
Log.e("sound", String.valueOf(mSoundFile));
}
/**
* Show a "final" alert dialog that will exit the activity
* after the user clicks on the OK button. If an exception
* is passed, it's assumed to be an error condition, and the
* dialog is presented as an error, and the stack trace is
* logged. If there's no exception, it's a success message.
*/
private void showFinalAlert(Exception e, CharSequence message) {
CharSequence title;
if (e != null) {
Log.e("Ringdroid", "Error: " + message);
Log.e("Ringdroid", getStackTrace(e));
title = getResources().getText(R.string.alert_title_failure);
setResult(RESULT_CANCELED, new Intent());
} else {
Log.v("Ringdroid", "Success: " + message);
title = getResources().getText(R.string.alert_title_success);
}
new AlertDialog.Builder(MainActivity.this)
.setTitle(title)
.setMessage(message)
.setPositiveButton(
R.string.alert_ok_button,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
finish();
}
})
.setCancelable(false)
.show();
}
private void showFinalAlert(Exception e, int messageResourceId) {
showFinalAlert(e, getResources().getText(messageResourceId));
}
#Override
public void waveformTouchStart(float x) {
}
#Override
public void waveformTouchMove(float x) {
}
#Override
public void waveformTouchEnd() {
}
#Override
public void waveformFling(float x) {
}
#Override
public void waveformDraw() {
mWidth = mWaveformView.getMeasuredWidth();
if (mOffsetGoal != mOffset) {
// updateDisplay();
}
else if (mIsPlaying) {
// updateDisplay();
} else if (mFlingVelocity != 0) {
// updateDisplay();
}
}
private long getCurrentTime() {
return System.nanoTime() / 1000000;
}
private String getStackTrace(Exception e) {
StringWriter writer = new StringWriter();
e.printStackTrace(new PrintWriter(writer));
return writer.toString();
}
public void buttonClick(View view) {
Toast.makeText(MainActivity.this, "test", Toast.LENGTH_SHORT).show();
mediaPlayer.start();
ismIsPlaying = true;
}
}
In your onDraw(Canvas canvas) add the following lines
if (i + start <= mPlaybackPos) {
Paint mPaint = new Paint(paint);
mPaint.setColor(Color.RED);
drawWaveformLine(
canvas, ((widths/width)*i),
ctr - mHeightsAtThisZoomLevel[start + i],
ctr + 1 + mHeightsAtThisZoomLevel[start + i],
mPaint);
}
add them above the line:
if (i + start == mPlaybackPos) {
And if this works, consider to allocate the Paint-object outside the onDraw() method.
For my Android app I need to get more or less accurately the step count. I say "more or less" because what I need to do is to know if the steps taken in 2 seconds are more or less than the previous ones.
I have tried the following two algorithms, and none of them worked effectively. Also I have tested requesting the step count to Google Fit, but it sometimes returns 215, and then 155, so I can't rely on that.
My solutions were as follows:
private SensorEventListener sensorEventListener = new SensorEventListener() {
//Listens for change in acceleration, displays and computes the steps
#Override
public void onSensorChanged(SensorEvent event) {
//Gather the values from accelerometer
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
//Fetch the current y
currentY = y;
//Measure if a step was taken
if(Math.abs(currentY - previousY) > threshold) {
numSteps++;
textViewSteps.setText(String.valueOf(numSteps));
//Vibramos
Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
vibrator.vibrate(200);
}
//Display the values
//textViewX.setText(String.valueOf(x));
//textViewY.setText(String.valueOf(y));
//textViewZ.setText(String.valueOf(z));
//Store the previous y
previousY = y;
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
private SensorEventListener sensorEventListener = new SensorEventListener()
{
private final static String TAG = "StepDetector";
private float mLimit = 10;
private float mLastValues[] = new float[3*2];
private float mScale[] = new float[2];
private float mYOffset;
private float mLastDirections[] = new float[3*2];
private float mLastExtremes[][] = { new float[3*2], new float[3*2] };
private float mLastDiff[] = new float[3*2];
private int mLastMatch = -1;
//Como no podemos crear un constructor en una clase anónima, uso un inicializador de instancia (instance initializer)
{
int h = 480;
mYOffset = h * 0.5f;
mScale[0] = - (h * 0.5f * (1.0f / (SensorManager.STANDARD_GRAVITY * 2)));
mScale[1] = - (h * 0.5f * (1.0f / (SensorManager.MAGNETIC_FIELD_EARTH_MAX)));
}
public void setSensitivity(float sensitivity) {
mLimit = sensitivity; // 1.97 2.96 4.44 6.66 10.00 15.00 22.50 33.75 50.62
}
//public void onSensorChanged(int sensor, float[] values) {
public void onSensorChanged(SensorEvent event) {
if(calculateKmhtime == 0)
calculateKmhtime = System.currentTimeMillis();
Sensor sensor = event.sensor;
synchronized (this) {
if (sensor.getType() == Sensor.TYPE_ORIENTATION) {
}
else {
int j = (sensor.getType() == Sensor.TYPE_ACCELEROMETER) ? 1 : 0;
if (j == 1) {
float vSum = 0;
for (int i=0 ; i<3 ; i++) {
final float v = mYOffset + event.values[i] * mScale[j];
vSum += v;
}
int k = 0;
float v = vSum / 3;
float direction = (v > mLastValues[k] ? 1 : (v < mLastValues[k] ? -1 : 0));
if (direction == - mLastDirections[k]) {
// Direction changed
int extType = (direction > 0 ? 0 : 1); // minumum or maximum?
mLastExtremes[extType][k] = mLastValues[k];
float diff = Math.abs(mLastExtremes[extType][k] - mLastExtremes[1 - extType][k]);
if (diff > mLimit) {
boolean isAlmostAsLargeAsPrevious = diff > (mLastDiff[k]*2/3);
boolean isPreviousLargeEnough = mLastDiff[k] > (diff/3);
boolean isNotContra = (mLastMatch != 1 - extType);
if (isAlmostAsLargeAsPrevious && isPreviousLargeEnough && isNotContra) {
Log.i(TAG, "step");
//Hemos detectado un paso. Aumentamos el número de pasos
numSteps++;
textViewSteps.setText(String.valueOf(numSteps));
mLastMatch = extType;
long currentTime = System.currentTimeMillis();
//Vibramos
Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
vibrator.vibrate(200);
if(currentTime - calculateKmhtime >= CALCULATE_KMH_DELAY) {
calculateKmh(stepsInSpecifiedSeconds, (currentTime - calculateKmhtime) / 1000);
calculateKmhtime = System.currentTimeMillis();
stepsInSpecifiedSeconds = 0;
}else{
stepsInSpecifiedSeconds++;
}
}
else {
mLastMatch = -1;
}
}
mLastDiff[k] = diff;
}
mLastDirections[k] = direction;
mLastValues[k] = v;
}
}
}
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
How can it be improved?
Thank you
I am very new to android. I made a very basic pong game. I want to launch the dialog box when the ball is out. This code indicates that the ball is out
////// end game
if (ball1.getEndGame()&&ball2.getEndGame()){
Log.e(TAG, "END of game");
}
this is my activity:
public class GameScreenActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
// full screen
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
View gameview = new GameView(this);
setContentView(gameview);
}
}
this is my GameView class which is extending from the view
public class GameView extends View {
// declare variables
private static final String TAG = null; // for log.e
private Ball ball1; // ball1
private Ball ball2; // ball2
private GameContainer gameContainer; // frame for the game
private Racket racket; // controller
int viewWidth = 0; // width onchange
int viewHeight = 0; // height onchange
DisplayMetrics metrics = this.getResources().getDisplayMetrics();
int width = metrics.widthPixels; // width of screen
int height = metrics.heightPixels; // height of the screen
int rectSize = 200; // width of the controller
int rectHeight = 40; // height of the controller
int rectL = (width/2 - (rectSize/2)); // x
int rectT = height-(rectHeight*3); // y
int rectR = (width/2 + (rectSize/2)); // x + rectSize
int rectB = rectT + rectHeight; // y + rectHeight
// random numbers for speed
Random r = new Random();
int randomNo1 = r.nextInt(20 - 3) + 3;
int randomNo2 = r.nextInt(20 - 3) + 3;
int randomNo3 = r.nextInt(20 - 3) + 3;
int randomNo4 = r.nextInt(20 - 3) + 3;
// random numbers for location
int randomXLocation1 = r.nextInt((width-10) - 1) + 1;
int randomYLocation1 = r.nextInt(height/2 - 1) + 1;
int randomXLocation2 = r.nextInt((width-10) - 1) + 1;
int randomYLocation2 = r.nextInt(height/2 - 1) + 1;
// getter for speed
float getSpeedX;
float getSpeedY;
// score
private Score score;
int currentScore = 0;
// constructor
public GameView(Context context) {
super(context);
randomNo1 = randomNo1 * -1;
randomNo2 = randomNo2 * -1;
randomNo3 = randomNo3 * -1;
randomNo4 = randomNo4 * -1;
ball1 = new Ball(Color.GREEN, 24, randomNo1, randomNo2); // colour, radius,speedx, speedy
ball1.setBallLocation(randomXLocation1, randomYLocation1); // x, y of ball
ball2 = new Ball(Color.RED, 24, randomNo3, randomNo4); // colour, radius,speedx, speedy
ball2.setBallLocation(randomXLocation2, randomYLocation2); // x, y of ball
gameContainer = new GameContainer(Color.GRAY);
racket = new Racket(Color.BLACK);
score = new Score(Color.WHITE);
}
#Override
public void onDraw(Canvas canvas){
//randomNo1 = r.nextInt(20 - 1) + 1;
//randomNo2 = r.nextInt(20 - 1) + 1;
//randomNo3 = r.nextInt(20 - 1) + 1;
//randomNo4 = r.nextInt(20 - 1) + 1;
gameContainer.container(1, 2, width-2, height-3);
gameContainer.display(canvas);
ball1.drawBall(canvas);
ball1.moveBall(gameContainer);
//ball.collides(racket);
if(ball1.collides(racket)){
String collided = "collided Yes";
Log.e(TAG, collided);
getSpeedX = ball1.getBallSpeedX();
getSpeedY = ball1.getBallSpeedY();
getSpeedY = getSpeedY * -1;
randomNo1 = (int) getSpeedX;
randomNo2 = (int) getSpeedY;
if (randomNo1 > 0) { randomNo1 += 1; }else{randomNo1 = randomNo1 + (-1); }
if (randomNo2 > 0) { randomNo2 += 1; }else{randomNo2 = randomNo2 + (-1); }
ball1.setBallSpeed(randomNo1, randomNo2);
currentScore = currentScore + 1;
}
ball2.drawBall(canvas);
ball2.moveBall(gameContainer);
if(ball2.collides(racket)){
String collided = "collided Yes";
Log.e(TAG, collided);
getSpeedX = ball2.getBallSpeedX();
getSpeedY = ball2.getBallSpeedY();
getSpeedY = getSpeedY * -1;
randomNo3 = (int) getSpeedX;
randomNo4 = (int) getSpeedY;
if (randomNo3 > 0) { randomNo3 += 1; }else{randomNo3 = randomNo3 + (-1); }
if (randomNo4 > 0) { randomNo4 += 1; }else{randomNo4 = randomNo4 + (-1); }
ball2.setBallSpeed(randomNo3, randomNo4);
currentScore = currentScore + 1;
}
//racket.setRacket((width/2)-60, height-220, (width/2)+60, height-160);
racket.setRacket(rectL, rectT, rectR, rectB);
racket.setLine(2, rectT+(rectHeight/2)-1, width-2, rectT+(rectHeight/2)+1);
racket.drawRacket(canvas);
score.drawScore(canvas, 20, 40,Integer.toString(currentScore));
////// end game
if (ball1.getEndGame()&&ball2.getEndGame()){
Log.e(TAG, "END of game");
}
// Delay
try {
Thread.sleep(50);
} catch (InterruptedException e) { }
invalidate(); // re-draw
}
}
did you try
if (ball1.getEndGame()&&ball2.getEndGame()){
Log.e(TAG, "END of game");
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
builder.setMessage("End of game");
builder.setPositiveButton("ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface arg0, int arg1) {
//do whatever u want here
}
});
AlertDialog mAlert = builder.create();
mAlert.show();
}
mContext has to be your application context. Also declare the mAlert outside of the function.
you can also add other options to the builder as you want.
I am getting the accelerometer values continuously (i.e) X and Y values in the run time. My question is that when the values of the accelerometer changes in mobile the corresponding values should be accumulated as per the change.
This is my code :
public class MainActivity extends Activity implements SensorEventListener {
private SensorManager sensorManager;
private float accumulation_x = 0;
private float accumulation_y = 0;
private float accumulation_z = 0;
private TextView acessTextview, angleTextview;
private float value;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById();
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL);
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
int count = 1;
while(count!=0){
float x = (float) 0.9887777;
float y = (float) 0.187359372;
float z = (float) 0.0228636;
float X_axis = (float) (x + (0.02724095));
float Y_axis = (float) (y + (-0.027792556));
float Z_axis = (float) (z - (0.105689));
accumulation_x = accumulation_x + X_axis;
accumulation_y = accumulation_y + Y_axis;
accumulation_z = accumulation_z + Z_axis;
value = (y / z);
float angle = (float) Math.toDegrees(Math.atan(value));
angleTextview.setText("Angle:" + angle);
acessTextview.setText("accumulation_x :" + X_axis + "\n"
+ "accumulation_y :" + Y_axis + "\n"
+ "accumulation_z :" + Z_axis);
count++;
}
}
}
private void findViewById() {
// TODO Auto-generated method stub
acessTextview = (TextView) findViewById(R.id.accessTextview);
angleTextview = (TextView) findViewById(R.id.angleTextview);
}
}
Your code is correct, only minor changes are require, I have updated your code with an extra method called refreshValues(). This method will set the latest values of X,Y in to TextView. This method will get called from onSensorChanged() method.
public class MainActivity extends Activity implements SensorEventListener {
private SensorManager sensorManager;
private float accumulation_x = 0;
private float accumulation_y = 0;
private float accumulation_z = 0;
private TextView acessTextview, angleTextview;
private float value;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById();
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL);
}
public void onAccuracyChanged(Sensor sensor, int accuracy) { }
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
int count = 1;
while(count!=0){
float x = (float) 0.9887777;
float y = (float) 0.187359372;
float z = (float) 0.0228636;
float X_axis = (float) (x + (0.02724095));
float Y_axis = (float) (y + (-0.027792556));
float Z_axis = (float) (z - (0.105689));
accumulation_x = accumulation_x + X_axis;
accumulation_y = accumulation_y + Y_axis;
accumulation_z = accumulation_z + Z_axis;
value = (y / z);
float angle = (float) Math.toDegrees(Math.atan(value));
angleTextview.setText("Angle:" + angle);
acessTextview.setText("accumulation_x :" + X_axis + "\n"
+ "accumulation_y :" + Y_axis + "\n"
+ "accumulation_z :" + Z_axis);
count++;
}
}
refreshValues ( accumulation_x,accumulation_y );
}
private void findViewById() {
// TODO Auto-generated method stub
acessTextview = (TextView) findViewById(R.id.accessTextview);
angleTextview = (TextView) findViewById(R.id.angleTextview);
}
private void refreshValues ( float x, float y )
{
acessTextview.setText ( String.valueOf(x) );
angleTextview.setText( ( String.valueOf(y)));
}
}