如何将媒体控制器放入流媒体视频?

时间:2011-04-27 09:51:06

标签: android android-layout

我使用SurfaceView播放流媒体视频,使用Media Player播放视频流。任何人都可以告诉我如何将媒体控制器放在surfaceview中?

这是我的代码:

package com.menu.donationvideos;

import android.app.Activity;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.media.MediaPlayer.OnVideoSizeChangedListener;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.MediaController;
import android.widget.MediaController.MediaPlayerControl;
import android.widget.Toast;
import android.widget.VideoView;

import com.menu.R;


public class VideoPlay extends Activity implements OnBufferingUpdateListener, OnCompletionListener,
OnPreparedListener, OnVideoSizeChangedListener, SurfaceHolder.Callback
{
    private static final String TAG = "MediaPlayerDemo";
    private int mVideoWidth;
    private int mVideoHeight;
    SurfaceHolder holder;
    VideoInfo videoInfo;
    String pos,videoURL;
    private MediaPlayer mMediaPlayer;
    private SurfaceView mPreview;
    private String path;
    private boolean mIsVideoSizeKnown = false;
    private boolean mIsVideoReadyToBePlayed = false;


public void onCreate(Bundle savedInstanceState)
{

        super.onCreate(savedInstanceState);
        setContentView(R.layout.video_play);
        Bundle bundle=new Bundle();
        bundle=this.getIntent().getExtras();
        pos=bundle.getString("position");
        videoInfo=VideoList.m_video.get(Integer.parseInt(pos));
        videoURL=videoInfo.getVideoFile();

        try
        {
            mPreview = (SurfaceView)findViewById(R.id.mySurfaceView);
            holder=mPreview.getHolder();
            holder.addCallback(this);
            holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        }

        catch(Exception e)
        { 
            e.printStackTrace();
        }

}

 private void playVideo()
 {
        doCleanUp();
        try 
        {
                    path = videoURL;
                    if (path == "")
                    {
                        Toast.makeText(VideoPlay.this,"URL Not found", Toast.LENGTH_LONG).show();
                    }

            mMediaPlayer = new MediaPlayer();
            mMediaPlayer.setDataSource(path);
            mMediaPlayer.setDisplay(holder);
            mMediaPlayer.prepare();
            mMediaPlayer.setOnBufferingUpdateListener(this);
            mMediaPlayer.setOnCompletionListener(this);
            mMediaPlayer.setOnPreparedListener(this);
            mMediaPlayer.setScreenOnWhilePlaying(true);
            mMediaPlayer.setOnVideoSizeChangedListener(this);
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

        }
        catch (Exception e) 
        {
            e.printStackTrace();
        }
    }

    public void onBufferingUpdate(MediaPlayer arg0, int percent) 
    {
        Log.d(TAG,"Buffering:"+percent);
    }

    public void onCompletion(MediaPlayer arg0) 
    {
        Log.d(TAG, "onCompletion called");
        finish();
    }

    public void onVideoSizeChanged(MediaPlayer mp, int width, int height) 
    {
        Log.v(TAG, "onVideoSizeChanged called");
        if (width == 0 || height == 0)
        {
            Log.e(TAG, "invalid video width(" + width + ") or height(" + height + ")");
            return;
        }

        mIsVideoSizeKnown = true;
        mVideoWidth = width;
        mVideoHeight = height;

        if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) 
        {
            startVideoPlayback();
        }
    }

    public void onPrepared(MediaPlayer mediaplayer) 
    {
        Log.d(TAG, "onPrepared called");
        mIsVideoReadyToBePlayed = true;
        if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) 
        {

            startVideoPlayback();

        }
    }

    public void surfaceChanged(SurfaceHolder surfaceholder, int i, int j, int k) 
    {

        Log.d(TAG, "surfaceChanged called");

    }

    public void surfaceDestroyed(SurfaceHolder surfaceholder) 
    {
        Log.d(TAG, "surfaceDestroyed called");                      

    }


    public void surfaceCreated(SurfaceHolder holder)
    {
        Log.d(TAG, "surfaceCreated called");
        playVideo();

    }

    @Override
    protected void onPause() 
    {
        super.onPause();
        releaseMediaPlayer();
        doCleanUp();
    }

    @Override
    protected void onDestroy() 
    {
        super.onDestroy();
        releaseMediaPlayer();
        doCleanUp();
    }

    private void releaseMediaPlayer() 
    {
        if (mMediaPlayer != null) 
        {
            mMediaPlayer.release();
            mMediaPlayer = null;
        }

    }

    private void doCleanUp()
    {
        mVideoWidth = 0;
        mVideoHeight = 0;
        mIsVideoReadyToBePlayed = false;
        mIsVideoSizeKnown = false;

    }

    private void startVideoPlayback() 
    {
        Log.v(TAG, "startVideoPlayback");
        holder.setFixedSize(mVideoWidth, mVideoHeight);
        mMediaPlayer.start();

    }

}

