Android Visualizer won't pick up audio from Spotify streaming music - android

I'm making an Android audio visualizer app for streaming Spotify music. I'm using Spotify's android-streaming-sdk which creates a local service (no need to have the Spotify app installed) and it plays music from within the app. I'm having a difficult time getting Androids Visualizer library to pick up any audio from Spotify (it works fine if I use a local .mp3 file).
//Start playing spotify track
player.playUri(MainActivity.operationCallback,
VisualizerModel.getInstance().getTrackURI(), 0, 0);
.... other code ....
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
int audioSessionId = mediaPlayer.getAudioSessionId();
visualizer = new Visualizer(audioSessionId);
visualizer.setCaptureSize(audioSampleSize);
visualizer.setDataCaptureListener(this, Visualizer.getMaxCaptureRate(), true, true);
visualizer.setEnabled(true);
If I run this, everything compiles and runs okay, but the visualizer does not pick up any audio. This makes me thing that the audio sessionId is not the same one as Spotify is playing on. However, if I switch the audioSessionId to 0 (which should listen to all the audio sessions mixed from what I understand) it crashes with this error:
E/AudioEffect: set(): AudioFlinger could not create effect, status: -1
E/visualizers-JNI: Visualizer initCheck failed -3
E/Visualizer-JAVA: Error code -3 when initializing Visualizer.
According to their documentation that error means: Operation failed due to bad object initialization.
I'm targetting API 24 (Android 7.0).
Please let me know if you have suggestions or an alternative to using Android's Visualizer library. I feel like my main problem is that I'm not sure how to find the audioSessionId that Spotify is playing on, and because Spotify's android-streaming-sdk is in beta (and not mentioned on their website) there is virtually no documentation on it from what I can see on Github.
Thank you for taking the time to read my issue!

I was facing the same error. Adding "android.permission.RECORD_AUDIO" to manifest and requesting for runtime permissions fixed the issue.
to protect privacy of certain audio data (e.g voice mail) the use of the visualizer requires the permission android.permission.RECORD_AUDIO
Also
Creating a Visualizer on the output mix (audio session 0) requires permission Manifest.permission.MODIFY_AUDIO_SETTINGS
Android docs for Visualizer class

Related

Getting "Cannot initialize Visualizer engine, error: -3" when trying to use Visualizer with ExoPlayer

I am using ExoPlayer to play audio from a URL. I need to use a visualizer and picked the following library to do that: https://github.com/gauravk95/audio-visualizer-android
Problem is, when I use it with ExoPlayer (and not MediaPlayer), I am getting the following error even after making sure the permissions are in place:
java.lang.RuntimeException: Cannot initialize Visualizer engine, error: -3
at android.media.audiofx.Visualizer.<init>(Visualizer.java:218)
at com.example.visualizer.BaseVisualizer.setAudioSessionId(BaseVisualizer.java:196)
and this is while trying to create a new instance of Visualizer in BaseVisualizer:
mVisualizer = new Visualizer(audioSessionId);
The audio session Id is passed to BaseVisualizer from SimpleExoPlayer instance created to play the media. When I checked the logs, the session id is 0.
On the permissions front, I have added both RECORD_AUDIO and MODIFY_AUDIO_SETTINGS in manifest and checking for RECORD_AUDIO permission in run time if not given already. Permissions are getting granted correctly and I have verified the same in the app.
What could be going wrong here? Any ideas?
Thanks,
AB

MediaPlayer playing in background throws unexpected end of stream

We are developing an app that plays podcasts, we are using services and the media player to play the files that are in the server, in some Marshmallow devices we are encountering this error (Motorola g4):
W/MediaHTTPConnection: readAt 22575768 / 32768 => java.net.ProtocolException: unexpected end of stream
But it only happens when the app is killed and the service starts to run, when the app is in foreground it works well, we have noticed that the buffering is working well, but when the app is killed it cannot buffer more, it recahes a limit and then it throws that error... In other devices the buffering is working well.
Here is the chunk of the code that prepares the media player.
Map<String, String> headers = new HashMap<>();
headers.put("Content-Type", "audio/mp3");
headers.put("Accept-Ranges", "bytes");
headers.put("Status", "206");
mp = new MediaPlayer();
Uri uri = Uri.parse(songPath);
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
mp.setDataSource(getApplicationContext(), uri, headers);
mp.prepareAsync();
The headers were added because a post we saw, but it has the same result as if it doesn't have it.
Any advice?
Playing audio in background is a bit more complex than that. If you're just using a MediaPlayer, then that component's container (i.e. Activity) or the open http connection are probably being destroyed when Android decides to release resources. This can happen as soon as you switch to another app, or when the device (some other app) is using too many resources, or when the operating system decides it's a good time to do it.
However, MediaPlayer is just one part of the background audio playing.
I'd advice you to take a look at the oficial guide on how to build an Audio app.
https://developer.android.com/guide/topics/media-apps/audio-app/building-an-audio-app.html
I also found a well-explained step-by-step tutorial that can also help
https://code.tutsplus.com/tutorials/background-audio-in-android-with-mediasessioncompat--cms-27030

