In the following class the playback of the .ogg file is triggered.
public class HomeScreenFragment extends Fragment {
...
private AudioPlayer mPlayer = new AudioPlayer();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
...
mStandbyButton = (Button)v.findViewById(R.id.standby_button);
mStandbyButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mPlayer.play(getActivity());
}
});
}
public void onDestroy() {
super.onDestroy();
mPlayer.stop();
}
}
Despite of using the setOnCompletionListener() the files keep on looping unlike .wav
public class AudioPlayer {
private MediaPlayer mPlayer;
public void stop() {
if(mPlayer != null) {
mPlayer.release();
mPlayer = null;
}
}
public void play(Context c) {
stop();
mPlayer = MediaPlayer.create(c, R.raw.hassium);
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
stop();
}
});
mPlayer.start();
}
}
How to ensure they don't loop once playback is completed?
I could possibly work with .wav files but curious as to why this happens and if possible prevent them from looping.
Searching shows that there may be ANDROID_LOOP in ogg metadata: ANDROID_LOOP = true -- how to avoid MediaPlayer looping audios with this metadata tag
Related tickets in Google Code:
MediaPlayer setLooping(false) does not work for ogg files
Should document ANDROID_LOOP flag for OGG files
You can try to use MediaPlayer.setLooping(false) to see if it can help
Related
I want to play a music file which will be retrieved from a cloud storage service (such as Google drive or Mega.nz). I shared the file so anyone who have the link can access to it.
I'm using MediaPlayer class to handle this playback. So when I tried a direct link something like this, it worked well. But when I tried with a link from Google Drive, such as this, it didn't work.
Here is some code which I used to play the music file:
MusicPlayerFragment class
public class MusicPlayerFragment extends Fragment {
private MusicPlayer musicPlayer;
boolean isPlaying;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View layout = inflater.inflate(R.layout.fragment_music_player, container, false);
final ImageButton buttonPlayPause = layout.findViewById(R.id.button_play_pause);
buttonPlayPause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!isPlaying) {
musicPlayer.play();
buttonPlayPause.setImageResource(R.drawable.baseline_pause_24);
isPlaying = true;
}
else {
musicPlayer.pause();
buttonPlayPause.setImageResource(R.drawable.baseline_play_arrow_24);
isPlaying = false;
}
}
});
return layout;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
musicPlayer = new MusicPlayer();
musicPlayer.loadMedia("http://ssaurel.com/tmp/mymusic.mp3"); //work on physical device
//musicPlayer.loadMedia("https://drive.google.com/file/d/1Tj0a5f4dUMNnlPILr3vZzpPOwHKsP3Va/view?usp=sharing"); //doesn't work at all
}
}
MusicPlayer class
public class MusicPlayer{
private MediaPlayer mediaPlayer;
public void loadMedia(String url) {
if (mediaPlayer == null) {
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
try {
mediaPlayer.setDataSource(url);
mediaPlayer.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void play() {
if (mediaPlayer != null && !mediaPlayer.isPlaying()) {
mediaPlayer.start();
}
}
public void pause() {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.pause();
}
}
public void reset() {
if (mediaPlayer != null) {
mediaPlayer.reset();
}
}
public void release() {
if (mediaPlayer != null) {
mediaPlayer.release();
}
}
}
I'm working with SQL Server too, which will store data of the music and URL to that music file to play. But since it didn't work so there are 2 things I'm wondering:
1st: Where am I wrong in here? In my opinion, I'm suspecting that I'm not using the setDataSource(url) method in the correct way.
2nd: Is the URL of Google Drive in the right format to use? If it is not the right format to use with any (overloaded) setDataSource() method, then how can I store a music file with the right URL format it needs? (the right format like this, I think: "http://domain/path/audiofilename.mp3"). I'm accessing the database on local machine.
You have the answer hidden in your question itself. When you're passing the direct download link to the music, it works, meaning, you need to use something that will be able to directly download the file.
When you give the Google Drive link, you don't give the complete address of the file, instead, you go on the page which tells you to manually download the file.
You should use something like FirebaseStorage to store the songs, so you'll be able to get the direct download links of those songs.
I'm using MediaPlayer for playing sounds onClick. Until the sound is finished the click event is not play the sound again. How can it play the sound again on click, when the sound is currently playing?
final MediaPlayer mistake = MediaPlayer.create(getActivity(), R.raw.mistake);
tv_mistake.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mistake.start();
}
});
You must create a new MediaPlayer object to play the sound again like so.
tv_mistake.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mistake != null) {
mistake.release();
mistake = MediaPlayer.create(getActivity(), R.raw.mistake);
}
mistake.start();
}
});
You can read more about MediaPlayer in the following links.
Also a quite similar question
MediaPlayer, MediaPlayer Tutorial, MediaPlayer Tutorial From Google
Most of the errors in MediaPlayer comes due to improper handling of different states of its object.
You should release MediaPlayer object after completing playback or before calling start() again.
It is also recommended that once a MediaPlayer object is no longer being used, call release() immediately so that resources used by the internal player engine associated with the MediaPlayer object can be released immediately.
Create a MediaPlayer object as:
Mediaplayer mediaPlayer = null;
And call playMistakeSound() on button click:
tv_mistake.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
playMistakeSound()
}
});
Implement playMistakeSound() as:
void playMistakeSound() {
try {
// releases MediaPlayer object before calling create() again while previous is still playing
if (mediaPlayer != null){
mediaPlayer.reset();
mediaPlayer.release();
mediaPlayer = null;
}
mediaPlayer = MediaPlayer.create(getActivity() /*Context*/, R.raw.mistake);
// this will release MediaPlayer as soon as it completes
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
if (mp != null) {
mp.reset();
mp.release();
mediaPlayer = null;
}
}
});
mediaPlayer.start();
} catch (Exception e) {
// log exception and handle
e.printStackTrace();
}
}
setOnCompletionListener is detecting the completion of a song the first time only. In the code below song1 and song2 are played one after the other but the remaining songs are not being played.
I want to play the songs one by one and add some silence between songs.
MediaPlayer song0=new MediaPlayer();
int track = 0;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
song0=MediaPlayer.create(this,R.raw.song1);
play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
function();
}
});
song0.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer song0) {
track++;
loadsong();
function();
}
});
}
void loadsong()
{
if(track==1) song0=MediaPlayer.create(this,R.raw.song2);
if(track==2) song0=MediaPlayer.create(this,R.raw.song3);
if(track==3) song0=MediaPlayer.create(this,R.raw.song4);
}**strong text**
void function(){
if(track<4) song0.start();
else
song0.stop();
}
The problem is that you create MediaPlayer object every time you need to play songs. So you need to set OnCompletionListener every time after creating MediaPlayer object for another song.
So you can change a few lines in your code to fix the issue.
MediaPlayer song0=new MediaPlayer();
int track = 0;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
song0=MediaPlayer.create(this,R.raw.song1);
play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
function();
}
});
song0.setOnCompletionListener(m_CompletionListener);
}
void loadsong()
{
if(track==1) {
song0=MediaPlayer.create(this,R.raw.song2);
song0.setOnCompletionListener(m_CompletionListener);
}
if(track==2) {
song0=MediaPlayer.create(this,R.raw.song3);
song0.setOnCompletionListener(m_CompletionListener);
}
if(track==3) {
song0=MediaPlayer.create(this,R.raw.song4);
song0.setOnCompletionListener(m_CompletionListener);
}
}**strong text**
void function(){
if(track<4) song0.start();
else
song0.stop();
}
MediaPlayer.OnCompletionListener m_CompletionListener = new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer song0) {
track++;
loadsong();
function();
}
};
Another way to implement is to create only one MediaPlayer object and instead of creating MediaPlayer object everytime, call setDataSource function for playing other songs.
If you need this way more detail, i can make sample code also.
I hope it will help you!
Your onclickListener event only starting for once. If you want to play song one by one you have to create a loop or have to do it recursively. Here's a snippet where I used song0.setOnCompletionListener inside loadsong() and in the event recursively called loadsong() every time. Changed your loadsong() method a little bit. Here is the code:
public class MainActivity extends AppCompatActivity {
private Button play;
MediaPlayer song0 = new MediaPlayer();
int track = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
play = findViewById(R.id.play);
play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
loadsong();
}
});
}
void loadsong() {
track++;
if (track == 1) {
song0 = MediaPlayer.create(this, R.raw.track1);
song0.start();
}else if (track == 2) {
song0 = MediaPlayer.create(this, R.raw.track2);
song0.start();
}else if (track == 3) {
song0 = MediaPlayer.create(this, R.raw.track3);
song0.start();
}else if (track > 3) {
song0.stop();
}
song0.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer song) {
song.stop();
loadsong();
}
});
}
}
I am trying to develop a simple test project that plays sound when I tap the button and stop automatically after a few minutes after playing the sound.
Here is a code snippet:
Code for playing:
if (mPlayer != null) mPlayer = null;
mPlayer = MediaPlayer.create(this, R.raw.shush_v2);
mPlayer.setLooping(true);
mPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
}
});
Code for stopping:
if(mPlayer != null && mPlayer.isPlaying()) {
mPlayer.stop();
mPlayer.reset();
mPlayer.release();
mPlayer = null;
}
But sometimes I can still hear two sounds playing after I've stopped the sound.
Have so ever seen this behaviour before?
You should clear your media player.
//example usage of clearing media player when its over.
ourSong.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
clearMediaPlayer(mp);
}
});
//You can use this to stop media player.
private void clearMediaPlayer(MediaPlayer mp){
if(mp!=null){
mp.stop();
mp.release();// this will clear memory
mp = null;
}
}
public class PlayerApp extends Activity {
Button btnStart;
MediaPlayer mediaPlayer = null;
// Use the handler to stop the Player, after specific time
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_player_app);
btnStart = (Button)findViewById(R.id.btnStart);
btnStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view)
{
// Initialize Player and start it.
// Call the Handler same time.
mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.test);
mediaPlayer.start();
startHandler();
}
});
}
private void startHandler()
{
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
// if Player is not null, then Stop it and Reset Null.
if(mediaPlayer!=null)
{
mediaPlayer.stop();
mediaPlayer = null;
}
}
}, 2500);
}
}
I want to play Sound Files from raw folder using MediaPlayer but I don't want to use MediaPlayer.create() method, since I want to play it multiple times and want to retain MediaPlayer object. I was successful in compiling the following code but it plays nothing and I can't hear any sound.
public void STARTSOUND(SOUND sound) throws IOException {
switch(sound) {
case SOUND_MENUBG:
Uri uri = Uri.parse("R.raw.mainmenu");
PLAYSOUND(uri);
break;
}
}
public void PLAYSOUND(Uri file) throws IOException {
mPlayerLoopSound.setDataSource(GameManager.getInstance().getCurrentActivity(),file);
mPlayerLoopSound.prepareAsync();
mPlayerLoopSound.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
if (!mPlayerLoopSound.isPlaying()){
mPlayerLoopSound.setVolume(1.0f, 1.0f);
//start the player
mPlayerLoopSound.start();
}
}
});
}
The onPrepared() method never gets called..
Am I doing anything wrong?
private void playButtonSound(final Context context, final int resourceId)
{
final MediaPlayer mediaPlayer = MediaPlayer.create(context, resourceId);
if (mediaPlayer != null)
{
mediaPlayer.setOnCompletionListener(new OnCompletionListener()
{
#Override
public void onCompletion(MediaPlayer mediaPlayer)
{
if (mediaPlayer != null)
{
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
}
});
mediaPlayer.start();
}
}
Call this method like this.
playButtonSound(PopScreenActivity.this, R.raw.soundfilename);
First, hopefully you're initializing your MediaPlayer with:
mPlayerLoopSound = new MediaPlayer();
Next, make sure you call:
mPlayerLoopSound.setAudioStreamType(AudioManager.STREAM_MUSIC);
which:
Sets the audio stream type for this MediaPlayer. See AudioManager for a list of stream types. Must call this method before prepare() or prepareAsync() in order for the target stream type to become effective thereafter.
Then, in your OnPreparedListener(), when onPrepared() is called, notice the parameter it has: MediaPlayer mp. This is the MediaPlayer that is ready for playback, so you can use it:
#Override
public void onPrepared(MediaPlayer mp) {
if(!mp.isPlaying()) {
mp.setVolume(1.0f, 1.0f);
mp.start();
}
}