I'm receiving a null reference when I try to play a sound through my Android chat app. Every time a smile appears in the protocol string, I want to play an audio sound. My sound files are in OGG format and are located in res->raw->mysound.ogg.
I have the following SoundManager class in my Android class:
package chatclient.utility;
import java.util.HashMap;
import android.content.Context;
import android.media.AudioManager;
import android.media.SoundPool;
public class SoundManager {
private SoundPool mSoundPool;
private HashMap<Integer, Integer> mSoundPoolMap;
private AudioManager mAudioManager;
private Context mContext;
public SoundManager()
{
}
public 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 void addSound(int Index,int SoundID)
{
mSoundPoolMap.put(1, mSoundPool.load(mContext, SoundID, 1));
}
public void playSound(int index) {
int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
mSoundPool.play(mSoundPoolMap.get(index), streamVolume, streamVolume, 1, 0, 1f);
}
public void playLoopedSound(int index) {
int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
mSoundPool.play(mSoundPoolMap.get(index), streamVolume, streamVolume, 1, -1, 1f);
}
}
And here is my code in my main class to call it:
In my onCreate:
mSoundManager = new chatclient.utility.SoundManager();
mSoundManager.initSounds(getBaseContext());
mSoundManager.addSound(1, R.raw.bigsmilesmiley ); //:D
mSoundManager.addSound(2, R.raw.smilesmiley ); //:)
mSoundManager.addSound(3, R.raw.tonguesmiley ); //:P
mSoundManager.addSound(4, R.raw.confusedsmiley ); //:S
mSoundManager.addSound(5, R.raw.ofacesmiley ); //:O
mSoundManager.addSound(6, R.raw.sadsmiley); //:(
And then to call it:
if (pollServerResult.contains(":)")) {
mSoundManager.playSound(2);
} else if (pollServerResult.contains(":D)")) {
mSoundManager.playSound(1);
} else if (pollServerResult.contains(":P")) {
mSoundManager.playSound(3);
} else if (pollServerResult.contains(":S")) {
mSoundManager.playSound(4);
} else if (pollServerResult.contains(":O")) {
mSoundManager.playSound(5);
} else if (pollServerResult.contains(":(")) {
mSoundManager.playSound(6);
}
The only problem is I get a null reference when someone posts one of these faces.
Change this:
public void addSound(int Index,int SoundID) {
mSoundPoolMap.put(1, mSoundPool.load(mContext, SoundID, 1));
}
With this :
public void addSound(int Index,int SoundID) {
mSoundPoolMap.put(Index, mSoundPool.load(mContext, SoundID, 1));
}
Related
I am trying to figure out how to load a variety of sounds in an app. I have my soundmanager working smoothly, shown below:
package com.beeseries.contextclues;
import java.util.HashMap;
import android.content.Context;
import android.media.AudioManager;
import android.media.SoundPool;
public class SoundManager {
private SoundPool mSoundPool;
private HashMap mSoundPoolMap;
private AudioManager mAudioManager;
private Context mContext;
public void initSounds(Context theContext) {
mContext = theContext;
mSoundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
mSoundPoolMap = new HashMap();
mAudioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
}
public void addSound(int index, int SoundID)
{
mSoundPoolMap.put(index, mSoundPool.load(mContext, SoundID, 1));
}
public void loadWritingSounds(){
mSoundPoolMap.put(0, mSoundPool.load(mContext, R.raw.writing1, 1));
mSoundPoolMap.put(1, mSoundPool.load(mContext, R.raw.writing2, 1));
mSoundPoolMap.put(2, mSoundPool.load(mContext, R.raw.writing3, 1));
mSoundPoolMap.put(3, mSoundPool.load(mContext, R.raw.writing4, 1));
mSoundPoolMap.put(4, mSoundPool.load(mContext, R.raw.writing5, 1));
}
public void playSound(int index)
{
float streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
streamVolume = streamVolume / mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
mSoundPool.play((Integer) mSoundPoolMap.get(index), streamVolume, streamVolume, 1, 0, 1f);
}
public void playLoopedSound(int index)
{
float streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
streamVolume = streamVolume / mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
mSoundPool.play((Integer) mSoundPoolMap.get(index), streamVolume, streamVolume, 1, -1, 1f);
}
}
My opening activity for my app contains the following snippets of code to make the sounds work:
public SoundManager mSoundManager;
mSoundManager = new SoundManager();
mSoundManager.initSounds(getBaseContext());
mSoundManager.loadWritingSounds();
And the following code to play a random sound (WHICH DOES WORK, BUT ONLY ON THE OPENING ACTIVITY):
int b = randSound1.nextInt((whichSound.length));
mSoundManager.playSound(b);
So my dilemma is that I need to be able to load the WritingSounds for ALL activities at once, because right now, if I try to play a sound on another activity, it won't work unless I add the snippets of code to make the soundmanager work.
What do I do!?
I am working on making a metronome that slowing speeds up as it runs and I need help with the sendMessageDelayed function.
First, I tried the Thread.sleep() But is was too laggy. I later I read there that it "Does not return until at least the specified number of milliseconds has elapsed".
Next, I read-about/tried using if statements with the SystemClock.elapsedRealtime() such as:
long nextbeep = SystemClock.elapsedRealtime() + waitms;
while(nextbeep > SystemClock.elapsedRealtime()){
//wait
}//end while
mpbeep.start();
but it made the CPU run too hard and the beep was uneven.
Edit: this is what worked for me:
bstart.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
textviewone.setText("start");
beepandwait();
}// void onClick
});// end b start listener
public void beepandwait() {
mSoundManager.playSound(soundnumber); //beep
mHandler.sendMessageDelayed(mHandler.obtainMessage(1), currentms); //wait
}//end beep and wait
private Handler mHandler = new Handler() {
public void handleMessage(Message m) {
beepandwait(); //and repeat
}//end handleMessage
};//Handler
Here is how to make sounds without lagging the system:
package com.bgryderclock.example;
import java.util.HashMap;
import android.content.Context;
import android.media.AudioManager;
import android.media.SoundPool;
public class SoundManager {
private SoundPool mSoundPool;
private HashMap<Integer, Integer> mSoundPoolMap;
private AudioManager mAudioManager;
private Context mContext;
public SoundManager()
{
}
public 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 void addSound(int Index,int SoundID)
{
mSoundPoolMap.put(Index, mSoundPool.load(mContext, SoundID, 1));
}
public void playSound(int index) {
int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
mSoundPool.play(mSoundPoolMap.get(index), streamVolume, streamVolume, 1, 0, 1f);
}
public void playLoopedSound(int index) {
int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
mSoundPool.play(mSoundPoolMap.get(index), streamVolume, streamVolume, 1, -1, 1f);
}
}
I am developing a memory game, in which I want to play background music while starting the game.
I used sound pool class and successfully executed it, but I have problem in playing. I added .mp3 audio file of two minutes, but it's playing only for 15 seconds more.
Can anyone say what problem I have? This is my soundclass file:
public class Soundclass {
private SoundPool soundpool;
private HashMap<Integer, Integer> soundpoolmap;
private AudioManager audiomanager;
private Context context;
public void initSounds(Context thecontext) {
context = thecontext;
soundpool = new SoundPool(4, AudioManager.STREAM_MUSIC, 100);
soundpoolmap = new HashMap<Integer, Integer>();
audiomanager = (AudioManager) context
.getSystemService(Context.AUDIO_SERVICE);
}
public Soundclass() {
}
public void addSound(int Index, int soundID) {
soundpoolmap.put(Index, soundpool.load(context, soundID, 1));
}
public void playSound(int Index) {
float streamVolume = audiomanager
.getStreamVolume(AudioManager.STREAM_MUSIC);
streamVolume = streamVolume
/ audiomanager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
soundpool.play(soundpoolmap.get(Index), streamVolume, streamVolume, 1,
0, 1f);
}
public void playLoopedSound(int Index) {
float streamVolume = audiomanager
.getStreamVolume(AudioManager.STREAM_MUSIC);
streamVolume = streamVolume
/ audiomanager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
soundpool.play(soundpoolmap.get(Index), streamVolume, streamVolume, 1,
-1, 1f);
}
}
and i used this class for given activitycalss .in oncreate function
Button btn = (Button) findViewById(R.id.sound);
soundclass = new Soundclass();
soundclass.initSounds(getBaseContext());
soundclass.addSound(1, R.raw.jinglebells);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
soundclass.playSound(1);
}
});
Soundpool is not meant to be used for background music. It has many limitations such as file size loading and playing time. It's mainly used for sound effects.
Use the MediaPlayer class for background music.
I use sound pool to play a sound when a user presses a button. After a number of button presses the app force closes. The sound that is playing is only a few seconds long. Is there a better way to implement audio?
I use this class:
public class SoundManager {
private SoundPool mSoundPool;
private HashMap<Integer, Integer> mSoundPoolMap;
private AudioManager mAudioManager;
private Context mContext;
public SoundManager()
{
}
public void initSounds(Context theContext) {
mContext = theContext;
mSoundPool = new SoundPool(200, AudioManager.STREAM_MUSIC, 0);
mSoundPoolMap = new HashMap<Integer, Integer>();
mAudioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
}
public void addSound(int Index,int SoundID)
{
mSoundPoolMap.put(Index, mSoundPool.load(mContext, SoundID, 1));
}
public void playSound(int index) {
int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
mSoundPool.play(mSoundPoolMap.get(index), streamVolume, streamVolume, 1, 0, 1f);
}
public void playLoopedSound(int index) {
int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
mSoundPool.play(mSoundPoolMap.get(index), streamVolume, streamVolume, 1, -1, 1f);
}
public void clear(){
mSoundPoolMap.clear();
mSoundPool.release();
}
}
It seems you are trying to play sound before it is loaded. SoundPool.load method is not synchronous. So if you call
addSound(...);
playSound(..);
You will get 100% crash in runtime.
You should invoke play() only after onLoadComplete is called:
public void addSound(int index, int soundResId) {
soundPool.setOnLoadCompleteListener((sp, sampleId, status) -> {
if (status == 1) {
mSoundPoolMap.put(index, sampleId);
}
});
soundPool.load(context, soundResId, 1);
}
I am unable to use the following code to play multiple sounds/beeps simultaneously. In my onclicklistener I have added:
public void onClick(View v) {
mSoundManager.playSound(1);
mSoundManager.playSound(2);
}
But this plays only one sound at a time, sound with index 1 followed by sound with index 2.
How can I play at least 2 sounds simultaneously using this code whenever there is an onClick() event?
public class SoundManager {
private SoundPool mSoundPool;
private HashMap<Integer, Integer> mSoundPoolMap;
private AudioManager mAudioManager;
private Context mContext;
public SoundManager() {
}
public 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 void addSound(int Index,int SoundID) {
mSoundPoolMap.put(1, mSoundPool.load(mContext, SoundID, 1));
}
public void playSound(int index) {
int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
mSoundPool.play(mSoundPoolMap.get(index), streamVolume, streamVolume, 1, 0, 1f);
}
public void playLoopedSound(int index) {
int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
mSoundPool.play(mSoundPoolMap.get(index), streamVolume, streamVolume, 1, -1, 1f);
}
}
Having the following class to play sound fx using sound pool:
public class SoundManager {
public static int SOUNDPOOLSND_MENU_BTN = 0;
public static int SOUNDPOOLSND_WIN = 1;
public static int SOUNDPOOLSND_LOOSE = 2;
public static int SOUNDPOOLSND_DRAW = 3;
public static int SOUNDPOOLSND_TICK1 = 4;
public static int SOUNDPOOLSND_TICK2 = 5;
public static int SOUNDPOOLSND_OUT_OF_TIME = 6;
public static int SOUNDPOOLSND_HISCORE = 7;
public static int SOUNDPOOLSND_CORRECT_LETTER = 8;
public static boolean isSoundTurnedOff;
private static SoundManager mSoundManager;
private SoundPool mSoundPool;
private SparseArray <Integer> mSoundPoolMap;
private AudioManager mAudioManager;
public static final int maxSounds = 4;
public static SoundManager getInstance(Context context)
{
if (mSoundManager == null){
mSoundManager = new SoundManager(context);
}
return mSoundManager;
}
public SoundManager(Context mContext)
{
mAudioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
mSoundPool = new SoundPool(maxSounds, AudioManager.STREAM_MUSIC, 0);
// mSoundPool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
// public void onLoadComplete(SoundPool soundPool, int sampleId,int status) {
// loaded = true;
// }
// });
mSoundPoolMap = new SparseArray<Integer>();
mSoundPoolMap.put(SOUNDPOOLSND_MENU_BTN, mSoundPool.load(mContext, R.raw.menubutton, 1));
mSoundPoolMap.put(SOUNDPOOLSND_WIN, mSoundPool.load(mContext, R.raw.win, 1));
mSoundPoolMap.put(SOUNDPOOLSND_LOOSE, mSoundPool.load(mContext, R.raw.lose, 1));
mSoundPoolMap.put(SOUNDPOOLSND_TICK1, mSoundPool.load(mContext, R.raw.tick_0, 1));
mSoundPoolMap.put(SOUNDPOOLSND_TICK2, mSoundPool.load(mContext, R.raw.tick_1, 1));
mSoundPoolMap.put(SOUNDPOOLSND_OUT_OF_TIME, mSoundPool.load(mContext, R.raw.out_of_time, 1));
mSoundPoolMap.put(SOUNDPOOLSND_HISCORE, mSoundPool.load(mContext, R.raw.personal_highscore, 1));
mSoundPoolMap.put(SOUNDPOOLSND_CORRECT_LETTER, mSoundPool.load(mContext, R.raw.correct_letter, 1));
// testing simultaneous playing
int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
mSoundPool.play(mSoundPoolMap.get(0), streamVolume, streamVolume, 1, 20, 1f);
mSoundPool.play(mSoundPoolMap.get(1), streamVolume, streamVolume, 1, 2, 1f);
mSoundPool.play(mSoundPoolMap.get(2), streamVolume, streamVolume, 1, 0, 1f);
}
public void playSound(int index) {
if (isSoundTurnedOff)
return;
int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
mSoundPool.play(mSoundPoolMap.get(index), streamVolume, streamVolume, 1, 0, 1f);
}
public static void clear()
{
if (mSoundManager != null){
mSoundManager.mSoundPool = null;
mSoundManager.mAudioManager = null;
mSoundManager.mSoundPoolMap = null;
}
mSoundManager = null;
}
}
it DOES play simultaneously 3 sounds mentioned below the comment "testing simultaneous playing". It seems like you need to implement commented in my code listener (OnLoadCompleteListener). It could happen that system just didn't load sounds atm you start playing it. If you dont want to implement mentioned listener try to wait some time after your playing sounds activity started and start playing sounds after a while.