Android SDK Mediaplayer.create randomly returns null - android

I am having an issue where occasionally the MediaPlayer.create method will return null, even though the audio file is definitely there. In fact, if I put the call to create into a while loop, the media player will eventually be created successfully. This only seems to happen on my phone (HTC Hero running 2.1) and never in the emulator.
Is this just an issue with the phone? Or is there a different way I should be playing these audio files?
Note that I want to be loading them dynamically which is get I am making the call to getIndentifer. If there is a better way of playing these dynamically please let me know.
public void playAudio(String audioFile){
//instance variable of type MediaPlayer
_player = null;
while(_player == null){
_player = MediaPlayer.create(_context, getResources().getIdentifier(audioFile, "raw", _context.getPackageName()));
}
_player.start();
}
Thanks.

A SoundPool (Docs) might be something to consider.

Related

Android: Possible maximum number of audiosessions or effect engines for audio? (EQ, REV...)

for awhile now, I am working on a media playing app. In this app, I also programmed a little 5 Band EQ using mainly this code:
try
{
AppPreferencesClass ap = new AppPreferencesClass(ctx);
if (Activity_Player.eq != null)
{
Activity_Player.eq.Dispose();
}
Activity_Player.eq = new Android.Media.Audiofx.Equalizer(0, Activity_Player.mediaPlayerSessionId);
Activity_Player.eq.SetEnabled(true);
await Task.Run(() =>
{
if (Activity_Player.EqActive)
{
if (ap.getAwesomeSound())
{
Activity_Player.eq.SetBandLevel(0, Convert.ToInt16(Activity_Equalizer.awesomesound0));
Activity_Player.eq.SetBandLevel(1, Convert.ToInt16(Activity_Equalizer.awesomesound1));
Activity_Player.eq.SetBandLevel(2, Convert.ToInt16(Activity_Equalizer.awesomesound2));
Activity_Player.eq.SetBandLevel(3, Convert.ToInt16(Activity_Equalizer.awesomesound3));
Activity_Player.eq.SetBandLevel(4, Convert.ToInt16(Activity_Equalizer.awesomesound4));
}
else
{
Activity_Player.eq.SetBandLevel(0, Convert.ToInt16(ap.getEQ0()));
Activity_Player.eq.SetBandLevel(1, Convert.ToInt16(ap.getEQ1()));
Activity_Player.eq.SetBandLevel(2, Convert.ToInt16(ap.getEQ2()));
Activity_Player.eq.SetBandLevel(3, Convert.ToInt16(ap.getEQ3()));
Activity_Player.eq.SetBandLevel(4, Convert.ToInt16(ap.getEQ4()));
}
}
});
}
catch
{
}
For many days, this worked just fine but out of NO WHERE, the catch block sometimes gets activated. But only occasionally.On other times, try works fine but there are just no more changes to the audio being played. This is odd enough, since I never changed anything on this code after it starting working.
I then tried another phone (Samsung S4) on my code and the eq worked just perfectly.
So this got me googleing and I think I might have heard that there can only be as many audiosession IDs after you just would run out. I tested and the audio session ID used here is somewhere at 74,000.
So this could be an issue I thought but this would easialy be tested because I already had this very app running in the google play store just an older version of it. I am 100 percent positive, that in this version the EQ worked on my phone. Otherwise I would have not uploaded that version.
Anyway, I downloaded my old app from the play store and here we go:
It doesnt work anymore. The EQ in the old version also has simply NO effect on the audio. While ofcourse on my other phones this old version works perfectly.
Before I am going to reset my own personal phone I wanted to ask you guys if this could be infact the case.
Another thing is, that I am using many static variables in order to get the EQ to work right. Actually, the variable EQ itself is static. Do maybe static variables sort of leave a "trace" behind and maybe I have set the eq up just "too" many times? Although I am disposing of the object before intialising it again (see in my code).
Summing up:
1.) Can there maybe be a maxmium number of EQ or AudioSessionIDs and I have passed those?
2.) Can creating static variables over and over again in my code cause a memory leak so big, even deinstalling the app doesnt do anything?
Thank you!
This is the error log:
11-20 12:16:43.736 E/AudioEffect(16990): set(): AudioFlinger could not create effect, status: -38
11-20 12:16:43.736 E/AudioEffects-JNI(16990): Error setting AudioEffect
11-20 12:16:43.737 E/AudioEffect-JAVA(16990): Error code -19 when initializing AudioEffect.
Thread started: #311-20 12:16:43.745 V/MediaPlayerNative(16990): unrecognized message: (6, 0, 0)
After 2 days of googeling and trying evetything out, here is the issue:
NOT CALLING RELEASE() will have you eventually have to REBOOT your phone. It wont allow too many instances of an EQ to be set.
Solution:
if (eq != null)
{
eq.Release();
}

MediaPlayer crashes on setDataSource with R.raw audio

I'm making an Audio Player app that will load some predefined audios from inside its raw resource folder.
I've sent the test APK for some people to test it, and it worked on 99% of the cases. But then, I started to get some crash reports on Crashlytics for a single device, the OnePlus A5000, running Android 8.1.0.
The stacktrace on crashlytics is as follows:
Fatal Exception: java.lang.IllegalStateException
at android.media.MediaPlayer._setDataSource(MediaPlayer.java)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1270)
at com.example.home.MediaPlayerHolder.loadMedia(MediaPlayerHolder.kt:56)
at com.example.home.HomePresenter.playSound(HomePresenter.kt:26)
at com.example.home.HomeFragment.onPlaySelected(HomeFragment.kt:178)
at com.example.home.SoundItemAdapter$ViewHolder$bind$1.onClick(SoundItemAdapter.kt:30)
package names were changed for privacy reasons
This is happening almost every time he clicks on the sound item play button. It also happens on the first time he clicks on any sound item.
I've tried to reproduce this crash on some devices, all of then have API <= 25, but I had no success doing so. All of them ran without an issue. I'm clueless of the probable cause of this error, or even if it's an edge case problem, or if there's indeed something wrong with my code.
This is how I'm loading the audio on the MediaPlayer:
if (mediaPlayer?.isPlaying == true) {
mediaPlayer?.release()
mediaPlayer = null
}
if (mediaPlayer == null) {
mediaPlayer = MediaPlayer()
}
val fileDescriptor = context.resources.openRawResourceFd(resource)
mediaPlayer?.setDataSource(fileDescriptor.fileDescriptor, fileDescriptor.startOffset, fileDescriptor.length)
fileDescriptor.close()
mediaPlayer?.prepare()
mediaPlayer?.start()
The reason was you can't start services in the background anymore after API 26. So you have to start ForegroundService above API 26.

What means the message "internal/external state mismatch corrected" at the MediaPlayer?

I work with a MediaPlayer and set the state of the player often programmatically like for example:
if(mp.isPlaying()) {
mp.pause();
animationPausedMusic();
}
private void animationPausedMusic() {
// Changing button image to play button
btn_play.setBackgroundResource(R.drawable.play);
... // more code
}
But sometimes the logcat gives me the message:
"internal/external state mismatch corrected"
And then the play and pause function is not working anymore.
What does this message mean? And how can I solve it?
After going through the android's native framework for media player I found that in source file mediaplayer.cpp inside function bool MediaPlayer::isPlaying() The developer is checking if the currentState of media player is in STARTED state and yet the media player is not playing any media, so it tries to change the state to PAUSED state so that the state consistency should be maintained for API users.(and here is where he is printing the message "ALOGE("internal/external state mismatch corrected");")
Now If you go through the media player state diagram below:
You would notice that this may happen when the MediaPlayer moved to 'STARTED' state after a call to start() and at this time for some obscure reason has not yet started the playback and you fire a MediaPlayer.isPlaying() method call , The Framework treat this as state inconsistency and moves to 'PAUSED' state and that's why you cannot see anything playing further.
However, if someone has some better understanding please share your thoughts!
I ran into this recently, and like some other questions say, it's this bug (marked obsolete alas)
https://code.google.com/p/android/issues/detail?id=9732
I found this error occurs when playing a MIDI file, but only sometimes. It happens when mp.isPlaying() is called quickly after mp.start()
If you can manage to not call mp.isPlaying() for a little bit, the error doesn't occur. In my case, a 10th of a second or so made the difference between getting the error or not. It's awkward, but it works.
e.g.
//setting a new track
mp.setDataSource(path);
mp.prepare();
mp.start();
//calling mp.isPlaying() here or shortly after starts the problem
//since we know it's playing, we can store that state, or call
updateUiPlaying(); //eg instead of updateUi();
//or just call some code here that takes more time first
updateScaledImages(); //something that might take time
Log.v(TAG, "mp.isPlaying = " + mp.isPlaying()); //now isPlaying() shouldn't cause that error
Also, I put a check in when I pause later.
mp.pause()
if(mp.isPlaying()){
//shouldn't be playing, must be in error
mp.stop();
mp.release();
mp = new MediaPlayer();
//any other initialization here
}
Though the problem doesn't occur if there is a wait before calling isPlaying()
Apparently there is more than one cause of this message. The following solution worked for me. It may or may not work for you. I called the method MediaPlayer.reset() immediately after instantiating the MediaPlayer object:
MediaPlayer mp = new MediaPlayer();
mp.reset();

If mp.isPlaying() causes app to crush

I am using a MediaPlayer. Somewhere inside my code I use:
if (mp != null) {
System.out.println("This");
if (mp.isPlaying()) //1
System.out.println("That"); //2
}
And as I run it, the app for some reason stops from working. If I delete the //1 and //2 lines, is runs normally and it prints "This". But why, I just want to check if mp is playing or not
as you can see on Android MediaPlayer documentations
public boolean isPlaying ()
Added in API level 1 Checks whether the MediaPlayer is playing.
Returns true if currently playing, false otherwise Throws
IllegalStateException if the internal player engine has not been
initialized or has been released.
check if you are initialising the MediaPlayer correctly and that you haven't released it before calling isPlaying().
please mark it as correct answer if that helped you.

sound stopped working phonegap media

$(document).on('click', '#bar img', function () {
alphaLetter = $(this).data('club-id');
audio_file_path = '/android_asset/www/audio/'+alphaLetter+'.mp3';
var my_media = null;
my_media = new Media(audio_file_path);
my_media.play();
});
Above is my code to play sound. It played sound, but when I restarted my project it has stopped working since then, and gives these errors;
E/MediaPlayer(2306): error (-19, 0)
E/MediaPlayer(2306): Attempt to call getDuration without a valid mediaplayer
E/MediaPlayer(2306): error (-38, 0)
E/MediaPlayer(2306): Error (-19,0)
This can be caused by you having too many media objects running at the same time. After the sound is finished you should release it.
The PhoneGap documentation says this about release:
Function media.release is a synchronous function that releases the
underlying operating systems audio resources. This function is
particularly important for Android as there are a finite amount of
OpenCore instances for media playback. Developers should call the
'release' function when they no longer need the Media resource.
I got the same error as well and using reset after finished sounds worked swell for me. Remember to call it after the sound has completed though, such as:
var my_media = null;
my_media = new Media(audio_file_path, function()
{
this.release();
});
my_media.play();
I've written more about the problem here if you are interested but the above solution should work well.
It seems as if this error pops up whenever you try to play the sound even though it is not fully loaded at the certain moment (Attempt to call getDuration).
I looked up the Phonegap documentation and couldn't find a method that may check for the availability of the sound. What you can do is:
Build a Timer that always waits for some time until the sound shall be played.
Use var media = new Media(src, mediaSuccess, [mediaError], [mediaStatus]); for some further handling when playing the sound fails.

Categories

Resources