简体   繁体   中英

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);
        }
    }

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();
}

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()

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

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);
        }
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM