android soundpool堆大小溢出

标签 android overflow soundpool

我在 Debug 中运行时出现数百次此错误,它似乎不影响程序,但我如何摆脱它?

根据其他帖子我知道可以追溯到SoundPool

09-15 09:03:09.190:错误/AudioCache(34):堆大小溢出!请求大小:1052672,最大大小:1048576

最佳答案

SoundPool 将所有加载文件的缓冲区大小硬编码为 1M。因此,当您将太多文件加载到 SoundPool 中时,您可能会遇到“堆大小溢出”错误。我在将游戏声音 FX 加载到 SoundPool 的游戏项目中也遇到了这个问题,解决方案如下:

  1. 在 MediaPlayer 中播放长/大背景音乐。
  2. 在多个 SoundPool 实例中播放短声音文件以防止堆错误。多 SoundPools 的示例代码:


 /**
  * Multi SoundPool to prevent memory error.
  */
public class SoundPools {<p></p>

  private static final String TAG = "SoundPools";

  private static final int MAX_STREAMS_PER_POOL = 15;

  private List<SoundPoolContainer> containers;

  public SoundPools() {
    containers = Collections.synchronizedList(new ArrayList<SoundPoolContainer>());
  }

  public void loadSound(Context context, String id, String file) {
    Log.d(TAG, "SouldPools load sound " + file);
    try {
      for (SoundPoolContainer container : containers) {
        if (container.contains(id)) {
          return;
        }
      }
      for (SoundPoolContainer container : containers) {
        if (!container.isFull()) {
          container.load(context, id, file);
          return;
        }
      }
      SoundPoolContainer container = new SoundPoolContainer();
      containers.add(container);
      container.load(context, id, file);
    } catch (Exception e) {
      Log.w(TAG, "Load sound error", e);
    }
  }

  public void playSound(Context context, String id, String file) {
    Log.d(TAG, "SouldPools play sound " + file);
    try {
      for (SoundPoolContainer container : containers) {
        if (container.contains(id)) {
          container.play(context, id, file);
          return;
        }
      }
      for (SoundPoolContainer container : containers) {
        if (!container.isFull()) {
          container.play(context, id, file);
          return;
        }
      }
      SoundPoolContainer container = new SoundPoolContainer();
      containers.add(container);

      container.play(context, id, file);
    } catch (Exception e) {
      Log.w(TAG, "Play sound error", e);
    }
  }

  public void onPause() {
    for (SoundPoolContainer container : containers) {
      container.onPause();
    }
  }

  public void onResume() {
    for (SoundPoolContainer container : containers) {
      container.onResume();
    }
  }

  private static class SoundPoolContainer {
    SoundPool soundPool;
    Map<String, Integer> soundMap;
    AtomicInteger size;

    public SoundPoolContainer() {
      this.soundPool = new SoundPool(MAX_STREAMS_PER_POOL, android.media.AudioManager.STREAM_MUSIC, 0);
      this.soundMap = new ConcurrentHashMap<String, Integer>(MAX_STREAMS_PER_POOL);
      this.size = new AtomicInteger(0);
    }

    public void load(Context context, String id, String file) {
      try {
        this.size.incrementAndGet();
        soundMap.put(id, soundPool.load(context.getAssets().openFd(file), 1));
      } catch (Exception e) {
        this.size.decrementAndGet();
        Log.w(TAG, "Load sound error", e);
      }
    }

    public void play(Context context, String id, String file) {
      android.media.AudioManager audioManager = (android.media.AudioManager) context
          .getSystemService(Context.AUDIO_SERVICE);
      final int streamVolume = audioManager.getStreamVolume(android.media.AudioManager.STREAM_MUSIC);
      Integer soundId = soundMap.get(id);
      if (soundId == null) {
        soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
          @Override
          public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
            soundPool.play(sampleId, streamVolume, streamVolume, 1, 0, 1f);
          }
        });
        try {
          this.size.incrementAndGet();
          soundPool.load(context.getAssets().openFd(file), 1);
        } catch (IOException e) {
          this.size.decrementAndGet();
          Log.w(TAG, "Load/Play sound error", e);
        }
      } else {
        try {
          soundPool.play(soundId, streamVolume, streamVolume, 1, 0, 1f);
        } catch (Exception e) {
          Log.w(TAG, "Play sound error", e);
        }
      }
    }

    public boolean contains(String id) {
      return soundMap.containsKey(id);
    }

    public boolean isFull() {
      return this.size.get() >= MAX_STREAMS_PER_POOL;
    }

    public void onPause() {
      try {
        soundPool.autoPause();
      } catch (Exception e) {
        Log.w(TAG, "Pause SoundPool error", e);
      }
    }

    public void onResume() {
      try {
        soundPool.autoResume();
      } catch (Exception e) {
        Log.w(TAG, "Resume SoundPool error", e);
      }
    }
  }

}

关于android soundpool堆大小溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7428448/

相关文章:

android - 线性布局如何获得焦点?

java - 在 volley 中发送 int 和 String 作为参数

css - 如何将垂直滚动条添加到 div 的一部分,同时保持两个滚动条控件可见?

C# 创建缓冲区溢出

android - Android:播放心率BPM声音

java - StrictMode Activity 实例计数违规(2 个实例,1 个预期)在完全空 Activity 轮换时

java - Android 主页按钮箭头方向

html - 在元素两侧均匀分布溢出文本

android - 如何在 Java 中以编程方式禁用有线耳机

android - 应用程序加载后立即启动音频 Android 应用程序