首页 文章

Android MediaPlayer在自定义音频流应用程序(适用于Android 2.1)中运行良好,但在较高版本中无效

提问于
浏览
18

EDIT:

Android 2.2 MediaPlayer is working fine with one SHOUTcast URL but not with the other one

我需要播放来自外部URL(shoutcast流)的音频文件 . 目前,音频文件会逐步下载并在我们在手机本地临时存储中获得足够的音频时立即播放 . 我正在使用StreamingMediaPlayer class .

检查这段代码:

private MediaPlayer createMediaPlayer(File mediaFile)
            throws IOException {
        MediaPlayer mPlayer = new MediaPlayer();
        //example of mediaFile =/data/data/package/cache/playingMedia0.dat
        FileInputStream fis = new FileInputStream(mediaFile);
        mPlayer.setDataSource(fis.getFD());
        mPlayer.prepare();
        return mPlayer;
    }

Current status:

1-从Android 1.6到2.1工作正常,但在Android 2.2等更高版本中没有 .

2-“mPlayer.setDataSource(fis.getFD())”是抛出错误的行 .

3-错误是“无法创建媒体播放器”

Other Solution tried:

我尝试了下面的替代解决方案但到目前为止没有任

Android 2.2 MediaPlayer is working fine with one SHOUTcast URL but not with the other one

What i am looking for?

我的目标是拥有可以在Android 2.1及更高版本上运行的代码 .

This issue is also discussed here:

1- Inconsistent 2.2 Media Player Behavior

2- android code for streaming shoutcast stream breaks in 2.2

3-本期网站上的很多问题也讨论了这个问题,但我发现答案没有 .

4- markmail.org

LogCat trace:

Unable to to create media player
Error copying buffered conent.
java.lang.NullPointerException
com.ms.iradio.StreamingMediaPlayer.startMediaPlayer(StreamingMediaPlayer.java:251)
com.ms.iradio.StreamingMediaPlayer.access$2(StreamingMediaPlayer.java:221)
com.ms.iradio.StreamingMediaPlayer$2.run(StreamingMediaPlayer.java:204)
android.os.Handler.handleCallback(Handler.java:587)
android.os.Handler.dispatchMessage(Handler.java:92)
android.os.Looper.loop(Looper.java:123)
android.app.ActivityThread.main(ActivityThread.java:3683)
java.lang.reflect.Method.invokeNative(Native Method)
java.lang.reflect.Method.invoke(Method.java:507)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
dalvik.system.NativeStart.main(Native Method)

