Cancle AsyncTask when onBackPressed

I'm trying to cancle my AsyncTask when I click Back Button by using this code :

 @Override
    public void onBackPressed() {
        super.onBackPressed();
        if (mediaPlayer.isPlaying()) {
            mediaPlayer.stop();
        }
        if(playerTask!=null && !playerTask.isCancelled()) playerTask.cancel(true);
        this.finish();
    }

But doesn't work playerTask still works :

  PlayerTask playerTask = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pop_for_ringtone);
        mediaPlayer = new MediaPlayer();
        playerTask = new PlayerTask();
        playerTask.execute(url);

/***/

 @SuppressLint("StaticFieldLeak")
    public class PlayerTask extends AsyncTask<String, Void, Boolean> {
        ProgressBar pb = findViewById(R.id.progress);

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
                AudioAttributes attribs = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build();
                mediaPlayer.setAudioAttributes(attribs);

            } else {
                mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            }
        }

        @Override
        protected Boolean doInBackground(String... strings) {
            if(!isCancelled()) {
            try {
                mediaPlayer.setDataSource(strings[0]);
                mediaPlayer.prepare();
                prepared = true;
            } catch (IOException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalStateException e) {
                e.printStackTrace();
            }
            mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mediaPlayer) {
                    mediaPlayer.start();
                }
            });

        }
        else
        {
            playerTask.cancel(true);
        }
        return prepared;

        }

        @Override
        protected void onPostExecute(Boolean aBoolean) {
            super.onPostExecute(aBoolean);
            music.setEnabled(true);
            music.setVisibility(View.VISIBLE);
            music.setChecked(true);
        }
    }

Upvotes: 0

Views: 279

Answers (4)

Jaspreet Kaur
Jaspreet Kaur

Reputation: 1720

I have created the wave while media play with following code, and stop the player while clicking on the back button or stop button.

Copy in xml file.

<VisualizerView
            android:id="@+id/waveform_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/white"/>

MainActivity.java

private MediaPlayer myMediaPlayer;      
private VisualizerView mWaveformView;   
Visualizer audioOutput = null;

onCreate()
{
     mWaveformView = (VisualizerView) findViewById(R.id.waveform_view);
     myButtonPlayLastRecordAudio.setOnClickListener(this);
}

  @Override
    public void onClick(View v) {
        switch (v.getId()) {
              case R.id.buttonPlay:
                myAudioSavePathInDevice = Environment.getExternalStorageDirectory().toString() + "/" +
                        "AudioRecording.3gp";


                myMediaPlayer = new MediaPlayer();
                myMediaPlayer.setVolume(1.5f, 1.5f);
                if (myAudioSavePathInDevice == null || myAudioSavePathInDevice.isEmpty()) {
                    Toast.makeText(MainActivity.this, "No Audio Found", Toast.LENGTH_LONG).show();
                } else {
                    try {
                        FileInputStream is = new FileInputStream(myAudioSavePathInDevice);
                        myMediaPlayer.setDataSource(is.getFD());


                        myMediaPlayer.prepare();
                        myMediaPlayer.start();
                        Toast.makeText(AudioRecordingActivity.this, "Recording Playing", Toast.LENGTH_LONG).show();

                        mWaveformView.clear();
                        createVisualizer();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                    myMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                        @Override
                        public void onCompletion(MediaPlayer mp) {
                            audioOutput.setEnabled(false);
                        }
                    });
                }

                break;

            case R.id.buttonStopAudio:
                mediaPlayerReleaseResources();

                break;

        }
}



 private void createVisualizer() {
        int rate = Visualizer.getMaxCaptureRate();
        audioOutput = new Visualizer(myMediaPlayer.getAudioSessionId()); // get output audio stream

        audioOutput.setDataCaptureListener(new Visualizer.OnDataCaptureListener() {
            @Override
            public void onWaveFormDataCapture(Visualizer visualizer, byte[] waveform, int samplingRate) {
                int max = 0, min = 255;
                for (int i = 0; i < waveform.length; i++) {
                    int w = (int) waveform[i] & 0xFF;
                    max = Math.max(w, max);
                    min = Math.min(w, min);
                }
                mWaveformView.addAmplitude((max - min)); // update the VisualizeView
                mWaveformView.invalidate(); // refresh the VisualizerView
            }

            @Override
            public void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate) {

            }
        }, rate, true, false); // waveform not freq data
        audioOutput.setEnabled(true);
    }


     private void mediaPlayerReleaseResources() {
        if(myMediaPlayer != null) {
            if (myMediaPlayer.isPlaying()) {
                myMediaPlayer.stop();
            }
        }
        if( audioOutput != null)
            audioOutput.setEnabled(false);
    }


     @Override
    public void onBackPressed() {
        super.onBackPressed();
        mediaPlayerReleaseResources();
    }

VisualizerView.class

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

import java.util.ArrayList;
import java.util.List;

public class VisualizerView extends View {
    private static final int LINE_WIDTH = 3; // width of visualizer lines
    private static final int LINE_SCALE = 4; // scales visualizer lines
    private List<Float> amplitudes; // amplitudes for line lengths
    private int width; // width of this View
    private int height; // height of this View
    private Paint linePaint; // specifies line drawing characteristics

