com.orange.ocara.ui.dialog.AudioPlayerDialog.java Source code

Java tutorial

Introduction

Here is the source code for com.orange.ocara.ui.dialog.AudioPlayerDialog.java

Source

/**
 * Copyright (C) 2015 Orange
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

package com.orange.ocara.ui.dialog;

import android.content.DialogInterface;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.DialogFragment;
import android.view.Gravity;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.SeekBar;
import android.widget.TextView;

import com.orange.ocara.R;

import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.Click;
import org.androidannotations.annotations.EFragment;
import org.androidannotations.annotations.ViewById;

import java.io.IOException;
import java.util.Formatter;
import java.util.Locale;

import timber.log.Timber;

@EFragment(resName = "dialog_audio_player")
public class AudioPlayerDialog extends BaseDialogFragment
        implements MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener {

    public static AudioPlayerDialog newInstance(String uri, int x, int y) {
        AudioPlayerDialog dialog = new AudioPlayerDialog_();
        Bundle args = new Bundle();
        args.putString("uri", uri);
        if (x >= 0) {
            args.putInt("x", x);
        }
        if (y >= 0) {
            args.putInt("y", y);
        }
        dialog.setStyle(DialogFragment.STYLE_NO_TITLE | DialogFragment.STYLE_NORMAL, 0);
        dialog.setArguments(args);
        return dialog;
    }

    private static final int SHOW_PROGRESS = 2;

    private Uri uri;

    @Override
    public void onDismiss(DialogInterface dialog) {
        super.onDismiss(dialog);
        releasePlayer();
    }

    @ViewById(resName = "play_pause_button")
    Button playPauseButton;

    @ViewById(resName = "total_time")
    TextView totalTime;

    @ViewById(resName = "current_time")
    TextView currentTime;

    @ViewById(resName = "audio_player_progress")
    ProgressBar progressBar;
    private boolean draggingProgressBar = false;

    private Handler handler = new MessageHandler();

    MediaPlayer mediaPlayer;
    boolean playWhenFirstTimeLaunched = true;

    private StringBuilder formatBuilder;
    private Formatter formatter;

    @AfterViews
    public void setUri() {
        String stringUri = getArguments().getString("uri");
        this.setUri(Uri.parse(stringUri));
    }

    @Click(resName = "close_dialog")
    public void closeDialog() {
        getDialog().dismiss();
    }

    @Click(resName = "play_pause_button")
    public void playPauseButtonClicked() {
        doPlayPause();
    }

    @Override
    public void onResume() {
        super.onResume();
        initPlayer();
    }

    @Override
    public void onPause() {
        super.onPause();
        releasePlayer();
    }

    @Override
    public void onStart() {
        super.onStart();

        // safety check
        if (getDialog() == null)
            return;

        // set dialog width

        Window window = getDialog().getWindow();

        // set "origin" to top left corner
        window.setGravity(Gravity.TOP); //| Gravity.LEFT);

        int width = getResources().getDimensionPixelSize(R.dimen.audioPlayerDialogWidth);
        window.setLayout(width, WindowManager.LayoutParams.WRAP_CONTENT);

        WindowManager.LayoutParams attributes = window.getAttributes();

        Integer argX = getArguments().getInt("x");
        Integer argY = getArguments().getInt("y");
        if (argX != null && argX >= 0) {
            attributes.x = argX;
        }
        if (argY != null && argY >= 0) {
            attributes.y = argY;
        }

        window.setAttributes(attributes);

    }

    void initPlayer() {
        mediaPlayer = new MediaPlayer();
        mediaPlayer.setOnPreparedListener(this);
        mediaPlayer.setOnCompletionListener(this);

        formatBuilder = new StringBuilder();
        formatter = new Formatter(formatBuilder, Locale.getDefault());

        if (progressBar instanceof SeekBar) {
            SeekBar seeker = (SeekBar) progressBar;
            seeker.setOnSeekBarChangeListener(mSeekListener);
        }
        progressBar.setMax(1000);

        reset();
    }

    public void reset() {
        try {
            mediaPlayer.reset();
            if (uri != null) {
                mediaPlayer.setDataSource(getActivity(), uri);
                mediaPlayer.prepareAsync();
            }
        } catch (IOException e) {
            Timber.e("Could not open file " + uri + " for playback.", e);
        }
    }

    protected void releasePlayer() {
        if (mediaPlayer != null) {
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }

    public void setUri(Uri uri) {
        this.uri = uri;
        if (mediaPlayer != null) {
            reset();
        }
    }

    @Override
    public void onPrepared(MediaPlayer mp) {
        Timber.v("Media player prepared %s", uri);
        if (playWhenFirstTimeLaunched) {
            playWhenFirstTimeLaunched = false;
            doPlayPause();
        } else {
            updatePausePlay();
            updateProgress();
        }

    }

    @Override
    public void onCompletion(MediaPlayer mp) {
        // reset player to be 'ready' to replay the same source
        reset();
    }

    private void doPlayPause() {
        if (mediaPlayer.isPlaying()) {
            mediaPlayer.pause();
        } else {
            mediaPlayer.start();
            // cause the progress bar to be updated
            handler.sendEmptyMessage(SHOW_PROGRESS);
        }
        updatePausePlay();
        updateProgress();
    }

    public void updatePausePlay() {
        if (mediaPlayer.isPlaying()) {
            playPauseButton.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_media_pause, 0, 0, 0);
            playPauseButton.setText(R.string.audio_player_pause);
        } else {
            playPauseButton.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_media_play, 0, 0, 0);
            playPauseButton.setText(R.string.audio_player_play);
        }
    }

    private int updateProgress() {
        int position = mediaPlayer.getCurrentPosition();
        int duration = mediaPlayer.getDuration();
        if (progressBar != null) {
            if (duration > 0) {
                // use long to avoid overflow
                long pos = 1000L * position / duration;
                progressBar.setProgress((int) pos);
            }
        }

        if (totalTime != null)
            totalTime.setText(stringForTime(duration));

        updateCurrentTime(position);

        return position;
    }

    private void updateCurrentTime(int position) {
        if (currentTime != null)
            currentTime.setText(stringForTime(position));
    }

    private String stringForTime(int timeMs) {
        int totalSeconds = timeMs / 1000;

        int seconds = totalSeconds % 60;
        int minutes = (totalSeconds / 60) % 60;
        int hours = totalSeconds / 3600;

        formatBuilder.setLength(0);
        if (hours > 0) {
            return formatter.format("%d:%02d:%02d", hours, minutes, seconds).toString();
        } else {
            return formatter.format("%02d:%02d", minutes, seconds).toString();
        }
    }

    // There are two scenarios that can trigger the seekbar listener to trigger:
    //
    // The first is the user using the touchpad to adjust the posititon of the
    // seekbar's thumb. In this case onStartTrackingTouch is called followed by
    // a number of onProgressChanged notifications, concluded by onStopTrackingTouch.
    // We're setting the field "draggingProgressBar" to true for the duration of the dragging
    // session to avoid jumps in the position in case of ongoing playback.
    //
    // The second scenario involves the user operating the scroll ball, in this
    // case there WON'T BE onStartTrackingTouch/onStopTrackingTouch notifications,
    // we will simply apply the updated position without suspending regular updates.
    private SeekBar.OnSeekBarChangeListener mSeekListener = new SeekBar.OnSeekBarChangeListener() {
        public void onStartTrackingTouch(SeekBar bar) {

            draggingProgressBar = true;

            // By removing these pending progress messages we make sure
            // that a) we won't update the progress while the user adjusts
            // the seekbar and b) once the user is done dragging the thumb
            // we will post one of these messages to the queue again and
            // this ensures that there will be exactly one message queued up.
            handler.removeMessages(SHOW_PROGRESS);
        }

        public void onProgressChanged(SeekBar bar, int progress, boolean fromuser) {
            if (mediaPlayer == null) {
                return;
            }

            if (!fromuser) {
                // We're not interested in programmatically generated changes to
                // the progress bar's position.
                return;
            }

            long duration = mediaPlayer.getDuration();
            long newPosition = (duration * progress) / 1000L;
            mediaPlayer.seekTo((int) newPosition);
            updateCurrentTime((int) newPosition);
        }

        public void onStopTrackingTouch(SeekBar bar) {
            draggingProgressBar = false;
            updateProgress();
            updatePausePlay();

            // Ensure that progress is properly updated in the future,
            // the call to show() does not guarantee this because it is a
            // no-op if we are already showing.
            handler.sendEmptyMessage(SHOW_PROGRESS);
        }
    };

    private class MessageHandler extends Handler {

        @Override
        public void handleMessage(Message msg) {
            if (mediaPlayer == null) {
                return;
            }

            int pos;
            switch (msg.what) {
            case SHOW_PROGRESS:
                pos = updateProgress();
                if (!draggingProgressBar && mediaPlayer.isPlaying()) {
                    msg = obtainMessage(SHOW_PROGRESS);
                    sendMessageDelayed(msg, 1000 - (pos % 1000));
                }
                break;
            }
        }
    }

}