-2

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;
}       
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
  • 1
    possible duplicate of [Unfortunately MyApp has stopped. How can I solve this?](http://stackoverflow.com/questions/23353173/unfortunately-myapp-has-stopped-how-can-i-solve-this) – njzk2 Dec 09 '14 at 21:11
  • My problem is about running a task using AsyncTask. When I remove this part, the program works fine. – user3687068 Dec 09 '14 at 23:05

2 Answers2

0

Part of your problem may be that you are not reading the audio data fast enough. I would suggest moving the audio read into it's own thread with audio urgent priority, once the data is out of AudioRecord, you can decide to throw away what you don't want after your sleep cycle.

http://developer.android.com/reference/android/media/AudioRecord.html:

The application is responsible for polling the AudioRecord object in time using one of the following three methods

Gary Bak
  • 4,746
  • 4
  • 22
  • 39
  • Thank you for your reply. The thing is when I remove the part of code that is related to creating an AsyncTask (computeDrivingParams bt = new computeDrivingParams();), the program works perfect. So, my conclusion is that the problem is related to making a AsyncTask. – user3687068 Dec 09 '14 at 23:02
  • If your AsyncTask seems to hang, there may be another running. AsyncTasks are run serially on a single background thread. To get around this you can call bt.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); and see if that helps. – Gary Bak Dec 10 '14 at 14:49
0

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