MediaPlayer can't play music from SD Storage - android

I'm trying to play music from a ListView (which takes data from a file path). But everytime i click, it gets an error like this:
09-14 09:58:42.996 1229-1276/? W/AudioTrack﹕ AUDIO_OUTPUT_FLAG_FAST denied by client
Even I use file path directly, it still doesn't work.
Here is my code:
private MediaPlayer mMediaPlayer;
private File dir = new File(Environment.getExternalStorageDirectory() + "/MyOwnMusicFolder");
private File[] files;
public void playSong(int position){ //position of the item in the ListView
if(mMediaPlayer !=null) {
if(mMediaPlayer.isPlaying()){
mMediaPlayer.pause();
}
try {
mMediaPlayer.setDataSource(dir + File.separator + files[position].getName());
mMediaPlayer.prepare();
mMediaPlayer.start();
}
catch (IOException e){
//something...
}
}
}
Edit: I'm using Android Studio + Android Studio Emulator
Edit 2: my mp3 files are completely normal

"Most likely, the tap sound got a AUDIO_OUTPUT_FLAG_FAST in order to use low-latency playback if possible, but the AudioTrack class considered the track settings to be incompatible with the low-latency audio output, so the flag got removed and the track got treated as if the flag hadn't been set to begin with. So I wouldn't consider this to be something to worry about.
As for the reason why the flag got denied; I'd still say that the most probable reason is a sample rate mismatch. The log in the question you linked to appears to have been added in this commit to the AOSP. But if we look at the master branch of the code base used on many Qualcomm-based devices we see that it still has the "AUDIO_OUTPUT_FLAG_FAST denied by client" log in the case were there was a sample rate mismatch. Which logs you get depends on the exact implemetation running on your device (i.e. which device and Android version you're running)."
Answer was taken from here. Credits to Michael
This most like is caused by mismatch on the sample rate and it should not affect the program runtime IF it is running on an actual device. Ref:

Related

What is happening in my Android app to cause it to lose data?

I have an android app. I have a few users who have a recurring problem: When the app shuts down, every file the app saved is gone. Every folder created is gone. Everything is completely wiped back to square one.
I am carefully saving the game data during every transition and game event, so I am very confident that this is not a case of the user crashing out before the data can be written. Somehow, the data that IS being written but then it's just not persisting after the app is removed from memory.
So-- has anyone had this situation and solved it? The only thing I can imagine is that there's some kind of "filesystem.commit" command I need to call after writing the files, but I can't find that documented anywhere.
Please help!
(Edit) I'm using native code to read and write files. The code I use to write a file is this:
bool WriteFile(char *theFilename, char *theDataPtr, int theLen)
{
FILE* aFile=fopen(theFilename,"w+");
if(!aFile) {Alert("unable to create file %s with error %d", theFilename, errno);return false;}
if(aFile) fclose(aFile);
aFile=fopen(theFilename,"w+b");
if(!aFile) {Alert ("unable to open file %s", theFilename);return false;}
if (aFile)
{
fwrite(theDataPtr, 1, theLen,aFile);
fclose(aFile);
return true;
}
return false;
}
Note:No customers are reporting any alert popups, which are just normal Android message boxes. Also note that this code works on almost every other system-- there's just a few customers that get the wiped data, so I was wondering if it's some weird security or some extra step I need to do to be 100% compatible with all systems.
(Edit) One more piece of information... this is the Java code I use to get the storage path for the app... all files that I try to write are put in this folder.
private void SetFilePath()
{
String storagePath = getFilesDir().getAbsolutePath();
// SDCARD
try {
String storageState = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(storageState))
storagePath = getExternalFilesDir(null).getAbsolutePath();
} catch (Exception e) {
Log.v(IDS.LOG,
"No permission to access external storage, missing android.permission.WRITE_EXTERNAL_STORAGE");
}
SetFilePathNative(storagePath); // Tells the native code the path
mStorageDir = storagePath;
}

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

Play single track spotify sdk