MediaPlayer not working on some android devices

I am trying to play the mp3 file from web using media player class , on some devices it is working fine but for few devices it is giving following error .
QCMediaPlayer mediaplayer NOT present
Unable to create media player
error (-38, 0)
Attempt to call getDuration without a valid mediaplayer
any help on this will be of great help.
In general error -38 means you are trying to call a function in wrong state for the player.
In your case as error says, you call getDuration() when player is not prepared or started. Set setOnPreparedListener() then start the player mp.start(), then you can call getDuration().
Check this Tutorial to stream audio from web

Detect Microphone State Change on Android to detect audio recording

I was trying to make an Android APP whose main function is to detect
if other android APPs are recording voice using Microphone. So far, I learned
that getRecordingState() from AudioRecord class can be used to get the state
of whether microphone is recording or not... but I need something like a broadcast
so I can catch the intent while the state of microphone starts to record voice...
any idea ? Thanks in advance!!
getRecordingState() returns the state for the particular AudioRecord instance that you call the method on. It doesn't give you some global state for all recorders.
There's currently no API available for applications to check globally whether there's ongoing recording from the microphone. The AudioFlinger has that information (though not about which specific application that is doing the recording), but the only way for you to get hold of it would be to modify Android itself and run your own custom Android version.
Try AudioManager.isMicrophoneMute()
http://developer.android.com/reference/android/media/AudioManager.html#isMicrophoneMute()

Using audioSessionId value to instantiate AudioFx class?

I have read the Android APIs and tried searching over the internet about declaring a custom audioSessionId and then using that audioSessionId to initialize an AudioFx class and assign my MediaPlayer or AudioTrack the hardcoded audioSessionId.
This method would allow me to create an AudioFx first and later attach a new MediaPlayer or AudioTrack to this audioSessionId.
I'm currently able to use this method on Android 2.3.6 but on Android 4.x I'm running into issues with errors that initialization fails or on other ICS/JellyBean devices this error is silent but calling a function leads to exceptions.
Samsung Galaxy S II [Android 4.0.3]: [Issue no longer happens with Android 4.0.4]
E/AudioEffect(13250): set(): AudioFlinger could not create effect, status: -38
E/AudioEffects-JNI(13250): AudioEffect initCheck failed -5
E/AudioEffect-JAVA(13250): Error code -5 when initializing AudioEffect.
W/WrapEqualizer(13250): createEqualizer() -> Effect library not loaded
Motorola Xoom [Android 4.1.2]
Fails it seems silently after the constructor. Then calling on getProperties() it crashes.
java.lang.RuntimeException: AudioEffect: set/get parameter error
at android.media.audiofx.AudioEffect.checkStatus(AudioEffect.java:1247)
at android.media.audiofx.Equalizer.getProperties(Equalizer.java:532)
Nexus 4 [Android 4.2.1]
Using audioSessionId=0 everything works fine but using any other number the device will report the following silent error every time I try to change the preset, band level, bass boost to ON or Virtualizer to ON. The effect ID reported is different depending on the FX I'm trying to modify.
W/AudioPolicyManagerBase(165): unregisterEffect() unknown effect ID 1381
Update 08/11/12:
I'm able to use audioSessionId as 0. I know it's deprecated but it works using the permission. <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> Should I be using the AudioFx with the audio session id 0?
You should look at: this
Apparently it is an unsolved issue came up in ICS, and probably wasn't solved either in JB.
Should I be using the AudioFx with the audio session id 0?
It will probably work in some cases, but don't count on it to continue to do so on future Android versions. You'll already be compromising interoperability between your app and other apps on Jellybean. Just take a look at what the AudioFlinger does when an effect is enabled:
// suspend all effects in AUDIO_SESSION_OUTPUT_MIX when enabling any effect on
// another session. This gives the priority to well behaved effect control panels
// and applications not using global effects.
// Enabling post processing in AUDIO_SESSION_OUTPUT_STAGE session does not affect
// global effects
if ((sessionId != AUDIO_SESSION_OUTPUT_MIX) && (sessionId != AUDIO_SESSION_OUTPUT_STAGE)) {
setEffectSuspended_l(NULL, enabled, AUDIO_SESSION_OUTPUT_MIX);
}
i know this issue
if somebody want to try
do this
Equalizer eq=null;
.
.
.
.
.
//in any function before initialization do this
if(eq!=null)
eq.release();
eq=new Equalizer(0, audiosessionid);
try it once
Other than session 0 which is the "deprecated global session", my understanding of the AudioFlinger code shows that sessions are only created for classes which actually do audio IO, that is, AudioRecord, AudioTrack, MediaPlayer etc. You should create these classes, and then get their session ID, and then attach the effect.
Any other value you supply for session ID will correspond to an audio session that does not exist, and so will fail.

Categories

Resources