12

我正在编写一个使用服务来播放警报音的 Android 警报应用程序。目前,我可以播放音频,但它以可以通过调低设备音量来静音的形式播放。因此,我试图添加一个调用setAudioStreamType(AudioManager.STREAM_ALARM);来防止这种情况。

onStartCommand()的服务功能如下:

MediaPlayer mMP;    
@Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        try
        {
            mMP = MediaPlayer.create(this, R.raw.alarm);
            mMP.setAudioStreamType(AudioManager.STREAM_ALARM);
            mMP.setLooping(true);
            //mMP.prepare(); commented out since prepare() is called in create
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        if (mMP != null) mMP.start();

        return START_STICKY;
    }

我的问题是调用 setAudioStreamType(),MediaPlayer 永远不会播放音频。如果我注释掉那条线,音频就会播放。

输入该行后,我收到以下运行时错误:

04-10 19:32:03.115: E/MediaPlayer(3411): setAudioStream 在状态 8 中调用

04-10 19:32:03.115: E/MediaPlayer(3411): 错误 (-38, 0)

04-10 19:32:03.115: E/MediaPlayer(3411): 在状态 0 中开始调用

04-10 19:32:03.115: E/MediaPlayer(3411): 错误 (-38, 0)

04-10 19:32:03.115: E/MediaPlayer(3411): 错误 (-38,0)

04-10 19:32:03.115: E/MediaPlayer(3411): 错误 (-38,0)

一些研究(我现在找不到链接)告诉我,setAudioStreamType()在被调用后无法prepare()调用,并且create()隐式调用prepare().

无论如何,如果setAudioStreamType()没有这样的错误,我应该怎么做?

4

2 回答 2

13

您可以调用mp.reset()然后设置流类型、数据源,然后进行准备。或者只使用默认构造函数并自己处理初始化。

编辑:

Resources res = getResources();
AssetFileDescriptor afd = res.openRawResourceFd(R.raw.alarm);

mp.reset();
mp.setAudioStreamType(AudioManager.STREAM_ALARM);
mp.setLooping(true);
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
mp.prepare();
mp.start();
于 2012-04-10T23:46:25.763 回答
3

接受的答案是抛出IllegalStateException。这是有效的

MediaPlayer mediaPlayer = new MediaPlayer();

try {
  mediaPlayer.setDataSource(
          this,
          getCustomToneUri()
  );

  mediaPlayer.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);

  mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
    @Override
    public void onPrepared(MediaPlayer mp) {
      mp.start();
    }
  });

  mediaPlayer.prepareAsync();
} catch (IOException e) {
  e.printStackTrace();
}
于 2016-03-16T16:29:09.237 回答