I am using the Spotify android SDK, and I am trying to get a single song to play, and I would like to potentially play a song after the current one is completed. The issue is that after the song completes Spotify plays a random song afterwards. Is it possible to play the song and not have anything else automatically play after it?
I am simply calling the app remotes player API play function,
mSpotifyAppRemote?.getPlayerApi()?.play(uri)
#Mikee you are doing nothing wrong, Spotify messes around with track replay if you are only using the Free version, if you use Premium it will work correctly. Funny enough if you try playing by an alblum or artist that works with the Free version.
I'm not an expert but from their documentation it looks like you could watch the PlayerState. I'm also not sure when a PlayerState event would trigger but if it's coming back relatively often you could check the track value and see if it's gone to null, or another value and work using that.
Here's a Java example from their website:
// Subscribe to PlayerState
mSpotifyAppRemote.getPlayerApi()
.subscribeToPlayerState()
.setEventCallback(new Subscription.EventCallback<PlayerState>() {
public void onEvent(PlayerState playerState) {
// See what values are in playerState, might be able to determine
// if it's now randomly playing?
final Track track = playerState.track;
if (track != null) {
Log.d("MainActivity", track.name + " by " + track.artist.name);
// If the track is now different, your song has finished, stop it?
}
}
});
I've put a few extra comments in the code above that might yield some results!

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.

VideoView / MediaPlayer Error (1, -18)

I have an application that is built to API level 2.2. This application contains a video that starts playing as soon as it is launched. The video is played inside a VideoView and the actually video file is stored in my internal storage (files directory for my apps package).
Most of the time it starts up just fine. But occasionally I get an error pop - up that says "Sorry, this video cannot be played." and has an Ok button. As soon as I press the ok button the video starts playing correctly. I need to figure out what is causing this error, or at the very least how I can catch whatever error it is and have it try again since it always works perfect after I hit ok. Inside the logs when this error box is shown I see these messages:
ERROR/PVOMXAudDecNode(21215): Ln 2232 OMX_EventError nData1 -2147479547 nData2 0
ERROR/PlayerDriver(21215): Command PLAYER_PREPARE completed with an error or info -18
ERROR/MediaPlayer(9282): message received msg=100, ext1=1, ext2=-18
ERROR/MediaPlayer(9282): error (1, -18)
ERROR/MediaPlayer(9282): callback application
ERROR/MediaPlayer(9282): back from callback
ERROR/MediaPlayer(9282): Error (1,-18)
DEBUG/VideoView(9282): Error: 1,-18
Where can I find a reference as to what exactly error code -18 indicates? And does anyone have any suggestions I could try to prevent it from happening in the first place. I have only observed This error on the Sprint Epic 4g.
Edit: well as far as I can tell no exceptions are getting thrown to me. I assume what is happening is that the video view knows to catch whatever exception is causing and it throws up the pop-up. Inside my log there is no exception stack trace just this reference to error -18.
As for how I am calling prepare. I use this:
mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer arg0) {
mVideoView.start();
}
});
and this:
mVideoView.setVideoPath(file.getAbsolutePath());
it calls prepare as part of setVideoPath (I assume it does anyway, but this method is undocumented). which causes onPrepared to get called in my listener.
Edit 2: for now i've just added an onErrorListener like so:
EDIT IMORTANT! this code will infinte error loop on ICS. For ICS devices I took out the setPath call, and returned false instead. It tries again by itself once and it succeeds.
mVideoView.setOnErrorListener(new OnErrorListener(){
#Override
public boolean onError(MediaPlayer arg0, int arg1, int arg2) {
Log.i(myTag, "MP ERROR: "+ arg1 + " - " + arg2);
mVideoView.setVideoPath(file.getAbsolutePath());
return true;
}
});
this catches the error and I can see in my logs that arg2 = -18 when this error happens. I just have it retry and return true so it doesn't throw up the dialog. So far i've never seen it fail twice in a row so this always starts the video correctly and doesn't make infinite loop.
I am still very interested if anyone can tell me exactly what error code -18 indicates though.
How do you catch potential exceptions thrown by prepare()? Do you catch IOException specifically and then retry calling the prepare()?
Try using prepareAsync() instead, which does not block and calls listener when player is ready. Also it does not throw IOException.
If you are running it on Froyo or Gingerbread the problem might be your device is not supporting playback of the file. Lower versions do not support videos encoded with formats other than baseline format. You may use some tools like video info on pc and check if the files are baseline formatted.

Categories

Resources