【问题标题】:(Android MediaPlayer) How am I supposed to call setAudioStreamType() if MediaPlayer.create() implicitly calls prepare()?(Android MediaPlayer) 如果 MediaPlayer.create() 隐式调用 prepare(),我应该如何调用 setAudioStreamType()?
【发布时间】:2012-04-10 23:35:16
【问题描述】:

我正在编写一个使用服务来播放警报音的 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()

【问题讨论】:

    标签: android android-mediaplayer


    【解决方案1】:

    您可以调用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();
    

    【讨论】:

    • 听起来你在建议一些类似的东西(在调用create()之后开始):reset();setAudioStreamType();setLooping();prepare();我说对了吗?如果是这样,我在调用准备时收到以下错误:04-10 20:06:25.515: E/MediaPlayer(845): start called in state 104-10 20:06:25.515: E/MediaPlayer(845): error (-38, 0)
    • 似乎您在调用start() 时遇到了错误,而不是prepare()。您可以将更新后的代码添加到问题中吗?
    • 你是对的,那个特定的错误是在调用 start 之后出现的,还有一个关于调用准备的错误,我在发布评论时错过了日志。 04-10 21:42:11.896: E/MediaPlayer(593): prepareAsync called in state 1.
    • 我不是,但是它学习了create()中的数据源,当我通过R.raw.alarm时。我现在需要打电话给setDataSource(),因为打电话给reset()吗?如果是这样,我将如何引用该文件,因为它位于我项目的res/raw 目录中?
    • 是的,一旦你重置它,它就完全未初始化,这就是为什么我相当肯定你可以只使用默认构造函数(除非 create() 方法中有一些基本功能必须是除了上面显示的函数之外初始化)并将调用完全保存到create()。试试上面的例子,让我知道它是否适合你。
    【解决方案2】:

    接受的答案是抛出 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();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-21
      • 1970-01-01
      • 1970-01-01
      • 2016-09-30
      • 1970-01-01
      • 1970-01-01
      • 2012-05-10
      • 2020-01-27
      相关资源
      最近更新 更多