1. 游戲中的即時(shí)音效:
在游戲中,根據(jù)情況播放的即時(shí)音效較為短暫、可以重復(fù)、也可以同時(shí)播放。由于Android中提供的MediaPlayer會(huì)占用大量的系統(tǒng)資源,而且播放時(shí)還會(huì)進(jìn)行緩沖,有較大的延時(shí),因此使用MediaPlayer無法實(shí)現(xiàn)即時(shí)音效的播放。而在Android中專門提供的SoundPool類主要用于管理和播放應(yīng)用程序中的聲音資源,使用該類時(shí)首先需要通過該類將聲音資源加載到內(nèi)存中,然后在需要的即時(shí)音效的地方播放即可,幾乎沒有延時(shí)現(xiàn)象。【由于SoundPool設(shè)計(jì)的初衷是用于無延時(shí)地播放游戲中的即時(shí)音效,因此實(shí)際開發(fā)中應(yīng)該只講長度小于7s的聲音資源放進(jìn)soundPool,否則可能會(huì)加載失敗或內(nèi)存占用過大】
SoundPool類:
public SoundPool (int maxSreams, int streamType, int srcQuality):創(chuàng)建SoundPool對象:maxStreams[該參數(shù)用于設(shè)置最多同時(shí)播放多少個(gè)音效]streamType[該參數(shù)設(shè)置音頻類型,在游戲中通常設(shè)置為STREAM_MUSIC]srcQuality[該參數(shù)設(shè)置音頻文件的質(zhì)量,目前還沒有具體的作用,設(shè)置為0(默認(rèn)值)]
public int load(Context context, int resId, int PRiority):架子啊音頻文件:context[該參數(shù)為應(yīng)用程序的上下文]resId[該參數(shù)為要加載的音效資源的ID]priority[優(yōu)先級]
public final int play (int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate):播放音效:soundID[該參數(shù)為要播放的音效ID]leftVolume[用來控制左聲道音量]rightVolume[用來控制右聲道音量]priority[該參數(shù)為優(yōu)先級,0為最低]loop[該參數(shù)為音效的循環(huán)次數(shù),0為不循環(huán),-1為永遠(yuǎn)循環(huán)]rate[該參數(shù)為音效的回放速率,該值在0.5~2.0f,1.0f為正常速度]
public final void pause(int streamID):暫停音效的播放:streamID[要暫停音效的ID]
public final void stop(int streamID):停止播放音效:streamID[要停止播放音效的ID]
實(shí)例:
//初始化聲音池的方法 public void initialsnd() { //初始化SoundPool對象 sp=new SoundPool(4,AudioManager.STREAM_MUSIC,0); //初始化hashMap hm=new HashMap<Integer,Integer>(); //加載音效文件ff,并設(shè)置為1號聲音放入到hm中 hm.put(1,sp.load(this,R.raw.ff,1)); }//音效播放 public void playSound(int sound,int loop) { //獲取AudioManager引用 AudioManager am=(AudioManager)this.getSystemService(Context.AUDIO_SERVICE); //獲取當(dāng)前系統(tǒng)音量 float v1=am.getStreamVolume(AudioManager.STREAM_MUSIC); //獲取系統(tǒng)的最大音量 float v2=am.getStreamMaxVolume(AudioManager.STREAM_MUSIC); //計(jì)算得到播放音量 float v=v1/v2; //調(diào)用SoundPool的play方法播放文件 currentId=sp.play(hm.get(sound),v,v,1,loop,1.0f); }
2.背景音樂播放:
在游戲中,背景音樂可以使用不大于7s的一小節(jié)音樂將SoundPool的loop設(shè)置為-1即可;但在實(shí)際開發(fā)中,背景音效對延時(shí)并不是特別敏感,因此較長音效可以使用MediaPlayer進(jìn)行播放。
2.1MediaPlayer的聲明周期:MediaPlayer的生命周期包括10種狀態(tài),每種狀態(tài)下可以調(diào)用相應(yīng)的方法來實(shí)現(xiàn)音/視頻文件的管理或播放。
<1>Idle狀態(tài):使用new方法創(chuàng)建一個(gè)MediaPlayer對象或者調(diào)用了其reset方法時(shí),該MediaPlayer對象處于idle狀態(tài)。在此狀態(tài)下調(diào)用getDuration等方法,reset方法進(jìn)入idle狀態(tài)的話會(huì)觸發(fā)OnErrorListener.onError,同時(shí)MediaPlayer對象進(jìn)入Error狀態(tài),當(dāng)然new方法不會(huì)。
<2>End狀態(tài):通過release方法可以進(jìn)入End狀態(tài),只要MediaPlayer對象不再被使用,就應(yīng)當(dāng)盡快將其通過release方法釋放掉,以釋放占用的軟、硬件資源,這其中有些資源是互斥的。如果MediaPlayer進(jìn)入到End狀態(tài)就不會(huì)再進(jìn)行其他任何狀態(tài)。
<3>Initialized狀態(tài):MediaPlayer調(diào)用setDataSource方法就進(jìn)入了Initialized狀態(tài),表示此時(shí)要播放的文件已經(jīng)裝備好了。
<4>Prepared狀態(tài):初始化完成之后還需要調(diào)用prepare或prepareAsync方法進(jìn)行準(zhǔn)備,這兩種方法一種是同步的,一種是異步的。只有進(jìn)入了Prepared狀態(tài),才表明MediaPlayer到目前為止都工作正常,可以進(jìn)行音樂文件的播放。
<5>Preparing狀態(tài):主要是與prepareAsync異步準(zhǔn)備方法配合,如果異步準(zhǔn)備完成,會(huì)觸發(fā)OnPreparedListener.onPrepared,進(jìn)而進(jìn)入Prepared狀態(tài)。
<6>Started狀態(tài):MediaPlayer準(zhǔn)備完成之后,通過調(diào)用start方法,將進(jìn)入Started狀態(tài)。所謂Started狀態(tài),也就是播放中的狀態(tài),開發(fā)中可以使用isPlaying方法測試MediaPlayer是否處于Started狀態(tài)。
<7>Paused狀態(tài):Started狀態(tài)下調(diào)用paused方法可以暫停播放,從而進(jìn)入Paused狀態(tài)。暫停狀態(tài)時(shí)可以調(diào)用seekTo方法,這時(shí)此MediaPlayer的狀態(tài)是不變的。
<8>Stop狀態(tài):Started狀態(tài)和Paused狀態(tài)下均可調(diào)用stop方法并進(jìn)入Stop狀態(tài),如果處于Stop狀態(tài)的MediaPlayer要想重新播放,需要通過調(diào)用prepareAsync或prepare方法返回到先前的Prepared狀態(tài)重新開始才可以。
<9>PlaybackCompleted狀態(tài):文件正常播放完畢,而又沒有設(shè)置循環(huán)播放的話就進(jìn)入該狀態(tài),并會(huì)觸發(fā)OnCompletionListener接口中的OnCompletion方法。此時(shí)可以調(diào)用start方法重新從頭開始播放文件呢,也可以調(diào)用stop方法停止播放,或者調(diào)用seekTo方法來重新定位播放位置。
<10>Error狀態(tài):由于某種原因MediaPlayer出現(xiàn)了錯(cuò)誤,就會(huì)觸發(fā)OnErrorListener.onError回調(diào)方法,此時(shí)MediaPlayer將會(huì)進(jìn)入Error狀態(tài)。及時(shí)捕捉并妥善處理這些錯(cuò)誤可以釋放相關(guān)的軟、硬件資源,也可以改善用戶體驗(yàn)。如果MediaPlayer進(jìn)入了Error狀態(tài),可以通過調(diào)用reset方法來恢復(fù),使得MediaPlayer重新返回Idle狀態(tài)。
2.2MediaPlayer類:
首首先需要調(diào)用Activity對象的getSystemService(Context.AUDIO_SERVICE)方法獲取AudioManager對象。然后調(diào)用MediaPlayer類中的相關(guān)方法進(jìn)行音量控制。
public void adjustVolume(int direction, int flags):調(diào)用該方法可以調(diào)節(jié)音量大小。參數(shù)direction為調(diào)節(jié)的方向,ADJUST_LOWER減小音量、ADJUST_RAISE增大音量、ADJUST_SAME保持音量不變;參數(shù)flags為標(biāo)記,通常設(shè)置為0。
public int getStreamMaxVolume(int streamtype):獲取系統(tǒng)最大音量。
public int getStreamVolume(int StreamType):獲取系統(tǒng)當(dāng)前音量。
void android.media.AudioManager.setStreamVolume(int streamType, int index, int flags):調(diào)用該方法可以設(shè)置音量的大小,參數(shù)streamType為聲音的類型,index為要設(shè)置的音頻的索引值,參數(shù)flags為標(biāo)記,通常設(shè)置為AudioManager.FLAG_PLAY_SOUND。
package com.mycompany.myapp;import android.app.*;import android.os.*;import android.view.*;import android.widget.*;import android.media.*;import android.content.*;import android.view.View.*;public class MainActivity extends Activity{ MediaPlayer mp; AudioManager am; private int maxvolume; private int curvolume; private int stpvolume; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mp=new MediaPlayer(); try{ mp.setDataSource("sdcard/kgmusic/download/One T - The Magic Key.mp3"); mp.prepare(); }catch(Exception e){ e.printStackTrace(); } am=(AudioManager)this.getSystemService(Context.AUDIO_SERVICE); maxvolume=am.getStreamMaxVolume(AudioManager.STREAM_MUSIC); stpvolume=maxvolume/6; Button bstart=(Button)this.findViewById(R.id.playbtn); Button bpause=(Button)this.findViewById(R.id.pausebtn); Button bstop=(Button)this.findViewById(R.id.stopbtn); Button bincrease=(Button)this.findViewById(R.id.increasevolumebtn); Button breduce= (Button)this.findViewById(R.id.reducevolumebtn); bstart.setOnClickListener(new OnClickListener(){ public void onClick(View v){ mp.start(); Toast.makeText(getBaseContext(),"開始播放",Toast.LENGTH_LONG).show(); } }); bpause.setOnClickListener(new OnClickListener(){ public void onClick(View v){ mp.pause(); Toast.makeText(getBaseContext(),"暫停播放",Toast.LENGTH_LONG).show(); } }); bstop.setOnClickListener(new OnClickListener(){ public void onClick(View v){ mp.stop(); Toast.makeText(getBaseContext(),"停止播放",Toast.LENGTH_LONG).show(); } }); bincrease.setOnClickListener(new OnClickListener(){ public void onClick(View v){ curvolume=am.getStreamVolume(AudioManager.STREAM_MUSIC); int tmpvolume=curvolume+stpvolume; am.setStreamVolume(AudioManager.STREAM_MUSIC,curvolume,AudioManager.FLAG_PLAY_SOUND); Toast.makeText(getBaseContext(),"音量增加",Toast.LENGTH_LONG).show(); } }); breduce.setOnClickListener(new OnClickListener(){ public void onClick(View v){ curvolume=am.getStreamVolume(AudioManager.STREAM_MUSIC); int tmpvolume=curvolume-stpvolume; curvolume=tmpvolume>0?tmpvolume:0; am.setStreamVolume(AudioManager.STREAM_MUSIC,curvolume,AudioManager.FLAG_PLAY_SOUND); Toast.makeText(getBaseContext(),"音量減小",Toast.LENGTH_LONG); } }); }}
新聞熱點(diǎn)
疑難解答
圖片精選