Cyh的博客

          Email:kissyan4916@163.com
          posts - 26, comments - 19, trackbacks - 0, articles - 220

          導航

          公告

          一直努力努力努力,像奴隸奴隸奴隸!~~
          <2025年7月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          常用鏈接

          隨筆檔案(25)

          文章分類(219)

          文章檔案(220)

          新聞檔案(66)

          相冊

          收藏夾(7)

          最新隨筆

          搜索

          •  

          最新評論

          閱讀排行榜

          Android游戲開發之旅(十六) 異步音樂播放

          Posted on 2010-12-03 10:29 啥都寫點 閱讀(695) 評論(0)  編輯  收藏 所屬分類: Android

          在Android游戲開發中我們必須考慮背景音樂播放問題,在Android平臺中提供了MediaPlayer類可以播放聲音,但是游戲除了播放音樂外還需要考慮畫面的流暢性,以及多種音效同時播放,所以必須用到Android多線程機制和異步音效播放。Android SDK從1.0開始就提供了AsyncPlayer類,這里我們為了根據我們自己的需要可以派生或修改出更靈活的播放類。

          view plaincopy to clipboardprint?
          import android.content.Context;  
          import android.net.Uri;  
          import android.os.PowerManager;  
          import android.os.SystemClock;  
          import android.util.Log;  
          import java.io.IOException;  
          import java.lang.IllegalStateException;  
          import java.util.LinkedList;  
             
          public class AsyncPlayer {  
              private static final int PLAY = 1;  
              private static final int STOP = 2;  
              private static final boolean mDebug = false;  
              private static final class Command {  
                  int code;  
                  Context context;  
                  Uri uri;  
                  boolean looping;  
                  int stream;  
                  long requestTime;  
                  public String toString() {  
                      return "{ code=" + code + " looping=" + looping + " stream=" + stream  
                              + " uri=" + uri + " }";  
                  }  
              }  
              private LinkedList<Command> mCmdQueue = new LinkedList();  //用一個鏈表保存播放參數隊列  
              private void startSound(Command cmd) {  
             
                  try {  
                      MediaPlayer player = new MediaPlayer();  
                      player.setAudioStreamType(cmd.stream);  
                      player.setDataSource(cmd.context, cmd.uri);  //設置媒體源,這里Android123提示大家本類的public void play (Context context, Uri uri, boolean looping, int stream) 類第二個參數Uri為媒體位置。  
                      player.setLooping(cmd.looping);  
                      player.prepare();  
                      player.start();  
                      if (mPlayer != null) {  
                          mPlayer.release();  
                      }  
                      mPlayer = player;  
                    }  
                  catch (IOException e) {  
                      Log.w(mTag, "error loading sound for " + cmd.uri, e);  
                  } catch (IllegalStateException e) {  
                      Log.w(mTag, "IllegalStateException (content provider died?) " + cmd.uri, e);  
                  }  
              }  
              private final class Thread extends java.lang.Thread {   //通過多線程方式不阻塞調用者  
                  Thread() {  
                      super("AsyncPlayer-" + mTag);  
                  }  
                  public void run() {  
                      while (true) {  
                          Command cmd = null;  
                          synchronized (mCmdQueue) {   //同步方式執行  
                                  cmd = mCmdQueue.removeFirst();  
                          }  
                          switch (cmd.code) {  
                          case PLAY:  
                                           startSound(cmd);  
                              break;  
                          case STOP:  
             
                              if (mPlayer != null) {  
                                                   mPlayer.stop();  
                                  mPlayer.release();  
                                  mPlayer = null;  
                              } else {  
                                  Log.w(mTag, "STOP command without a player");  
                              }  
                              break;  
                          }  
                          synchronized (mCmdQueue) {  
                              if (mCmdQueue.size() == 0) {  
                       
                                  mThread = null;  
                                  releaseWakeLock();  
                                  return;  
                              }  
                          }  
                      }  
                  }  
              }  
              private String mTag;  
              private Thread mThread;  
              private MediaPlayer mPlayer;  
              private PowerManager.WakeLock mWakeLock;  
             
              private int mState = STOP;  
             
              public AsyncPlayer(String tag) {  
                  if (tag != null) {  
                      mTag = tag;  
                  } else {  
                      mTag = "AsyncPlayer";  
                  }  
              }  
             
              public void play(Context context, Uri uri, boolean looping, int stream) {  
                  Command cmd = new Command();  
                  cmd.requestTime = SystemClock.uptimeMillis(); //這里為了測試性能,傳遞了開始執行前的系統tickcount計時器值  
                  cmd.code = PLAY;  
                  cmd.context = context;  
                  cmd.uri = uri;  
                  cmd.looping = looping;  
                  cmd.stream = stream;  
                  synchronized (mCmdQueue) {  
                      enqueueLocked(cmd);  
                      mState = PLAY;  
                  }  
              }  
               
             
              public void stop() {  
                  synchronized (mCmdQueue) {  
                           if (mState != STOP) {  
                          Command cmd = new Command();  
                          cmd.requestTime = SystemClock.uptimeMillis();  
                          cmd.code = STOP;  
                          enqueueLocked(cmd);  
                          mState = STOP;  
                      }  
                  }  
              }  
              private void enqueueLocked(Command cmd) {  
                  mCmdQueue.add(cmd);  
                  if (mThread == null) {  
                      acquireWakeLock();  
                      mThread = new Thread();  
                      mThread.start();  
                  }  
              } 
          import android.content.Context;
          import android.net.Uri;
          import android.os.PowerManager;
          import android.os.SystemClock;
          import android.util.Log;
          import java.io.IOException;
          import java.lang.IllegalStateException;
          import java.util.LinkedList;
           
          public class AsyncPlayer {
              private static final int PLAY = 1;
              private static final int STOP = 2;
              private static final boolean mDebug = false;
              private static final class Command {
                  int code;
                  Context context;
                  Uri uri;
                  boolean looping;
                  int stream;
                  long requestTime;
                  public String toString() {
                      return "{ code=" + code + " looping=" + looping + " stream=" + stream
                              + " uri=" + uri + " }";
                  }
              }
              private LinkedList<Command> mCmdQueue = new LinkedList();  //用一個鏈表保存播放參數隊列
              private void startSound(Command cmd) {
           
                  try {
                      MediaPlayer player = new MediaPlayer();
                      player.setAudioStreamType(cmd.stream);
                      player.setDataSource(cmd.context, cmd.uri);  //設置媒體源,這里Android123提示大家本類的public void play (Context context, Uri uri, boolean looping, int stream) 類第二個參數Uri為媒體位置。
                      player.setLooping(cmd.looping);
                      player.prepare();
                      player.start();
                      if (mPlayer != null) {
                          mPlayer.release();
                      }
                      mPlayer = player;
                    }
                  catch (IOException e) {
                      Log.w(mTag, "error loading sound for " + cmd.uri, e);
                  } catch (IllegalStateException e) {
                      Log.w(mTag, "IllegalStateException (content provider died?) " + cmd.uri, e);
                  }
              }
              private final class Thread extends java.lang.Thread {   //通過多線程方式不阻塞調用者
                  Thread() {
                      super("AsyncPlayer-" + mTag);
                  }
                  public void run() {
                      while (true) {
                          Command cmd = null;
                          synchronized (mCmdQueue) {   //同步方式執行
                                  cmd = mCmdQueue.removeFirst();
                          }
                          switch (cmd.code) {
                          case PLAY:
                                           startSound(cmd);
                              break;
                          case STOP:
           
                              if (mPlayer != null) {
                                                   mPlayer.stop();
                                  mPlayer.release();
                                  mPlayer = null;
                              } else {
                                  Log.w(mTag, "STOP command without a player");
                              }
                              break;
                          }
                          synchronized (mCmdQueue) {
                              if (mCmdQueue.size() == 0) {
                    
                                  mThread = null;
                                  releaseWakeLock();
                                  return;
                              }
                          }
                      }
                  }
              }
              private String mTag;
              private Thread mThread;
              private MediaPlayer mPlayer;
              private PowerManager.WakeLock mWakeLock;
           
              private int mState = STOP;
           
              public AsyncPlayer(String tag) {
                  if (tag != null) {
                      mTag = tag;
                  } else {
                      mTag = "AsyncPlayer";
                  }
              }
           
              public void play(Context context, Uri uri, boolean looping, int stream) {
                  Command cmd = new Command();
                  cmd.requestTime = SystemClock.uptimeMillis(); //這里為了測試性能,傳遞了開始執行前的系統tickcount計時器值
                  cmd.code = PLAY;
                  cmd.context = context;
                  cmd.uri = uri;
                  cmd.looping = looping;
                  cmd.stream = stream;
                  synchronized (mCmdQueue) {
                      enqueueLocked(cmd);
                      mState = PLAY;
                  }
              }
            
           
              public void stop() {
                  synchronized (mCmdQueue) {
                           if (mState != STOP) {
                          Command cmd = new Command();
                          cmd.requestTime = SystemClock.uptimeMillis();
                          cmd.code = STOP;
                          enqueueLocked(cmd);
                          mState = STOP;
                      }
                  }
              }
              private void enqueueLocked(Command cmd) {
                  mCmdQueue.add(cmd);
                  if (mThread == null) {
                      acquireWakeLock();
                      mThread = new Thread();
                      mThread.start();
                  }
              }

          一般對于Android游戲而言下面的代碼不用考慮,一般用戶都在交互操作,不會出現屏幕鎖問題

          view plaincopy to clipboardprint?
          public void setUsesWakeLock(Context context) {  //電源管理wakelock處理  
                  if (mWakeLock != null || mThread != null) {  
                                throw new RuntimeException("assertion failed mWakeLock=" + mWakeLock  
                              + " mThread=" + mThread);  
                  }  
                  PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);  
                  mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, mTag);  
              }  
              private void acquireWakeLock() {   //加鎖  
                  if (mWakeLock != null) {  
                      mWakeLock.acquire();  
                  }  
              }  
              private void releaseWakeLock() { //解鎖  
                  if (mWakeLock != null) {  
                      mWakeLock.release();  
                  }  
              }  

           

          本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/JavaTiger427/archive/2010/11/25/6034662.aspx



                                                                                                                 --    學海無涯
                  

          主站蜘蛛池模板: 郴州市| 定陶县| 邵阳市| 黑山县| 句容市| 江口县| 金坛市| 石渠县| 桃园市| 时尚| 西乌珠穆沁旗| 宜兰县| 凌源市| 临西县| 诏安县| 鄱阳县| 梨树县| 绥化市| 长兴县| 香河县| 紫云| 西充县| 吉安市| 威海市| 论坛| 名山县| 石台县| 罗平县| 衢州市| 府谷县| 达拉特旗| 丰宁| 渝中区| 辛集市| 北宁市| 响水县| 田东县| 天等县| 夏河县| 麦盖提县| 时尚|