Mediaplayer stops working after clicking 14 times - android

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();
}

Related

Android Music Application

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

Can't add MediaController to VLC Android SDK

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

Why seek bar is not updating programmatically in android?

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.

Can't pass an int from button if / else case to media player

how are you supposed to let the mediaplayer know what it is supposed to play?
wholeTextPlayer = MediaPlayer.create(Lesson1Reading.this, engAu);
It works fine if I declare the file in the top:
MediaPlayer wholeTextPlayer;
private int engAu = R.raw.l1r_en_l10;
Button btn_default_acc_whole;
It doesn't work from within a button click if / else statement wherever I try to put it with the following combination:
MediaPlayer wholeTextPlayer;
private int engAu;
Button btn_default_acc_whole;
The button click:
final Button btn_default_acc_whole = (Button) findViewById(R.id.btn_default_acc_whole);
btn_default_acc_whole.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
if (wholeTextPlayer.isPlaying()) {
wholeTextPlayer.pause();
} else {
wholeTextPlayer.start();
startPlayProgressUpdater();
}
setEngAu(R.raw.l1r_en_l10); //this line doesn't want to fit anywhere
}
});
The setter:
public void setEngAu(int engAu) {
this.engAu = engAu;
}
Of course they are separately placed in the activity, I just copied and pasted the relevant bits from it.
Thanks guys.
Here is the whole code:
'public class Lesson1Grammar extends Activity {
private SeekBar seekBar;
MediaPlayer wholeTextPlayer;
private int engAu;
private final Handler handler = new Handler();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.lesson1grammar);
WholeDefAccPlayer();
final RelativeLayout playerScreen = (RelativeLayout)findViewById(R.id.playerScreen);
final ImageButton btn_player_screen = (ImageButton) findViewById(R.id.btn_player_screen);
btn_player_screen.setOnClickListener(new View.OnClickListener() {
//this hides/unhides the part of the layout in which the player is
#Override
public void onClick(View arg0) {
if (playerScreen.isShown()) {
playerScreen.setVisibility(View.GONE);
} else {
playerScreen.setVisibility(View.VISIBLE);
}
}
});
final Button btn_default_acc_whole = (Button) findViewById(R.id.btn_default_acc_whole);
btn_default_acc_whole.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
if (wholeTextPlayer.isPlaying()) {
wholeTextPlayer.pause();
} else {
setEngAu(R.raw.default_acc_audio);
wholeTextPlayer.start();
startPlayProgressUpdater();
}
}
});
}
public void setEngAu(int engAu) {
this.engAu = engAu;
}
private void WholeDefAccPlayer() {
wholeTextPlayer = MediaPlayer.create(Lesson1Grammar.this, engAu);
((TextView) findViewById(R.id.getTitleOfAccent)).setText(R.string.btn_lesson1reading);
seekBar = (SeekBar) findViewById(R.id.seekBar);
seekBar.setMax(wholeTextPlayer.getDuration());
seekBar.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
seekChange(v);
return false;
}
});
}
public void startPlayProgressUpdater() {
seekBar.setProgress(wholeTextPlayer.getCurrentPosition());
if (wholeTextPlayer.isPlaying()) {
Runnable notification = new Runnable() {
public void run() {
startPlayProgressUpdater();
}
};
handler.postDelayed(notification, 1000);
}
else wholeTextPlayer.pause();
}
// This is event handler thumb moving event
private void seekChange(View v){
if(wholeTextPlayer.isPlaying()){
SeekBar sb = (SeekBar)v;
wholeTextPlayer.seekTo(sb.getProgress());
}
}
}
'
if your plan is to make the method setEngAu() is the controller as you mentioned in the comment. then you you need to use that method like this
public void setEngAu(int enAu)
{
this.EngAu = enAu;
wholeTextPlayer.setDataSource(engAu);
wholeTextPlayer.prepare();
}
you need to implement onPrepared listener from the media player
I do not know your classes but I assume where you say something like;
wholeTextPlayer = new MediaPlayer();
wholeTextPlayer.setOnPreparedListener(this);
here you start the player after it became prepared
public void onPrepared(MediaPlayer player)
{
player.start();
}
Remember to you will need to call wholeTextPlayer.release() if you do not want the player to hold on that resource anymore( think of it as memory issues - recommended if you check the documentation)
EDIT :
I adjusted your code a little, please take a look and let me know.
private SeekBar seekBar;
MediaPlayer wholeTextPlayer;
private int engAu;
final Handler handler = new Handler();
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.lesson1grammar);
WholeDefAccPlayer();
final RelativeLayout playerScreen = (RelativeLayout) findViewById(R.id.playerScreen);
final ImageButton btn_player_screen = (ImageButton) findViewById(R.id.btn_player_screen);
btn_player_screen.setOnClickListener(new View.OnClickListener()
{
//this hides/unhides the part of the layout in which the player is
#Override
public void onClick(View arg0)
{
if(playerScreen.isShown())
{
playerScreen.setVisibility(View.GONE);
}
else
{
playerScreen.setVisibility(View.VISIBLE);
}
}
});
final Button btn_default_acc_whole = (Button) findViewById(R.id.btn_default_acc_whole);
btn_default_acc_whole.setOnClickListener(new View.OnClickListener()
{
public void onClick(View arg0)
{//problem here is
if(playerState == PlayerState_Playing)
{
wholeTextPlayer.pause();
setPlayerState(PlayerState_Paused);
}
else if(playerState == PlayerState_Paused)
{
wholeTextPlayer.start();
setPlayerState(PlayerState_Playing);
}
else
{
setEngAu(R.raw.default_acc_audio);
wholeTextPlayer.start();
startPlayProgressUpdater();
setPlayerState(PlayerState_Playing);
}
}
});
}
public void setEngAu(int engAu)
{
this.engAu = engAu;
if(wholeTextPlayer !=null)
{//just in case you call this method and player was not initialized yet
wholeTextPlayer.release();
}
setPlayerState(PlayerState_Preparing);
wholeTextPlayer = MediaPlayer.create(this, engAu);
}
private void WholeDefAccPlayer()
{
//this line probably will fail because engAu is not really initialized yet, unless you have default value for it
wholeTextPlayer = MediaPlayer.create(this, engAu);
((TextView) findViewById(R.id.getTitleOfAccent)).setText(R.string.btn_lesson1reading);
seekBar = (SeekBar) findViewById(R.id.seekBar);
//you can not call getDuration unless the player is prepared, so this might crash you
// seekBar.setMax(wholeTextPlayer.getDuration());
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
{
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b)
{
if(playerState != PlayerState_Preparing)
{//if player state is preparing it means we can not seek yet, player.start() must be called first
wholeTextPlayer.seekTo(i);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar)
{
}
#Override
public void onStopTrackingTouch(SeekBar seekBar)
{
}
});
}
public void startPlayProgressUpdater()
{
if(seekBar.getMax() != wholeTextPlayer.getDuration())
{//in case you change track later, this will check if the seek bar max value with track duration.
// if they are not the same, then it will adjust it for you
seekBar.setMax(wholeTextPlayer.getDuration());
}
seekBar.setProgress(wholeTextPlayer.getCurrentPosition());
if(wholeTextPlayer.isPlaying())
{
Runnable notification = new Runnable()
{
public void run()
{
startPlayProgressUpdater();
}
};
handler.postDelayed(notification, 1000);
}
else wholeTextPlayer.pause();
}
// This is event handler thumb moving event
private void seekChange(View v)
{
if(wholeTextPlayer.isPlaying())
{
SeekBar sb = (SeekBar) v;
wholeTextPlayer.seekTo(sb.getProgress());
}
}
private final int PlayerState_Preparing = 0;
private final int PlayerState_Playing = 1;
private final int PlayerState_Paused = 2;
private int playerState;
private void setPlayerState(int state)
{//this is used to track the player state, because wholeTextPlayer.isPlaying() can return false in many conditions ( too general )
//you can check in the media player documentation to know more details about this
playerState = state;
}

SoundPool error "erase can not get the lock"

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?

Categories

Resources