从res/raw播放声音

8

我将制作一款应用程序,该应用程序应使用mediaPlayer播放几个声音。这是我使用的代码:

String[] name = {"sonar_slow","sonar_medium","sonar_fast"};
    String link = "/res/raw/" + name[state-1] + ".mp3";

    try {
        player.setDataSource(link);
        player.prepare();
        player.start();
    } catch(Exception e) {
        e.printStackTrace();
    }

我也试过这个:
        if(state==1){
            player.create(this, R.raw.sonar_slow);
        }else if(state==2){
            player.create(this, R.raw.sonar_medium);
        }else if(state==3){
            player.create(this, R.raw.sonar_fast);
        }
        player.start();

但是上述方法都没有起作用。我的应用程序没有崩溃,但声音没有播放。有什么想法吗?
4个回答

29

有两个问题。

问题1

您不能以这种方式引用项目/res/raw目录中的资源。您项目目录中的文件"/res/raw/sonar_slow.mp3"不会存储在您的apk中的"/res/raw/sonar_slow.mp3"中。请改为以下内容:

MediaPlayer mp = MediaPlayer.create(this);  
mp.setSource("sonar_slow");

你需要使用

MediaPlayer mp = MediaPlayer.create(this, R.raw.sonar_slow); 

问题 2

以下代码有误:它调用了一个不修改player的静态方法。

player.create(this, R.raw.sonar_slow); 

你应该使用替代的调用方式

player = MediaPlayer.create(this, R.raw.sonar_slow);

完整解决方案

以下是一个可重用的AudioPlayer类,它封装了MediaPlayer。这是从《Android编程:大型终极指南》中稍作修改的。它确保记得清理资源。

package com.example.hellomoon;

import android.content.Context;
import android.media.MediaPlayer;

public class AudioPlayer {

    private MediaPlayer mMediaPlayer;

    public void stop() {
        if (mMediaPlayer != null) {
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
    }

    public void play(Context c, int rid) {
        stop();

        mMediaPlayer = MediaPlayer.create(c, rid);
        mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mediaPlayer) {
                stop();
            }
        });

        mMediaPlayer.start();
    }

}

我使用了下面这行代码:MediaPlayer mp = MediaPlayer.create(this, R.raw.sonar_slow); 但它没有起作用。我也收到了静态访问警告。 - mremremre1
已修正你在顶部示例中使用 R.raw.sonar_slow 的问题。 - Brian Attwell
我在我的AudioPlayer示例中修复了一个资源泄漏问题,以防你复制了这个代码。 - Brian Attwell

5
如何使用MediaPlayer播放文件:
MediaPlayer mp = MediaPlayer.create(this, R.raw.mysound); // sound is inside res/raw/mysound
mp.start();

这是一个使用Android MediaPlayer 播放声音的简单示例。
有两个按钮,每个按钮都会播放不同的声音。选择声音和实际播放声音是在manageSound()方法中完成的。声音文件“hello”、“goodbye”和“what”位于res/raw目录中。
MediaPlayer mp        = null;
String hello         = "Hello!";
String goodbye        = "GoodBye!";

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    final Button buttonHello = (Button) findViewById(R.id.idHello);
    buttonHello.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            managerOfSound(hello);
        } // END onClick()
    }); // END buttonHello


    final Button buttonGoodBye = (Button) findViewById(R.id.idGoodBye);
    buttonGoodBye.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            managerOfSound(goodbye);
        } // END onClick()
    }); // END buttonGoodBye
} // END onCreate()


protected void manageSound(String theText) {
    if (mp != null) {
        mp.reset();
        mp.release();
    }
    if (theText.equals(hello))
        mp = MediaPlayer.create(this, R.raw.hello);
    else if (theText.equals(goodbye))
        mp = MediaPlayer.create(this, R.raw.goodbye);
    else
        mp = MediaPlayer.create(this, R.raw.what);
    mp.start();
}

从这里获取:http://www.badprog.com/android-mediaplayer-example-of-playing-sounds 此外,我强烈建议使用SoundPool代替MediaPlayer,以获得更好的性能和可用性。
请参考:http://developer.android.com/reference/android/media/SoundPool.html 请确保您的声音未静音 - 我知道这听起来很愚蠢,但我们中的最佳人选也会发生这种情况;)

这正是我在我的应用程序中所做的,但仍然没有声音。我需要添加一些权限吗? - mremremre1
不,据我所知,你不需要任何权限,否则你的应用程序会崩溃。请考虑使用SoundPool并检查您的声音是否已静音:D - Philipp Jahoda

0
你需要这样做:
 try{
      mp.prepare();
    } catch (IllegalStateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
    } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
    }           
    mp.start();

在调用 start 之前,您需要先调用 prepare。 - arshu
这并不是真正的修复,更像是掩盖问题的补丁。 - Broak
它既不是修复程序,也不是补丁,这是媒体播放器工作的方式。有一个叫做状态图的东西,用于媒体播放器的状态流程。请参考此链接:http://developer.android.com/reference/android/media/MediaPlayer.html#StateDiagram。 - arshu

-1

确保文件准备完成后再进行播放。


1
播放器的prepare()方法不够吗? - mremremre1
我非常确定prepare()方法正在阻塞。 - user755921

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接