    private float temp_scale = 3;
    float heighest = temp_scale;

    // constructor
    public VisualizerView(Context context, AttributeSet attrs) {
        super(context, attrs); // call superclass constructor
        linePaint = new Paint(); // create Paint for lines
        linePaint.setColor(Color.BLACK); // set color to green
        linePaint.setStrokeWidth(LINE_WIDTH); // set stroke width
    }

    // called when the dimensions of the View change
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        width = w; // new width of this View
        height = h; // new height of this View
        amplitudes = new ArrayList<Float>(width / LINE_WIDTH);

    }

    // clear all amplitudes to prepare for a new visualization
    public void clear() {
        heighest = 3;
        amplitudes.clear();
    }

    // add the given amplitude to the amplitudes ArrayList
    public void addAmplitude(float amplitude) {
        amplitudes.add(amplitude); // add newest to the amplitudes ArrayList

        // if the power lines completely fill the VisualizerView
        if (amplitudes.size() * LINE_WIDTH >= width) {
            amplitudes.remove(0); // remove oldest power value
        }
    }

    // draw the visualizer with scaled lines representing the amplitudes
    @Override
    public void onDraw(Canvas canvas) {
        int middle = height / 2; // get the middle of the View
        float curX = 0; // start curX at zero

        // for each item in the amplitudes ArrayList
        for (float power : amplitudes) {
            heighest = Math.max(power, heighest);
            temp_scale = heighest / height;

            float scaledHeight = power / temp_scale; // LINE_SCALE; // scale the power
            curX += (LINE_WIDTH); // increase X by LINE_WIDTH
            // draw a line representing this item in the amplitudes ArrayList
            canvas.drawLine(curX, middle + scaledHeight / 2, curX, middle
                    - scaledHeight / 2, linePaint);
        }
    }

}

Upvotes: 1

Truong Giang Dam
Truong Giang Dam

Reputation: 500

Try this

@Override
public void onBackPressed() {
    // if playerTask == null mediaPlayer is never start, no need to handle

    if(playerTask != null && playerTask.getStatus() == AsyncTask.Status.FINISHED) {
        if (mediaPlayer.isPlaying()) {
            mediaPlayer.stop();
        }
    } else if (playerTask != null && playerTask.getStatus() != AsyncTask.Status.FINISHED) {
        // It mean your task is running, should stop your mediaPlayer inside your task
        playerTask.cancel(true);
    }
   super.onBackPressed();
}

And in your PlayerTask override onCancelled method

@Override
protected void onCancelled(Boolean aBoolean) {
    if(isCancelled() && mediaPlayer.isPlaying()) {
         mediaPlayer.stop();
    }
}

Hope it help

Upvotes: 2

Napster
Napster

Reputation: 1373

Referring to the docs for AsyncTask.cancel(boolean), AsyncTask cancel(boolean), we see that this method only sets the isCancelled() to give true and results in onCancelled() function to execute instead of onPostExecute(). So if you need to cancel the AsyncTask properly you need to add a flag to periodically check if(!isCancelled()) in doInBackground() and stop execution. Your code would look something like this

@Override
        protected Boolean doInBackground(String... strings) {

            if(!isCancelled()){
            //ToDo:whatever you need to do in the asynctask
            }
            else{
            //ToDo: cancel the execution
            }
            }

        }

  MediaPlayer mediaPlayer = new MediaPlayer();
  if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
    AudioAttributes attribs = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build();
    mediaPlayer.setAudioAttributes(attribs);

  } else {
    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
  }
  mediaPlayer.setDataSource(url);
  mediaPlayer.prepareAsync();
  mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
    @Override
    public void onPrepared(MediaPlayer mediaPlayer) {
      mediaPlayer.start();
      music.setEnabled(true);
      music.setVisibility(View.VISIBLE);
      music.setChecked(true);
    }
  });

And then onBackPressed() you can do mediaPlayer.release()

Upvotes: 1

KeLiuyue
KeLiuyue

Reputation: 8237

You have 2 problem to change .

1.When you call super.onBackPressed(); before you canceled the playerTask ,your activity will destroy firstly .So you should call after playerTask canceled .

2.When you judged that the playTask is running , you also need to use playerTask.getStatus() == AsyncTask.Status.RUNNING .

Change

@Override
public void onBackPressed() {
    super.onBackPressed();
    if (mediaPlayer.isPlaying()) {
        mediaPlayer.stop();
    }
    if(playerTask!=null && !playerTask.isCancelled()) playerTask.cancel(true);
    this.finish();
}

to

@Override
public void onBackPressed() {
    if (mediaPlayer.isPlaying()) {
        mediaPlayer.stop();
    }
    if(playerTask!=null && !playerTask.isCancelled() && playerTask.getStatus() == AsyncTask.Status.RUNNING){
        playerTask.cancel(true);
        playerTask = null;
    }
    super.onBackPressed();
    this.finish();
}

Upvotes: 1

Related Questions