Android_Mediaplayer和SoundPool音樂播放的簡單應用

Android開發中我們經常使用MediaPlayer來播放音頻文件。

MediaPlayer的使用方法如下:

//聲明MediaPlayer

MediaPlayer mediaPlayer=null;

指定音頻的源,這裏會有兩種情況,一種是音樂文件在應用中,一種是音樂文件在SD卡中

一、當音樂文件在應用中時,使用create來創建

mediaPlayer =MediaPlayer.create(MainActivity.this, R.raw.audio);

二、當音樂文件在SD卡中時

mediaPlayer=new MediaPlayer();

mediaPlayer.setDataSource(文件路徑);

 

 

指定完要播放的文件後,要調用Prepare()

mediaPlayer.Prepare();

//開始播放音樂,在播放前可以判斷一下當前是否已經在播放用isPlaying

mediaPlayer.Start();

//暫停播放音樂

mediaPlayer.Pause();

//重置音樂

mediaPlayer.reset();

 

 

 

 

但是MediaPlayer存在一些不足,例如:資源佔用量較高、延遲時間較長、不支持多個音頻同時播放等。這些缺點決定了MediaPlayer在某些場合的使用情況不會很理想,例如在對時間精準度要求相對較高的遊戲開發中。在遊戲開發中我們經常需要播放一些遊戲音效(比如:子彈爆炸,物體撞擊等),這些音效的共同特點是短促、密集、延遲程度小。在這樣的場景下,我們可以使用SoundPool代替MediaPlayer來播放這些音效。

1. SoundPool載入音樂文件使用了獨立的線程,不會阻塞UI主線程的操作。但是這裏如果音效文件過大沒有載入完成,我們調用play方法時可能產生嚴重的後果,這裏Android SDK提供了一個SoundPool.OnLoadCompleteListener類來幫助我們瞭解媒體文件是否載入完成,我們重載 onLoadComplete(SoundPool soundPool, int sampleId, int status) 方法即可獲得。 
2. 從上面的onLoadComplete方法可以看出該類有很多參數,比如類似id,是的SoundPoolload時可以處理多個媒體一次初始化並放入內存中,這裏效率比MediaPlayer高了很多。 
3. SoundPool類支持同時播放多個音效,這對於遊戲來說是十分必要的,而MediaPlayer類是同步執行的只能一個文件一個文件的播放。  

 

 

 

 

SoundPool的使用方法如下:

SoundPool的使用步驟是 :

1.res中新建raw文件夾,然後將需要播放的音頻放入其中;

2.初始化SoundPool實例;

3.調用SoundPoolplay函數進行播放。

4.調用SoundPool的Pause函數進行暫停。

 

 

1.幾個重要的函數:

soundPool的構造函數

public SoundPool (int maxStreams, int streamType, int srcQuality)

參數:
maxStream —— 同時播放的流的最大數量 
streamType —— 流的類型,一般爲STREAM_MUSIC(具體在AudioManager類中列出
srcQuality —— 採樣率轉化質量,當前無效果,使用0作爲默認值  

 

例如:

SoundPool soundPool = new SoundPool(3, AudioManager.STREAM_MUSIC, 0); 
創建了一個最多支持3個流同時播放的,類型標記爲音樂的SoundPool。 

 

 

2.一般把多個聲音放到HashMap中去

比如 
soundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 100); 
soundPoolMap = new HashMap<Integer, Integer>();   
soundPoolMap.put(1, soundPool.load(this, R.raw.dingdong, 1)); 



soundpool的加載: 

int  load(Context context, int resId, int priority)  //APK資源載入 
int  load(FileDescriptor fd, long offset, long length, int priority)  //FileDescriptor對象載入 
int  load(AssetFileDescriptor afd, int priority)  //Asset對象載入 
int  load(String path, int priority)  //從完整文件路徑名載入 
最後一個參數爲優先級。

 

3.創建音效播放函數用來播放音樂文件
public void playSounds(int sound, int number){
//實例化AudioManager對象,控制聲音
AudioManager am = (AudioManager)this.getSystemService(this.AUDIO_SERVICE);
//最大音量
float audioMaxVolumn =am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
//當前音量
float audioCurrentVolumn = am.getStreamVolume(AudioManager.STREAM_MUSIC);
float volumnRatio = audioCurrentVolumn/audioMaxVolumn;

 

//播放
sp.play(spMap.get(sound),    //聲音資源
volumnRatio,        //左聲道
volumnRatio,            //右聲道
1,            //優先級,0最低
number,        //循環次數,0是不循環,-1是永遠循環
1);               //回放速度,0.5-2.0之間。1爲正常速度
}

 

 

