读书人

流媒体 播发 理论篇

发布时间: 2012-09-14 11:53:44 作者: rapoo

流媒体 播放 理论篇

流媒体播放

?

之所以为理论篇 因为该篇仅实现了播放功能 但还有一些其他待解决/完善功能 所以称之为理论篇

?

而且该篇以原理居多 故暂不释放源码

?

?

?

[原理]

public void startStreaming(final String mediaUri){ Runnable r = new Runnable(){@Overridepublic void run() {// TODO Auto-generated method stubtry {readStream(mediaUri);} catch (MalformedURLException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}} }; new Thread(r).start(); }

?

?

?

2. 创建目标URI 并下载之

?

public void readStream(String mediaUri) throws MalformedURLException, IOException{    URLConnection uc = new URL(mediaUri).openConnection();    uc.connect();        InputStream is = uc.getInputStream();    if(is == null){    //error, InputStream is null    }        dlMedia = new File(context.getCacheDir(),"downloadingMedia.dat");    if(dlMedia.exists()){    dlMedia.delete();    }        FileOutputStream fo = new FileOutputStream(dlMedia);        byte buf[] = new byte[16384];    loadByte = 0;        do {    int numread = is.read(buf);         loadByte += numread;        if(numread <= 0){//end of stream, so exist        break;        }        fo.write(buf, 0, numread);        testMediaBuffer();    }    while(true);    is.close();        //buffer all stream to MediaPlayer if end of stream    transferBufferToMediaPlayer();    

?

?

?

3. 根据此刻下载的byte 判断是:开始播放 还是 缓冲下载数据

?

public void testMediaBuffer(){    Runnable update = new Runnable(){@Overridepublic void run() {// TODO Auto-generated method stub//initial MediaPlayer if nullif(mp == null){if(loadByte >= INTIAL_KB_BUFFER){loadByte = 0;startMediaPlayer();}}//load buffer while 1000else if(loadByte > BUFFER_KEY_BYTE) {loadByte = 0;transferBufferToMediaPlayer();}}        };        handler.post(update);    }

?

?

?

4. 开始播放 并跟踪播放进度

?

public void startPlayProgressUpdater() {    //float progress = mp.getCurrentPosition();        if (mp.isPlaying()) {    Runnable notification = new Runnable() {            public void run() {            startPlayProgressUpdater();    }        };        handler.postDelayed(notification,100);    }    }        public 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(dlMedia,bufferedFile);        mp = createMediaPlayer(bufferedFile);            // We have pre-loaded enough content and started the MediaPlayer so update the buttons & progress meters.        mp.start();                startPlayProgressUpdater();        } catch (IOException e) {        //Log.e(getClass().getName(), "Error initializing the MediaPlayer.", e);        return;        }       }

?

?

?

5. 缓冲下载数据

?

private void transferBufferToMediaPlayer() {        try {        //remember current position         int curPosition = mp.getCurrentPosition();                // Copy the currently downloaded content to a new buffered File.  Store the old File for deleting later.         File bufferedFile = new File(context.getCacheDir(),"playingMedia" + (counter++) + ".dat");        moveFile(dlMedia,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        mp.pause();                // Create a new MediaPlayer rather than try to re-prepare the prior one.        mp = createMediaPlayer(bufferedFile);    mp.seekTo(curPosition);    mp.start();            // Lastly delete the previously playing buffered File as it's no longer needed.        bufferedFile.delete();                }catch (Exception e) {        //error, to print    }    }

?

?

6. 文件移动

?

private void moveFile(File oldLocation, FilenewLocation)    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() );        }    }

?

?

?

7. 播放指定目标

?

private MediaPlayer createMediaPlayer(File mediaFile)    throws IOException {    MediaPlayer mPlayer = new MediaPlayer();    //  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;    }
?

?

8. Toast 信息提示:

?

public void popMsg(String msg){    Toast.makeText(context, msg, Toast.LENGTH_LONG).show();    }

?

?

9. done, plx test it, post feedback, thanks

?

1 楼 bingtian 2010-05-28 你好,这个如果已经播放缓冲的,音乐停止了,等缓冲开始多了,音乐还会继续播放吗? 2 楼 gryphone 2010-05-28 bingtian 写道你好,这个如果已经播放缓冲的,音乐停止了,等缓冲开始多了,音乐还会继续播放吗?
是的啊 但是从效果看不是太好 我现在也在寻找更smooth的方法

读书人网 >移动开发

热点推荐