使用mediacontroller从TTS播放wav / mp3输出

时间:2013-12-21 08:49:25

标签: android android-mediaplayer

我正在尝试从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;

安迪

1 个答案:

答案 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和中提琴,我有一个控制器。它没有长时间显示,所以要注意。可能有一个参数要设置显示超时。

相关问题