使用MediaPlayer从Android中的URL传输音频?

时间:2021-10-27 15:06:35

I've been trying to stream mp3's over http using Android's built in MediaPlayer class. The documentation would suggest to me that this should be as easy as :

我一直在尝试使用Android在MediaPlayer类中内置的http来传输mp3。文件将向我建议,这应该象:

MediaPlayer mp = new MediaPlayer();
mp.setDataSource(URL_OF_FILE);
mp.prepare();
mp.start();

However I am getting the following repeatedly. I have tried different URLs as well. Please don't tell me that streaming doesn't work on mp3's.

然而,我不断地得到以下信息。我也尝试过不同的url。请不要告诉我,流媒体不能在mp3上播放。

E/PlayerDriver(   31): Command PLAYER_SET_DATA_SOURCE completed with an error or info PVMFErrNotSupported
W/PlayerDriver(   31): PVMFInfoErrorHandlingComplete
E/MediaPlayer(  198): error (1, -4)
E/MediaPlayer(  198): start called in state 0
E/MediaPlayer(  198): error (-38, 0)
E/MediaPlayer(  198): Error (1,-4)
E/MediaPlayer(  198): Error (-38,0)

Any help much appreciated, thanks S

非常感谢,非常感谢。

7 个解决方案

#1


69  

simple Media Player with streaming example.For xml part you need one button with id button1 and two images in your drawable folder with name button_pause and button_play and please don't forget to add the internet permission in your manifest.

简单的媒体播放器与流媒体的例子。对于xml部分,您需要一个带有id button1的按钮和两个带有名称button_pause和button_play的可绘制文件夹中的图像,请不要忘记在清单中添加internet权限。

public class MainActivity extends Activity {
private Button btn;
/**
 * help to toggle between play and pause.
 */
private boolean playPause;
private MediaPlayer mediaPlayer;
/**
 * remain false till media is not completed, inside OnCompletionListener make it true.
 */
private boolean intialStage = true;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    btn = (Button) findViewById(R.id.button1);
    mediaPlayer = new MediaPlayer();
    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    btn.setOnClickListener(pausePlay);

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
}

private OnClickListener pausePlay = new OnClickListener() {

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        // TODO Auto-generated method stub

        if (!playPause) {
            btn.setBackgroundResource(R.drawable.button_pause);
            if (intialStage)
                new Player()
                        .execute("http://www.virginmegastore.me/Library/Music/CD_001214/Tracks/Track1.mp3");
            else {
                if (!mediaPlayer.isPlaying())
                    mediaPlayer.start();
            }
            playPause = true;
        } else {
            btn.setBackgroundResource(R.drawable.button_play);
            if (mediaPlayer.isPlaying())
                mediaPlayer.pause();
            playPause = false;
        }
    }
};
/**
 * preparing mediaplayer will take sometime to buffer the content so prepare it inside the background thread and starting it on UI thread.
 * @author piyush
 *
 */

class Player extends AsyncTask<String, Void, Boolean> {
    private ProgressDialog progress;

    @Override
    protected Boolean doInBackground(String... params) {
        // TODO Auto-generated method stub
        Boolean prepared;
        try {

            mediaPlayer.setDataSource(params[0]);

            mediaPlayer.setOnCompletionListener(new OnCompletionListener() {

                @Override
                public void onCompletion(MediaPlayer mp) {
                    // TODO Auto-generated method stub
                    intialStage = true;
                    playPause=false;
                    btn.setBackgroundResource(R.drawable.button_play);
                    mediaPlayer.stop();
                    mediaPlayer.reset();
                }
            });
            mediaPlayer.prepare();
            prepared = true;
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            Log.d("IllegarArgument", e.getMessage());
            prepared = false;
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            prepared = false;
            e.printStackTrace();
        } catch (IllegalStateException e) {
            // TODO Auto-generated catch block
            prepared = false;
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            prepared = false;
            e.printStackTrace();
        }
        return prepared;
    }

    @Override
    protected void onPostExecute(Boolean result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
        if (progress.isShowing()) {
            progress.cancel();
        }
        Log.d("Prepared", "//" + result);
        mediaPlayer.start();

        intialStage = false;
    }

    public Player() {
        progress = new ProgressDialog(MainActivity.this);
    }

