App freezes while recording accelerometer data: Android - android

I'm simply trying to record accelerometer data and write a file in sdcard with a button click. While running the app in my Nexus S (with 4.1.2), it freezes after a minute. I tried to run it in Galaxy Nexus phone and it works smoothly. For some reasons I have to work in Nexus S. Can anyone suggest me what might be the reason of crashing. I tried to see the log, but it does not through any error message.
Here's my code:
final SensorEventListener mySensorEventListener = new SensorEventListener() {
public void onSensorChanged(SensorEvent sensorEvent) {
if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
xAxis_lateralA = sensorEvent.values[0];
yAxis_longitudinalA = sensorEvent.values[1];
zAxis_verticalA = sensorEvent.values[2]; // TODO apply the acceleration changes to your application.
textView.append("\nACC_x = "+ xAxis_lateralA + ", ACC_y = "+yAxis_longitudinalA+ ", ACC_z = " + zAxis_verticalA);
acc += "\n"+miliSec()+", "+xAxis_lateralA + ", "+ yAxis_longitudinalA+", "+zAxis_verticalA;
try {
File myFile = new File("/sdcard/acc.txt");
myFile.createNewFile();
FileOutputStream fOut = new FileOutputStream(myFile);
OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut);
myOutWriter.append(acc);
myOutWriter.close();
fOut.close();
} catch (Exception e) {
Toast.makeText(getBaseContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
};
startButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Toast.makeText(getBaseContext(),"Done writing SD 'acc.txt'",Toast.LENGTH_SHORT).show();
sm = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
int sensorType = Sensor.TYPE_ACCELEROMETER;
sm.registerListener(mySensorEventListener,sm.getDefaultSensor(sensorType), SensorManager.SENSOR_DELAY_NORMAL);
}// onClick
}); // btnWriteSDFile
stopButton = (Button) findViewById(R.id.stopButton);
stopButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
int sensorType = Sensor.TYPE_ACCELEROMETER;
sm.unregisterListener(mySensorEventListener, sm.getDefaultSensor(sensorType));
Toast.makeText(getBaseContext(), "Stopped Recording",Toast.LENGTH_SHORT).show();
finish();
}// onClick
}); // btnstopButton

Issue is due to the way your writing values to text file.
You are opening/writing/closiing the file for everytime you get sensor reading.
Even for Sensor reading frequency of 50Hz it takes lot computation,writing these in text for 50 times/second is not efficient.
Use BufferedWriter ,it gives better performance.

Related

Force ToggleButton to stop writing into my local memory file

I have a variable MyFinalPressure which is populated with sensor data from the sensors pressure. If MyFinalPressure is == to 4000 (4000 points or 40 sec) then stop writing to local storage.
But it looks like when I debug the code, it hits the boolean MaxPoints and is still writing. I wonder if my logic is wrong or not.
Could you please help me out.
public Boolean Store = false;
Boolean MaxPoints = false;
if (activity.Store) {
activity.writeToFile(MyFinalPressure);//MyFinalPressure is float of one dimension array or stream of array.
}
if (MyFinalPressure==4000){ //this conditon, am trying to stop wrting to local memory.
activity.MaxPoints = true;
}
FileOutputStream fileOutputStream;
//method to write into local memory.
public void writeToFile(final float MyFinalPressure) {
Log.d(TAG, "writeToFile.");
String finalData;
finalData = String.valueOf(MyFinalPressure);
try {
// true here for 'append'
fileOutputStream = new FileOutputStream(file, true);
String Space = " ";
byte[] convert = Space.getBytes();
fileOutputStream.write(finalData.getBytes());
fileOutputStream.write(convert);
fileOutputStream.flush();
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//write to file.
StartWriting = (ToggleButton) findViewById(R.id.startWriting);
StartWriting.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (StartWriting.isChecked()) {
Store = true;
Toast.makeText(getApplicationContext(), "Data Starts writing into (Message.txt) file", Toast.LENGTH_LONG).show();
} else {
if (!StartWriting.isChecked()|| MaxPoints==true) { //here - this is wrong logic to stop writing to my file.
Toast.makeText(getApplicationContext(), "Data Stored at myAppFile", Toast.LENGTH_SHORT).show();
String finalData1;
finalData1 = String.valueOf(fileOutputStream);
Log.i(TAG, "of_writes: " + finalData1);
// Toast.makeText(getApplicationContext(), "Data_write_number: " + finalData1.length(), Toast.LENGTH_SHORT).show();
Store = false;
}
}
}
});
Just take out !StartWriting.isChecked()
Because of the above if statement StartWriting.isChecked() will always be false. Then because you are checking for "!StartWriting.isChecked()" it will always enter the statement.

