I have a listview of all musics in the phone. Whenever user click on the item of the listview it starts a same activity of my player class every time. The first music chosen by user plays great. But the problem is when user choose the second music, it starts play new one without stopping previous one. So the result is two musics playing together.
This is my listview onItemClickListener()
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView tv = (TextView) view;
String songId = tv.getText().toString();
Intent i = new Intent(getActivity(), player.class);
i.putExtra("id", songId);
startActivity(i);
}
});
and the main portion of my player class:
private MediaPlayer mp;
Bundle extras = getIntent().getExtras();
String songId = null;
if(extras != null){
songId = extras.getString("id");
play.setBackgroundResource(R.drawable.pause);
}
find(songId);
private void find(String songName) {
for(int t = 0; t < songs.size(); t++){
if(("" + songs.get(t)).endsWith(songName)){ //songs, an ArrayList of music files path
Uri myUri = Uri.parse("" + songs.get(t));
stopPlaying();
mp = MediaPlayer.create(this, myUri);
mp.start();
break;
}
}
}
private void stopPlaying() {
if (mp != null) {
mp.stop();
mp.release();
mp = null;
}
}
I have tried a several way to get rid of this problem. But I din't understand what I am missing. I can provide full code if needed.
Since you have called stopPlaying method, ideally it should stop. Try adding this line of code
mp.setLooping(false); before mp.start();
Not sure if this would fix the issue.
Also Try this
if(mp!=null && mp.isPlaying())
instead of
if (mp != null)
in addition to previous answer
Define your media player as static
static MediaPlayer mp;
Related
I have created a ListView and an each ListView item has 2 TextViews, an image and an audio file. Everything works fine and the audio files are played, but when I click on items several times and scroll up and down, the audio file is not played. What is wrong at that part?
Here is my java code :
public class NumbersActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_numbers);
ArrayList<Word> words = new ArrayList<>();
words.add(new Word("one","un",R.drawable.number_one,R.raw.one));
words.add(new Word("two","deux",R.drawable.number_two,R.raw.two));
.......
ListView listView = (ListView) findViewById(R.id.numberViewlist);
WordAdapter itemsAdapter = new WordAdapter(this,
words,R.color.category_numbers,listView);
listView.setAdapter(itemsAdapter);
}
}
and this is the code for the WordAdaper :
lView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
MediaPlayer mp = MediaPlayer.create(getContext(),currentWord.getsound());
mp.start();
}
});
Use this code:
if (mp != null) {
if (mp.isPlaying()) {
mp.stop();
}
mp.release();
mp = null;
}
Please refer this Doc !
I got a problem with playing two MediaPlayers simultaneously.
In my code I made a spinner to let the user to choose his first song and then the second song, at the moment that the user chooses the first song it starts to play and when the user choose the second song it will play with the first one.
But the problem is that, when the user chse the second song it stops the first one...
What can I do to fix it?
Ty!
The code:
public void setSpinner() {
Spinner spine = (Spinner) findViewById(R.id.spinner3);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.song, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spine.setAdapter(adapter);
final MediaPlayer mp1 = new MediaPlayer();
spine.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
{
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String st = parent.getItemAtPosition(position).toString();
if (st.equals("First Song")) {
setMedia1(mp1);
mp1.start();
}
if (st.equals("Second Song")) {
setMedia2(mp1);
mp1.start();
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
public void setMedia1(MediaPlayer mp2) {
Bundle b1=getIntent().getExtras();
float s = b1.getFloat("speed");
Bundle b2=getIntent().getExtras();
float v = b2.getFloat("volume");
try {
String s1 = getIntent().getStringExtra("song1");
final Uri uri1 = Uri.parse(s1);
mp2.setDataSource(getApplicationContext(), uri1);
mp2.prepare();
mp2.setVolume(v,v);
mp2.setPlaybackParams(mp2.getPlaybackParams().setSpeed(s));
} catch (Exception e) {
}
}
public void setMedia2(MediaPlayer mp2) {
Bundle b3 = getIntent().getExtras();
float sp1 = b3.getFloat("speed1");
Bundle b4 = getIntent().getExtras();
float vo1 = b4.getFloat("volume1");
try {
String s2 = getIntent().getStringExtra("song3");
final Uri uri2 = Uri.parse(s2);
mp2.setDataSource(getApplicationContext(), uri2);
mp2.prepare();
mp2.setVolume(vo1, vo1);
mp2.setPlaybackParams(mp2.getPlaybackParams().setSpeed(sp1));
} catch (Exception e) {
}
}
try SoundPool,its a better method of dealing with multiple audio files at the same time.
Heres the documentation:
http://developer.android.com/reference/android/media/SoundPool.html
Heres the example:
http://examples.javacodegeeks.com/android/android-soundpool-example
Hope this helps
Reference
Try using two MediaPlayer instances. Change your setSpinner method to do something like:
public void setSpinner() {
Spinner spine = (Spinner)findViewById(R.id.spinner3);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.song, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spine.setAdapter(adapter);
// You were only creating a single MediaPlayer instance in your version...
final MediaPlayer mpA = new MediaPlayer();
final MediaPlayer mpB = new MediaPlayer();
spine.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
{
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String st = parent.getItemAtPosition(position).toString();
if (st.equals("First Song")) {
// Use mpA for the first song
setMedia1(mpA);
mpA.start();
}
else if (st.equals("Second Song")) {
// Use mpB for the second song
setMedia2(mpB);
mpB.start();
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
I do not know if that will get the exact behavior you are looking for, but it stands a better chance at playing two songs simultaneously than using a single MediaPlayer instance.
My app has a layout looking like this
LAyout
And this is inflated by a adapter, creating a listview containing many such layouts with the contents of the layout changing according to the position.
Everything is ok upto this.
Now I need to set a onClickListener on the playButton and it will play a very short music and its imagesrc will change from play image to pause image.
I implemented the the playing of music in the adapter itself by setting an onClickListeners on each of playButton in the layouts I inflated. in getView(). (is this the best way to do this?)
Now that also worked perfectly untill I tried changing the imagesrc when the playButtton will be Clicked.
What happens is the last layout that is inflated by the adapter only its imagesrc changes on clicking. That is no matter which layout's playButton I click on, the correct music plays, but the imagesrc is changed of the playButton in the last layout inflated last by the adapter.
Why is this happening?
Here is the code of my adapter
public class MyAdapter extends ArrayAdapter<MyCustomObject> {
private static AudioManager mAudioManager;
private static MediaPlayer mMedia;
private ImageView mPlayButton;
private Context mContext;
/**
* A custom created Constructor
* this is used to inflate a custom created layout file
*/
public MyAdapter(Activity context, ArrayList<MyCustomObject> wordArrayList) {
super(context, 0, wordArrayList);
this.mContext = context;
}
private MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mPlayButton.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_action_play));
releaseMediaPlayer();
}
};
public static AudioManager.OnAudioFocusChangeListener mOnAudioFocusChangeListener = new AudioManager.OnAudioFocusChangeListener() {
#Override
public void onAudioFocusChange(int focusChange) {
if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT ||
focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
mMedia.pause();
mMedia.seekTo(0);
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
mMedia.start();
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
releaseMediaPlayer();
}
}
};
public static void releaseMediaPlayer() {
if (mMedia != null) {
mMedia.release();
mMedia = null;
mAudioManager.abandonAudioFocus(mOnAudioFocusChangeListener);
}
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
View currentView = convertView;
if (currentView == null)
currentView = LayoutInflater.from(getContext()).inflate(R.layout.layout_to_be_inflated, parent, false);
final MyCustomObject currentObject = getItem(position);
/**Setting the {#id englishID} of the miwokenglishlist.xml
* to the the desired english value
*/
//Getting the ID
TextView defalutTextView = (TextView) currentView.findViewById(R.id.englishID);
//Changing the text of the view
defalutTextView.setText(currentWordObject.getEnglishWord());
/**
* Setting the {#id miwokID} of the miwokenglishlist.xml
* to the current miwok word
*/
// Getting the ID
TextView secondaryTextView = (TextView) currentView.findViewById(R.id.secondID);
// Changing the text to the current miwok word
miwokTextView.setText(currentObject.getSecondWord());
/**
* Checking whether current Word object has a image associated with it or not
*/
// Getting the image id from the current word object
int currImageID = currentObject.getImageResourceID();
// Getting the ID for the image in miwokenglishlist.xml
ImageView imageViewID = (ImageView) currentView.findViewById(R.id.imageID);
// if image is present for the current object
if (currImageID != -1) {
// Setting the image on the layout
imageViewID.setImageResource(currImageID);
}
// if image is not present for the current object
else {
imageViewID.setVisibility(View.GONE);
}
mPlayButton = (ImageView) currentView.findViewById(R.id.imageButton);
mPlayButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// If there are already underlying resources
releaseMediaPlayer();
int result = mAudioManager.requestAudioFocus(mOnAudioFocusChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
mMedia = MediaPlayer.create(getContext(), currentWordObject.getPronunciation());
mMedia.start();
mMedia.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
`//Changing the playButton resource to pause`
mPlayButton.setImageDrawable(ContextCompat.getDrawable(mContext,
R.drawable.ic_action_pause));
}
});
mMedia.setOnCompletionListener(mCompletionListener);
}
}
});
// Returning the modified inflated View
return currentView;
}
}
So how do i do this?
UPDATE: I solved the issue, i was calling setDrawablesrc on the mPlayButton id which referred to the playButton in the last layout which was inflated. So, I called the setDrawablesrc on the view that was passed in the onClick method of the onClickListener.
Here is the updated code
mPlayButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View view) {
// If there are already underlying resources
releaseMediaPlayer();
int result = mAudioManager.requestAudioFocus(mOnAudioFocusChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
//Storing the view in the instance variable to refer to it in the onCompletionlIstener of the MediaPlayer
mPlayButtonView = (ImageView) view;
mMedia = MediaPlayer.create(getContext(), currentWordObject.getPronunciation());
mMedia.start();
mMedia.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
//Changing the imagesrc of the view that is passed
((ImageView)view).setImageDrawable(ContextCompat.getDrawable(mContext,
R.drawable.ic_action_pause));
}
});
mMedia.setOnCompletionListener(mCompletionListener);
}
}
});
And in the onCompletionListener i took the instance variable and changed its imagesrc.
Worked perfectly! :)
Now one question lies, is this the best way to do this?
Hi i have recyclerView row item consists of a play Button(Which change to stop and Play as toggle) and a play seek bar and TextView.
The each row plays different audios .
When i click on play button of respective row i am able to stop the other row audio ..
Addressing to the problem ..
When i am playing a audio of a respective row, the button of earlier row has to stow a play symbol (in the sense it has to change the state ) please help me how to update the other rows of recyclerView when the other item is clicked
#Override
public void onBindViewHolder(final ViewHolder holder, final int i) {
if (holder.viewType == ROW_TYPE){
// holder.play_button.setImageResource(R.drawable.play_button);
if(i == selected_item){
}
else {
// holder.play_button.setImageResource();
}
JSONObject obj;
String mp3_url = null, caption = null, thumbnail_url = null;
try {
obj = voicesArray.getJSONObject(i);
mp3_url = obj.getString("mp3_url");
caption = obj.getString("caption");
thumbnail_url = obj.getString("thumbnail_url");
} catch (JSONException e) {
e.printStackTrace();
}
holder.list_text.setText(caption);
imageLoader.DisplayImage(thumbnail_url, holder.list_image);
final String finalMp3_url = mp3_url;
holder.play_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
selected_item = i;
int ii = holder.getOldPosition();
// holder.play_button.setImageResource();
// updateItem(ii);
if(player != null){
player.reset();
holder.play_button.setImageResource(R.drawable.play_button);
myAudioPlay(holder, finalMp3_url);
}
else {
myAudioPlay(holder,finalMp3_url);
/*if (player == null) {
player = new MediaPlayer();
playAudiFile(finalMp3_url);
holder.play_button.setImageResource(R.drawable.pause_button);
} else if (player.isPlaying()) {
holder.play_button.setImageResource(R.drawable.play_button);
player.stop();
Log.d("player", "" + player);
player.reset();
} else {
holder.play_button.setImageResource(R.drawable.pause_button);
playAudiFile(finalMp3_url);
}*/
}
}
});
}
}
Apparently the purpose of a recyclerView is to recycle the views to minimize memory usage required for rendering view so setting an image in the view is not an apt solution,Their are many solutions for your problem the One i would pick(Pseudo code) is given below
Step 1. Create a Boolean value in your model class
bool isPlay=true;
Step 2. When you are playing an audio loop through your Model for the recycler adapter and set the value for isPlay accourdingly
for(object obj in listOfModels)
if(obj.Id!=idOfthePlayingView)
obj.isPlay=false;
Then notify your adapter
yourRecyclerAdapterObject.notifyDatasetChanged()
I want played musics According to item of list for example if clicked on Forty items,played Forty musics
Im use from followin code but only played First music.
Where is the problem??
this is my activity:
int intArray[] = {R.raw.alaa,R.raw.basemtavasol};
.
.
.
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
// TODO Auto-generated method stub
super.onListItemClick(l, v, position, id);
Faslha fasl = faslha.get(position);
Intent next = new Intent(this, Second.class);
next.putExtra("my_array", intArray);
next.putExtra("thisfasl", fasl);
startActivity(next);
}
.
.
.
this is Second Activity:
.
.
.
Bundle extras = getIntent().getExtras();
int[] arrayInB = extras.getIntArray("my_array");
songProgressBar = (SeekBar) findViewById(R.id.sb);
mp = MediaPlayer.create(this, arrayInB[0]);
.
.
.
I am not getting why you are starting another activity. Instead of calling activity directly
Run Media player.
mMediaPlayer = MediaPlayer.create(context,"your path");
mMediaPlayer.setLooping(false);
mMediaPlayer.start();