I am trying to write an android application that collects different sensors data, and do some computation with it. I want to constantly collect data every 50msec and store it an array, and when the we collect enough data (windowsize = 100), we do some computation with that data.
I used AsyncTask for computation part. But my problem is whenever I start the computation, the application hanks and I've got this message: Unfortunately, Accelerometer has stopped.
Here it is the MainActivity code:
package com.hrmb.accelometer;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.ExecutionException;
import android.hardware.SensorManager;
import android.location.Location;
import android.location.LocationManager;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.view.Menu;
import android.widget.TextView;
public class MainActivity extends Activity {
SensorManager sm;
TextView result_textView;
TextView result2_textView;
TextView textView1;
// the data variable stores the current window size data.
sensordata[] data;
sensordata currentdata = new sensordata();
sensors sensorobj;
private LocationManager lm;
locationReader locReader;
behaviorAnalyser analyser;
// index in the data
private final int windowSize = constants.windowSize;
private int index =0;
//
private static final int sampleRate = 8000;
private AudioRecord audio;
private int bufferSize;
//private double lastLevel = 0;
private Thread thread;
private static final int SAMPLE_DELAY = constants.SAMPLE_DELAY;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
sm = (SensorManager) getSystemService(SENSOR_SERVICE);
result_textView = (TextView) findViewById(R.id.result_textView);
result2_textView = (TextView) findViewById(R.id.result2_textView);
textView1 = (TextView) findViewById(R.id.textView1);
textView1.append("onCreate\n");
data = new sensordata[windowSize];
sensorobj = new sensors(sm);
locReader = new locationReader(lm);
analyser = new behaviorAnalyser();
try {
bufferSize = AudioRecord
.getMinBufferSize(sampleRate, AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT);
} catch (Exception e) {
android.util.Log.e("TrackingFlow", "Exception", e);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
protected void onResume() {
textView1.append("onResume\n");
super.onResume();
audio = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT, bufferSize);
audio.startRecording();
thread = new Thread(new Runnable() {
public void run() {
while(thread != null && !thread.isInterrupted()){
//Let's make the thread sleep for a the approximate sampling time
try{Thread.sleep(SAMPLE_DELAY);}catch(InterruptedException ie){ie.printStackTrace();}
currentdata = sensorobj.getSensorData();
readAudioBuffer();//After this call we can get the last value assigned to the currentdata.SOUNDLEVEL variable
// read the data from other sensors
Location myloc = locReader.getCurrentLocation();
currentdata.LOC_LAT = (float) myloc.getLatitude();
currentdata.LOC_LNG = (float) myloc.getLongitude();
//storing data into array
index = index % windowSize;
data[index] = currentdata;
index ++;
runOnUiThread(new Runnable() {
@Override
public void run() {
if(index == (constants.windowSize -1)){
//calculating driving parameters
sensordata[] data2 = new sensordata[constants.windowSize];
System.arraycopy(data, 0, data2, 0, data.length);
drivingParameters result = new drivingParameters();
computeDrivingParams bt = new computeDrivingParams();
bt.execute(data2);
try {
result = bt.get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
result2_textView.setText(" Analyse Driving: \n" + "Num Turn Right: "+ result.numTurnRight + "\n" +
"Num Turn Left: "+ result.numTurnLeft + "\n" +
"Num Acceleration: "+ result.numAcceleration + "\n" +
"Num Breaks: "+ result.numBreaks + "\n");
}
result_textView.setText("ACC X: "+ currentdata.ACC_X + " , ACC Y: "+ currentdata.ACC_Y +
" , ACC Z: "+ currentdata.ACC_Z + "\n" +
"GYR X: "+ currentdata.GYR_X + " , GYR Y: "+ currentdata.GYR_Y +
" , GYR Z: "+ currentdata.GYR_Z + "\n" +
" LAT : "+ currentdata.LOC_LAT + " , LOG : "+ currentdata.LOC_LNG + "\n" +
currentdata.CURR_DATE + " , "+ currentdata.CURR_TIME + "\n" +
"noise: "+ currentdata.SOUNDLEVEL + "\n");
}
});
}
}
});
thread.start();
}
/**
* Functionality that gets the sound level out of the sample
*/
private void readAudioBuffer() {
try {
short[] buffer = new short[bufferSize];
int bufferReadResult = 1;
if (audio != null) {
// Sense the voice...
bufferReadResult = audio.read(buffer, 0, bufferSize);
double sumLevel = 0;
for (int i = 0; i < bufferReadResult; i++) {
sumLevel += buffer[i];
}
currentdata.SOUNDLEVEL = (float)Math.abs((sumLevel / bufferReadResult));
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void onPause() {
textView1.append("onPause\n");
super.onPause();
thread.interrupt();
thread = null;
try {
if (audio != null) {
audio.stop();
audio.release();
audio = null;
}
} catch (Exception e) {e.printStackTrace();}
}
private class computeDrivingParams extends AsyncTask<sensordata, Void, drivingParameters>{
@Override
protected drivingParameters doInBackground(sensordata... arg0) {
// TODO Auto-generated method stub
return analyser.analyseDrivingParam(arg0);
}
}
}
And here it is the code for analyser class , it is the place that I do computation, I didn't put real computation here.
package com.hrmb.accelometer;
public class behaviorAnalyser {
public drivingParameters analyseDrivingParam(sensordata[] arg0){
drivingParameters result = new drivingParameters();
int len = arg0.length;
float sumacc =0;
for(int i=0; i<len; i++){
sumacc = arg0[i].ACC_X ;
}
result.numAcceleration = (int) sumacc/len;
result.numTurnRight = 2;
result.numTurnLeft = 5;
result.numBreaks = 10;
//end of analysing
return result;
}
}
I solved my problem in a very simple and strange way.
It turns out in the doInBackground when I call the function of another object, it doesn't work!!!!.
I put the code of method inside the doInBackground and it works....