package in.uncod.android.media.widget;

import java.io.IOException;

import android.content.Context;
import android.media.MediaPlayer;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.SeekBar;

public class AudioPlayerView extends LinearLayout implements MediaPlayer.OnPreparedListener,
        View.OnClickListener, MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener,
        SeekBar.OnSeekBarChangeListener {

    private MediaPlayer mMediaPlayer;
    private ImageButton mPlayPauseButton;
    private SeekBar mSeekBar;
    private String mMediaLocation;
    private PlayerState mPlayerState;
    Thread playbackProgressUpdater;

    Handler mHandler = new Handler();

    enum PlayerState {
        Playing, Paused, Preparing
    }

    public AudioPlayerView(Context context) {
        super(context);

        initPlayer();
    }

    public AudioPlayerView(Context context, AttributeSet attrs) {
        super(context, attrs);

        initPlayer();
    }

    public AudioPlayerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        initPlayer();
    }

    private void initPlayer() {
        mPlayPauseButton = new ImageButton(getContext());
        mPlayPauseButton.setOnClickListener(this);
        addView(mPlayPauseButton);

        updateButtonState(PlayerState.Preparing);

        mSeekBar = new SeekBar(getContext());
        mSeekBar.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT));
        addView(mSeekBar);
        mSeekBar.setOnSeekBarChangeListener(this);

        setGravity(Gravity.CENTER_VERTICAL);
    }

    @Override
    public void onPrepared(MediaPlayer mediaPlayer) {

        mHandler.post(new Runnable() {
            @Override
            public void run() {
                updateButtonState(PlayerState.Paused);
            }
        });

        playbackProgressUpdater = new Thread(new ProgressUpdate());
        playbackProgressUpdater.start();
    }

    @Override
    public void onCompletion(MediaPlayer mediaPlayer) {
        updateButtonState(PlayerState.Paused);
    }

    @Override
    public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
        return false;
    }

    @Override
    public void onClick(View view) {
        switch (mPlayerState) {
        case Paused:

            mMediaPlayer.start();
            updateButtonState(PlayerState.Playing);

            break;

        case Playing:

            pausePlaying();

            break;
        }
    }

    public void setMediaLocation(String location) {

        mMediaPlayer = new MediaPlayer();
        mMediaPlayer.setOnPreparedListener(this);
        mMediaPlayer.setOnCompletionListener(this);
        mMediaPlayer.setOnErrorListener(this);
        mMediaLocation = location;

        prepareMediaPlayer();
    }

    private void prepareMediaPlayer() {
        updateButtonState(PlayerState.Preparing);

        if (mMediaLocation != null) {
            try {
                mMediaPlayer.setDataSource(mMediaLocation);
                mMediaPlayer.prepareAsync();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void updateButtonState(PlayerState playerState) {

        mPlayerState = playerState;

        switch (playerState) {
        case Paused:

            mPlayPauseButton.setImageResource(android.R.drawable.ic_media_play);
            mPlayPauseButton.setEnabled(true);

            break;
        case Playing:

            mPlayPauseButton.setImageResource(android.R.drawable.ic_media_pause);
            mPlayPauseButton.setEnabled(true);

            break;

        case Preparing:

            mPlayPauseButton.setImageResource(android.R.drawable.ic_media_play);
            mPlayPauseButton.setEnabled(false);

            break;
        }
    }

    private class ProgressUpdate implements Runnable {
        public void run() {
            while (mMediaPlayer != null) {
                double percent = (double) mMediaPlayer.getCurrentPosition() / mMediaPlayer.getDuration();
                final int progress = (int) (percent * 100.0);
                mHandler.post(new Runnable() {
                    public void run() {
                        mSeekBar.setProgress(progress);
                        mSeekBar.setMax(100);
                    }
                });
                try {
                    Thread.sleep(500);
                }
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void setEnabled(boolean enabled) {
        super.setEnabled(enabled);

        mPlayPauseButton.setEnabled(enabled);
        mSeekBar.setProgress(0);

        try {
            if (mMediaPlayer != null) {
                mMediaPlayer.seekTo(0);
            }
        }
        finally {
            // Ignore exception; should only happen when no media has been loaded into the player
        }
    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int i, boolean fromUser) {
        if (fromUser && mMediaPlayer != null) {
            int position = (int) (mMediaPlayer.getDuration() * (i / 100.0));
            mMediaPlayer.seekTo(position);
        }
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
    }

    public boolean isPlaying() {
        return mMediaPlayer != null && mMediaPlayer.isPlaying();
    }

    public void pausePlaying() {
        if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
            mMediaPlayer.pause();
            updateButtonState(PlayerState.Paused);
        }
    }

    public void stopPlaying() {
        if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
            mMediaPlayer.pause();
            mMediaPlayer.seekTo(0);
            updateButtonState(PlayerState.Paused);
        }
    }
}

@@ -1938,110 +1938,8 @@
 ) %7B%0A
-%0A        mHandler.post(new Runnable() %7B%0A            @Override%0A            public void run() %7B%0A        
     
@@ -1985,35 +1985,8 @@
 d);%0A
-            %7D%0A        %7D);%0A%0A
     
@@ -3347,32 +3347,38 @@
 dateButtonState(
+final 
 PlayerState play
@@ -3384,25 +3384,24 @@
 yerState) %7B%0A
-%0A
         mPla
@@ -3424,17 +3424,117 @@
 rState;%0A
-%0A
+        mHandler.post(new Runnable() %7B%0A            @Override%0A            public void run() %7B%0A        
         
@@ -3556,32 +3556,40 @@
 tate) %7B%0A        
+ 
+       
 case Paused:%0A%0A  
@@ -3590,32 +3590,40 @@
 d:%0A%0A            
+       
+ 
 mPlayPauseButton
@@ -3679,32 +3679,40 @@
 y);%0A            
+        
 mPlayPauseButton
@@ -3735,39 +3735,55 @@
 );%0A%0A            
+      
+  
 break;%0A
+        
         case Pla
@@ -3793,32 +3793,40 @@
 g:%0A%0A            
+    
+    
 mPlayPauseButton
@@ -3883,32 +3883,40 @@
 e);%0A            
+        
 mPlayPauseButton
@@ -3943,32 +3943,40 @@
             
+   
+     
 break;%0A%0A
         case
@@ -3955,32 +3955,40 @@
         break;%0A%0A
+        
         case Pre
@@ -4000,32 +4000,40 @@
 g:%0A%0A            
+ 
+       
 mPlayPauseButton
@@ -4077,32 +4077,40 @@
 ic_media_play);%0A
+        
             mPla
@@ -4146,32 +4146,40 @@
 );%0A%0A            
+        
 break;%0A        %7D
@@ -4169,33 +4169,67 @@
  break;%0A        
+      
-%7D
+  %7D%0A            %7D%0A        %7D);
 %0A    %7D%0A%0A    priv

Update button state on UI thread