-1

I am working on the following code, I looked into other questions such as AsyncTask Android example and How to properly use AsyncTask but I still have problems, could you please let me know what I am missing? Thanks a lot!!!

So, in UI I have a start button, s stop button, and a text view. I am getting the data from accelerometer sensor and store in a csv file. without using AsyncTask, the codes works fine, but when using it (as shown below), I get this error: a_datatest cannot be resolved to a variable

so, basically what I want is to start writing the accelerometer data in the background as soon as the start button is clicked, and then once the stop button is clicked, the text view shows "Data Stored!"

I appreciate any help!

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Criteria;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.content.Context;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity implements SensorEventListener, OnClickListener {

    private SensorManager sensorManager;
    private LocationManager locationManager;
    private Button start_bt;
    private Button stop_bt;
    private TextView result_view;
    private boolean started = false;
    String towers;    
    FileOutputStream fos;
    String FILENAME = "AccelOutput";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        Criteria crit = new Criteria();
        towers = locationManager.getBestProvider(crit, false);
        start_bt = (Button) findViewById(R.id.startButton);
        stop_bt = (Button) findViewById(R.id.stopButton);
        result_view = (TextView) findViewById(R.id.resultTextView);
        start_bt.setOnClickListener(this);
        stop_bt.setOnClickListener(this);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {        
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        if (started) {
            Sensor sensortype = event.sensor;

            if (sensortype.getType() == Sensor.TYPE_ACCELEROMETER) {

                double a_x = event.values[0];
                double a_y = event.values[1];
                double a_z = event.values[2];
                double a_a = event.accuracy;
                double a_ts = event.timestamp;
                long a_timestamp = System.currentTimeMillis();
                AccelData a_data = new AccelData(a_timestamp, a_ts, a_x, a_y, a_z, a_a);                
                String a_datatest = a_data.toString();

                new writeData().execute();
            }       
        }
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.startButton) {
            started = true;
            Sensor accel = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
            sensorManager.registerListener(this, accel, SensorManager.SENSOR_DELAY_FASTEST);
        } else if(v.getId() == R.id.stopButton) {
            started = false;
            sensorManager.unregisterListener(this);
        }
    }

    private class writeData extends AsyncTask<Void, Void, String>{

        @Override
        protected String doInBackground(Void... params) {
            // TODO Auto-generated method stub
            File sdCard = Environment.getExternalStorageDirectory();
            File directory = new File (sdCard.getAbsolutePath() + "/output");
            directory.mkdirs();

            String a_filename = "accelerometer.csv";
            File a_file = new File(directory, a_filename);
            FileOutputStream a_fOut = null;
            try {
                a_fOut = new FileOutputStream(a_file, true);
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            OutputStreamWriter a_osw = new OutputStreamWriter(a_fOut);
            try {
                a_osw.write(a_datatest + "\n");
                a_osw.flush();
                a_osw.close();
            } catch (IOException e) {

                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(String result) {
              result_view.setText("Data Stored!"); 
        }
    }
}
Community
  • 1
  • 1
kaman
  • 95
  • 1
  • 2
  • 8

2 Answers2

1

declare the variable within the class scope. i.e use it as a member variable

you are declaring a_datatest in onSensorChanged method so it has no validity out of this scope. So you can not use it in doInBackGround method

delcare within the class like

private String a_datatest;

in onSensorChanged method use like

a_datatest = a_data.toString();
stinepike
  • 54,068
  • 14
  • 92
  • 112
0

I don't think AsyncTask is the best way to acomplish this. AsyncTask is designed to be used for a one-off operation, e.g. downloading a set of data from a server. The AsyncTask starts, performs something in the background, and then reports back to the UI thread. While it is possible to stop an AsyncTask it does not work the way you want.

I would suggest just using a Service for this. You could start your reading of values with the push of a button and then just stop the Service onClick of the stop button.

Rarw
  • 7,645
  • 3
  • 28
  • 46
  • yes, like I said, the code works fine without AsyncTask, but the reason I want to use AsyncTask is that a while after I start logging the data, the UI freezes, meaning that you cannot stop the logging by the stop button, so you have to swap the app away and kill the app. I wanted to put all the writing tasks in the background so it does not interfere with the UI. Do you think I am on the right track? – kaman Jun 20 '13 at 17:55
  • You're 100% right to use a background thread so you don't block the UI. All I'm saying is I don't think you should use an `AsyncTask`. – Rarw Jun 20 '13 at 17:57
  • to my understanding, I can use AsyncTask or use Handler so I can put some tasks running in the background. is there a better way, or basically what is the most appropriate way ? Thanks. – kaman Jun 20 '13 at 18:01
  • Based on what you're describing - starting a background process, running for some time, and then stopping on user input, I would use anything other than an `AsyncTask`. A `Handler` would be a good alternative. Basicly any normal background thread set up would make more sense than a `AsyncTask`. As I said, the `AsyncTask` was intended for one off operations - like get this picture, or post this status update. It was not intedned to be a listener that you can stop at will. – Rarw Jun 20 '13 at 18:22