xRay
xRay

Reputation: 801

Stop the audio, with or without the delay

I have a button. When I click on it, audio will be played. That audio will always be repeated with a delay. I.e. the audio will be played and then there is a pause for 5 seconds and then it will be played over and over again. So far, that works fine.

public static MediaPlayer mediaPlayer = new MediaPlayer();
public View mView;
private Context mContext;
public boolean status;

public boolean getStatus() {
    return status;
}
public void setStatus(boolean status) {
    this.status = status;
}

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void toggle(View view, Context context) {
    this.mView = view;
    this.mContext = context;

    // Activate the scanner
    if (!mediaPlayer.isPlaying()) {
        this.start();
    }
    // Deactivate the scanner
    else {
        this.stop();
    }

}

/**
 * Star the scanner
 */
@SuppressLint("UseCompatLoadingForColorStateLists")
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void start() {
    if (!mediaPlayer.isPlaying()) {
        mediaPlayer = MediaPlayer.create(mContext, scanner);
        mediaPlayer.setOnPreparedListener(mediaPlayerListener -> mediaPlayer.start());
        mediaPlayer.setOnCompletionListener(listener -> Helper.setTimeout(() -> mediaPlayer.start(), 5000));
    }
}

/**
 * Stop the scanner
 */
@SuppressLint("UseCompatLoadingForColorStateLists")
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void stop() {
    if (mediaPlayer.isPlaying()) {
        mediaPlayer.stop();
        mediaPlayer.release();
        mView.setBackgroundTintList(null);
        Snackbar.make(mView, "Scanner is OFF", Snackbar.LENGTH_LONG).setAction("Action", null).show();
        setStatus(false);
    }
}
public static void setTimeout(Runnable runnable, int delay) {
    new Handler(Looper.getMainLooper()).postDelayed(runnable, delay);
}

The Problem

I use toggle() for my button. So when I click on it, the audio will be played and when I click again, it should be stopped. That used to work fine, until I added setOnCompletionListener(). So now the audio will only stop when it is already playing. But when I click on that button during the 5000ms delay, it will not work.

I want my toggle button to work, with or without that delay. So is there a way I could cancel that CompletionListener?

Upvotes: 0

Views: 61

Answers (1)

Reza Saadati
Reza Saadati

Reputation: 5419

The interesting part of your code is getStatus(). You should make use of it. Somehow like this:

public class Scanner {
    public static MediaPlayer mediaPlayer = new MediaPlayer();
    public View mView;
    private Context mContext;
    public boolean status;
    private boolean mScannerIsWating = false;

    public boolean getStatus() {
        return status;
    }
    public void setStatus(boolean status) {
        this.status = status;
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public void toggle(View view, Context context) {
        this.mView = view;
        this.mContext = context;

        // Activate the scanner
        if (!mediaPlayer.isPlaying() && !getStatus()) {
            this.start();
        }
        // Deactivate the scanner
        else if (mediaPlayer.isPlaying() || getStatus()) {
            this.stop();
        }

    }

    /**
     * Star the scanner
     */
    @SuppressLint("UseCompatLoadingForColorStateLists")
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public void start() {
        if (!mediaPlayer.isPlaying()) {
            setStatus(true);
            mediaPlayer = MediaPlayer.create(mContext, scanner);
            mediaPlayer.setOnPreparedListener(mediaPlayerListener -> mediaPlayer.start());
            int scanTimer = (!Objects.equals(Helper.getSharedPreference(mContext, "scanTimer"), "")) ? Integer.parseInt(Helper.getSharedPreference(mContext,"scanTimer")) * 1000 : 0;
            mediaPlayer.setOnCompletionListener(listener -> Helper.setTimeout(() -> {
                if (getStatus()) {
                    mediaPlayer.start();
                }
            }, scanTimer));

            // View
            mView.setBackgroundTintList(mView.getResources().getColorStateList(R.color.darkRed));
            Snackbar.make(mView, "Scanner is ON", Snackbar.LENGTH_LONG).setAction("Action", null).show();
        }
    }

    /**
     * Stop the scanner
     */
    @SuppressLint("UseCompatLoadingForColorStateLists")
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public void stop() {
        setStatus(false);
        if (mediaPlayer.isPlaying()) {
            mediaPlayer.stop();
        }
        mView.setBackgroundTintList(null);
        Snackbar.make(mView, "Scanner is OFF", Snackbar.LENGTH_LONG).setAction("Action", null).show();
    }
}

Hint: You should remove mediaPlayer.release(), otherwise you may get an error when you stop and start the mediaplayer.

Upvotes: 2

Related Questions