Writing to storage from handler

I'm trying to write the stream of my array that is coming from Bluetooth module and read from (HandleRead), to the internal storage directly. Is that possible in the first place?
Note that I am reading 100 samples per second. That means the file will fill up quickly. I am not familiar with storage, and my code isn't executed as I expected.
public class MainActivity extends ActionBarActivity implements SensorEventListener {
File Root = Environment.getExternalStorageDirectory();
File Dir = new File (Root.getAbsolutePath()+"/myAppFile");
File file = new File(Dir,"Message.txt");
#Override
protected void onCreate(Bundle savedInstanceState){
String state;
state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)){
if (!Dir.exists()){
Dir.mkdir();
}
}
private void handleRead(Message msg) {
byte[] readBuf = (byte[]) msg.obj;
String readMessage = new String(readBuf);
ByteBuffer buffer = ByteBuffer.wrap(readBuf, 0, readBuf.length);
buffer.order(ByteOrder.BIG_ENDIAN);
buffer.clear();
final String[] strNumbers = readMessage.split("\n");
for (int j = 1; j <= strNumbers.length - 2; j++) {
pressure = Integer.parseInt(readMessage2);
MyFinalPressure = (float) (9.677 +0.831 * pressure);
// trying to store directly to internal sotrage
activity.save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
FileOutputStream fileOutputStream = new FileOutputStream(activity.file);
fileOutputStream.write((int) MyFinalPressure);
fileOutputStream.close();
Toast.makeText(activity.getApplicationContext(),"Message saved ", Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e){
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
}
}
It appears you are not setting the FileOutputStream to 'append' (you need to add 'true' as 2nd parameter in constructor.)
This would write over the file from the file-start every time
also your 'setOnClickListener' is INSIDE your loop. This doesn't do anything for you as far as I can tell.
I recommend always setting up UI elements in a private void setupUI() {...} method that onCreate calls. The public void onClick(View v) {buttonForSavingPresssed()} where buttonForSavingPressed(){...} is the 'logic' of your onClick() method.
This will help you clean up the class and not have stray onClickListener assignments, etc.
My guess is that either your multiple assignments is very inefficient, since clickListeners aren't cheap, or... the clickListener might not even work at all because of a timing issue (if your loop is long running and you press the button and the listener has already been swapped for a new one)
I've cleaned up your code some, There are some suggestions and some log statements that should help you figure out what is going on.
// this is inside your onCreate()
...
activity.save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) { buttonPressed();}
});
...
// Here is where you would put your logic when the button is presssed
public void buttonPressed(){
Toast.makeText(activity.getApplicationContext(),"Button Pressed ",
Toast.LENGTH_SHORT).show();
}
// you should make 'helper' functions that consolidate separate pieces of logic like this,
// that way you can more easily track what is happening in each method.
// Plus it helps keep each method shorter for ease of understanding, etc.
public void writeToFile(float finalPressure){
Log.d(LOG_TAG // where LOG_TAG is the String name of this class
"writeToFile(float) called." );
try{
// true here for 'append'
FileOutputStream fileOutputStream = new
FileOutputStream(activity.file, true);
fileOutputStream.write((int) finalPressure);
fileOutputStream.close();
}catch (FileNotFoundException e){
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
// now back to your handleRead, is this method called async wenever
// a message is read? Then wouldn't this be called a lot? I'm lost as to why
// you had the button in here at all.
private void handleRead(Message msg) {
Log.d(LOG_TAG // where LOG_TAG is the String name of this class
"handleRead(Message) called." );
byte[] readBuf = (byte[]) msg.obj;
String readMessage = new String(readBuf);
ByteBuffer buffer = ByteBuffer.wrap(readBuf, 0, readBuf.length);
buffer.order(ByteOrder.BIG_ENDIAN);
buffer.clear();
final String[] strNumbers = readMessage.split("\n");
Log.d(LOG_TAG // where LOG_TAG is the String name of this class
"strNumbers length: " + strNumbers.length );
for (int j = 1; j <= strNumbers.length - 2; j++) {
pressure = Integer.parseInt(readMessage2);
MyFinalPressure = (float) (9.677 +0.831 * pressure);
// trying to store directly to internal sotrage
writeToFile(MyFinalPressure);
}
}

Android parse accelerometer data into xml

Hey:) I am trying to pasre to accelerometer data into an xml file when the start button is clicked but the problem is it only parses me the first accelerometer data so not the others or if i write it like the code down here it parse 1000 times the same value
Thank you
public class Secondet extends Activity implements SensorEventListener {
TextView currentX;
TextView currentY;
TextView currentZ;
TextView locationx;
TextView locationy;
float deltaX = 0;
float deltaY = 0;
float deltaZ = 0;
double X = 0;
double Y = 0;
protected LocationManager locationManager;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.secondactivity);
initializeViews();
SensorManager sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
Sensor accelerometer = sensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorManager.registerListener(this, accelerometer,
SensorManager.SENSOR_DELAY_NORMAL);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
}
public void initializeViews() {
currentX = (TextView) findViewById(R.id.currentX);
currentY = (TextView) findViewById(R.id.currentY);
currentZ = (TextView) findViewById(R.id.currentZ);
final Button start = (Button) findViewById(R.id.start);
}
#Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub
}
#Override
public void onSensorChanged(SensorEvent event) {
float lastX = 0, lastY = 0, lastZ = 0;
deltaX = (Math.abs(lastX - event.values[0]));
deltaY = (Math.abs(lastY - event.values[1]));
deltaZ = (Math.abs(lastZ - event.values[2]));
displayCurrentValues();
}
public void location() {
Location location = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
X = location.getLongitude();
Y = location.getLatitude();
}
public void displayCurrentValues() {
currentX.setText(Float.toString(deltaX));
currentY.setText(Float.toString(deltaY));
currentZ.setText(Float.toString(deltaZ));
final Button start = (Button) findViewById(R.id.start);
start.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
parse();
}
});
}
public void parse() {
String xAxis = Float.toString(deltaX);
String yAxis = Float.toString(deltaY);
String zAxis = Float.toString(deltaZ);
// Creat XML File
File newxmlfile = new File(Environment.getExternalStorageDirectory()
+ "/newtest1.xml");
try {
newxmlfile.createNewFile();
} catch (IOException e) {
Log.e("IOException", "exception in createNewFile() method");
}
// we have to bind the new file with a FileOutputStream
FileOutputStream fileos = null;
try {
fileos = new FileOutputStream(newxmlfile);
} catch (FileNotFoundException e) {
Log.e("FileNotFoundException", "can't create FileOutputStream");
}
XmlSerializer serializer = Xml.newSerializer();
try {
// we set the FileOutputStream as output for the serializer, using
// UTF-8 encoding
serializer.setOutput(fileos, "UTF-8");
// Write <?xml declaration with encoding (if encoding not null) and
// standalone flag (if standalone not null)
serializer.startDocument(null, Boolean.valueOf(true));
// set indentation option
serializer.setFeature(
"http://xmlpull.org/v1/doc/features.html#indent-output",
true);
// start a tag called "root"
serializer.startTag(null, "root");
// i indent code just to have a view similar to xml-tree
// int i = 0;
final Button stop = (Button) findViewById(R.id.Stop);
stop.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
int i = 2;
}
});
for (int i = 0; i <= 1000; i++) {
// serializer.startTag(null, "Location");
// serializer.startTag(null, "Longitude");
// serializer.text(locationX);
// serializer.endTag(null, "Longitude");
// serializer.startTag(null, "Latitude");
// serializer.text(locationY);
// serializer.endTag(null, "Latitude");
// serializer.endTag(null, "Location");
serializer.startTag(null, "Acceleration");
serializer.startTag(null, "X-Axis");
serializer.text(Float.toString(deltaX));
serializer.endTag(null, "X-Axis");
serializer.startTag(null, "Y-Axis");
serializer.text(Float.toString(deltaX));
serializer.endTag(null, "Y-Axis");
serializer.startTag(null, "Z-Axis");
serializer.text(Float.toString(deltaX));
serializer.endTag(null, "Z-Axis");
serializer.endTag(null, "Acceleration");
}// while(i == 0);
serializer.endTag(null, "root");
serializer.endDocument();
// write xml data into the FileOutputStream
serializer.flush();
// finally we close the file stream
fileos.close();
Toast.makeText(getApplicationContext(),
"file has been created on SD card)", Toast.LENGTH_LONG)
.show();
} catch (Exception e) {
Log.e("Exception", "error occurred while creating xml file");
}
}
}
You need to make a loop. Right now, your code simply calls "parse" once, and that's why it parses that same value 1000 times. Make multiple operations:
An operation that opens the XML File
An operation that closes the XML File
An operation that adds the value to the XML File
When the start button is pressed, initialize the XML File. Then, each time onSensorChanged( ) is called, add the values to the XML File. Once you have 1000 values (implement a simple counter), turn off the accelerometer and call the operation that closes the XML File. The XML File will need to be a global variable, not a local variable, so that all operations can access it.