    @Override
    protected void onPreExecute() {
        // TODO Auto-generated method stub
        super.onPreExecute();
        this.progress.setMessage("Buffering...");
        this.progress.show();

    }
}

@Override
protected void onPause() {
    // TODO Auto-generated method stub
    super.onPause();
    if (mediaPlayer != null) {
        mediaPlayer.reset();
        mediaPlayer.release();
        mediaPlayer = null;
    }
}

#2


35  

Android MediaPlayer doesn't support streaming of MP3 natively until 2.2. In older versions of the OS it appears to only stream 3GP natively. You can try the pocketjourney code, although it's old (there's a new version here) and I had trouble making it sticky — it would stutter whenever it refilled the buffer.

Android MediaPlayer在2.2之前不支持MP3的流媒体。在旧版本的操作系统中,它似乎只本地流3GP。您可以尝试pocketjourney代码,尽管它是旧的(这里有一个新版本),而且我在使它具有粘性方面遇到了麻烦——每当它重新填充缓冲区时,它就会结结巴巴地说不出话来。

The NPR News app for Android is open source and uses a local proxy server to handle MP3 streaming in versions of the OS before 2.2. You can see the relevant code in lines 199-216 (r94) here: http://code.google.com/p/npr-android-app/source/browse/Npr/src/org/npr/android/news/PlaybackService.java?r=7cf2352b5c3c0fbcdc18a5a8c67d836577e7e8e3

Android的NPR新闻应用程序是开源的,使用本地代理服务器在2.2之前处理OS版本的MP3流。您可以在第199-216行(r94)中看到相关代码:http://code.google.com/p/npr-android- app/source/browse/npr/src/org/npr/org/npr/android/news/playbackservice.java?

And this is the StreamProxy class: http://code.google.com/p/npr-android-app/source/browse/Npr/src/org/npr/android/news/StreamProxy.java?r=e4984187f45c39a54ea6c88f71197762dbe10e72

这是StreamProxy类:http://code.google.com/p/npr-android- app/source/browse/npr/src/org/npr/android/news/streamproxy .java?

The NPR app is also still getting the "error (-38, 0)" sometimes while streaming. This may be a threading issue or a network change issue. Check the issue tracker for updates.

美国国家公共广播电台的应用程序有时也会在流媒体上出现“错误(- 38,0)”。这可能是线程问题或网络更改问题。检查问题跟踪器更新。

#3


9  

I guess that you are trying to play an .pls directly or something similar.

我猜你是在尝试扮演一个。请直接或类似的角色。

try this out:

试试这个:

1: the code

1:代码

mediaPlayer = MediaPlayer.create(this, Uri.parse("http://vprbbc.streamguys.net:80/vprbbc24.mp3"));
mediaPlayer.start();

2: the .pls file

2:请文件

This URL is from BBC just as an example. It was an .pls file that on linux i downloaded with

这个URL来自BBC,就像一个例子。它是我下载的linux上的一个。pls文件

wget http://foo.bar/file.pls

and then i opened with vim (use your favorite editor ;) and i've seen the real URLs inside this file. Unfortunately not all of the .pls are plain text like that.

然后我用vim打开(使用您最喜欢的编辑器;),我看到了这个文件中的真实url。不幸的是,并不是所有的。pls都是这样的纯文本。

I've read that 1.6 would not support streaming mp3 over http, but, i've just tested the obove code with android 1.6 and 2.2 and didn't have any issue.

我读过1.6不支持http上的流式mp3,但是,我刚刚用android 1.6和2.2测试了obove代码,没有任何问题。

good luck!

好运!

#4


2  

I've had the same error as you have and it turned out that there was nothing wrong with the code. The problem was that the webserver was sending the wrong Content-Type header.

我有和你一样的错误,结果发现代码没有问题。问题是webserver发送了错误的内容类型头。

Try wireshark or something similar to see what content-type the webserver is sending.

尝试wireshark或类似的东西来查看webserver发送的内容类型。

#5


2  

Use

使用

 mediaplayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
 mediaplayer.prepareAsync();
 mediaplayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
      @Override
      public void onPrepared(MediaPlayer mp) {
          mediaplayer.start();
      }
 });

#6


1  

No call mp.start with an OnPreparedListener to avoid the zero state i the log..

没有打电话给*。从OnPreparedListener开始,避免日志中的0状态。

#7


1  

Looking my projects:

看我的项目:

  1. https://github.com/master255/ImmortalPlayer http/FTP support, One thread to read, send and save to cache data. Most simplest way and most fastest work. Complex logic - best way!
  2. https://github.com/master255/ImmortalPlayer http/FTP支持,一个用于读取、发送和保存数据的线程。最简单的方法和最快的工作。复杂的逻辑——最好的方法!
  3. https://github.com/master255/VideoViewCache Simple Videoview with cache. Two threads for play and save data. Bad logic, but if you need then use this.
  4. https://github.com/master255/VideoViewCache简单的带缓存的Videoview。用于播放和保存数据的两个线程。逻辑很糟糕,但如果需要的话,可以使用这个。

#1


69  

simple Media Player with streaming example.For xml part you need one button with id button1 and two images in your drawable folder with name button_pause and button_play and please don't forget to add the internet permission in your manifest.

简单的媒体播放器与流媒体的例子。对于xml部分,您需要一个带有id button1的按钮和两个带有名称button_pause和button_play的可绘制文件夹中的图像,请不要忘记在清单中添加internet权限。

public class MainActivity extends Activity {
private Button btn;
/**
 * help to toggle between play and pause.
 */
private boolean playPause;
private MediaPlayer mediaPlayer;
/**
 * remain false till media is not completed, inside OnCompletionListener make it true.
 */
private boolean intialStage = true;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    btn = (Button) findViewById(R.id.button1);
    mediaPlayer = new MediaPlayer();
    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    btn.setOnClickListener(pausePlay);

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
}

private OnClickListener pausePlay = new OnClickListener() {

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        // TODO Auto-generated method stub

        if (!playPause) {
            btn.setBackgroundResource(R.drawable.button_pause);
            if (intialStage)
                new Player()
                        .execute("http://www.virginmegastore.me/Library/Music/CD_001214/Tracks/Track1.mp3");
            else {
                if (!mediaPlayer.isPlaying())
                    mediaPlayer.start();
            }
            playPause = true;
        } else {
            btn.setBackgroundResource(R.drawable.button_play);
            if (mediaPlayer.isPlaying())
                mediaPlayer.pause();
            playPause = false;
        }
    }
};
/**
 * preparing mediaplayer will take sometime to buffer the content so prepare it inside the background thread and starting it on UI thread.
 * @author piyush
 *
 */

class Player extends AsyncTask<String, Void, Boolean> {
    private ProgressDialog progress;

    @Override
    protected Boolean doInBackground(String... params) {
        // TODO Auto-generated method stub
        Boolean prepared;
        try {

            mediaPlayer.setDataSource(params[0]);

            mediaPlayer.setOnCompletionListener(new OnCompletionListener() {

                @Override
                public void onCompletion(MediaPlayer mp) {
                    // TODO Auto-generated method stub
                    intialStage = true;
                    playPause=false;
                    btn.setBackgroundResource(R.drawable.button_play);
                    mediaPlayer.stop();
                    mediaPlayer.reset();
                }
            });
            mediaPlayer.prepare();
            prepared = true;
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            Log.d("IllegarArgument", e.getMessage());
            prepared = false;
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            prepared = false;
            e.printStackTrace();
        } catch (IllegalStateException e) {
            // TODO Auto-generated catch block
            prepared = false;
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            prepared = false;
            e.printStackTrace();
        }
        return prepared;
    }

    @Override
    protected void onPostExecute(Boolean result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
        if (progress.isShowing()) {
            progress.cancel();
        }
        Log.d("Prepared", "//" + result);
        mediaPlayer.start();

        intialStage = false;
    }

    public Player() {
        progress = new ProgressDialog(MainActivity.this);
    }

    @Override
    protected void onPreExecute() {
        // TODO Auto-generated method stub
        super.onPreExecute();
        this.progress.setMessage("Buffering...");
        this.progress.show();

    }
}

@Override
protected void onPause() {
    // TODO Auto-generated method stub
    super.onPause();
    if (mediaPlayer != null) {
        mediaPlayer.reset();
        mediaPlayer.release();
        mediaPlayer = null;
    }
}

#2


35  

