AsyncTask isCancelled() returns true but doInBackground doesn't end
<p>I have an AsyncTask which record audio. The problem is once I call <code>cancel(true)</code> from the UI thread, <code>isCancelled()</code> returns <code>true</code> (like it's supposed to) but the <code>doInBackground</code> function keeps running and if I run <code>getStatus()</code> on the AsyncTask it returns <strong>RUNNING</strong> and neither of the <code>onCancelled</code> methods are called nore does <code>onPostExecute</code>...</p>

<p>Since all the <code>doInBackground</code> code is placed inside <code>while(!isCancelled())</code>, the method should end once the task is cancelled...</p>

<p>The while(!isCancelled()) loop ends once I call AsyncTask.cancel(). I think the problem is that <code>return null</code> isn't being called and that's why <code>doInBackground</code> doesn't end... I may be wrong though...</p>

<p><strong><em>code:</em></strong></p>

<pre><code>package Classes;

import android.content.Context;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.AsyncTask;
import android.util.Log;

import com.appetizers.app.trytabs.Main2Activity;

/**
 * Created by Alon on 09-Aug-16.
 */
public class RecordingTask2 extends AsyncTask&lt;Void,Void,Void&gt; {

    AudioRecord record;
    Context context;
    int bufferSize;
    int numSample=0;
    private static int[] mSampleRates = new int[] { 8000, 11025, 22050, 44100 };
    short[] audioBuffer;

    public RecordingTask2(Context context) {
        this.context = context;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        Log.d("RECTASK", "onPre");
        record = findAudioRecord();
        record.startRecording();
    }

    @Override
    protected Void doInBackground(Void... params) {

        audioBuffer = new short[bufferSize/2];

        Log.d("RECTASK","before while");
        while(!isCancelled())
        {
            //Log.d("RECTASK","isCancelled = "+isCancelled());
            int numberOfShort = record.read(audioBuffer, 0, audioBuffer.length);
            numSample +=numberOfShort;
        }
        Log.d("RECTASK", "after while\nisCancelled = "+isCancelled());

        return null;
    }

    @Override
    protected void onCancelled() {
        super.onCancelled();
        Log.d("RECTASK", "reached onCancel()");
        end();
    }

    @Override
    protected void onCancelled(Void aVoid) {
        super.onCancelled(aVoid);
        Log.d("RECTASK", "reached onCancelled(Void)");
        end();
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        Log.d("RECTASK", "reached onPost");
        end();
    }

    private void end()
    {
        Log.d("RECTASK","reached end function");
        record.stop();
        record.release();
        ((Main2Activity)context).setNumOfSamples(numSample);
        ((Main2Activity)context).setSamples(audioBuffer);
    }

    public AudioRecord findAudioRecord() {
        for (int rate : mSampleRates) {
            for (short audioFormat : new short[] { AudioFormat.ENCODING_PCM_8BIT, AudioFormat.ENCODING_PCM_16BIT }) {
                for (short channelConfig : new short[] { AudioFormat.CHANNEL_IN_MONO, AudioFormat.CHANNEL_IN_STEREO }) {
                    try {
                        Log.d("FINDAUDIO", "Attempting rate " + rate + "Hz, bits: " + audioFormat + ", channel: "
                                + channelConfig);
                        bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat);

                        if (bufferSize != AudioRecord.ERROR_BAD_VALUE) {
                            // check if we can instantiate and have a success
                            AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, rate, channelConfig, audioFormat, bufferSize);

                            Log.d("FINDAUDIO", "AudioRecorder state = "+recorder.getState());

                            if (recorder.getState() == AudioRecord.STATE_INITIALIZED)
                                return recorder;
                        }
                    } catch (Exception e) {
                        Log.e("FINDAUDIO", rate + "Exception, keep trying.",e);
                    }
                }
            }
        }
        return null;
    }

}
</code></pre>

<p>Here's the part of the code in my MainActivity class where I call and cancel the AsyncTask</p>

<pre><code>recordSlideBar.setDownRun(new Runnable() {
            @Override
            public void run() {
                Log.d("MAINACT","onDown");
                if(recTask==null || recTask.getStatus()!= AsyncTask.Status.RUNNING) {
                    recTask = new RecordingTask2(Main2Activity.this);
                    recTask.execute();
                }
            }
        });

        recordSlideBar.setUpRun(new Runnable() {
            @Override
            public void run() {
                Log.d("MAINACT", "onUp");
                recTask.cancel(true);
                Log.d("MAINACT", "after cancel\nstatus = "+recTask.getStatus());
                while(recTask.getStatus()!= AsyncTask.Status.FINISHED)
                {
                    //waiting for task to end...
                }
                ShortBuffer shortBuffer = ShortBuffer.allocate(samples.length);
                playTask = new PlayingTask(Main2Activity.this,shortBuffer,numOfSamples);

            }
        });
</code></pre>

<p><code>recordSlideBar</code> is a custom view I wrote that has an onTouchListener in it while <code>recordSlideBar.setDownRun(Runnable)</code> sets a <code>Runnable</code> to the <code>MotionEvent.ACTION_DOWN</code> and <code>recordSlideBar.setUpRun(Runnable)</code> sets a <code>Runnable</code> to the <code>MotionEvent.ACTION_UP</code>.</p>

<p>Basically, I create the AsyncTask and execute it when <code>ACTION_DOWN</code> is called and cancel it when <code>ACTION_UP</code> is called...</p>

<p>I'm new to the whole audio capturing techniques so you might see some errors in my code regarding that. Please remember that the issue right now is the AsyncTask ;)</p>

<p><strong>EDIT:</strong> Here's a print-screen of the debugger panel after I cancel the task. notice that the AsyncTask status is <strong>WAIT</strong>, and in the Variables tab, <code>mCancelled</code> is <code>true</code> and <code>mStatus</code> is <code>Running</code></p>

<p><a href="http://i.stack.imgur.com/oEjvK.jpg" rel="nofollow">Screen-shot: asynctask status=wait,cancelled=true,status=running</a></p>