Get data from Smartwatch Android Wear to Smartphone

I have made some apps (pedometer, heart rate, audio recorder) for the moto360 with android wear. everything works fine, but I don't know how to save the data on the watch and how to access the data on the smartphone. I have managed to send messages to the watch, but I can't send data from the watch to the phone. I can save my data on the smartphone, but I don't know how to manage it on the smartwatch. can someone show me a tutorial or an example? thank you so much!
edit:
The following Code below is used for tracking the heartrate on the Moto360 and it works fine.
I tried to transfer the data from the watch to the Phone for that I used this tutorial -> https://developer.android.com/training/wearables/data-layer/data-items.html
After implementing the Code from the android page I couldn`t run the Project on the device!
public class MainActivity extends Activity implements SensorEventListener {
private static final String TAG = "MainActivity";
private TextView mTextViewStepCount;
private TextView mTextViewStepDetect;
private TextView mTextViewHeart;
PutDataMapRequest dataMap = PutDataMapRequest.create("/count");
GoogleApiClient mGoogleApiClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
#Override
public void onLayoutInflated(WatchViewStub stub) {
mTextViewStepCount = (TextView) stub.findViewById(R.id.step_count);
mTextViewStepDetect = (TextView) stub.findViewById(R.id.step_detect);
mTextViewHeart = (TextView) stub.findViewById(R.id.heart);
getStepCount();
}
});
}
private void getStepCount() {
SensorManager mSensorManager = ((SensorManager) getSystemService(SENSOR_SERVICE));
Sensor mHeartRateSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_HEART_RATE);
Sensor mStepCountSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
Sensor mStepDetectSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
mSensorManager.registerListener(this, mHeartRateSensor, SensorManager.SENSOR_DELAY_NORMAL);
mSensorManager.registerListener(this, mStepCountSensor, SensorManager.SENSOR_DELAY_NORMAL);
mSensorManager.registerListener(this, mStepDetectSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
private String currentTimeStr() {
Calendar c = Calendar.getInstance();
SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");
return df.format(c.getTime());
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
Log.d(TAG, "onAccuracyChanged - accuracy: " + accuracy);
}
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_HEART_RATE) {
String msg = "" + (int) event.values[0];
mTextViewHeart.setText(msg);
Log.d(TAG, msg);
} else if (event.sensor.getType() == Sensor.TYPE_STEP_COUNTER) {
String msg = "Count: " + (int) event.values[0];
mTextViewStepCount.setText(msg);
Log.d(TAG, msg);
} else if (event.sensor.getType() == Sensor.TYPE_STEP_DETECTOR) {
String msg = "Detected at " + currentTimeStr();
mTextViewStepDetect.setText(msg);
Log.d(TAG, msg);
} else {
Log.d(TAG, "Unknown sensor type");
}
}
}
this code helps me a lot, i hope it helps many other people :)
https://github.com/pocmo/SensorDashboard
You need to uses data assets. Image sample:
private static Asset createAssetFromBitmap(Bitmap bitmap) {
final ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteStream);
return Asset.createFromBytes(byteStream.toByteArray());
}
and then
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image);
Asset asset = createAssetFromBitmap(bitmap);
PutDataRequest request = PutDataRequest.create("/image");
request.putAsset("profileImage", asset);
Wearable.DataApi.putDataItem(mGoogleApiClient, request);
more http://developer.android.com/training/wearables/data-layer/assets.html

Stop recording accelerometer data with button click

I have written the following lines to record accelerometer data in a file with a button click
startButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
final SensorEventListener mySensorEventListener = new SensorEventListener() {
public void onSensorChanged(SensorEvent sensorEvent) {
if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
xAxis_lateralA = sensorEvent.values[0];
yAxis_longitudinalA = sensorEvent.values[1];
zAxis_verticalA = sensorEvent.values[2]; // TODO apply the acceleration changes to your application.
textView.append("\nACC_x = "+ xAxis_lateralA + ", ACC_y = "+yAxis_longitudinalA+ ", ACC_z = " + zAxis_verticalA);
acc+="\n"+xAxis_lateralA + ", "+ yAxis_longitudinalA+", "+zAxis_verticalA;
try {
File myFile = new File("/sdcard/acc.txt");
myFile.createNewFile();
FileOutputStream fOut = new FileOutputStream(myFile);
OutputStreamWriter myOutWriter =
new OutputStreamWriter(fOut);
myOutWriter.append(acc);
myOutWriter.close();
fOut.close();
Toast.makeText(getBaseContext(),
"Done writing SD 'acc.txt'",
Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(getBaseContext(), e.getMessage(),
Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
};
// write on SD card file data in the text box
sm = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
int sensorType = Sensor.TYPE_ACCELEROMETER;
sm.registerListener(mySensorEventListener,sm.getDefaultSensor(sensorType), SensorManager.SENSOR_DELAY_NORMAL);
}// onClick
});
Now I want it to stop recording the data with another button click. For example -
stopButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
int sensorType = Sensor.TYPE_ACCELEROMETER;
sm.unregisterListener(listener, sensor)
}// onClick
}); // btnstopButton
}
Wanted to use unregisterListener but most of the time it is saying deprecated.
Can anyone help please?
The documentation says that using the methods associated with SensorListener are deprecated, and to use SensorEventListener instead. Your code snippet should not throw a deprecated warning, but if you use SensorListener, it would.
I think you want to declare your SensorEventListener object outside of the onClick() method so you can unregister it in the other onClick() method:
sm.unregisterListener(mySensorEventListener, sensorType);
That's the method signature you want to use according to the docs.

Categories

Resources