Android MediaPlayer doesn't support streaming of MP3 natively until 2.2. In older versions of the OS it appears to only stream 3GP natively. You can try the pocketjourney code, although it's old (there's a new version here) and I had trouble making it sticky — it would stutter whenever it refilled the buffer.

Android MediaPlayer在2.2之前不支持MP3的流媒体。在旧版本的操作系统中,它似乎只本地流3GP。您可以尝试pocketjourney代码,尽管它是旧的(这里有一个新版本),而且我在使它具有粘性方面遇到了麻烦——每当它重新填充缓冲区时,它就会结结巴巴地说不出话来。

The NPR News app for Android is open source and uses a local proxy server to handle MP3 streaming in versions of the OS before 2.2. You can see the relevant code in lines 199-216 (r94) here: http://code.google.com/p/npr-android-app/source/browse/Npr/src/org/npr/android/news/PlaybackService.java?r=7cf2352b5c3c0fbcdc18a5a8c67d836577e7e8e3

Android的NPR新闻应用程序是开源的,使用本地代理服务器在2.2之前处理OS版本的MP3流。您可以在第199-216行(r94)中看到相关代码:http://code.google.com/p/npr-android- app/source/browse/npr/src/org/npr/org/npr/android/news/playbackservice.java?

And this is the StreamProxy class: http://code.google.com/p/npr-android-app/source/browse/Npr/src/org/npr/android/news/StreamProxy.java?r=e4984187f45c39a54ea6c88f71197762dbe10e72

这是StreamProxy类:http://code.google.com/p/npr-android- app/source/browse/npr/src/org/npr/android/news/streamproxy .java?

The NPR app is also still getting the "error (-38, 0)" sometimes while streaming. This may be a threading issue or a network change issue. Check the issue tracker for updates.

美国国家公共广播电台的应用程序有时也会在流媒体上出现“错误(- 38,0)”。这可能是线程问题或网络更改问题。检查问题跟踪器更新。

#3


9  

I guess that you are trying to play an .pls directly or something similar.

我猜你是在尝试扮演一个。请直接或类似的角色。

try this out:

试试这个:

1: the code

1:代码

mediaPlayer = MediaPlayer.create(this, Uri.parse("http://vprbbc.streamguys.net:80/vprbbc24.mp3"));
mediaPlayer.start();

2: the .pls file

2:请文件

This URL is from BBC just as an example. It was an .pls file that on linux i downloaded with

这个URL来自BBC,就像一个例子。它是我下载的linux上的一个。pls文件

wget http://foo.bar/file.pls

and then i opened with vim (use your favorite editor ;) and i've seen the real URLs inside this file. Unfortunately not all of the .pls are plain text like that.

然后我用vim打开(使用您最喜欢的编辑器;),我看到了这个文件中的真实url。不幸的是,并不是所有的。pls都是这样的纯文本。

I've read that 1.6 would not support streaming mp3 over http, but, i've just tested the obove code with android 1.6 and 2.2 and didn't have any issue.

我读过1.6不支持http上的流式mp3,但是,我刚刚用android 1.6和2.2测试了obove代码,没有任何问题。

good luck!

好运!

#4


2  

I've had the same error as you have and it turned out that there was nothing wrong with the code. The problem was that the webserver was sending the wrong Content-Type header.

我有和你一样的错误,结果发现代码没有问题。问题是webserver发送了错误的内容类型头。

Try wireshark or something similar to see what content-type the webserver is sending.

尝试wireshark或类似的东西来查看webserver发送的内容类型。

#5


2  

Use

使用

 mediaplayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
 mediaplayer.prepareAsync();
 mediaplayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
      @Override
      public void onPrepared(MediaPlayer mp) {
          mediaplayer.start();
      }
 });

#6


1  

No call mp.start with an OnPreparedListener to avoid the zero state i the log..

没有打电话给*。从OnPreparedListener开始,避免日志中的0状态。

#7


1  

Looking my projects:

看我的项目:

  1. https://github.com/master255/ImmortalPlayer http/FTP support, One thread to read, send and save to cache data. Most simplest way and most fastest work. Complex logic - best way!
  2. https://github.com/master255/ImmortalPlayer http/FTP支持,一个用于读取、发送和保存数据的线程。最简单的方法和最快的工作。复杂的逻辑——最好的方法!
  3. https://github.com/master255/VideoViewCache Simple Videoview with cache. Two threads for play and save data. Bad logic, but if you need then use this.
  4. https://github.com/master255/VideoViewCache简单的带缓存的Videoview。用于播放和保存数据的两个线程。逻辑很糟糕,但如果需要的话,可以使用这个。