Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android How to run an AsyncTask every second?

I'm new in Android and not really knowing how to deal this problem: I have an AsyncTask which reads a position (X,Y,Z) from a XML file. As this position changes every second, I want, after I push a button (called with "StartListener") to read and draw every new position CONTINUOUSLY and stop reading it when I press the button again...
Somebody can help me? - Here is a part of my MainActivity

(For the moment my app reads and draws a position only when I press the button...)

      private OnClickListener StartListener = new OnClickListener() {

          @Override
          public void onClick(View v) {

                TextView ButText = (TextView)findViewById(R.id.buttonStart);

                 String value=ButText.getText().toString();
                 if(value.equals("Start positioning")){
                     ButText.setText("Stop positioning");

                     new PositionAsync().execute(); //read data from XML file

                 }
                 else if(value.equals("Stop positioning")){
                     ButText.setText("Start positioning");
                     //new PositionAsync().cancel(true);
                 }              
            }                   
      }; // END LISTENER START BUTTON


// READ XML FILE
class PositionAsync extends AsyncTask<Void, Void, Void> {

    XMLHelper helper;
    @Override
    protected Void doInBackground(Void... arg0) {
        helper = new XMLHelper();
        helper.get();
        return null;
    }   

    @Override
    protected void onPostExecute(Void result) {         

        Paint paintBlack = new Paint(); paintBlack.setAntiAlias(true); paintBlack.setColor(Color.BLACK);

        BitmapFactory.Options myOptions = new BitmapFactory.Options();
        myOptions.inDither = true;
        myOptions.inScaled = false;
        myOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;// important
        myOptions.inPurgeable = true;
        File ImageSource = new File("/sdcard/app_background3.jpg");
        Bitmap bitmap2 = BitmapFactory.decodeFile(ImageSource.getAbsolutePath(),myOptions);         
        Bitmap workingBitmap = Bitmap.createBitmap(bitmap2);
        Bitmap mutableBitmap2 = workingBitmap.copy(Bitmap.Config.ARGB_8888, true);

        Canvas canvas2 = new Canvas(mutableBitmap2);

        float RoomWidthPx = canvas2.getWidth();
        float RoomHeightPx = canvas2.getHeight();
        float RoomXmeter = (float) 9.3;
        float RoomZmeter = (float) 14.7;

        for (PositionValue position : helper.positions) {

            String PosX = position.getPositionX(); String PosY = position.getPositionY(); String PosZ = position.getPositionZ();

            float x = Float.valueOf(PosX); float y = Float.valueOf(PosY); float z = Float.valueOf(PosZ);

            float xm = x*RoomWidthPx/RoomXmeter; 
            float zm = z*RoomHeightPx/RoomZmeter;

            canvas2.drawCircle(xm, zm, 25, paintBlack);

            ImageView imageView = (ImageView)findViewById(R.id.imageView1);
            imageView.setAdjustViewBounds(true);
            imageView.setImageBitmap(mutableBitmap2);

            // SAVE DRAWINGS INTO FILE
            FileOutputStream fos = null;
            try {
            fos = new FileOutputStream ("/sdcard/app_background3.jpg");
            mutableBitmap2.compress (Bitmap.CompressFormat.JPEG, 95, fos); 
            } catch (Throwable ex) {ex.printStackTrace (); }    
        };

    }
} //END READ XML FILE
like image 315
user2748484 Avatar asked Sep 09 '13 15:09

user2748484


2 Answers

I think you are doing too many task in just one second. You could, instead, prepare all heavy staff in the onPreExecute() of the AsyncTask, read the XML and do the painting in the doInBackground(), resfresh the ImageView in the onProgressUpdate() and finally, when the task is done, save the image to the sdcard.

I've modified your Asynctask to accomplish the above scenario, I've not tested it but it gives you the idea.

In the onCreate() method of your activity you start the AsyncTask just once. It stays executing or sleeping until you set the Quit_Task variable to true. When the button is pressed you toggle the variable Do_Drawing: Do_Drawing=!Do_Drawing; and that's it.

private boolean Do_Drawing = false;
private boolean Quit_Task = false;

