everybody.
First of all, I'm a newbie. I created an activity to play a specific mp3 from raw folder. It works fine and playing it well. I implemented the Media Player as you will see in my code below. But the problem is when I change the orientation of my smartphone , the player continues playing the sound, but a new activity is opened/ updated with the same elements reseted and if I click on PLAY button, the mp3 starts playing, but the old activity stills running on back, playing the mp3.... so, there are 2 same songs playing now...
I don't want to update the activity or open a new one. I just want to continue playing the song where it was playing before I change the smartphone orientation.
Here is my code:
MP3PlayerActivity.java (main)
public class Mp3PlayerActivity extends Activity implements OnPreparedListener {
/** Called when the activity is first created. */
private Button btnPlay;
private Button btnPause;
private int current = 0;
private boolean running = true;
private int duration = 0;
private MediaPlayer mPlayer;
private SeekBar mSeekBarPlayer;
private TextView mMediaTime;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
mPlayer = MediaPlayer.create(getApplicationContext(), R.raw.goodthings);
btnPlay = (Button) findViewById(R.id.button1);
btnPause = (Button) findViewById(R.id.button2);
mMediaTime = (TextView)findViewById(R.id.mediaTime);
mSeekBarPlayer = (SeekBar)findViewById(R.id.progress_bar);
mPlayer.setOnPreparedListener(this);
mSeekBarPlayer.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if(fromUser){
mPlayer.seekTo(progress);
updateTime();
}
}
});
btnPlay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
try {
mPlayer.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mPlayer.start();
mSeekBarPlayer.postDelayed(onEverySecond, 1000);
}
public void onCompletion( MediaPlayer mPlayer)
{
mPlayer.release();
}
});
btnPause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
mPlayer.pause();
}
public void onCompletion( MediaPlayer mPlayer)
{
mPlayer.release();
}
});
}
private Runnable onEverySecond = new Runnable() {
#Override
public void run(){
if(true == running){
if(mSeekBarPlayer != null) {
mSeekBarPlayer.setProgress(mPlayer.getCurrentPosition());
}
if(mPlayer.isPlaying()) {
mSeekBarPlayer.postDelayed(onEverySecond, 1000);
updateTime();
}
}
}
};
private void updateTime(){
do {
current = mPlayer.getCurrentPosition();
System.out.println("duration - " + duration + " current- "
+ current);
int dSeconds = (int) (duration / 1000) % 60 ;
int dMinutes = (int) ((duration / (1000*60)) % 60);
int dHours = (int) ((duration / (1000*60*60)) % 24);
int cSeconds = (int) (current / 1000) % 60 ;
int cMinutes = (int) ((current / (1000*60)) % 60);
int cHours = (int) ((current / (1000*60*60)) % 24);
if(dHours == 0){
mMediaTime.setText(String.format("%02d:%02d / %02d:%02d", cMinutes, cSeconds, dMinutes, dSeconds));
}else{
mMediaTime.setText(String.format("%02d:%02d:%02d / %02d:%02d:%02d", cHours, cMinutes, cSeconds, dHours, dMinutes, dSeconds));
}
try{
Log.d("Value: ", String.valueOf((int) (current * 100 / duration)));
if(mSeekBarPlayer.getProgress() >= 100){
break;
}
}catch (Exception e) {}
}while (mSeekBarPlayer.getProgress() <= 100);
}
#Override
public void onPrepared(MediaPlayer arg0) {
// TODO Auto-generated method stub
duration = mPlayer.getDuration();
mSeekBarPlayer.setMax(duration);
mSeekBarPlayer.postDelayed(onEverySecond, 1000);
}
}
when you rotate your device, onCreate() is called again, so all the stuff you do in onCreate() is done all over again - which means recreating your MediaPlayer and re-setting all of the variables.
What you need to do is only create those things if this is the first time onCreate() is being called.
Have a look here for more info on that.:
http://developer.android.com/guide/topics/resources/runtime-changes.html
Related
I've just developed a simple media player that sounds a song and it has a seekbar that regulate the song volume.
That's my code:
public class MainActivity extends AppCompatActivity {
Button playBtn;
SeekBar positionBar;
SeekBar volumeBar;
TextView elapsedTimeLabel;
TextView remainingTimeLabel;
MediaPlayer mp;
int totalTime;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
playBtn = (Button) findViewById(R.id.playBtn);
elapsedTimeLabel = (TextView) findViewById(R.id.elapsedTimeLabel);
remainingTimeLabel = (TextView) findViewById(R.id.remainingTimeLabel);
// Media Player
mp = MediaPlayer.create(this, R.raw.song);
mp.setLooping(true);
mp.seekTo(0);
mp.setVolume(0.5f, 0.5f);
totalTime = mp.getDuration();
// Position Bar
positionBar = (SeekBar) findViewById(R.id.positionBar);
positionBar.setMax(totalTime);
positionBar.setOnSeekBarChangeListener(
new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
mp.seekTo(progress);
positionBar.setProgress(progress);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
}
);
// Volume Bar
volumeBar = (SeekBar) findViewById(R.id.volumeBar);
volumeBar.setOnSeekBarChangeListener(
new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
float volumeNum = progress / 100f;
mp.setVolume(volumeNum, volumeNum);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
}
);
// Thread (Update positionBar & timeLabel)
new Thread(new Runnable() {
#Override
public void run() {
while (mp != null) {
try {
Message msg = new Message();
msg.what = mp.getCurrentPosition();
handler.sendMessage(msg);
Thread.sleep(1000);
} catch (InterruptedException e) {}
}
}
}).start();
}
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
int currentPosition = msg.what;
// Update positionBar.
positionBar.setProgress(currentPosition);
// Update Labels.
String elapsedTime = createTimeLabel(currentPosition);
elapsedTimeLabel.setText(elapsedTime);
String remainingTime = createTimeLabel(totalTime-currentPosition);
remainingTimeLabel.setText("- " + remainingTime);
}
};
public String createTimeLabel(int time) {
String timeLabel = "";
int min = time / 1000 / 60;
int sec = time / 1000 % 60;
timeLabel = min + ":";
if (sec < 10) timeLabel += "0";
timeLabel += sec;
return timeLabel;
}
public void playBtnClick(View view) {
if (!mp.isPlaying()) {
// Stopping
mp.start();
playBtn.setBackgroundResource(R.drawable.ic_stop);
} else {
// Playing
mp.pause();
playBtn.setBackgroundResource(R.drawable.ic_play);
}
} }
Now, when I regulate the volume with the media player seekbar, the phone system volume didn't change and the other way around.
How can I syncronize the volume seekbar with the phone system volume so as to adjust the volume with both?
Using the Audio Manager to Raise and Down Volume.
AudioManager audioManager = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
//Using volume control UI visibility
//To increase media player volume
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_RAISE, AudioManager.FLAG_SHOW_UI);
//To decrease media player volume
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_LOWER, AudioManager.FLAG_SHOW_UI);
//Without volume control UI
//To increase media player volume
audioManager.adjustVolume(AudioManager.ADJUST_RAISE, AudioManager.FLAG_PLAY_SOUND);
//To decrease media player volume
audioManager.adjustVolume(AudioManager.ADJUST_LOWER, AudioManager.FLAG_PLAY_SOUND);
Hi Community,
I'm developing whats-app like application.In that I am facing a
problem in recycle view while scrolling the items.The problem is even
specific to audio files itself.These files were playing irrelevant to
item data position.Please help me to resolve this issue.
MyAdapterClass:
#Override
public void onBindViewHolder(SwappingHolder holder, int position) {
MessageDetails messageData = messagesList.get(position);
if (messageData != null) {
switch (messageData.getMessageType()) {
case MessageDetails.MESSAGE_TEXT_TYPE:
TextTypeViewHolder textViewHolder = (TextTypeViewHolder) holder;
textViewHolder.updateView(messageData);
break;
case MessageDetails.MESSAGE_IMAGE_TYPE:
ImageTypeViewHolder imageViewHolder = (ImageTypeViewHolder) holder;
imageViewHolder.updateImageFile(messageData);
break;
case MessageDetails.MESSAGE_AUDIO_TYPE:
AudioTypeViewHolder audioHolder = (AudioTypeViewHolder) holder;
audioHolder.initializeAudioPlayer(messageData);
break;
case MessageDetails.MESSAGE_VIDEO_TYPE:
VideoTypeViewHolder videoHolder = (VideoTypeViewHolder) holder;
videoHolder.updateVideoMessage(messageData);
break;
case MessageDetails.MESSAGE_LOCATION_TYPE:
MapTypeHolder mapHolder = (MapTypeHolder) holder;
mapHolder.loadMapThumbView(messageData);
break;
case MessageDetails.MESSAGE_CONTACT_TYPE:
ContactsTypeHolder contactsHolder = (ContactsTypeHolder) holder;
contactsHolder.setContactData(messageData);
break;
case MessageDetails.MESSAGE_FILE_TYPE:
FileTypeHolder fileTypeHolder = (FileTypeHolder)holder;
fileTypeHolder.updateFileData(messageData);
}
}
}
MyHolderClass:
public class AudioTypeViewHolder extends SwappingHolder implements View.OnClickListener, View.OnLongClickListener {
SeekBar seekBar;
TextView timer, tv_time;
ImageView btn_play, iv_smile;
CardView cardView;
RelativeLayout parentView;
CustomizedAudioPlayer player;
MessageDetails messageDetails;
MediaPlayer mediaPlayer;
public AudioTypeViewHolder(View itemView) {
super(itemView, multiSelector);
this.timer = (TextView) itemView.findViewById(R.id.timer);
this.seekBar = (SeekBar) itemView.findViewById(R.id.audio_seekBar);
this.btn_play = (ImageView) itemView.findViewById(R.id.btnPlay);
this.tv_time = (TextView) itemView.findViewById(R.id.timeright);
this.cardView = (CardView) itemView.findViewById(R.id.card_view);
this.parentView = (RelativeLayout) itemView.findViewById(R.id.parent_view);
this.iv_smile =(ImageView) itemView.findViewById(R.id.smile1);
this.mediaPlayer = new MediaPlayer();
btn_play.setOnClickListener(this);
player = new CustomizedAudioPlayer(mediaPlayer, seekBar, btn_play, timer);
itemView.setOnLongClickListener(this);
itemView.setLongClickable(true);
btn_play.setOnLongClickListener(this);
btn_play.setLongClickable(true);
}
void initializeAudioPlayer(MessageDetails messageDetails) {
int colorId, gravity;
this.messageDetails = messageDetails;
if(messageDetails.getAudioPlayer() == null)
messageDetails.setAudioPlayer(player);
if (messageDetails.getSender().equals("to")) {
colorId = mContext.getResources().getColor(R.color.color_recevied_item);
gravity = Gravity.LEFT;
iv_smile.setVisibility(View.GONE);
} else {
colorId = mContext.getResources().getColor(R.color.color_sent_item);
gravity = Gravity.RIGHT;
iv_smile.setVisibility(View.VISIBLE);
iv_smile.setBackgroundResource(updateMessageStatus(messageDetails.getMstatus()));
}
player.initializePlayer(messageDetails.getMessage());
tv_time.setText(messageDetails.getTime());
cardView.setCardBackgroundColor(colorId);
parentView.setGravity(gravity);
}
#Override
public void onClick(View view) {
int id = view.getId();
if (id == R.id.btnPlay) {
if (!mediaPlayer.isPlaying()) {
// check my player is playing
//if not, stop if any other player is playing
for (MessageDetails messageDetails : messagesList) {
CustomizedAudioPlayer customPlayer = messageDetails.getAudioPlayer();
if(customPlayer != null)
customPlayer.stopTheMediaPlay();
}
//start my player
btn_play.setImageResource(R.drawable.img_pause);
player.startThePlayer();
notifyDataSetChanged();
} else {
btn_play.setImageResource(R.drawable.img_play);
player.stopTheMediaPlay();
}
}
}
#Override
public boolean onLongClick(View view) {
onItemLongPressed(this, messageDetails);
return true;
}
}
My Custom Audio Player
public class CustomizedAudioPlayer implements SeekBar.OnSeekBarChangeListener,MediaPlayer.OnCompletionListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener {
private Handler myHandler = new Handler();
SeekBar seekbar;
MediaPlayer mediaPlayer;
boolean isPaused;
ImageView playBtn;
TextView timer;
StringBuilder mFormatBuilder;
Formatter mFormatter;
int totalDuration, currentDuration;
String path, chatId;
public CustomizedAudioPlayer(MediaPlayer mediaPlayer, SeekBar seekbar, ImageView view, TextView timer){
this.seekbar = seekbar;
this.playBtn = view;
this.timer = timer;
this.mediaPlayer = mediaPlayer;
mFormatBuilder = new StringBuilder();
mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
this.seekbar.setProgress(0);
this.seekbar.setMax(100);
this.seekbar.setOnSeekBarChangeListener(this);
}
public void initializePlayer(String filePath){
try{
if(path == null){
this.path = filePath;
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setOnErrorListener(this);
mediaPlayer.setDataSource(path);
mediaPlayer.prepare();
timer.setText(stringForTime( mediaPlayer.getDuration()));
}
}catch (Exception e){
}
}
public void startThePlayer(){
totalDuration = mediaPlayer.getDuration();
mediaPlayer.seekTo(currentDuration);
myHandler.postDelayed(updateProgress,100);
mediaPlayer.start();
}
public void stopTheMediaPlay(){
if(mediaPlayer.isPlaying()){
playBtn.setImageResource(R.drawable.img_play);
currentDuration = mediaPlayer.getCurrentPosition();
timer.setText(stringForTime( mediaPlayer.getDuration()));
myHandler.removeCallbacks(updateProgress);
mediaPlayer.pause();
}
}
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
playBtn.setImageResource(R.drawable.img_play);
seekbar.setProgress(0);
timer.setText(stringForTime( mediaPlayer.getDuration()));
myHandler.removeCallbacks(updateProgress);
}
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
myHandler.removeCallbacks(updateProgress);
playBtn.setImageResource(R.drawable.img_play);
mediaPlayer.pause();
isPaused = true;
}
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
currentDuration = progressToTimer(seekBar.getProgress(), totalDuration);
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
if(fromUser){
mediaPlayer.seekTo(currentDuration);
}
} else if (mediaPlayer == null) {
seekBar.setProgress(0);
}
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
currentDuration = progressToTimer(seekBar.getProgress(), totalDuration);
if (mediaPlayer.isPlaying() && mediaPlayer != null || (isPaused && mediaPlayer != null)) {
isPaused = false;
mediaPlayer.seekTo(currentDuration);
myHandler.postDelayed(updateProgress,100);
mediaPlayer.start();
playBtn.setImageResource(R.drawable.img_pause);
}
}
#Override
public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
return false;
}
private Runnable updateProgress = new Runnable() {
public void run() {
totalDuration = mediaPlayer.getDuration();
currentDuration = mediaPlayer.getCurrentPosition();
int progress = getProgressPercentage();
float progressPer = ((float)progress/100);
float newPosition = (totalDuration) * progressPer;
seekbar.setProgress(progress);
timer.setText(stringForTime( (int) newPosition));
myHandler.postDelayed(this, 100);
}
};
private String stringForTime(int timeMs) {
int totalSeconds = timeMs / 1000;
int seconds = totalSeconds % 60;
int minutes = (totalSeconds / 60) % 60;
int hours = totalSeconds / 3600;
mFormatBuilder.setLength(0);
if (hours > 0) {
return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString();
} else {
return mFormatter.format("%02d:%02d", minutes, seconds).toString();
}
}
public int getProgressPercentage(){
long currentSeconds = (currentDuration / 1000);
long totalSeconds = (totalDuration / 1000);
Double percentage =(((double)currentSeconds)/totalSeconds)*100;
return percentage.intValue();
}
public int progressToTimer(int progress, int totalDuration) {
totalDuration = (totalDuration / 1000);
int currentDuration = (int) ((((double)progress) / 100) * totalDuration);
// return current duration in milliseconds
return currentDuration * 1000;
}
}
I even tried by placing
setIsRecyclable(false);
Using this, the positions of items are stable, but the item not updating while playing audio file(i.e. seekbar, file time not updating)
You can closely find my problem in following screenshot
I have a ListView which displays voice messages (just like WhatsApp's), I'm using BaseAdapter, and my layout contains a play button and a SeekBar.
What I want is to play the audio on the click of the play button, and update the SeekBar.
So I implemented this custom SeekBar which updates itself.
SelfUpdatingSeekBar.java:
public class SelfUpdatingSeekBar extends SeekBar {
MediaPlayer mp;
boolean mActive;
public void setMediaPlayer(MediaPlayer mp){
this.mp = mp;
}
Runnable mUpdate = new Runnable() {
#Override
public void run() {
long totalDuration = mp.getDuration();
long currentDuration = mp.getCurrentPosition();
// Updating progress bar
int progress = (int)(getProgressPercentage(currentDuration, totalDuration));
setProgress(progress);
postDelayed(this, 100);
}
} ;
public void setActive(int progress) {
if (!mActive) {
mActive = true;
removeCallbacks(mUpdate);
setProgress(progress);
post(mUpdate);
}
}
public void setInactive(int progress) {
if (mActive) {
mActive = false;
removeCallbacks(mUpdate);
}
setProgress(progress);
}
public SelfUpdatingSeekBar(Context context) {
super(context);
}
public SelfUpdatingSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SelfUpdatingSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public SelfUpdatingSeekBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public int getProgressPercentage(long currentDuration, long totalDuration){
Double percentage = (double) 0;
long currentSeconds = (int) (currentDuration / 1000);
long totalSeconds = (int) (totalDuration / 1000);
// calculating percentage
percentage =(((double)currentSeconds)/totalSeconds)*100;
// return percentage
return percentage.intValue();
}
}
This is how my getView() looks like:
public View getView(final int i, View convertView, ViewGroup viewGroup){
final ViewHolder viewHolder;
if(convertView == null){
LayoutInflater inflater = ((MainActivity) context).getLayoutInflater();
viewHolder = new ViewHolder();
convertView = inflater.inflate(R.layout.sent_voice_bubble, viewGroup, false);
viewHolder.sent_voice_seekbar = (SelfUpdatingSeekBar) convertView.findViewById(R.id.sent_seekbar);
viewHolder.sent_voice_seekbar.setMediaPlayer(mMediaPlayer);
viewHolder.sent_voice_play = (ImageView) convertView.findViewById(R.id.sent_playAudio);
viewHolder.sent_voice_container = convertView.findViewById(R.id.sent_vmessagesection);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(((int)(x * 0.7f)), RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
viewHolder.sent_voice_container.setLayoutParams(params);
convertView.setTag(viewHolder);
}else{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.sent_voice_play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Check if the Item is currently playing
if(list.get(i).isPlaying()){
// Stop audio and save progress
stopItemAudio(list.get(i), viewHolder.sent_voice_seekbar);
// Change button's image to Pause ||
((ImageView) v).setImageDrawable(((MainActivity) context).pauseDrawable);
}else{
// Start audio and update the SeekBar
playItemAudio(list.get(i), viewHolder.sent_voice_seekbar);
// Change button's image to Play >
((ImageView) v).setImageDrawable(((MainActivity) context).playDrawable);
}
}
});
if(list.get(i).isPlaying()){
viewHolder.sent_voice_seekbar.setActive(list.get(i).seekbar_resume_position);
viewHolder.sent_voice_play.setImageDrawable(((MainActivity) context).pauseDrawable);
}else{
viewHolder.sent_voice_seekbar.setInactive(list.get(i).seekbar_resume_position);
viewHolder.sent_voice_play.setImageDrawable(((MainActivity) context).playDrawable);
}
return convertView;
}
public void stopItemAudio(AudioRow item, SelfUpdatingSeekBar seekBar){
if(mMediaPlayer == null){
mMediaPlayer = new MediaPlayer();
}
mMediaPlayer.stop();
item.setPlaying(false);
int percentage = getProgressPercentage(mMediaPlayer.getCurrentPosition(), mMediaPlayer.getDuration());
item.setSeekBarResumePosition(percentage);
item.setMediaPlayerResumePosition(mMediaPlayer.getCurrentPosition());
seekBar.setInactive(percentage);
notifyDataSetChanged();
}
public void playItemAudio(final AudioRow item, SelfUpdatingSeekBar seekBar){
if(mMediaPlayer == null){
mMediaPlayer = new MediaPlayer();
}
try {
mMediaPlayer.reset();
mMediaPlayer.setDataSource(item.audioPath);
mMediaPlayer.prepare();
mMediaPlayer.seekTo(item.mediaPlayer_resume_position);
seekBar.setActive(item.seekbar_resume_position); // Starts from where it stopped
mMediaPlayer.start();
// declaring Item started to play
item.setPlaying(true);
notifyDataSetChanged();
mMediaPlayer.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
item.setSeekBarResumePosition(0);
item.setPlaying(false);
}
});
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
public int getProgressPercentage(long currentDuration, long totalDuration){
Double percentage = (double) 0;
long currentSeconds = (int) (currentDuration / 1000);
long totalSeconds = (int) (totalDuration / 1000);
// calculating percentage
percentage =(((double)currentSeconds)/totalSeconds)*100;
// return percentage
return percentage.intValue();
}
}
The problem is when I click on Item1, and it starts playing, and click on Item2 both SeekBars animate at the same time, and that is expected since I did not stop Item1 on the click of Item2
My question is:
What is the proper way to stop the previous played Item1 on the click of Item2?
Your SeekBar implementation should not have its own MediaPlayer. Have only one MediaPlayer instance in your activity. Every time a "play" button is clicked in your list view you do something like this:
MediaPlayer mMediaPlayer = ((MainActivity) context).getSingleMediaPlayer();
((MainActivity) context).setCurrentlyPlayingItem(i);
mMediaPlayer.reset();
mMediaPlayer.setDataSource(item.audioPath);
mMediaPlayer.prepare();
notifyDatasetHasChanged()
Now on your getView() implementation, if the first argument: i is not equal to the currently playing item of MainActivity its SeekBar should be at zero.
MainActivity should also be the one implementing the update runnable. At this point you might want to use just a normal SeekBar. To update the correct View, you need to figure out first if it is visible, because the user could have scrolled to a different position, so you need this function in your MainActivity:
public View getVisibleItemView(int position){
if(listview.getCount() > 0) {
int start = listview.getFirstVisiblePosition();
for (int i = start, j = listview.getLastVisiblePosition(); i <= j; i++) {
if (i == position) {
return listview.getChildAt(i - start);
}
}
}
return null;
}
This function returns the view with the SeekBar that you want to update, but only if it is visible, otherwise it returns null. in your update runnable you should call it, and if the result is not null, you update the SeekBar.
Also, you might want to consider using an interface instead of casting context references to MainActivity in your adapter.
This sort of question seems to have come up a here a lot, but they are all a slightly different case to mine and have just confused me. I am trying to get my SeekBar to synchronise with a single and specified mp3. With the code below, the audio plays and if you move the SeekBar the audio DOES seek, however the SeekBar does not move on its own to update with the music. Could someone please see if they can find the problem that is stopping the SeekBar from updating?
FIXED NOW but don't know why it fixed.
This is my FIXED Java code. Changes in bold:
MediaPlayer mediaPlayer;
Button buttonPlayPause;
ImageView Image;
SeekBar seekBar;
Handler handler;
private int stateMediaPlayer;
private final int stateMP_NotStarter = 0;
private final int stateMP_Playing = 1;
private final int stateMP_Pausing = 2;
private int mediaPos;
private int mediaMax;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.playerwere);
Image = (ImageView) findViewById(R.id.pdfview);
Image.setImageResource(R.drawable.wereim);
seekBar = (SeekBar) findViewById(R.id.seekBar);
buttonPlayPause = (Button) findViewById(R.id.playpause);
buttonPlayPause.setOnClickListener(buttonPlayPauseOnClickListener);
seekBar.setOnSeekBarChangeListener(seekBarOnSeekChangeListener);
initMediaPlayer();
mediaPos = mediaPlayer.getCurrentPosition();
mediaMax = mediaPlayer.getDuration();
seekBar.setMax(mediaMax); // Set the Maximum range of the
// seekBar.setProgress(mediaPos);// set
// current progress to song's
seekBar.setProgress(mediaPos);// set current progress to song's
handler.removeCallbacks(moveSeekBarThread);
handler.postDelayed(moveSeekBarThread, 100);
}
private Runnable moveSeekBarThread = new Runnable() {
public void run() {
if (mediaPlayer.isPlaying()) {
int mediaPos_new = mediaPlayer.getCurrentPosition();
int mediaMax_new = mediaPlayer.getDuration();
seekBar.setMax(mediaMax_new);
seekBar.setProgress(mediaPos_new);
handler.postDelayed(this, 100); // Looping the thread after 0.1
// seconds
} **else {
int mediaPos_new = mediaPlayer.getCurrentPosition();
int mediaMax_new = mediaPlayer.getDuration();
seekBar.setMax(mediaMax_new);
seekBar.setProgress(mediaPos_new);
handler.postDelayed(this, 100); // Looping the thread after 0.1
// seconds
}**
}
};
private void initMediaPlayer() {
handler = new Handler();
mediaPlayer = new MediaPlayer();
mediaPlayer = MediaPlayer.create(were.this, R.raw.were);
stateMediaPlayer = stateMP_NotStarter;
}
Button.OnClickListener buttonPlayPauseOnClickListener = new Button.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (stateMediaPlayer) {
case stateMP_NotStarter:
mediaPlayer.start();
buttonPlayPause
.setBackgroundResource(android.R.drawable.ic_media_pause);
stateMediaPlayer = stateMP_Playing;
break;
case stateMP_Playing:
mediaPlayer.pause();
buttonPlayPause
.setBackgroundResource(android.R.drawable.ic_media_play);
stateMediaPlayer = stateMP_Pausing;
break;
case stateMP_Pausing:
mediaPlayer.start();
buttonPlayPause
.setBackgroundResource(android.R.drawable.ic_media_pause);
stateMediaPlayer = stateMP_Playing;
break;
}
}
};
SeekBar.OnSeekBarChangeListener seekBarOnSeekChangeListener = new SeekBar.OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
if (fromUser) {
mediaPlayer.seekTo(progress);
seekBar.setProgress(progress);
}
}
};
}
I want to play live stream using VideoView but what is the error I got error :
04-21 21:13:27.326: D/MediaPlayer(29449): Couldn't open file on client side, trying server side
04-21 21:13:27.529: D/dalvikvm(29449): GC_CONCURRENT freed 81K, 2% free 9218K/9328K, paused 5ms+3ms, total 28ms
04-21 21:14:17.654: E/MediaPlayer(29449): error (1, -1004)
04-21 21:14:17.654: E/MediaPlayer(29449): Error (1,-1004)
04-21 21:14:17.654: D/VideoView(29449): Error: 1,-1004
My code to play the live streaming :
public class VideoStreamingActivity extends Activity implements OnPreparedListener,OnErrorListener{
private Vibrator vibrator;
private boolean readyToPlay;
private ProgressBar progress;
private ProgressDialog loading;
private TextView mediaTimeElapsed;
private TextView mediaTime;
private TextView mediaInfo;
private Button play;
private Button stop;
private String url;
private VideoView vvStreaming;
private CountDownTimer timer;
/** Called when the activity is first created.*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(R.layout.activity_video_streaming);
//variables init
vvStreaming = (VideoView)findViewById(R.id.vvStreaming);
url ="http://www.ted.com/talks/download/video/8584/talk/761";
play = (Button)findViewById(R.id.btnPlay);
stop = (Button)findViewById(R.id.btnPause);
mediaInfo = (TextView) findViewById(R.id.tvMediaInfo);
mediaTime = (TextView)findViewById(R.id.tvTime);
mediaTimeElapsed = (TextView)findViewById(R.id.tvTimeElapsed);
progress = (ProgressBar) findViewById(R.id.progressBar1);
loading = new ProgressDialog(this);
loading.setMessage("Loading...");
vibrator = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
//flag indicating that content is ready for playback
readyToPlay = false;
// listeners for VideoView:
//vvStreaming.setOnPreparedListener(this);
//vvStreaming.setOnErrorListener(this);
vvStreaming.setVideoURI(Uri.parse(url));
vvStreaming.setMediaController(new MediaController(this));
vvStreaming.start();
}
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
loading.hide();
return false;
}
#Override
public void onPrepared(MediaPlayer mp) {
Log.d(this.getClass().getName(), "prepared");
mp.setLooping(true);
loading.hide();
//onVideoSizeChangedListener declaration
/* mp.setOnVideoSizeChangedListener(new OnVideoSizeChangedListener() {
#Override
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
if(width!=0 && height!=0) {
Log.d(this.getClass().getName(), "logo off");
logo.setVisibility(ImageView.INVISIBLE);
} else {
Log.d(this.getClass().getName(), "logo on");
logo.setVisibility(ImageView.VISIBLE);
}
}
});*/
//onBufferingUpdateListener declaration
mp.setOnBufferingUpdateListener(new OnBufferingUpdateListener()
{
// show updated information about the buffering progress
#Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
Log.d(this.getClass().getName(), "percent: " + percent);
progress.setSecondaryProgress(percent);
}
});
//onSeekCompletionListener declaration
mp.setOnSeekCompleteListener(new OnSeekCompleteListener() {
//show current frame after changing the playback position
#Override
public void onSeekComplete(MediaPlayer mp) {
if(mp.isPlaying()) {
// playMedia(null);
// playMedia(play);
} else {
// playMedia(null);
// playMedia(play);
// playMedia(null);
}
// mediaTimeElapsed.setText(countTime(vvStreaming.getCurrentPosition()));
}
});
mp.setOnCompletionListener(null);
readyToPlay = true;
int time = vvStreaming.getDuration();
int time_elapsed = vvStreaming.getCurrentPosition();
progress.setProgress(time_elapsed);
timer = new CountDownTimer(time, 500) {
#Override
public void onTick(long millisUntilFinished) {
// mediaTimeElapsed.setText(countTime(vvStreaming.getCurrentPosition()));
float a = vvStreaming.getCurrentPosition();
float b = vvStreaming.getDuration();
progress.setProgress((int)(a/b*100));
}
#Override
public void onFinish() {
// stopMedia(null);
}
};
//onTouchListener declaration
progress.setOnTouchListener(new OnTouchListener() {
// enables changing of the current playback position
#Override
public boolean onTouch(View v, MotionEvent event) {
ProgressBar pb = (ProgressBar) v;
int newPosition = (int) (100 * event.getX() / pb.getWidth());
if (newPosition > pb.getSecondaryProgress()) {
newPosition = pb.getSecondaryProgress();
}
switch (event.getAction()) {
// update position when finger is DOWN/MOVED/UP
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
pb.setProgress(newPosition);
vvStreaming.seekTo((int) newPosition * vvStreaming.getDuration() / 100);
break;
}
return true;
}
});
}
}
Check your manifest user-permission:
<uses-permission android:name="android.permission.INTERNET" />