Reputation: 1061
I have connected one sensor with Android Phone
. The Sensor measures the response and display the respective result on the app. I tried to use the Java Timer
but now planning to move to Thread
.
While in continuous mode, the app will be totally disable and don't need any user attraction. User need to set some pre-acquisition setting and then press the start button. After starting this button, the main GUI
will be updated continuously but while the operation is going, user can't interact with the app. User need to press that "start" button again to stop the app. Start button will act as stop button at this moment.
I am new to Android so i studied on internet and found that instead of thread
, Asyntask
is better option. And then someone also mentioned that Service
can be better too for running long processes or Concurrent
. I want my app to run for a long time without halting or memory leak.
What do you think is better in my case? and in the meantime, i tried to use AsyncTask
.
Here is my code using AsynTask
. I want this code to run continuously and update the UI thread. UI
has a graph which will be updated with the data from background.
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Button button = (Button) findViewById(R.id.button1); //This button will start and stop the app.
button.setOnClickListener(addOnButtonClick(button));
}
//From main a button will be pressed and then from button signal, Aysnctask will be called. I just implemented the doInBackground
funtion.
View.OnClickListener addOnButtonClick(final Button button){
return new View.OnClickListener()
{
public void onClick(View v)
{
new AsyncTaskActivity().doInBackground();
//Here i want to add one flag, which will be activated as 'true`when the
//button will be pressed once and `fasle` when the button will be pressed //second time.
//True-> activity run, false ->activity stop.
}
};
}
public class AsyncTaskActivity extends AsyncTask<Void , Void, Void>{
@Override
protected Void doInBackground(Void... params){
nativeData = getDatafromsensor(); //Data from native.
DataPoint[] data = new DataPoint[Size];
for (int i=0; i<Size; i++) {
double x = i;
double y = nativeData[i];
DataPoint v = new DataPoint(x, y);
data[i] = v;
}
}
series.resetData(data);
}
return null;
}
Upvotes: 1
Views: 1116
Reputation: 1061
I used your technique and in the pre
, i set the graphical index and initialized the conditions. In the background
thing, i called the native function and got the data from the sensor. In the publish
I am displaying that data in graphical form and for that i used GraphView
library. Here is the code
public class AsyncTaskActivity extends AsyncTask<Void, Double, Void> {
protected void onPreExecute() {
viewport.setMinY(0);
viewport.setMaxY(8000);
viewport.setMinX(0);
viewport.setMaxX(330);
staticLabelsFormatter = new StaticLabelsFormatter(graph);
staticLabelsFormatter.setHorizontalLabels(new String[]{"400", "500", "600", "730"});
graph.getGridLabelRenderer().setLabelFormatter(staticLabelsFormatter);
}
protected Void doInBackground(Void... params) {
while (!isCancelled()) {
synchronized (nativeData) {
nativeData = getDatafromsensor(); // Data from native.
}
publishProgress(null); // this invokes onProgressUpdate on UI thread
}
}
protected void onProgressUpdate(Void... values) {
///This one here
series.setBackgroundColor(Color.rgb((int) spec_data[WeightSize], (int) spec_data[WeightSize+1], (int) spec_data[WeightSize+2]));
series.resetData(data);
}
protected void onCancelled(Void result) {
Log.d("Updates", "I am In Cancelled");
if (mSensorTask != null)
mSensorTask.cancel(true);
}
}
Issue:
The problem is that in ProgressUpdate
, when i am setting the background color. It is flickering a lot. Like sometimes it don't show for more than 30 seconds, even though the graph is changing perfectly. Do i need to put sleep. But the why graph is changing instantly?
Upvotes: 0
Reputation: 30985
I think Service
might be the way to go long-term, but here's how you can get going with AsyncTask
.
You should read the "Usage" section of AsyncTask docs very carefully so you understand the interaction between the UI thread methods and the background thread methods. In your onClick()
method, you are calling doInBackground()
directly, and that's a no-no. You call execute()
and doInBackground()
is invoked on a different thread as a result.
AsyncTask
has a way to update progress. It's meant to be used to update (for example) a progress bar (which has to be done from the UI thread) while the background thread is still running. You can actually use this to achieve your goal.
Here is some example code:
Make a subclass of AsyncTask
to run your data capture thread:
public class SensorTask extends AsyncTask<Void, List<Double>, Void> {
protected void onPreExecute() {
// runs on the UI thread
// TODO set up your UI for data acquisition
}
protected Void doInBackground(Void... params) {
// TODO initialize sensor for acquisition
while (! isCancelled()) {
nativeData = getDatafromsensor(); //Data from native.
List<Double> sensorData = new ArrayList<Double>();
for (int i = 0; i < nativeData.length; i++) {
sensorData.add(new Double(nativeData[i]);
}
publishProgress(sensorData); // this invokes onProgressUpdate on UI thread
Thread.sleep(DELAY_TIME); // if you need to
}
// TODO sensor cleanup
}
protected void onProgressUpdate(List<Double>... values) {
// runs on the UI thread
// TODO update your UI with the sensor data
}
protected void onCancelled(Void result) {
// runs on the UI thread
// TODO update UI for acquisition complete
}
}
And here's how you kick it off:
public void onClick(View v) {
// you need to keep a reference to the task so you can cancel it later
if (mSensorTask != null) {
// task already exists -- if running, stop it
mSensorTask.cancel(false);
mSensorTask = null;
} else {
// task doesn't exist -- make a new task and start it
mSensorTask = new SensorTask();
mSensorTask.execute();
// this will make doInBackground() run on background thread
}
};
And this is important: Make sure you cancel the task in the activity's onPause()
method so the thread only runs when the Activity is current.
EDIT:
Using a global array has the advantage of eliminating extra object allocations. Just make sure you synchronize access to the data array.
Here's another way to code the AsyncTask
for using a global array:
public class SensorTask extends AsyncTask<Void, Void, Void> {
protected void onPreExecute() {
// runs on the UI thread
// TODO set up your UI for data acquisition
}
protected Void doInBackground(Void... params) {
// TODO initialize sensor for acquisition
while (! isCancelled()) {
synchronized (nativeData) {
nativeData = getDatafromsensor(); // Data from native.
}
publishProgress(null); // this invokes onProgressUpdate on UI thread
Thread.sleep(DELAY_TIME); // if you need to
}
// TODO sensor cleanup
}
protected void onProgressUpdate(Void... values) {
// runs on the UI thread
synchronized (nativeData) {
// TODO update your UI with the sensor data
}
}
protected void onCancelled(Void result) {
// runs on the UI thread
// TODO update UI for acquisition complete
}
}
Upvotes: 1