我使用此标准的SoundManager。它在我所有的设备上都能正常工作,但仅在市场上出现,然后出现这些错误
SoundManager.playSound(SoundManager.java:87)中的
SoundManager.cleanup(SoundManager.java:107)中的
这是代码:
public class SoundManager {
private static SoundManager _instance;
private static SoundPool mSoundPool;
private static HashMap<Integer, Integer> mSoundPoolMap;
private static AudioManager mAudioManager;
private static Context mContext;
private SoundManager(){ }
static synchronized public SoundManager getInstance(){
if (_instance == null)
_instance = new SoundManager();
return _instance;
}
public static void initSounds(Context theContext){
mContext = theContext;
mSoundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 0);
mSoundPoolMap = new HashMap<Integer, Integer>();
mAudioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
}
public static void addSound(int Index,int SoundID){
mSoundPoolMap.put(Index, mSoundPool.load(mContext, SoundID, 1));
}
public static void loadSounds(){
mSoundPoolMap.put(1, mSoundPool.load(mContext, R.raw.kick1, 1));
mSoundPoolMap.put(2, mSoundPool.load(mContext, R.raw.kick2, 1));
mSoundPoolMap.put(3, mSoundPool.load(mContext, R.raw.kick3, 1));
}
public static void playSound(int index, float volume){
**line 87:** float streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
streamVolume = streamVolume / mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
mSoundPool.play(mSoundPoolMap.get(index), streamVolume*volume, streamVolume*volume, 1, 0, 1);
}
public static void stopSound(int index){
mSoundPool.stop(mSoundPoolMap.get(index));
}
public static void cleanup(){
**line 107:** mSoundPool.release();
mSoundPool = null;
mSoundPoolMap.clear();
mAudioManager.unloadSoundEffects();
_instance = null;
}
}
这是在开始 Activity 中进行的清除的调用:
//REMOVE SOUND MEMORY ALLOCATION
@Override
public void onDestroy()
{
super.onDestroy();
SoundManager.cleanup();
}
有谁知道是什么原因导致这些偶发的罕见错误以及如何防止它们发生?这在我使用此SoundManager的所有应用中都发生了。。。甚至一点点推测都可能会有所帮助。
最佳答案
初始化SoundManager时,请使用应用程序上下文。您可能在 Activity 之间移动问题。如果SoundManager的生命周期比您的 Activity 时间长。您甚至可以在应用程序中进行初始化。
public class MyAndroidApp extends Application {
@Override
public void onCreate() {
super.onCreate();
SoundManager.initSounds(this);
}
}
我也同意WarrenFaith的观点。唯一的静态变量应该是_instance和getInstance()。
同样,如果您将声音加载到Application类中,则无需担心同步。
如果有帮助,您可以看一下我使用的代码。它使用了http://code.google.com/p/opensl-soundpool/的OpenSL SoundPool库
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;
import java.util.concurrent.atomic.AtomicBoolean;
import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import com.kytomaki.openslsoundpool.JavaSoundPool;
import com.kytomaki.openslsoundpool.OpenSLSoundPool;
import com.kytomaki.openslsoundpool.SoundPoolIf;
final public class SoundManager
{
// Predetermined sound ID's
public static final int NO_SOUND = -1 ;
public static final int WINNER = -2 ;
// Tag for logging
protected static final String TAG = "SoundManager" ;
/** Used to load and play sounds **/
private Context context ;
/** Sound can be disable from separate thread **/
private final AtomicBoolean useSound ;
// Sound Arrays
private final ArrayList<Integer> winningSounds ;
private final SoundPoolIf soundPool ;
private final HashMap<Integer, Integer> soundPoolMap ;
private final AudioManager audioManager ;
/** Singleton object for sound play back **/
private static SoundManager soundManagerInstance ;
private static final int USE_SOUNDPOOL = 1 ;
private static final int USE_OPENSL = 2 ;
private static int use = USE_SOUNDPOOL ;
/**
* Private Method to create a new SoundManager<br>
* This is a Singleton Object
* @param context Should be the Application Context
*/
private SoundManager( final Context context )
{
setContext( context ) ;
useSound = new AtomicBoolean( true ) ;
audioManager = (AudioManager) context.getSystemService( Context.AUDIO_SERVICE ) ;
soundPoolMap = new HashMap<Integer, Integer>() ;
winningSounds = new ArrayList<Integer>() ;
if ( use == USE_OPENSL )
{
soundPool = new OpenSLSoundPool( 2, OpenSLSoundPool.RATE_44_1, OpenSLSoundPool.FORMAT_16, 1) ;
} else {
soundPool = new JavaSoundPool( 2 ) ;
}
}
/**
* Must be called before using<br>
* Best to initialize in Application Class
* @param context
*/
public static void initSoundManager( final Context context )
{
if ( soundManagerInstance == null )
{
soundManagerInstance = new SoundManager( context ) ;
}
else
{
throw new UnsupportedOperationException( "Sound manager has already been created" ) ;
}
}
/**
* Overloaded method to allow use of OpenSL
* @param context
* @param useOpenSL
*/
public static void initSoundManager( final Context context, final boolean useOpenSL){
if(useOpenSL){
use = USE_OPENSL;
}
initSoundManager(context);
}
/**
* Must initialize first with {@link SoundManager#initSoundManager(Context)}
* @return instance of SoundManager
*/
public static SoundManager getSoundManagerInstance()
{
if ( soundManagerInstance != null )
{
return soundManagerInstance ;
}
else
{
throw new UnsupportedOperationException( "SoundManager must be initalized" ) ;
}
}
/**
* Add a sound from an android resource file R.id.sound<br>
* To be played back with SoundManager.play(soundId)
* @param soundId
* @param soundResourceId
*/
public void addSound( final int soundId, final int soundResourceId )
{
soundPoolMap.put(soundId, soundPool.load(getContext(), soundResourceId));
}
/**
* Adds a winning sound from a resource to be played at random<br>
* Called by SoundManager.play(WINNER)
* @param soundResourceId
*/
public void addWinningSound( final int soundResourceId )
{
winningSounds.add( soundResourceId ) ;
}
/**
* Plays a sound first checking if sound is enabled
* @param soundToPlay soundId or WINNER to play random winning sound
*/
public synchronized void play( final int soundToPlay )
{
if ( isUseSound() )
{
switch ( soundToPlay )
{
case NO_SOUND :
break ;
case WINNER :
// Play a random winning sound using media player
final MediaPlayer mp ;
mp = MediaPlayer.create( getContext(), randomWinnerSound() ) ;
if ( mp != null )
{
mp.seekTo( 0 ) ;
mp.start() ;
}
break ;
default :
playSound( soundToPlay ) ;
break ;
}
}
}
/**
* Calls soundpool.play
* @param soundToPlay
*/
private void playSound( final int soundToPlay )
{
float streamVolume = audioManager.getStreamVolume( AudioManager.STREAM_MUSIC ) ;
streamVolume = streamVolume / audioManager.getStreamMaxVolume( AudioManager.STREAM_MUSIC ) ;
soundPool.play(soundPoolMap.get(soundToPlay), streamVolume);
}
/**
* @return random winning sound position
*/
private int randomWinnerSound()
{
final Random rand = new Random() ;
final int playNumber = rand.nextInt( winningSounds.size() ) ;
return winningSounds.get( playNumber ) ;
}
/**
* @param context the context to set
*/
private final void setContext( final Context context )
{
this.context = context ;
}
/**
* @return the context
*/
private final Context getContext()
{
return context ;
}
/**
* @param useSound false to disable sound
*/
public final void setUseSound( final boolean useSound )
{
this.useSound.set( useSound ) ;
}
/**
* @return the useSound
*/
public boolean isUseSound()
{
return useSound.get() ;
}
}
仍在进行中,但可以完成工作。