我正在尝试从Android中的TTS输出MP3或wav,然后通过mediaplayer播放。 TTS输出到文件运行良好,mp3文件在sdcard上的以下位置可用:
/sdcard/tmp/tmp.mp3
我遇到的问题是音频文件只播放一次,如果用户重新选择“播放”按钮则文件不播放。
我遇到的第二个问题是媒体控制器在文件正在播放/用户触摸屏幕时没有显示。 代码的重要部分如下:
//audio file playback here
public MediaPlayer mediaPlayer;
public MediaController mediaController;
private Handler handler = new Handler();
@Override
public void onCreate(Bundle savedInstanceState) {
//mediaplayer stuff
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnPreparedListener(this);
mediaController = new MediaController(this);
}
播放按钮onclick如下所示:
String text = inputText.getText().toString();
if (text!=null && text.length()>0) {
// tts.speak(text, TextToSpeech.QUEUE_ADD, null);
//trial synth to file here
HashMap<String, String> myHashRender = new HashMap<String, String>();
myHashRender.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, text);
String tempDestFile = Environment.getExternalStorageDirectory().getPath()+"/tmp/tmp.wav";
tts.synthesizeToFile(text, myHashRender, tempDestFile);
//todo hand to media player for play pause etc
//todo handle delete of the file at some stage - creation of activity?
tts.setOnUtteranceProgressListener(new UtteranceProgressListener() {
public void onDone(String utteranceId){
// Speech file is created
// Initializes Media Player
Log.d("File created ", "init mediaplayer then call playAudio()");
initializeMediaPlayer();
//now play the audio
playAudio();
}
@Override
public void onError(String utteranceId) {
// TODO Auto-generated method stub
}
@Override
public void onStart(String utteranceId) {
// TODO Auto-generated method stub
}
});
}else{
}
}
mediaplayer的初始化如下所示:
private void initializeMediaPlayer(){
String fileName = Environment.getExternalStorageDirectory().getAbsolutePath() + "/tmp/tmp.wav";
Uri uri = Uri.parse("file://"+fileName);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mediaPlayer.setDataSource(getApplicationContext(), uri);
mediaPlayer.prepare();
} catch (Exception e) {
e.printStackTrace();
}
}
playAudio:
private void playAudio() {
mediaPlayer.start();
mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mediaPlayer) {
Log.d("MediaPlayer", " finished so release");
mediaPlayer.release();
}
});
}
@Override
protected void onStop() {
super.onStop();
mediaController.hide();
mediaPlayer.stop();
mediaPlayer.release();
}
public void start() {
mediaPlayer.start();
}
public void pause() {
mediaPlayer.pause();
}
public int getDuration() {
return mediaPlayer.getDuration();
}
public int getCurrentPosition() {
return mediaPlayer.getCurrentPosition();
}
public void seekTo(int i) {
mediaPlayer.seekTo(i);
}
public boolean isPlaying() {
return mediaPlayer.isPlaying();
}
public int getBufferPercentage() {
return 0;
}
public boolean canPause() {
return true;
}
public boolean canSeekBackward() {
return true;
}
public boolean canSeekForward() {
return true;
}
public void onPrepared(MediaPlayer mediaPlayer) {
Log.d("onPrepared", " is running");
mediaController.setMediaPlayer(this);
mediaController.setAnchorView(findViewById(R.layout.activity_main));
handler.post(new Runnable() {
public void run() {
mediaController.setEnabled(true);
mediaController.show();
}
});
}
最后,ouTouchEvent就在这里:
public boolean onTouchEvent(MotionEvent me) {
mediaController.show();
return gDetector.onTouchEvent(me);
}
Logcat似乎暗示媒体播放器在文件播放后正在发布并准备再次播放,这是我尝试播放文件两次时的logcat输出:
12-21 08:39:18.025: V/MediaPlayer-JNI(26717): isPlaying: 1
12-21 08:39:18.025: V/MediaPlayer-JNI(26717): getCurrentPosition: 2229 (msec)
12-21 08:39:18.025: V/MediaPlayer(26717): getDuration
12-21 08:39:18.030: V/MediaPlayer-JNI(26717): getDuration: 6288 (msec)
12-21 08:39:22.320: V/MediaPlayer(26717): message received msg=2, ext1=0, ext2=0
12-21 08:39:22.320: V/MediaPlayer(26717): playback complete
12-21 08:39:22.320: V/MediaPlayer(26717): callback application
12-21 08:39:22.325: D/MediaPlayer(26717): finished so release
12-21 08:39:22.325: V/MediaPlayer-JNI(26717): release
12-21 08:39:22.325: V/MediaPlayer(26717): back from callback
12-21 08:39:22.330: V/MediaPlayer(26717): setListener
12-21 08:39:22.330: V/MediaPlayer(26717): disconnect
12-21 08:39:22.345: V/MediaPlayer(26717): destructor
12-21 08:39:22.350: V/MediaPlayer(26717): disconnect
12-21 08:39:26.465: D/File created(26717): init mediaplayer then call playAudio()
12-21 08:39:26.465: V/MediaPlayer-JNI(26717): setAudioStreamType: 3
总之,我的两个问题是:
为什么音频只播放一次而不是每次按下播放ImageButton?
编辑:
感谢Dave的下面部分答案,每当用户按下播放按钮时,媒体就会播放。尽管如此,mediacontrols仍然没有显示出来。
我应该如何修改我的代码,以便mediacontrols显示标准播放暂停停止搜索等?
感谢您的帮助,这是我第一次尝试使用android中的mediaplayer;
安迪
答案 0 :(得分:1)
您需要更加关注MediaPlayer
的{{3}}并更加谨慎地设计与之互动。具体而言,您无法在完成回调中调用release
,并希望能够再次使用相同的MediaPlayer
。
您可以在完成回调中调用reset
,然后再次查看initializeMediaPlayer
中的代码。或者,您可以尝试寻求零以避免重新准备源(尽管准备本地文件在性能方面可以忽略不计)。
编辑:
关于你的MediaController
问题...在模拟器中可能有点不稳定。我有一些建议。
1)基本上从不使用getApplicationContext()
,尤其是Activity
(已经是Context
)。 (这可能无助于控制器显示,但只是一般提示。)
2)您正在将R.layout.activity_main
传递给findViewById
。我不认为这是正确的。对于在布局中定义的视图的ID,它应该是R.id.___
。您可以在布局XML中使用android:id
标记定义ID。
3)传递空LinearLayout
的ID时,我无法显示控制器。如果要使用布局,可能需要在其中放置某种视图。我在里面放了TextView
和中提琴,我有一个控制器。它没有长时间显示,所以要注意。可能有一个参数要设置显示超时。