1. 游戏中的即时音效:
在游戏中,根据情况播放的即时音效较为短暂、可以重复、也可以同时播放。由于Android中提供的MediaPlayer会占用大量的系统资源,而且播放时还会进行缓冲,有较大的延时,因此使用MediaPlayer无法实现即时音效的播放。而在Android中专门提供的SoundPool类主要用于管理和播放应用程序中的声音资源,使用该类时首先需要通过该类将声音资源加载到内存中,然后在需要的即时音效的地方播放即可,几乎没有延时现象。【由于SoundPool设计的初衷是用于无延时地播放游戏中的即时音效,因此实际开发中应该只讲长度小于7s的声音资源放进soundPool,否则可能会加载失败或内存占用过大】
SoundPool类:
public SoundPool (int maxSreams, int streamType, int srcQuality):创建SoundPool对象:maxStreams[该参数用于设置最多同时播放多少个音效]streamType[该参数设置音频类型,在游戏中通常设置为STREAM_MUSIC]srcQuality[该参数设置音频文件的质量,目前还没有具体的作用,设置为0(默认值)]
public int load(Context context, int resId, int priority):架子啊音频文件:context[该参数为应用程序的上下文]resId[该参数为要加载的音效资源的ID]priority[优先级]
public final int play (int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate):播放音效:soundID[该参数为要播放的音效ID]leftVolume[用来控制左声道音量]rightVolume[用来控制右声道音量]priority[该参数为优先级,0为最低]loop[该参数为音效的循环次数,0为不循环,-1为永远循环]rate[该参数为音效的回放速率,该值在0.5~2.0f,1.0f为正常速度]
public final void pause(int streamID):暂停音效的播放:streamID[要暂停音效的ID]
public final void stop(int streamID):停止播放音效:streamID[要停止播放音效的ID]
实例:
//初始化声音池的方法
public void initialsnd()
{
//初始化SoundPool对象
sp=new SoundPool(4,AudioManager.STREAM_MUSIC,0);
//初始化hashMap
hm=new HashMap<Integer,Integer>();
//加载音效文件ff,并设置为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);
//获取当前系统音量
float v1=am.getStreamVolume(AudioManager.STREAM_MUSIC);
//获取系统的最大音量
float v2=am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
//计算得到播放音量
float v=v1/v2;
//调用SoundPool的play方法播放文件
currentId=sp.play(hm.get(sound),v,v,1,loop,1.0f);
}
2.背景音乐播放:
在游戏中,背景音乐可以使用不大于7s的一小节音乐将SoundPool的loop设置为-1即可;但在实际开发中,背景音效对延时并不是特别敏感,因此较长音效可以使用MediaPlayer进行播放。
2.1MediaPlayer的声明周期:MediaPlayer的生命周期包括10种状态,每种状态下可以调用相应的方法来实现音/视频文件的管理或播放。
<1>Idle状态:使用new方法创建一个MediaPlayer对象或者调用了其reset方法时,该MediaPlayer对象处于idle状态。在此状态下调用getDuration等方法,reset方法进入idle状态的话会触发OnErrorListener.onError,同时MediaPlayer对象进入Error状态,当然new方法不会。
<2>End状态:通过release方法可以进入End状态,只要MediaPlayer对象不再被使用,就应当尽快将其通过release方法释放掉,以释放占用的软、硬件资源,这其中有些资源是互斥的。如果MediaPlayer进入到End状态就不会再进行其他任何状态。
<3>Initialized状态:MediaPlayer调用setDataSource方法就进入了Initialized状态,表示此时要播放的文件已经装备好了。
<4>Prepared状态:初始化完成之后还需要调用prepare或prepareAsync方法进行准备,这两种方法一种是同步的,一种是异步的。只有进入了Prepared状态,才表明MediaPlayer到目前为止都工作正常,可以进行音乐文件的播放。
<5>Preparing状态:主要是与prepareAsync异步准备方法配合,如果异步准备完成,会触发OnPreparedListener.onPrepared,进而进入Prepared状态。
<6>Started状态:MediaPlayer准备完成之后,通过调用start方法,将进入Started状态。所谓Started状态,也就是播放中的状态,开发中可以使用isPlaying方法测试MediaPlayer是否处于Started状态。
<7>Paused状态:Started状态下调用paused方法可以暂停播放,从而进入Paused状态。暂停状态时可以调用seekTo方法,这时此MediaPlayer的状态是不变的。
<8>Stop状态:Started状态和Paused状态下均可调用stop方法并进入Stop状态,如果处于Stop状态的MediaPlayer要想重新播放,需要通过调用prepareAsync或prepare方法返回到先前的Prepared状态重新开始才可以。
<9>PlaybackCompleted状态:文件正常播放完毕,而又没有设置循环播放的话就进入该状态,并会触发OnCompletionListener接口中的OnCompletion方法。此时可以调用start方法重新从头开始播放文件呢,也可以调用stop方法停止播放,或者调用seekTo方法来重新定位播放位置。
<10>Error状态:由于某种原因MediaPlayer出现了错误,就会触发OnErrorListener.onError回调方法,此时MediaPlayer将会进入Error状态。及时捕捉并妥善处理这些错误可以释放相关的软、硬件资源,也可以改善用户体验。如果MediaPlayer进入了Error状态,可以通过调用reset方法来恢复,使得MediaPlayer重新返回Idle状态。
2.2MediaPlayer类:
首首先需要调用Activity对象的getSystemService(Context.AUDIO_SERVICE)方法获取AudioManager对象。然后调用MediaPlayer类中的相关方法进行音量控制。
public void adjustVolume(int direction, int flags):调用该方法可以调节音量大小。参数direction为调节的方向,ADJUST_LOWER减小音量、ADJUST_RAISE增大音量、ADJUST_SAME保持音量不变;参数flags为标记,通常设置为0。
public int getStreamMaxVolume(int streamtype):获取系统最大音量。
public int getStreamVolume(int StreamType):获取系统当前音量。
void android.media.AudioManager.setStreamVolume(int streamType, int index, int flags):调用该方法可以设置音量的大小,参数streamType为声音的类型,index为要设置的音频的索引值,参数flags为标记,通常设置为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); } }); } }