3 个答案:

答案 0 :(得分:2)

我建议你看看source code of VideoView,它首先将所有内容组合在一起(或者使用VideoView而不是MediaPlayer本身)

答案 1 :(得分:2)

 do {
        numread = stream.read(buf); 
        if (numread <= 0)   
            break;   
        totalBytesRead += numread;


        totalKbRead = totalBytesRead/1000;
        Log.e(getClass().getName(),"Buffered byte: " +totalBytesRead+"");
        if(totalBytesRead>=100000){
        if(mediaPlayer!=null){
              int dura = mediaPlayer.getDuration();
            if(mediaPlayer.getDuration()>=90000){
                isInterrupted =false;
                stream.close();
                out.close();
                out.flush();
                break;
                }
            }

        }

这是我的代码,但我意识到媒体播放器在流式播放之前不会启动。

答案 2 :(得分:0)

嘿nirav此代码尝试用于媒体流

package com.pocketjourney.media;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Handler;
import android.util.Log;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import android.widget.TextView;

/**
 * MediaPlayer does not yet support streaming from external URLs so this class provides a pseudo-streaming function
 * by downloading the content incrementally & playing as soon as we get enough audio in our temporary storage.
 */
public class StreamingMediaPlayer {

    private static final int INTIAL_KB_BUFFER =  96*10/8;//assume 96kbps*10secs/8bits per byte

    private TextView textStreamed;

    private ImageButton playButton;

    private ProgressBar progressBar;

    //  Track for display by progressBar
    private long mediaLengthInKb, mediaLengthInSeconds;
    private int totalKbRead = 0;

    // Create Handler to call View updates on the main UI thread.
    private final Handler handler = new Handler();

    private MediaPlayer     mediaPlayer;

    private File downloadingMediaFile; 

    private boolean isInterrupted;

    private Context context;

    private int counter = 0;

    public StreamingMediaPlayer(Context  context,TextView textStreamed, ImageButton playButton, Button  streamButton,ProgressBar    progressBar) 
    {
        this.context = context;
        this.textStreamed = textStreamed;
        this.playButton = playButton;
        this.progressBar = progressBar;
    }

    /**  
     * Progressivly download the media to a temporary location and update the MediaPlayer as new content becomes available.
     */  
    public void startStreaming(final String mediaUrl, long  mediaLengthInKb, long   mediaLengthInSeconds) throws IOException {

        this.mediaLengthInKb = mediaLengthInKb;
        this.mediaLengthInSeconds = mediaLengthInSeconds;

        Runnable r = new Runnable() {   
            public void run() {   
                try {   
                    downloadAudioIncrement(mediaUrl);
                } catch (IOException e) {
                    Log.e(getClass().getName(), "Unable to initialize the MediaPlayer for fileUrl=" + mediaUrl, e);
                    return;
                }   
            }   
        };   
        new Thread(r).start();
    }

    /**  
     * Download the url stream to a temporary location and then call the setDataSource  
     * for that local file
     */  
    public void downloadAudioIncrement(String mediaUrl) throws IOException {

        URLConnection cn = new URL(mediaUrl).openConnection();   
        cn.connect();   
        InputStream stream = cn.getInputStream();
        if (stream == null) {
            Log.e(getClass().getName(), "Unable to create InputStream for mediaUrl:" + mediaUrl);
        }

        downloadingMediaFile = new File(context.getCacheDir(),"downloadingMedia.dat");

        // Just in case a prior deletion failed because our code crashed or something, we also delete any previously 
        // downloaded file to ensure we start fresh.  If you use this code, always delete 
        // no longer used downloads else you'll quickly fill up your hard disk memory.  Of course, you can also 
        // store any previously downloaded file in a separate data cache for instant replay if you wanted as well.
        if (downloadingMediaFile.exists()) {
            downloadingMediaFile.delete();
        }

        FileOutputStream out = new FileOutputStream(downloadingMediaFile);   
        byte buf[] = new byte[16384];
        int totalBytesRead = 0, incrementalBytesRead = 0;
        do {
            int numread = stream.read(buf);   
            if (numread <= 0)   
                break;   
            out.write(buf, 0, numread);
            totalBytesRead += numread;
            incrementalBytesRead += numread;
            totalKbRead = totalBytesRead/1000;

            testMediaBuffer();
            fireDataLoadUpdate();
        } while (validateNotInterrupted());   
            stream.close();
        if (validateNotInterrupted()) {
            fireDataFullyLoaded();
        }
    }  

    private boolean validateNotInterrupted() {
        if (isInterrupted) {
            if (mediaPlayer != null) {
                mediaPlayer.pause();
                //mediaPlayer.release();
            }
            return false;
        } else {
            return true;
        }
    }


    /**
     * Test whether we need to transfer buffered data to the MediaPlayer.
     * Interacting with MediaPlayer on non-main UI thread can causes crashes to so perform this using a Handler.
     */  
    private void  testMediaBuffer() {
        Runnable updater = new Runnable() {
            public void run() {
                if (mediaPlayer == null) {
                    //  Only create the MediaPlayer once we have the minimum buffered data
                    if ( totalKbRead >= INTIAL_KB_BUFFER) {
                        try {
                            startMediaPlayer();
                        } catch (Exception e) {
                            Log.e(getClass().getName(), "Error copying buffered conent.", e);               
                        }
                    }
                } else if ( mediaPlayer.getDuration() - mediaPlayer.getCurrentPosition() <= 1000 ){ 
                    //  NOTE:  The media player has stopped at the end so transfer any existing buffered data
                    //  We test for < 1second of data because the media player can stop when there is still
                    //  a few milliseconds of data left to play
                    transferBufferToMediaPlayer();
                }
            }
        };
        handler.post(updater);
    }

    private void startMediaPlayer() {
        try {   
            File bufferedFile = new File(context.getCacheDir(),"playingMedia" + (counter++) + ".dat");

            // We double buffer the data to avoid potential read/write errors that could happen if the 
            // download thread attempted to write at the same time the MediaPlayer was trying to read.
            // For example, we can't guarantee that the MediaPlayer won't open a file for playing and leave it locked while 
            // the media is playing.  This would permanently deadlock the file download.  To avoid such a deadloack, 
            // we move the currently loaded data to a temporary buffer file that we start playing while the remaining 
            // data downloads.  
            moveFile(downloadingMediaFile,bufferedFile);

            Log.e(getClass().getName(),"Buffered File path: " + bufferedFile.getAbsolutePath());
            Log.e(getClass().getName(),"Buffered File length: " + bufferedFile.length()+"");

            mediaPlayer = createMediaPlayer(bufferedFile);

            // We have pre-loaded enough content and started the MediaPlayer so update the buttons & progress meters.
            mediaPlayer.start();
            startPlayProgressUpdater();         
            playButton.setEnabled(true);
        } catch (IOException e) {
            Log.e(getClass().getName(), "Error initializing the MediaPlayer.", e);
            return;
        }   
    }

    private MediaPlayer createMediaPlayer(File mediaFile)
    throws IOException {
        MediaPlayer mPlayer = new MediaPlayer();
        mPlayer.setOnErrorListener(
                new MediaPlayer.OnErrorListener() {
                    public boolean onError(MediaPlayer mp, int what, int extra) {
                        Log.e(getClass().getName(), "Error in MediaPlayer: (" + what +") with extra (" +extra +")" );
                        return false;
                    }
                });

        //  It appears that for security/permission reasons, it is better to pass a FileDescriptor rather than a direct path to the File.
        //  Also I have seen errors such as "PVMFErrNotSupported" and "Prepare failed.: status=0x1" if a file path String is passed to
        //  setDataSource().  So unless otherwise noted, we use a FileDescriptor here.
        FileInputStream fis = new FileInputStream(mediaFile);
        mPlayer.setDataSource(fis.getFD());
        mPlayer.prepare();
        return mPlayer;
    }

    /**
     * Transfer buffered data to the MediaPlayer.
     * NOTE: Interacting with a MediaPlayer on a non-main UI thread can cause thread-lock and crashes so 
     * this method should always be called using a Handler.
     */  
    private void transferBufferToMediaPlayer() {
        try {
            // First determine if we need to restart the player after transferring data...e.g. perhaps the user pressed pause
            boolean wasPlaying = mediaPlayer.isPlaying();
            int curPosition = mediaPlayer.getCurrentPosition();

            // Copy the currently downloaded content to a new buffered File.  Store the old File for deleting later. 
            File oldBufferedFile = new File(context.getCacheDir(),"playingMedia" + counter + ".dat");
            File bufferedFile = new File(context.getCacheDir(),"playingMedia" + (counter++) + ".dat");

            //  This may be the last buffered File so ask that it be delete on exit.  If it's already deleted, then this won't mean anything.  If you want to 
            // keep and track fully downloaded files for later use, write caching code and please send me a copy.
            bufferedFile.deleteOnExit();   
            moveFile(downloadingMediaFile,bufferedFile);

            // Pause the current player now as we are about to create and start a new one.  So far (Android v1.5),
            // this always happens so quickly that the user never realized we've stopped the player and started a new one
            mediaPlayer.pause();

            // Create a new MediaPlayer rather than try to re-prepare the prior one.
            mediaPlayer = createMediaPlayer(bufferedFile);
            mediaPlayer.seekTo(curPosition);

            //  Restart if at end of prior buffered content or mediaPlayer was previously playing.  
            //  NOTE:  We test for < 1second of data because the media player can stop when there is still
            //  a few milliseconds of data left to play
            boolean atEndOfFile = mediaPlayer.getDuration() - mediaPlayer.getCurrentPosition() <= 1000;
            if (wasPlaying || atEndOfFile){
                mediaPlayer.start();
            }

            // Lastly delete the previously playing buffered File as it's no longer needed.
            oldBufferedFile.delete();

        }catch (Exception e) {
            Log.e(getClass().getName(), "Error updating to newly loaded content.", e);                  
        }
    }

    private void fireDataLoadUpdate() {
        Runnable updater = new Runnable() {
            public void run() {
                textStreamed.setText((totalKbRead + " Kb read"));
                float loadProgress = ((float)totalKbRead/(float)mediaLengthInKb);
                progressBar.setSecondaryProgress((int)(loadProgress*100));
            }
        };
        handler.post(updater);
    }

    private void fireDataFullyLoaded() {
        Runnable updater = new Runnable() { 
            public void run() {
                transferBufferToMediaPlayer();

                // Delete the downloaded File as it's now been transferred to the currently playing buffer file.
                downloadingMediaFile.delete();
                textStreamed.setText(("Audio full loaded: " + totalKbRead + " Kb read"));
            }
        };
        handler.post(updater);
    }

    public MediaPlayer getMediaPlayer() {
        return mediaPlayer;
    }

    public void startPlayProgressUpdater() {
        float progress = (((float)mediaPlayer.getCurrentPosition()/1000)/mediaLengthInSeconds);
        progressBar.setProgress((int)(progress*100));

        if (mediaPlayer.isPlaying()) {
            Runnable notification = new Runnable() {
                public void run() {
                    startPlayProgressUpdater();
                }
            };
            handler.postDelayed(notification,1000);
        }
    }    

    public void interrupt() {
        playButton.setEnabled(false);
        isInterrupted = true;
        validateNotInterrupted();
    }

    /**
     *  Move the file in oldLocation to newLocation.
     */
    public void moveFile(File   oldLocation, File   newLocation)
    throws IOException {

        if ( oldLocation.exists( )) {
            BufferedInputStream  reader = new BufferedInputStream( new FileInputStream(oldLocation) );
            BufferedOutputStream  writer = new BufferedOutputStream( new FileOutputStream(newLocation, false));
            try {
                byte[]  buff = new byte[8192];
                int numChars;
                while ( (numChars = reader.read(  buff, 0, buff.length ) ) != -1) {
                    writer.write( buff, 0, numChars );
                }
            } catch( IOException ex ) {
                throw new IOException("IOException when transferring " + oldLocation.getPath() + " to " + newLocation.getPath());
            } finally {
                try {
                    if ( reader != null ){                      
                        writer.close();
                        reader.close();
                    }
                } catch( IOException ex ){
                    Log.e(getClass().getName(),"Error closing files when transferring " + oldLocation.getPath() + " to " + newLocation.getPath() ); 
                }
            }
        } else {
            throw new IOException("Old location does not exist when transferring " + oldLocation.getPath() + " to " + newLocation.getPath() );
        }
    }
}