My app is crashing. I am trying to build an accelerometer based app. Though build is successful, it is not running in the Pixel Emulator. Where have I gone wrong?
I have been trying to find the error but am unsuccessful. I am attaching the run error message, the screenshot of the manifest file and the main code.
This is the error message:
The main code follows
package com.example.androidaccelerometerexample;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.app.Activity;
import android.text.Html;
import android.view.Menu;
import android.widget.TextView;
import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Vibrator;
import android.widget.TextView;
class Main extends Activity implements SensorEventListener {
private float lastX, lastY, lastZ;
private SensorManager sensorManager;
private Sensor accelerometer;
private float deltaXMax = 0;
private float deltaYMax = 0;
private float deltaZMax = 0;
private float deltaX = 0;
private float deltaY = 0;
private float deltaZ = 0;
private float vibrateThreshold = 0;
private TextView currentX, currentY, currentZ, maxX, maxY, maxZ;
public Vibrator v;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initializeViews();
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) {
// success! we have an accelerometer
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
vibrateThreshold = accelerometer.getMaximumRange() / 2;
} else {
// fai! we dont have an accelerometer!
}
//initialize vibration
v = (Vibrator) this.getSystemService(Context.VIBRATOR_SERVICE);
}
public void initializeViews() {
currentX = (TextView) findViewById(R.id.currentX);
currentY = (TextView) findViewById(R.id.currentY);
currentZ = (TextView) findViewById(R.id.currentZ);
maxX = (TextView) findViewById(R.id.maxX);
maxY = (TextView) findViewById(R.id.maxY);
maxZ = (TextView) findViewById(R.id.maxZ);
}
protected void onResume() {
super.onResume();
sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
#Override
public void onSensorChanged(#org.jetbrains.annotations.NotNull SensorEvent event) {
// clean current values
displayCleanValues();
// display the current x,y,z accelerometer values
displayCurrentValues();
// display the max x,y,z accelerometer values
displayMaxValues();
// get the change of the x,y,z values of the accelerometer
deltaX = Math.abs(lastX - event.values[0]);
deltaY = Math.abs(lastY - event.values[1]);
deltaZ = Math.abs(lastZ - event.values[2]);
// if the change is below 2, it is just plain noise
if (deltaX < 2)
deltaX = 0;
if (deltaY < 2)
deltaY = 0;
if ((deltaZ > vibrateThreshold) || (deltaY > vibrateThreshold) || (deltaX > vibrateThreshold)) {
v.vibrate(50);
}
}
public void displayCleanValues() {
currentX.setText("0.0");
currentY.setText("0.0");
currentZ.setText("0.0");
}
// display the current x,y,z accelerometer values
public void displayCurrentValues() {
currentX.setText(Float.toString(deltaX));
currentY.setText(Float.toString(deltaY));
currentZ.setText(Float.toString(deltaZ));
}
// display the max x,y,z accelerometer values
public void displayMaxValues() {
if (deltaX > deltaXMax) {
deltaXMax = deltaX;
maxX.setText(Float.toString(deltaXMax));
}
if (deltaY > deltaYMax) {
deltaYMax = deltaY;
maxY.setText(Float.toString(deltaYMax));
}
if (deltaZ > deltaZMax) {
deltaZMax = deltaZ;
maxZ.setText(Float.toString(deltaZMax));
}
}
}
Your activity class needs to be public and not package-private.
Change class Main to public class Main.
Related
I have to log my Sensor data from my Android Phone to a csv. file so I can use it further , the problem is I tried something with some code(FileWriter to csv) that I found and put it into my code and it does not work, can maybe someone tell me what I do wrong, where my error is. The idea is to just record different sensor data with different EventHandlers like in the Code Example and then write the sensor data to a csv. file together and that csv. file should be on the phone.
I have maybe to mention that I have never before programed in Java or did Android , so please try to answer me as simple as possible, thank you :)
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.CompoundButton;
import android.widget.ProgressBar;
import android.widget.Switch;
import android.widget.TextView;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
TextView txt_currentAccel, txt_prevAccel, txt_acceleration, txt_temp;
ProgressBar prog_shakeMeter;
Switch switch1;
//define Sensor Variables
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private SensorManager mSensorManagerNew;
private Sensor mTemp;
private double accelerationCurrentValue;
private double accelerationPreviousValue;
private int SwitchFlag = 0;
final String TAG = "SensorLog";
FileWriter writer;
private SensorEventListener sensorEventListener = new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER && SwitchFlag == 1) {
float x = sensorEvent.values[0];
float y = sensorEvent.values[1];
float z = sensorEvent.values[2];
accelerationCurrentValue = Math.sqrt((x * x + y * y + z * z));
double changeInAcceleration = Math.abs(accelerationCurrentValue - accelerationPreviousValue);
accelerationPreviousValue = accelerationCurrentValue;
//update text views
txt_currentAccel.setText("Current =" + accelerationCurrentValue);
txt_prevAccel.setText(("Prev = " + accelerationPreviousValue));
txt_acceleration.setText("Acceleration change =" + changeInAcceleration);
prog_shakeMeter.setProgress((int) changeInAcceleration);
try {
writer.write(String.format("ACC; %f; %f; %f; %f; %f; %f\n", sensorEvent.values[0], sensorEvent.values[1], sensorEvent.values[2], 0.f, 0.f, 0.f));
}catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
};
private SensorEventListener sensorEventListenerNew = new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
float temp = sensorEvent.values[0];
txt_temp.setText("Temp = " + temp);
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txt_acceleration = findViewById(R.id.txt_accel);
txt_prevAccel = findViewById(R.id.txt_prevAccel);
txt_currentAccel = findViewById(R.id.txt_currentAccel);
txt_temp = findViewById(R.id.txt_temp);
prog_shakeMeter = findViewById(R.id.prog_shakeMeter);
switch1 = findViewById(R.id.switch1);
// Initialize Sensors
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManagerNew = (SensorManager) getSystemService(SENSOR_SERVICE);
mTemp = mSensorManagerNew.getDefaultSensor(Sensor.TYPE_LIGHT);
switch1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (b == true) {
SwitchFlag = 1;
} else {
SwitchFlag = 0;
}
}
});
}
public void flag() {
if (SwitchFlag == 1) {
Log.d(TAG, "Writing to " + getStorageDir());
try {
writer = new FileWriter(new File(getStorageDir(), "sensors_" + System.currentTimeMillis() + ".csv"));
} catch (
IOException e) {
e.printStackTrace();
}
} else {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
protected void onResume() {
super.onResume();
mSensorManager.registerListener(sensorEventListenerNew, mTemp, SensorManager.SENSOR_DELAY_NORMAL);
mSensorManager.registerListener(sensorEventListener, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(sensorEventListener);
mSensorManager.unregisterListener(sensorEventListenerNew);
}
private String getStorageDir() {
return this.getExternalFilesDir(null).getAbsolutePath();
}
}
I have put somehow together a code that records my sensor data from the phone and i want to save them as csv file in some directory (maybe DCIM) in the internal Storage on the phone, but i cannot find something similar, i am also new to Android Studio and java.
On the bottom you can see ,i found that code example with
"getExternalFilesDir(null).getAbsolutePath()" , how can i change that , that my file is saved on the phone in internal storage and tell him exactly where so i can find it later and use it further ?
package com.example.shakedemo;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.CompoundButton;
import android.widget.ProgressBar;
import android.widget.Switch;
import android.widget.TextView;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
TextView txt_currentAccel, txt_prevAccel, txt_acceleration, txt_temp;
ProgressBar prog_shakeMeter;
Switch switch1;
//define Sensor Variables
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private SensorManager mSensorManagerNew;
private Sensor mTemp;
private double accelerationCurrentValue;
private double accelerationPreviousValue;
private int SwitchFlag = 0;
final String TAG = "SensorLog";
FileWriter writer;
private SensorEventListener sensorEventListener = new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER && SwitchFlag == 1) {
float x = sensorEvent.values[0];
float y = sensorEvent.values[1];
float z = sensorEvent.values[2];
accelerationCurrentValue = Math.sqrt((x * x + y * y + z * z));
double changeInAcceleration = Math.abs(accelerationCurrentValue - accelerationPreviousValue);
accelerationPreviousValue = accelerationCurrentValue;
//update text views
txt_currentAccel.setText("Current =" + accelerationCurrentValue);
txt_prevAccel.setText(("Prev = " + accelerationPreviousValue));
txt_acceleration.setText("Acceleration change =" + changeInAcceleration);
prog_shakeMeter.setProgress((int) changeInAcceleration);
try {
writer.write(String.format("ACC; %f; %f; %f; %f; %f; %f\n", sensorEvent.values[0], sensorEvent.values[1], sensorEvent.values[2], 0.f, 0.f, 0.f));
}catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
};
private SensorEventListener sensorEventListenerNew = new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
float temp = sensorEvent.values[0];
txt_temp.setText("Temp = " + temp);
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txt_acceleration = findViewById(R.id.txt_accel);
txt_prevAccel = findViewById(R.id.txt_prevAccel);
txt_currentAccel = findViewById(R.id.txt_currentAccel);
txt_temp = findViewById(R.id.txt_temp);
prog_shakeMeter = findViewById(R.id.prog_shakeMeter);
switch1 = findViewById(R.id.switch1);
// Initialize Sensors
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManagerNew = (SensorManager) getSystemService(SENSOR_SERVICE);
mTemp = mSensorManagerNew.getDefaultSensor(Sensor.TYPE_LIGHT);
switch1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (b == true) {
Log.d(TAG, "Writing to " + getStorageDir());
try {
writer = new FileWriter(new File(getStorageDir(), "sensors_" + System.currentTimeMillis() + ".csv"));
} catch (
IOException e) {
e.printStackTrace();
}
SwitchFlag = 1;
} else {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
SwitchFlag = 0;
}
}
});
}
protected void onResume() {
super.onResume();
mSensorManager.registerListener(sensorEventListenerNew, mTemp, SensorManager.SENSOR_DELAY_NORMAL);
mSensorManager.registerListener(sensorEventListener, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(sensorEventListener);
mSensorManager.unregisterListener(sensorEventListenerNew);
}
private String getStorageDir() {
return this.getExternalFilesDir(null).getAbsolutePath();
}
}
I am very close to finish my project that is related to count steps , distance covered and calculate velocity. I am using TYPE_COUNTER_STEP sensor to calculate the steps and using formulas to calculate distance i.e 0.415 for men and 0.413 for women to get foot length by multiplying with height So far every thing is working fine But i am suck to calculate the velocity. I do not know how to calculate, i mean i know s = vt but i need time to get the velocity/step. Anyone have any idea how to achieve that. This is the last part of my project. I have also look for it on the internet but i did not get working method to calculate the time. Someone suggest me to use timestamp but i used that but unfortunately i get infinity text instead of velocity
I cannot use GPS to calculate the velocity because GPS is not available all the time i.e inside tunnel or underground etc
Thanks
package com.lijianzhong13354146.coeur1;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.format.DateUtils;
import android.view.Display;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.TimeUnit;
public class AccurateStepCounter extends AppCompatActivity {
private long timestamp;
private TextView textViewStepCounter;
private TextView textViewStepDetector;
private Thread detectorTimeStampUpdaterThread;
private Handler handler;
Toolbar toolbar ;
private Button buttonStop ;
TextView stepValue ;
TextView distanceValue ;
TextView distanceTitle ;
int getCurrentStepValue ;
int actualStepTaken ;
SharedPreferences sharedPreferences ;
SharedPreferences.Editor editor ;
SharedPreferences sharedPreferencesFromSetting ;
SharedPreferences.Editor editorFromSetting ;
private boolean isRunning = true;
ArrayList<Step> arrayList ;
String gettingPersonHeight ;
double gettingPersonHeightInDoule ;
double step_length ;
SharedPreferences getSharedPreferencesHeight ;
SharedPreferences.Editor getEditoHeight ;
double timeInSecond ;
SharedPreferences sharedPreferencesGetGender ;
SharedPreferences.Editor editorGetGender;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_accurate_step_counter);
buttonStop = (Button) findViewById(R.id.buttonSTOP);
toolbar = (Toolbar) findViewById(R.id.toolbar);
stepValue = (TextView) findViewById(R.id.step_value);
distanceValue = (TextView) findViewById(R.id.distance_value);
arrayList = new ArrayList<>();
sharedPreferences = getSharedPreferences("saveInformation" , MODE_PRIVATE) ;
sharedPreferencesFromSetting = getSharedPreferences("EmailSave" , MODE_PRIVATE);
sharedPreferencesGetGender = getSharedPreferences("saveInformation" , MODE_PRIVATE);
getSharedPreferencesHeight = getSharedPreferences("Height" , MODE_PRIVATE);
distanceTitle = (TextView) findViewById(R.id.distance_title);
gettingPersonHeightInDoule = Double.parseDouble(
getSharedPreferencesHeight.getString("saveHeight" , "0"))/100;
if (sharedPreferencesGetGender.getString("GENDER" , null).equals("Male") ){
step_length = 0.415 * gettingPersonHeightInDoule ;
}else {
step_length = 0.413 * gettingPersonHeightInDoule ;
}
ToolbarConfig();
MediaPlayer mediaPlayer1 = MediaPlayer.create(this , R.raw.boom);
mediaPlayer1.start();
registerForSensorEvents();
onStopButtonClick();
// setupDetectorTimestampUpdaterThread();
}
#Override
public void onBackPressed() {
}
public void onStopButtonClick () {
buttonStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int actualSteps = getCurrentStepValue - arrayList.get(0);
editor = sharedPreferences.edit() ;
editor.putString("STEPS" , String.valueOf(actualSteps));
editor.commit() ;
startActivity(new Intent(AccurateStepCounter.this , FinalResultDisplay.class));
}
});
}
public void ToolbarConfig () {
toolbar.setTitle(getResources().getString(R.string.app_title));
toolbar.setSubtitle("Pedometer");
toolbar.setTitleTextColor(Color.WHITE);
toolbar.setSubtitleTextColor(Color.WHITE);
setSupportActionBar(toolbar);
}
public void registerForSensorEvents() {
SensorManager sManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
// Step Counter
sManager.registerListener(new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent event) {
Step step = new Step(event.values[0], System.currentTimeMillis());
arrayList.add(step);
getCurrentStepValue = (int) step.getStep();
stepValue.setText(getCurrentStepValue - arrayList.get(0) + "");
double distaneCovered = step_length * (getCurrentStepValue - arrayList.get(0));
// the elapsed time beetween 2 step will be:
if (arrayList.size() > 2) {
Step lastStep = arrayList.get(arrayList.size() - 1);
Step previousStep = arrayList.get(arrayList.size() - 2);
long msElapsedTime = lastStep.getTimestamp() - previousStep.getTimestamp();
timeInSecond = TimeUnit.MILLISECONDS.toSeconds(msElapsedTime);
}
double getVelocity = distaneCovered / timeInSecond ;
// distanceTitle shows the speed for now
distanceTitle.setText(getVelocity + " m/s");
distanceValue.setText("" + distaneCovered);
/* float steps = event.values[0];
arrayList.add((int)steps);
getCurrentStepValue = (int) steps ;
double distanceCovered = (step_length * (getCurrentStepValue - arrayList.get(0))) /1000;
stepValue.setText(getCurrentStepValue - arrayList.get(0) + "");
distanceValue.setText("" + String.format("%.2f" , distanceCovered));*/
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}, sManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER),
SensorManager.SENSOR_DELAY_FASTEST);
}
}
class Step {
private float step;
private long timestamp;
Step (float step , long timestamp) {
this.step = step;
this.timestamp = timestamp ;
}
public void setStep(float step) {
this.step = step;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public float getStep() {
return step;
}
public long getTimestamp() {
return timestamp;
}
// getters
// setters
}
You can calculate the elapsed time beetween 2 steps creating a Step class containing the timestamp as field. Then subtract the previous timestamp at the last!
public class Step {
private float step;
private long timestamp;
// constructor
// getters
// setters
}
#Override
public void onSensorChanged(SensorEvent event) {
Step step = new Step(event.values[0], System.currentTimeMillis());
arrayList.add(step);
getCurrentStepValue = (int) step.getStep();
stepValue.setText(getCurrentStepValue - arrayList.get(0) + "");
double distaneCovered = step_length * (getCurrentStepValue - arrayList.get(0));
// the elapsed time beetween 2 step will be:
if (arrayList.size() > 2) {
Step lastStep = arrayList.get(arrayList.size() - 1);
Step previousStep = arrayList.get(arrayList.size() - 2);
long msElapsedTime = lastStep.getTimestamp() - previousStep.getTimestamp();
}
distanceValue.setText("" + distaneCovered);
}
So you can do s=v/t
I tried to pass shake speed through a listener activity to main activity, but the code just won't work. It says "the application has unfortunately stopped"
listener code:
import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
/**
* Listener that detects shake gesture.
*/
public class AccReader implements SensorEventListener {
Activity foo;
SensorManager manager;
Sensor accelerometer;
private static final int MIN_FORCE = 10;
private static final int MIN_DIRECTION_CHANGE = 3;
private static final int MAX_PAUSE_BETHWEEN_DIRECTION_CHANGE = 200;
private static final int MAX_TOTAL_DURATION_OF_SHAKE = 400;
private long mFirstDirectionChangeTime = 0;
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;
private float totalMovement;
public AccReader(Activity foo) {
this.foo = foo;
manager = (SensorManager) this.foo.getSystemService(Context.SENSOR_SERVICE);
accelerometer = manager.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0);
manager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_GAME);
}
/**
* Interface for shake gesture.
*/
public interface OnShakeListener {
/**
* Called when shake gesture is detected.
*/
void onShake();
}
public void setOnShakeListener(OnShakeListener listener) {
mShakeListener = listener;
}
public float getTotalMovement() {
return this.totalMovement;
}
#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
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) {
// checkk 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) {}
}
main activity code:
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.EditText;
public abstract class MainActivity extends AppCompatActivity implements SensorEventListener {
private SensorManager mSensorManager;
private AccReader mSensorListener;
private Sensor mAccelerometer;
AccReader acc;
private EditText output;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(new AccReader(this), mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
output = (EditText) findViewById(R.id.editText1);
acc = new AccReader(this);
mSensorListener.setOnShakeListener(new AccReader.OnShakeListener() {
#Override
public void onShake() {
refresh();
}
});
}
public void refresh() {
output.setText("X:" + acc.getTotalMovement());
}
#Override
protected void onResume() {
super.onResume();
mSensorManager.registerListener(mSensorListener,
mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_UI);
}
#Override
protected void onPause() {
mSensorManager.unregisterListener(mSensorListener);
super.onPause();
}
The code has compiled correctly, but the resulting APK is unable to run.
Can anyone put light on what I may have done wrong?
P.S. I'm completely new to android development
EDIT:
Logcat:
09 - 03 23: 51: 26.680 1936 - 1936 / lamegames.app I / art﹕Not late - enabling - Xcheck: jni(already on)
09 - 03 23: 51: 27.195 1936 - 1936 / lamegames.app D / AndroidRuntime﹕Shutting down VM---------beginning of crash
09 - 03 23: 51: 27.195 1936 - 1936 / lamegames.app E / AndroidRuntime﹕FATAL EXCEPTION: main
Process: lamegames.slapapp,
PID: 1936
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo {
lamegames.app / lamegames.app.MainActivity
}: java.lang.InstantiationException: class lamegames.app.MainActivity cannot be instantiated
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java: 2236)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java: 2390)
at android.app.ActivityThread.access$800(ActivityThread.java: 151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java: 1303)
at android.os.Handler.dispatchMessage(Handler.java: 102)
at android.os.Looper.loop(Looper.java: 135)
at android.app.ActivityThread.main(ActivityThread.java: 5257)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java: 372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java: 903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java: 698)
Caused by: java.lang.InstantiationException: class lamegames.app.MainActivity cannot be instantiated
at java.lang.Class.newInstance(Class.java: 1587)
at``android.app.Instrumentation.newActivity(Instrumentation.java: 1066)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java: 2226)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java: 2390)
at android.app.ActivityThread.access$800(ActivityThread.java: 151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java: 1303)
at android.os.Handler.dispatchMessage(Handler.java: 102)
at android.os.Looper.loop(Looper.java: 135)
at android.app.ActivityThread.main(ActivityThread.java: 5257)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java: 372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java: 903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java: 698)
09 - 03 23: 52: 10.917 1936 - 1943 / lamegames.app W / art﹕Suspending all threads took: 19.739ms
09 - 03 23: 52: 24.263 1936 - 1936 / lamegames.app I / Process﹕Sending signal.PID: 1936 SIG: 9
MainActivity does not need to be abstract nor does it need to implement SensorEventListener. I'm also not sure why you were using two AccReader objects.
Here is the fixed MainActivity code:
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.EditText;
public class MainActivity extends AppCompatActivity {
private SensorManager mSensorManager;
private Sensor mAccelerometer;
AccReader acc;
private EditText output;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(new AccReader(this), mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
output = (EditText) findViewById(R.id.editText1);
acc = new AccReader(this);
acc.setOnShakeListener(new AccReader.OnShakeListener() {
#Override
public void onShake() {
refresh();
}
});
}
public void refresh() {
output.setText("X:" + acc.getTotalMovement());
}
#Override
protected void onResume() {
super.onResume();
mSensorManager.registerListener(acc,
mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_UI);
}
#Override
protected void onPause() {
mSensorManager.unregisterListener(acc);
super.onPause();
}
}
The last thing was a null check for mShakeListener in AccReader, because the shake event seemed to trigger multiple times, and confused the listener.
This code should go in your onSensorChanged method when you call onShake
if(mShakeListener != null)
mShakeListener.onShake();
I'm trying to implement a ShakeListener. So I made a Class called ShakeListener.java :
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;
public class ShakeListener implements SensorEventListener {
private SensorManager sensorManager;
private List<Sensor> sensors;
private Sensor sensor;
private long lastUpdate = -1;
private long currentTime = -1;
private float last_x, last_y, last_z;
private float current_x, current_y, current_z, currenForce;
private static final int FORCE_THRESHOLD = 900;
private final int DATA_X = SensorManager.DATA_X;
private final int DATA_Y = SensorManager.DATA_Y;
private final int DATA_Z = SensorManager.DATA_Z;
public ShakeListener(Activity parent) {
SensorManager sensorService = (SensorManager) parent
.getSystemService(Context.SENSOR_SERVICE);
this.sensorManager = sensorManager;
this.sensors = sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
if (sensors.size() > 0) {
sensor = sensors.get(0);
}
}
public void start() {
if (sensor != null) {
sensorManager.registerListener(this, sensor,
SensorManager.SENSOR_DELAY_GAME);
}
}
public void stop() {
sensorManager.unregisterListener(this);
}
public void onAccuracyChanged(Sensor s, int valu) {
}
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER
|| event.values.length < 3)
return;
currentTime = System.currentTimeMillis();
if ((currentTime - lastUpdate) > 100) {
long diffTime = (currentTime - lastUpdate);
lastUpdate = currentTime;
current_x = event.values[DATA_X];
current_y = event.values[DATA_Y];
current_z = event.values[DATA_Z];
currenForce = Math.abs(current_x + current_y + current_z - last_x
- last_y - last_z)
/ diffTime * 10000;
if (currenForce > FORCE_THRESHOLD) {
Log.d("ShakeListener", "SHAKE DETECTED");
}
last_x = current_x;
last_y = current_y;
last_z = current_z;
}
}
}
Now, I want to envoke it from my main activity (thinking about implementing a While-loop that waits for a shake boolean to change?). So in my main activity, I use :
private ShakeListener myShakeListener;
and then
myShakeListener = new ShakeListener(this);
myShakeListener.start();
But I get an NPE on the line :
this.sensors = sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
What am I doing wrong? How should I implement this?
Look at sensorService. It is wrong. Change your code:
SensorManager sensorService = (SensorManager) parent
.getSystemService(Context.SENSOR_SERVICE);
this.sensorManager = sensorManager;
to
SensorManager sensorService = (SensorManager) parent
.getSystemService(Context.SENSOR_SERVICE);
this.sensorManager = sensorService ;
or a better code:
this.sensorManager = (SensorManager) parent.getSystemService(Context.SENSOR_SERVICE);