3 回答

  • 1

    StreamingMediaPlayer 类正在使用双缓冲技术来解决Android 1.2之前版本中的限制 . Android OS的所有 生产环境 版本都包含支持流媒体的MediaPlayer(1) . 我建议这样做,而不是使用这种双缓冲技术来解决问题 .

    Android OS 2.2用FrightCast播放器替换旧的媒体播放器代码,在这种情况下可能采取不同的行为 .

    堆栈跟踪中的行号与're actually using. I'猜测 NullPointerException 报告的 NullPointerException 不同,但 FileInputStream 和返回的 FileDescriptor 都不能 null .

    (1)在2.2版之前,媒体播放器无法识别响应中带有"ICY/1.1"版本标头的ShoutCast流 . 通过创建用"HTTP/1.1"替换它的代理,您可以解决这个问题 . 有关示例,请参阅StreamProxy class here .

  • 5

    问题是不直接支持内容类型“audio / aacp”流式传输 . 一些解码库可用于播放“aacp”,请参阅下面的解决方案:

    Freeware Advanced Audio (AAC) Decoder for Android

    How to use this library?

    Consider legal issues while using it.

    [T]他的项目http://code.google.com/p/aacplayer-android/是根据GPL许可的,因此您可以在其上创建商业应用程序,但您需要填写GPL - 主要意味着也发布你的代码 . 如果您使用第二个项目http://code.google.com/p/aacdecoder-android/,则无需发布代码(该库是根据LGPL许可的) .

  • 3

    我正在使用此代码并运行2.2到更高版本的流媒体下载 .

    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.MediaPlayer;
    import android.os.Environment;
    import android.os.Handler;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.ImageButton;
    import android.widget.ProgressBar;
    import android.widget.TextView;
    
    
    public class StreamingMediaPlayer {
    private static final int INTIAL_KB_BUFFER =  96*10;//assume 96kbps*10secs/8bits per    byte
    
    private TextView textStreamed;
    
    private ImageButton playButton;
    
    private ProgressBar progressBar;
    ProgressBar pb;
    int audiofiletime=0;
    private long mediaLengthInSeconds;
    private int totalKbRead = 0;
    int totalsize=0;
    int numread;
    int totalBytesRead = 0;
    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,ProgressBar pb) 
    {
        this.context = context;
        this.textStreamed = textStreamed;
        this.playButton = playButton;
        this.progressBar = progressBar;
        this.pb=pb;
    }
    
    /**  
     * Progressivly download the media to a temporary location and update the MediaPlayer as new content becomes available.
     */  
    public void startStreaming(final String mediaUrl) throws IOException {
    
    
        //this.mediaLengthInSeconds = 100;
    
    
        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
     */  
    @SuppressWarnings({ "resource", "unused" })
    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);
        }
    
        ///////////////////save sdcard///////////////
        File direct = new File(Environment.getExternalStorageDirectory()+"/punya");
    
        if(!direct.exists()) {
            if(direct.mkdir()); //directory is created;
        }
    
        String[] files=mediaUrl.split("/");
    
        String fileName=files[files.length-1];
        fileName = fileName.replace(".m4a", ".rdo");
    
    
        //create a new file, to save the downloaded file 
    
        File file = new File(direct,fileName);
    
        @SuppressWarnings("resource")
        FileOutputStream fileOutput = new FileOutputStream(file);
    
        ///////////////////end/////////////////
    
        totalsize=cn.getContentLength();
    
        //mediaLengthInKb = 10000;
    
        downloadingMediaFile = new File(context.getCacheDir(),fileName);
    
        if (downloadingMediaFile.exists()) {
            downloadingMediaFile.delete();
        }
    
        FileOutputStream out = new FileOutputStream(downloadingMediaFile);   
        byte buf[] = new byte[16384];
        int incrementalBytesRead = 0;
        do {
            numread = stream.read(buf);   
            if (numread <= 0)   
                break;   
            out.write(buf, 0, numread);
            fileOutput.write(buf, 0, numread);
            totalBytesRead += numread;
            incrementalBytesRead += numread;
            totalKbRead = totalBytesRead/1000;
            // pb.setMax(100);
            // pb.setProgress(totalKbRead);
    
            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++) + ".m4a");
    
            //moveFile(downloadingMediaFile,bufferedFile);
    
            //  Log.e(getClass().getName(),"Buffered File path: " + bufferedFile.getAbsolutePath());
            //  Log.e(getClass().getName(),"Buffered File length: " + bufferedFile.length()+"");
    
            mediaPlayer = createMediaPlayer(downloadingMediaFile);
    
            //mediaPlayer.start();
            startPlayProgressUpdater();         
            //playButton.setEnabled(true);
            playButton.setVisibility(View.VISIBLE);
        } 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;
                    }
                });
    
        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 {
    
            boolean wasPlaying = mediaPlayer.isPlaying();
            int curPosition = mediaPlayer.getCurrentPosition();
    
            File oldBufferedFile = new File(context.getCacheDir(),"playingMedia" + counter + ".m4a");
            File bufferedFile = new File(context.getCacheDir(),"playingMedia" + (counter++) + ".m4a");
    
            bufferedFile.deleteOnExit();   
            moveFile(downloadingMediaFile,bufferedFile);
    
            //mediaPlayer.pause();
            mediaPlayer.release();
    
            mediaPlayer = createMediaPlayer(bufferedFile);
            mediaPlayer.seekTo(curPosition);
    
            boolean atEndOfFile = mediaPlayer.getDuration() - mediaPlayer.getCurrentPosition() <= 1000;
            if (wasPlaying || atEndOfFile){
                mediaPlayer.start();
            }
    
            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() {
    
                //float loadProgress = ((float)totalBytesRead/(float)mediaLengthInKb);
                //float per = ((float)numread/mediaLengthInKb) * 100;
                float per = ((float)totalBytesRead/totalsize) * 100;
                textStreamed.setText((totalKbRead + " Kb (" + (int)per + "%)"));
                progressBar.setSecondaryProgress((int)(per));
                pb.setSecondaryProgress((int)(per));
    
            }
        };
        handler.post(updater);
    }
    
    private void fireDataFullyLoaded() {
        Runnable updater = new Runnable() { 
            public void run() {
                transferBufferToMediaPlayer();
    
                downloadingMediaFile.delete();
                textStreamed.setText(("Download completed" ));
    
            }
        };
        handler.post(updater);
    }
    
    public MediaPlayer getMediaPlayer() {
        return mediaPlayer;
    }
    
    public void startPlayProgressUpdater() {
        audiofiletime   =mediaPlayer.getDuration();
        float progress = (((float)mediaPlayer.getCurrentPosition()/ audiofiletime) * 100);
        progressBar.setProgress((int)(progress));
        //pb.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[5461];
                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() );
        }
    }
    }
    

相关问题