Search code examples
androidandroid-asynctaskaccelerometer

Unfortunately, Accelerometer has stopped


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;
}       
}

Solution

  • 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....