4.暫停

暫停可以使用 pause(int streamID) 方法,這裏的streamIDsoundID均在構造SoundPool類的第一個參數中指明瞭總數量,id0開始。 

pause按鈕在第一次播放的時候好用,第一次之後的播放就不管用了,網上找到的解釋:

原來這個流對應的ID是需要play方法返回的,後來我用mPresentPlayId存儲play返回的流ID,在stop時將流ID使用mPresentPlayId來替換就沒問題了,後來輸出了下mPresentPlayId的值,發現這個值第一次是2.第二次是4,以後使用這個方法一定要注意這個問題。

 

 

具體代碼實現如下:

import java.io.IOException;
import java.util.HashMap;

import android.R.anim;
import android.R.integer;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.SoundPool;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;

public class MainActivity extends Activity
{
	Button btn_MediaPlayerStart = null;
	Button btn_MediaPlayerPause=null;
	Button btn_SoundPoolStart=null;
	Button btn_SoundPoolPause=null;
	MediaPlayer mp = null;
	SoundPool soundPool=null;
	int soundPoolPlayId=0;
	HashMap<Integer, Integer> SoundPoolMap =null;

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		initSounds();
		setContentView(R.layout.activity_main);
		btn_MediaPlayerStart = (Button) findViewById(R.id.btn_MediaPlayerStart);
		btn_MediaPlayerPause=(Button)findViewById(R.id.btn_MediaPlayerPause);
		btn_SoundPoolStart=(Button)findViewById(R.id.btn_SoundPoolStart);
		btn_SoundPoolPause=(Button)findViewById(R.id.btn_SoundPoolSPause);
		btn_MediaPlayerStart.setOnClickListener(buttonClickListener);
		btn_MediaPlayerPause.setOnClickListener(buttonClickListener);
		btn_SoundPoolStart.setOnClickListener(buttonClickListener);
		btn_SoundPoolPause.setOnClickListener(buttonClickListener);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu)
	{
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	//用於初始化mediaPlayer和soundPool聲音
	public void initSounds()
	{
		mp = MediaPlayer.create(MainActivity.this, R.raw.audio);
		soundPool=new SoundPool(4,AudioManager.STREAM_MUSIC,100);
		SoundPoolMap=new HashMap<Integer, Integer>();
		SoundPoolMap.put(1, soundPool.load(this,R.raw.global,1));
	}
	
	//創建了一個方法,用來開始播放soundPool聲音
	public void playSound(int sound,int loop)
	{
		AudioManager mgr=(AudioManager)this.getSystemService(Context.AUDIO_SERVICE);
		float streamVolumeCurrent=mgr.getStreamVolume(AudioManager.STREAM_MUSIC);
		float streamVolumeMax=mgr.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
		float volume=streamVolumeCurrent/streamVolumeMax;
		soundPoolPlayId=soundPool.play(SoundPoolMap.get(sound), volume, volume, 1, loop, 1f);
	}
	
	
	private OnClickListener buttonClickListener = new OnClickListener()
	{

		@Override
		public void onClick(View v)
		{
			//btn_MediaPlayerStart按鈕的單擊事件
			if (v == btn_MediaPlayerStart)
			{
				try
				{
					mp.prepare();
				} catch (IllegalStateException e)
				{
					e.printStackTrace();
				} catch (IOException e)
				{
					e.printStackTrace();
				}
				if (!mp.isPlaying())
				{
					mp.start();
				}
			}
			//btn_MediaPlayerPause按鈕的單擊事件
			else if(v==btn_MediaPlayerPause)
			{
				try
				{
					mp.prepare();
				} catch (IllegalStateException e)
				{
					// TODO 自動生成的 catch 塊
					e.printStackTrace();
				} catch (IOException e)
				{
					// TODO 自動生成的 catch 塊
					e.printStackTrace();
				}
				if (mp.isPlaying())
				{
					mp.pause();
				}
			}
			//btn_SoundPoolStart按鈕的單擊事件
			else if(v==btn_SoundPoolStart)
			{
				playSound(1, 0);
			}
			//btn_SoundPoolPause按鈕的單擊事件
			else if(v==btn_SoundPoolPause)
			{
				soundPool.pause(soundPoolPlayId);
			}
				
		}
	};
}


 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章