I am new to Android stuff and hope you could help me.
I try to make a little music application.
The application has to do somthing like this:
When the user presses the play button, an audio file, lets call it "mainFile", has to be played in loop.
While the "mainFile" plays and the user presses the fillin button, another audio file, called "fillinFile",
has to be started immediately after the last loop ended.
Therefore I use the "LoopMediaPlayer" from Not able to achieve Gapless audio looping so far on Android
Actually it works fine.
My problem:
If I press the fillin button, the app loops the "mainFile" twice before the "fillinFile" starts playing.
Here is my code:
public class SoundsFragment extends Fragment implements View.OnClickListener {
public static String TAG = "PLAYER";
private XButton fillIn;
private XButton stop;
private XButton play;
private LoopMediaPlayer mediaPlayerMain;
private LoopMediaPlayer mediaPlayerFillIn;
private Taal playingTaal;
View view;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.sounds, container, false);
bindButtons();
return view;
}
#Override
public void onClick(View v) {
//stop();
XButton button = (XButton) v;
switch (button.getId()) {
case R.id.fillin:
playFillIn();
break;
case R.id.play:
playMain();
break;
default:
}
}
private void playMain() {
mediaPlayerMain = LoopMediaPlayer.create(getContext(), R.raw.d_vb_01, R.raw.d_vb_01_var);
}
private void playFillIn() {
mediaPlayerMain.setStartedFollowers(true);
}
private void bindButtons() {
fillIn = (XButton) view.findViewById(R.id.fillin);
stop = (XButton) view.findViewById(R.id.stop);
play = (XButton) view.findViewById(R.id.play);
fillIn.setOnClickListener(this);
stop.setOnClickListener(this);
play.setOnClickListener(this);
}
}
public class LoopMediaPlayer {
public static final String TAG = LoopMediaPlayer.class.getSimpleName();
private Context mContext = null;
private int mFollowersResId= 0;
private int mCounter = 1;
private MediaPlayer mCurrentPlayer = null;
private MediaPlayer mNextPlayer = null;
private boolean mStartedFollowers = false;
private boolean mStartedMain = false;
private int mResId = 0;
public static LoopMediaPlayer create(Context context, int mainResId, int followersResId) {
return new LoopMediaPlayer(context, mainResId, followersResId);
}
private LoopMediaPlayer(Context context, int mainResId, int followersResId) {
mContext = context;
mResId = mainResId;
mFollowersResId = followersResId;
mCurrentPlayer = MediaPlayer.create(mContext, mResId);
mCurrentPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
mCurrentPlayer.start();
}
});
createNextMediaPlayer(mResId);
}
private void createNextMediaPlayer(int id) {
mNextPlayer = MediaPlayer.create(mContext, id);
mCurrentPlayer.setNextMediaPlayer(mNextPlayer);
mCurrentPlayer.setOnCompletionListener(onCompletionListener);
}
private MediaPlayer.OnCompletionListener onCompletionListener = new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
if(mStartedFollowers){
mResId = mFollowersResId;
}
mCurrentPlayer = mNextPlayer;
createNextMediaPlayer(mResId);
mediaPlayer.release();
}
};
public void setStartedFollowers(boolean started){
mStartedFollowers = started;
}
}
try by removing this createNextMediaPlayer(mResId); in private LoopMediaPlayer() constructor
Related
I'm building app which make tic sound on clicking the button. But the sound stops after clicking 14 time. The code is here:
dTextVeiw.setOnClickListener(new View.onClickListener() {
#Override
public void onClick(View view){
MediaPlayer mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.tic_sound);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.start();
}
});
No need to initialise it every time you click the button.
private MediaPlayer _mediaPlayer;
#Override
protected void onResume()
{
super.onResume();
_mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.tic_sound);
_mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
#Override
protected void onCreate(#Nullable Bundle savedInstanceState)
{
//...
dTextVeiw.setOnClickListener(new View.onClickListener() {
#Override
public void onClick(View view) {
_mediaPlayer.start();
}
});
}
For short sounds i would recommend using SoundPool
Class SoundPlayer(){
private final static float leftVol = 1.0f;
private final static float rightVol = 1.0f;
private final static float rate = 1.0f;
private final static int loop = 0;
private int priority = 1;
private int audioId = = -1;
AudioAttributes attributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
SoundPool soundPool= new SoundPool.Builder()
.setMaxStreams(2)
.setAudioAttributes(attributes)
.build();
public void loadSounds(Context context){
audioId = soundPool.load(context, R.raw.tic_sound, priority);
}
public void playAudio() {
soundPool.play(audioId, leftVol, rightVol, priority, loop, rate) ;
}
}
And use it like this
private SoundPlayer soundPlayer;
....
....
onCreate ...{
soundPlayer = SoundPlayer();
soundPLayer.loadSounds(this);
dTextVeiw.setOnClickListener(new View.onClickListener() {
#Override
public void onClick(View view){
soundPLayer.playAudio();
}
I tried creating an app that allow users watch live stream videos on their android device. From my lil research I found out VLC Sdk is cool because it support more protocols. From the code gotten from Tutorial on using vlc sdk
I was able to make the live watching app works, but the issue is I can't seem to add a control (such as pause, play, seeker etc) to the video. Please I need you help. Thanks
vlc sdk used is 1.9.8
Try this:
public class Show_Array extends AppCompatActivity implements IVLCVout.Callback {
private TextView container_extension;
private String stream_typee,stream_idd,container_extensionn ;
private String SAMPLE_URL = "";
public int mHeight;
public int mWidth;
private SurfaceView mVideoSurface = null;
private FrameLayout sdk;
private IVLCVout vlcVout;
private LibVLC mLibVlc = null;
private MediaPlayer mMediaPlayer = null;
private int flag = 0;
private ImageButton Resize;
private Media media;
private ArrayList<String> args;
private SurfaceHolder mSurfaceHolderVideo;
private MediaController controller;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.show__array);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
//Referances
Resize = findViewById(R.id.Resize);
mVideoSurface = findViewById(R.id.video_surface);
stream_typee = getIntent().getExtras().getString("stream_type");
stream_idd = getIntent().getExtras().getString("stream_id");
container_extensionn = getIntent().getExtras().getString("container_extension");
args = new ArrayList<>();
args.add("-vvv");
mLibVlc = new LibVLC(this, args);
mMediaPlayer = new MediaPlayer(mLibVlc);
vlcVout = mMediaPlayer.getVLCVout();
sdk = findViewById(R.id.sdk);
Resize_video();
setup_url();
controller = new MediaController(this);
controller.setMediaPlayer(playerInterface);
controller.setAnchorView(mVideoSurface);
mVideoSurface.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
controller.show(10000);
}
});
}
#Override
protected void onDestroy() {
super.onDestroy();
mMediaPlayer.release();
mLibVlc.release();
}
void Resize_video()
{
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
mHeight = displayMetrics.heightPixels;
mWidth = displayMetrics.widthPixels;
Resize.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
flag+=1;
int width = 1000;
int height = 560;
if(flag%2!=0) {
LinearLayout.LayoutParams myImageLayout = new LinearLayout.LayoutParams(width, height);
myImageLayout.gravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL;
sdk.setLayoutParams(myImageLayout);
vlcVout.setWindowSize(width,height);
}
else
{
LinearLayout.LayoutParams myImageLayout = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
myImageLayout.gravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL;
sdk.setLayoutParams(myImageLayout);
vlcVout.setWindowSize(mWidth,mHeight);
}
}
});
}
void setup_url()
{
//TextView
container_extension = findViewById(R.id.URL);
if (stream_typee.equals("live"))
{
SAMPLE_URL = "http://uautv.ru:2095/"+stream_typee+"/webserver/6tE#BzW73#sX/"+stream_idd+".ts";
container_extension.setText( SAMPLE_URL);
}else
{
SAMPLE_URL = "http://uautv.ru:2095/"+stream_typee+"/webserver/6tE#BzW73#sX/"+stream_idd+"."+container_extensionn;
container_extension.setText( SAMPLE_URL);
}
}
#Override
protected void onStart() {
super.onStart();
vlcVout.setWindowSize(mWidth,mHeight);
vlcVout.setVideoView(mVideoSurface);
vlcVout.attachViews();
mMediaPlayer.getVLCVout().addCallback(this);
if(!SAMPLE_URL.isEmpty()) {
media = new Media(mLibVlc, Uri.parse(SAMPLE_URL));
mMediaPlayer.setMedia(media);
media.release();
mMediaPlayer.play();
}else
{
Toast.makeText(getApplicationContext(),"URL EMPTY",Toast.LENGTH_LONG).show();
}
}
#Override
protected void onStop() {
super.onStop();
mMediaPlayer.stop();
mMediaPlayer.getVLCVout().detachViews();
mMediaPlayer.getVLCVout().removeCallback(this);
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
#Override
public void onNewLayout(IVLCVout vlcVout, int width, int height, int visibleWidth, int visibleHeight, int sarNum, int sarDen)
{ }
#Override
public void onSurfacesCreated(IVLCVout vlcVout) {
}
#Override
public void onSurfacesDestroyed(IVLCVout vlcVout) {
}
private MediaController.MediaPlayerControl playerInterface = new MediaController.MediaPlayerControl() {
public int getBufferPercentage() {
return 0;
}
public int getCurrentPosition() {
float pos = mMediaPlayer.getPosition();
return (int)(pos * getDuration());
}
public int getDuration() {
return (int)mMediaPlayer.getLength();
}
public boolean isPlaying() {
return mMediaPlayer.isPlaying();
}
public void pause() {
mMediaPlayer.pause();
}
public void seekTo(int pos) {
mMediaPlayer.setPosition((float)pos / getDuration());
}
public void start() {
mMediaPlayer.play();
}
public boolean canPause() {
return true;
}
public boolean canSeekBackward() {
return true;
}
public boolean canSeekForward() {
return true;
}
#Override
public int getAudioSessionId() {
return 0;
}
};
}
I was looking into this as well. You need to implement this yourself.
Simply use FrameLayout and overlay a view ( button? ) per functionality on the video surface.
Then make calls to the VLC MediaPlayer play() stop() pause() etc.
If you really want to dive deep then get the sources of the master, and see how it's done:
git clone https://code.videolan.org/videolan/vlc-android.git
In my app, I am using media player class. I want to update the progress of playing audio file on seek bar and for this I am using below code for playing media file
public class AudioPlayer implements MediaPlayer.OnCompletionListener {
private final static int SAMPLE_RATE = 16000;
private final int DELAY_FOR_HANDLER = 1_000;
static final String LOG_TAG = AudioPlayer.class.getSimpleName();
private Context mContext;
private MediaPlayer mPlayer;
private AudioTrack mProgressTone;
private MediaPlayerStatusCallbacks mMediaPlayerStatusCallBacks;
private Handler mHandler;
private PlayerUpdater mPlayerUpdater;
private SeekBar mSeekBar;
public AudioPlayer(SeekBar seekBar, Context context, MediaPlayerStatusCallbacks mediaPlayerStatusCallbacks) {
mPlayer = new MediaPlayer();
mPlayer.setOnCompletionListener(this);
mMediaPlayerStatusCallBacks = mediaPlayerStatusCallbacks;
mHandler = new Handler();
mContext = context;
mSeekBar = seekBar;
}
private void startSendingProgress() {
mPlayerUpdater = new PlayerUpdater();
((MessagingActivity) mContext).runOnUiThread(mPlayerUpdater);
}
private class PlayerUpdater implements Runnable {
#Override
public void run() {
if(mPlayer != null){
int currentProgress = mPlayer.getCurrentPosition() / 1000;
mSeekBar.setProgress(currentProgress);
}
mHandler.postDelayed(this, DELAY_FOR_HANDLER);
}
}
public static String getMediaDuration(String path) {
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
mmr.setDataSource(path);
String duration = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
mmr.release();
return duration;
}
public void playAudio(String path) throws IOException {
mPlayer.reset();
mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mPlayer.setDataSource(path);
mPlayer.prepare();
mSeekBar.setMax(mPlayer.getDuration());
mPlayer.start();
startSendingProgress();
}
public void stopAudio() {
if (mPlayer != null) {
mPlayer.stop();
}
}
public MediaPlayer getMediaPlayer() {
return mPlayer;
}
#Override
public void onCompletion(MediaPlayer mp) {
mMediaPlayerStatusCallBacks.onMediaCompleted();
mHandler.removeCallbacks(mPlayerUpdater);
}
}
And below is the code I am using in View Holder of my recycler view
public class AudioViewHolder extends RecyclerView.ViewHolder {
public View mView;
public QuickContactBadge qcbProfileImage;
public ImageView ivPlay, ivDeliveryStatus;
public SeekBar sbAudioPlayer;
public TextView tvDateTime, tvDuration;
public VoipMessage mItem;
public MyAudioViewsClickListener myAudioViewsClickListener;
public AudioViewHolder(View itemView) {
super(itemView);
mView = itemView;
qcbProfileImage = (QuickContactBadge) itemView.findViewById(R.id.img_view_user);
ivPlay = (ImageView) itemView.findViewById(R.id.iv_play);
sbAudioPlayer = (SeekBar) itemView.findViewById(R.id.sb_audio_player);
ivDeliveryStatus = (ImageView) itemView.findViewById(R.id.img_view_message_status);
tvDateTime = (TextView) itemView.findViewById(R.id.txt_view_duration);
tvDuration = (TextView) itemView.findViewById(R.id.txt_view_time);
myAudioViewsClickListener = new MyAudioViewsClickListener();
ivPlay.setOnClickListener(myAudioViewsClickListener);
}
private class MyAudioViewsClickListener implements View.OnClickListener {
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.iv_play:
try {
playAndPauseAudio(getAdapterPosition());
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
}
private void playAndPauseAudio(int adapterPosition) throws IOException {
VoipMessage currentMessage = mMessages.get(adapterPosition);
RecyclerView.ViewHolder holder = mRecyclerView.findViewHolderForLayoutPosition(adapterPosition);
final AudioViewHolder audioViewHolder = (AudioViewHolder) holder;
String audioPath = currentMessage.getMediaReference();
AudioPlayer audioPlayer = new AudioPlayer(audioViewHolder.sbAudioPlayer, mContext, new AudioPlayer.MediaPlayerStatusCallbacks() {
#Override
public void onMediaCompleted() {
ivPlay.setImageResource(R.drawable.ic_audio_play);
}
#Override
public void onUpdatedMediaProgress(int progress) {
//audioViewHolder.sbAudioPlayer.setProgress(progress);
Logger.e("test","progress in adapter " + progress);
//sbAudioPlayer.setProgress(progress);
}
#Override
public void setDuration(int duration) {
//audioViewHolder.sbAudioPlayer.setMax(duration);
//sbAudioPlayer.setMax(duration);
}
});
if (audioPlayer.getMediaPlayer().isPlaying()) {
audioPlayer.stopAudio();
ivPlay.setImageResource(R.drawable.ic_audio_play);
} else {
audioPlayer.playAudio(audioPath);
ivPlay.setImageResource(R.drawable.ic_audio_pause);
}
}
}
I am passing seek bar reference from ViewHolder to the Audio Player class. I am using thread for updating seek bar. Thread is calculating progress and setting that progress to seek bar but the problem is seek bar is not updating on UI. For clear understanding I am attaching image of UI.
enter image description here
My my seek bar is not updating any help. I have spent many hours but could not solve this problem.
Try mSeekBar.setMax(mPlayer.getDuration() / 1000); instead of mSeekBar.setMax(mPlayer.getDuration());, because You set current process in seconds:
int currentProgress = mPlayer.getCurrentPosition() / 1000;
mSeekBar.setProgress(currentProgress);
but max value is in milliseconds and progress is less than 1 px.
I coded a simple mp3 player a couple of days ago. The code is at Playing music in sleep/standby mode in Android 2.3.3
Everything works fine when the mp3 player (Samsung 3.6, Android 2.2) plays music on its own. I bought a bluetooth speaker (A2DP 3.0) and connected it to the mp3 player. The music still plays fine, but when the mp3 player screen goes dark into sleep mode, the music starts skipping on the bluetooth speaker.
It does not happen if the mp3 plays music on its own in sleep mode
Other music player apps in the mp3 player seem to play fine even in sleep mode over the bluetooth speaker
If I disable bluetooth, and play the music using the speaker connected by a cable, then the music plays fine even in standby mode.
This leads me to believe that something may be wrong with my code.
Here's my complete code:
public class MainActivity extends Activity {
private static String audioPath;
private static ArrayList<String> devotionalList;
private static ArrayList<String> christmasList;
private static ArrayList<String> cinemaList;
private static ImageButton playPauseButton;
private static TextView appMsg;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int maxVolume = audioManager
.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
int curVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
SeekBar volControl = (SeekBar) findViewById(R.id.volumeBar);
volControl.setMax(maxVolume);
volControl.setProgress(curVolume);
volControl
.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar arg0) {
}
#Override
public void onStartTrackingTouch(SeekBar arg0) {
}
#Override
public void onProgressChanged(SeekBar arg0, int arg1,
boolean arg2) {
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
arg1, 0);
}
});
File baseDir = Environment.getExternalStorageDirectory();
audioPath = baseDir.getAbsolutePath() + "/external_sd/music/";
devotionalList = loadSongs(audioPath + "devotional/");
christmasList = loadSongs(audioPath + "christmas/");
cinemaList = loadSongs(audioPath + "cinema/");
}
private ArrayList<String> loadSongs(String songDirectory) {
File directory = new File(songDirectory);
ArrayList<String> al1 = new ArrayList<String>();
for (String filename : directory.list()) {
al1.add(songDirectory + filename);
}
return al1;
}
public void playPauseSong(View v) {
if (MP3PlayerService.isPlaying) {
playPauseButton.setImageResource(android.R.drawable.ic_media_play);
// Intent i1 = new Intent(this, MP3PlayerService.class);
stopService(new Intent(this, MP3PlayerService.class));
} else {
if (MP3PlayerService.playerStarted) {
playPauseButton
.setImageResource(android.R.drawable.ic_media_pause);
startService(new Intent(this, MP3PlayerService.class));
}
}
}
public void playNextSong(View v) {
if (MP3PlayerService.playerStarted) {
startService(new Intent(this, MP3PlayerService.class));
}
}
public void playPreviousSong(View v) {
if (MP3PlayerService.playerStarted) {
MP3PlayerService.previousSong = true;
startService(new Intent(this, MP3PlayerService.class));
}
}
#Override
protected void onPause() {
super.onPause();
playPauseButton = null;
appMsg = null;
}
#Override
protected void onResume() {
super.onResume();
appMsg = (TextView) this.findViewById(R.id.txtAppMsg);
appMsg.setText("");
playPauseButton = (ImageButton) this.findViewById(R.id.btnPlayPause);
}
public void playDevotional(View v) {
playPlayList(devotionalList);
}
public void playChristmas(View v) {
playPlayList(christmasList);
}
public void playCinema(View v) {
playPlayList(cinemaList);
}
private void playPlayList(ArrayList<String> playList) {
if (MP3PlayerService.isPlaying) {
MP3PlayerService.mediaPlayer.stop();
MP3PlayerService.mediaPlayer.reset();
MP3PlayerService.mediaPlayer.release();
}
MP3PlayerService.songPosition = 0;
playPauseButton.setImageResource(android.R.drawable.ic_media_pause);
Intent i1 = new Intent(this, MP3PlayerService.class);
i1.putExtra("playListChoice", playList);
startService(i1);
}
}
And here's my code for the mediaplayer service:
public class MP3PlayerService extends Service implements OnCompletionListener {
private static ArrayList<String> al1;
private static FileInputStream fis;
private static FileDescriptor fd;
static boolean previousSong;
static boolean playerStarted = false;
static int songPosition;
static boolean isPlaying = false;
static String currentSong;
static ArrayList<String> songHistory;
static MediaPlayer mediaPlayer;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
songHistory = new ArrayList<String>();
}
#Override
public void onDestroy() {
songPosition = mediaPlayer.getCurrentPosition();
mediaPlayer.pause();
isPlaying = false;
}
#Override
public void onStart(Intent intent, int startid) {
if (songPosition == 0) {
Bundle extras = intent.getExtras();
if (extras == null) {
if (previousSong) {
playSong();
} else {
// Next Song Button clicked
playNextSong();
}
} else {
// A Playlist button is clicked
al1 = (ArrayList<String>) extras.get("playListChoice");
playSong();
}
} else {
songPosition = 0;
mediaPlayer.start();
}
isPlaying = true;
}
private void playNextSong() {
if (isPlaying) {
mediaPlayer.release();
playSong();
}
}
private void playSong() {
if (previousSong) {
mediaPlayer.release();
if (songHistory.size() > 1) {
currentSong = songHistory.get(songHistory.size() - 2);
songHistory.remove(songHistory.size() - 1);
} else {
currentSong = songHistory.get(0);
}
previousSong = false;
} else {
currentSong = al1.get(new Random().nextInt(al1.size()));
songHistory.add(currentSong);
}
try {
fis = new FileInputStream(currentSong);
fd = fis.getFD();
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(fd);
mediaPlayer.prepare();
mediaPlayer.seekTo(songPosition);
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.start();
playerStarted = true;
} catch (FileNotFoundException e) {
Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
e.printStackTrace();
} catch (IOException e) {
Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
#Override
public void onCompletion(MediaPlayer arg0) {
playNextSong();
}
}
I think I fixed it. The slider volume code was the source of the problem. Without that piece, the app was still working during standby mode using the bluetooth speakers. I wanted the slider bar, so I tried acquring a partial wake lock after instantiating the media player for each song and that kept the app going correctly duing standby mode (with the slider volume control as part of the app as well). I release the lock later after each song.
As far as I can tell, my app runs fine but I notice this error from the SoundPool being reporting often in the logcat.
E/SoundPool(28182): 2 mChannels.erase can not get the lock
Any ideas as to what would cause this? I tried removing my thread synchronization code but I am still receiving the error.
This was observed using a Galaxy S2 (SC-02C) running Android 2.3.6.
Another solution that I propose for you :
Create an instance of SoundPool by sound with maxStreams = 1
Set volume 0 to only one streamID returned by play() method
This solution is not very clean I agree...
public class Sound {
public final static int STREAM = AudioManager.STREAM_SYSTEM;
private SoundPool pool;
private int soundID;
private int streamID;
public Sound(Context context, int resID) {
pool = new SoundPool(1, STREAM, 0);
soundID = pool.load(context, resID, 1);
}
public final void play() {
streamID = pool.play(soundID, 1, 1, 1, 0, 1);
}
public final void stop() {
pool.setVolume(streamID, 0, 0);
}
}
public class MyActivity extends Activity {
public static Sound alarm1;
public static Sound alarm2;
#Override
public void onCreate(Bundle state) {
super.onCreate(state);
setContentView(R.layout.main);
setVolumeControlStream(Sound.STREAM);
if(alarm1 == null) alarm1 = new Sound(this, R.raw.alarm1);
if(alarm2 == null) alarm2 = new Sound(this, R.raw.alarm2);
findViewById(R.id.play_1).setOnClickListener( new OnClickListener() {
#Override public void onClick(View view) { alarm1.play(); }
});
findViewById(R.id.stop_1).setOnClickListener( new OnClickListener() {
#Override public void onClick(View view) { alarm1.stop(); }
});
findViewById(R.id.play_2).setOnClickListener( new OnClickListener() {
#Override public void onClick(View view) { alarm2.play(); }
});
findViewById(R.id.stop_2).setOnClickListener( new OnClickListener() {
#Override public void onClick(View view) { alarm2.stop(); }
});
}
}
And to manage all your sounds, we can imagine a library like this :
public class Soundlib {
private Context context;
private HashMap<Integer, Sound> library;
public Soundlib(Context context) {
this.context = context;
library = new HashMap<Integer, Sound>();
}
public final void add(int... rawID) {
for(int id : rawID) library.put(id, new Sound(context, id));
}
public final void play(int... rawID) {
for(int id : rawID) library.get(id).play();
}
public final void stop(int... rawID) {
for(int id : rawID) library.get(id).stop();
}
public final void stopAll() {
for(int id : library.keySet()) stop(id);
}
}
// to initilize sound library
if(soundlib == null) soundlib = new Soundlib(this){{
// to add one or more sounds
add(R.raw.alarm1, R.raw.alarm2);
}};
// to play one or more sounds
soundlib.play(R.raw.alarm1);
// to stop one or more sounds
soundlib.stop(R.raw.alarm1);
// to stop all sounds
soundlib.stopAll();
I think this error log is caused by the play() / stop() method of your SoundPool instance.
Do you try to play / stop an audio stream?