// READ XML FILE
class PositionAsync extends AsyncTask<Void, Void, Void>
{
    Paint paintBlack;
    BitmapFactory.Options myOptions;
    Bitmap mutableBitmap2;
    Canvas canvas2;
    XMLHelper helper;

    void Sleep(int ms)
    {
        try
        {
            Thread.sleep(ms);
        }
        catch (Exception e)
        {
        }
    }

    @Override
    protected void onPreExecute()
    {
        // Prepare everything for doInBackground thread
        paintBlack = new Paint();
        paintBlack.setAntiAlias(true);
        paintBlack.setColor(Color.BLACK);
        myOptions = new BitmapFactory.Options();
        myOptions.inDither = true;
        myOptions.inScaled = false;
        myOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;// important
        myOptions.inPurgeable = true;
        File ImageSource = new File("/sdcard/app_background3.jpg");
        Bitmap bitmap2 = BitmapFactory.decodeFile(ImageSource.getAbsolutePath(), myOptions);
        Bitmap workingBitmap = Bitmap.createBitmap(bitmap2);
        mutableBitmap2 = workingBitmap.copy(Bitmap.Config.ARGB_8888, true);
        canvas2 = new Canvas(mutableBitmap2);
        helper = new XMLHelper();
    }

    @Override
    protected Void doInBackground(Void... arg0)
    {
        while (!Quit_Task)
        {
            // Sleep until button is pressed or quit
            while (!Do_Drawing)
            {
                Sleep(1000);
                if (Quit_Task)
                    return null;
            }

            float RoomWidthPx = canvas2.getWidth();
            float RoomHeightPx = canvas2.getHeight();
            float RoomXmeter = (float) 9.3;
            float RoomZmeter = (float) 14.7;
            // keep drawing until button is pressed again or quit
            while (Do_Drawing)
            {
                if (Quit_Task)
                    return null;
                helper.get();
                for (PositionValue position : helper.positions)
                {
                    String PosX = position.getPositionX();
                    String PosY = position.getPositionY();
                    String PosZ = position.getPositionZ();

                    float x = Float.valueOf(PosX);
                    float y = Float.valueOf(PosY);
                    float z = Float.valueOf(PosZ);

                    float xm = x * RoomWidthPx / RoomXmeter;
                    float zm = z * RoomHeightPx / RoomZmeter;

                    canvas2.drawCircle(xm, zm, 25, paintBlack);
                }
                this.publishProgress((Void) null);
                Sleep(1000);
            }
        }
        return null;
    }

    @Override
    protected void onProgressUpdate(Void... progress)
    {
        // once all points are read & drawn refresh the imageview
        try
        {
            ImageView imageView = (ImageView) findViewById(R.id.imageView1);
            imageView.setAdjustViewBounds(true);
            imageView.setImageBitmap(mutableBitmap2);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    @Override
    protected void onPostExecute(Void result)
    {
        // SAVE DRAWINGS INTO FILE once the task is done.
        FileOutputStream fos = null;
        try
        {
            fos = new FileOutputStream(Environment.getExternalStorageDirectory().getPath() + "app_background3.jpg");
            mutableBitmap2.compress(Bitmap.CompressFormat.JPEG, 95, fos);
        }
        catch (Throwable ex)
        {
            ex.printStackTrace();
        }
    }
} // END READ XML FILE
like image 123
ja_mesa Avatar answered Oct 31 '22 19:10

ja_mesa


you can use Handlers to deal with this:

private boolean isBusy = false;//this flag to indicate whether your async task completed or not
private boolean stop = false;//this flag to indicate whether your button stop clicked
private Handler handler = new Handler();

public void startHandler()
{
    handler.postDelayed(new Runnable()
    {

        @Override
        public void run()
        {
            if(!isBusy) callAysncTask();

            if(!stop) startHandler();
        }
    }, 1000);
}

private void callAysncTask()
{
    //TODO
    new PositionAsync().execute();
}

set isBusy to true when the async task in doInBackground and set it back to false in the last line of onPostExecute.

when you click stop button set stop to true, when click start button set stop to false

like image 41
moh.sukhni Avatar answered Oct 31 '22 19:10

moh.sukhni