編輯:Android開發實例
前言
在Android中播放音頻文件經常會用到MediaPlayer,但是MediaPlayer存在一些不足的地方,如:資源占用量較高、加載延遲時間較長、不支持多個音頻同時播放等。這些缺點決定了MediaPlayer在某些需要密集使用不同音頻的情況不會理想,例如游戲開發。在游戲開發中,我們經常需要播放一些游戲的音效,這些音效的都需要是短促、密集、延遲小的,在這種場景下,需要使用到SoundPool來替代MediaPlayer播放這些音效,本篇就主要講解SoundPool的使用以及需要注意的地方,最後將以一個示例演示SoundPool的使用。
本篇的主要內容:
SoundPool
SoundPool(聲音池),所處於"android.media.SoundPool"包下,主要用於播放一些較短的聲音片段,支持從程序的資源或文件系統加載。與MediaPlayer相比,SoundPool的優勢在於CPU的資源占用量低、反應延遲小,並且可以加載多個音頻到SoundPool中,通過資源ID來管理。另外SoundPool還支持執行設置聲音的品質、音量、播放比率等參數。
SoundPool提供一個構造函數,以下是它的完整簽名:
SoundPool(int maxStreams,int streamType,int srcQuality)
通過上面的構造函數即可完成SoundPool的初始化,第一個參數為音頻池最多支持裝載多少個音頻,就是音頻池的大小;第二個參數指定聲音的類型,在AudioManager類中以常量的形式定義,一般指定為AudioManager.STREAM_MUSIC即可;第三個參數為音頻的質量,默認為0,這個參數為預留參數,現在沒有實際意義,為擴展預留字段,一般傳0即可。
對於一個音頻池,涉及到音頻的加載、播放、暫停、繼續、釋放資源等操作,SoundPool也為我們提供了相應的方法,其底層也是用C++編寫的native方法。以下介紹一些常用的SoundPool方法:
上面方法無疑Load()和play()是最重要的,Load()具有多種重載方法,從參數名就可以看出是什麼意思。這裡講解一下play()方法,soundID參數為資源ID;leftVolume和rightVolume個參數為左右聲道的音量,從大到小取0.0f~1.0f之間的值;priority為音頻質量,暫時沒有實際意義,傳0即可;loop為循環次數,0為播放一次,-1為無線循環,其他正數+1為播放次數,如傳遞3,循環播放4次;rate為播放速率,從大到小取0.0f~2.0f,1.0f為正常速率播放。
在使用load()裝載音頻的時候需要注意,load()方法是一個異步的方法,也就是說,在播放音頻的時候,很可能此段音頻還沒有裝載到音頻池中,這裡可以借助SoundPool的一個裝載完成的監聽事件SoundPool.setOnLoadCompleteListener來保證裝載完成在播放聲音。SoundPool.setOnLoadCompleteListener()需要實現一個SoundPool.OnLoadCompleteListener接口,其中需要實現onLoadComplete()方法,一下是onLoadComplete()方法的完整簽名:
onLoadComplete(SoundPool soundPool, int sampleId, int status)
使用SoundPool示例
上面已經介紹了SoundPool的使用所涉及到的內容,下面通過一個簡單的示例來演示一下SoundPool的使用,播放的音頻資源都是我從其他app中拷貝出來的,沒有實際意義。示例中的注釋寫的比較全,這裡不再累述了。
- package cn.bgxt.soundpooldemo;
- import java.util.HashMap;
- import java.util.Map;
- import android.media.AudioManager;
- import android.media.SoundPool;
- import android.media.SoundPool.OnLoadCompleteListener;
- import android.os.Bundle;
- import android.app.Activity;
- import android.util.Log;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.Toast;
- public class MainActivity extends Activity {
- private Button btn_newqqmsg, btn_newweibontf, btn_newweibotoast;
- private SoundPool pool;
- private Map<String, Integer> poolMap;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- btn_newqqmsg = (Button) findViewById(R.id.btn_newqqmsg);
- btn_newweibontf = (Button) findViewById(R.id.btn_newweibontf);
- btn_newweibotoast = (Button) findViewById(R.id.btn_newweibotoast);
- poolMap = new HashMap<String, Integer>();
- // 實例化SoundPool,大小為3
- pool = new SoundPool(3, AudioManager.STREAM_MUSIC, 0);
- // 裝載音頻進音頻池,並且把ID記錄在Map中
- poolMap.put("newqqmsg", pool.load(this, R.raw.qqmsg, 1));
- poolMap.put("newweibontf", pool.load(this, R.raw.notificationsound, 1));
- poolMap.put("newweibotoast", pool.load(this, R.raw.newblogtoast, 1));
- pool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
- @Override
- public void onLoadComplete(SoundPool soundPool, int sampleId,
- int status) {
- // 每次裝載完成均會回調
- Log.i("main", "音頻池資源id為:" + sampleId + "的資源裝載完成");
- // 當前裝載完成ID為map的最大值,即為最後一次裝載完成
- if (sampleId == poolMap.size()) {
- Toast.makeText(MainActivity.this, "加載聲音池完成!",
- Toast.LENGTH_SHORT).show();
- btn_newqqmsg.setOnClickListener(click);
- btn_newweibontf.setOnClickListener(click);
- btn_newweibotoast.setOnClickListener(click);
- // 進入應用播放四次聲音
- pool.play(poolMap.get("newweibotoast"), 1.0f, 1.0f, 0, 3,
- 1.0f);
- }
- }
- });
- }
- private View.OnClickListener click = new OnClickListener() {
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.btn_newqqmsg:
- if (pool != null) {
- pool.play(poolMap.get("newqqmsg"), 1.0f, 1.0f, 0, 0, 1.0f);
- }
- break;
- case R.id.btn_newweibontf:
- if (pool != null) {
- pool.play(poolMap.get("newweibontf"), 1.0f, 1.0f, 0, 0,
- 1.0f);
- }
- break;
- case R.id.btn_newweibotoast:
- if (pool != null) {
- pool.play(poolMap.get("newweibotoast"), 1.0f, 1.0f, 0, 0,
- 1.0f);
- }
- break;
- default:
- break;
- }
- }
- };
- @Override
- protected void onDestroy() {
- // 銷毀的時候釋放SoundPool資源
- if (pool != null) {
- pool.release();
- pool = null;
- }
- super.onDestroy();
- }
- }
效果展示:
SoundPool使用的注意事項
因為SoundPool的一些設計上的BUG,從固件版本1.0開始就有些沒有修復的,以後應該會慢慢修復。這裡簡單提一下:
源碼下載
總結
本篇介紹了SoundPool的使用,雖然SoundPool還有一些不足的地方,當時對於應用中一些簡短的特效音,如按鍵音、短消息音,或者一些游戲中密集的聲音,如射擊的槍聲,爆破的聲音等。都是可以使用SoundPool的,效率會比使用MediaPlayer要高的多。
實現定時器有很多種方式,在這裡我簡單的介紹幾種方式 (1)使用Handler + Runnable的方式 代碼如下: Handler handler = new
本文實例講述了Android編程實現二級下拉菜單及快速搜索的方法。分享給大家供大家參考,具體如下: 一、我們要做什麼? 上面有個搜索框,下面是一個二級下拉菜單。
Android提供了許多方法來控制播放的音頻/視頻文件和流。其中該方法是通過一類稱為MediaPlayer。Android是提供MediaPlayer類訪問內置的媒體播放
大家好,眾所周知,android裡兩個相同方向的ScrollView是不能嵌套的,那要是有這樣的需求怎麼辦?(這個需求一般都是不懂android的人提出來的)難道