我一直在尝试使用Android内置的MediaPlayer类通过http传输mp3。文档会告诉我,这应该像以下一样简单:
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(URL_OF_FILE);
mp.prepare();
mp.start();
然而,我反复得到以下内容。我也尝试过不同的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)
非常感谢任何帮助,谢谢 小号
答案 0 :(得分:71)
带流媒体示例的简单媒体播放器。对于xml部分,您需要一个带有id按钮1的按钮和两个带有名称button_pause和button_play的可绘制文件夹中的图像,请不要忘记在清单中添加互联网权限。
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;
}
}
答案 1 :(得分:35)
Android MediaPlayer在2.2之前不支持MP3本地流式传输。在旧版本的操作系统中,它似乎只能本地传输3GP。你可以尝试一下pocketjourney代码,虽然它已经过时了(有一个new version here)并且我很难把它变成粘滞的 - 只要它重新填充缓冲区就会口吃。
适用于Android的NPR新闻应用程序是开源的,使用本地代理服务器在2.2之前的操作系统版本中处理MP3流媒体。您可以在此处的第199-216行(r94)中查看相关代码:http://code.google.com/p/npr-android-app/source/browse/Npr/src/org/npr/android/news/PlaybackService.java?r=7cf2352b5c3c0fbcdc18a5a8c67d836577e7e8e3
NPR应用程序在流式传输时有时仍会出现“错误(-38,0)”。这可能是线程问题或网络更改问题。查看issue tracker for updates。
答案 2 :(得分:9)
我猜你是想尝试直接播放.pls或类似的东西。
试试这个:
1:代码
mediaPlayer = MediaPlayer.create(this, Uri.parse("http://vprbbc.streamguys.net:80/vprbbc24.mp3"));
mediaPlayer.start();
2:.pls文件
此网址仅以BBC为例。这是一个.pls文件,在我用
下载的linux上wget http://foo.bar/file.pls
然后我用vim打开(使用你最喜欢的编辑器;),我已经看到了这个文件中的真实URL。不幸的是,不是所有的.pls都是那样的纯文本。
我已经读过1.6不支持通过http流式传输mp3,但是,我刚用android 1.6和2.2测试了obove代码并且没有任何问题。
祝你好运!答案 3 :(得分:3)
使用
mediaplayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaplayer.prepareAsync();
mediaplayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mediaplayer.start();
}
});
答案 4 :(得分:2)
我遇到了同样的错误,结果证明代码没有任何问题。问题是网络服务器发送了错误的Content-Type标题。
尝试使用wireshark或类似内容来查看网络服务器正在发送的内容类型。
答案 5 :(得分:1)
没有使用OnPreparedListener调用mp.start以避免日志中的零状态..
答案 6 :(得分:1)
看我的项目: