MediaPlayer playing in background throws unexpected end of stream - android

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

Related

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

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

Playing sounds sequentially on android's google chrome (given the new restrictions on playing sound)

I have a small app that plays sequential sounds (a teaching app playing the sillables of a word)
This could be accomplished by firing an event right after each sound stopped playing. Something like:
var sounds = new Array(new Audio("1.mp3"), new Audio("2.mp3"));
var i = -1;
playSnd();
function playSnd() {
i++;
if (i == sounds.length) return;
sounds[i].addEventListener('ended', playSnd);
sounds[i].play();
}
(source)
However, now android chrome has implemented some new restrictions on how to play sound: Sound events must all be fired by a user action.
So, when I run code very similar to the above, the first sound plays, and then I get
Uncaught (in promise) DOMException: play() can only be initiated by a user gesture.
How can a sequence of sounds, determined at run time, be played on Android's Chrome?
To start with, Google Chrome on Android has been having the limitation of not allowing applications to play HTML audio(s) without an explicit action by the user. However, it is different than how stock browser(s), in most cases, handles it.
The reason, as Chromium Org puts it, is that, Autoplay is not honored on android as it will cost data usage.
You may find more details on the same here.
Apart from the fact that this results in wastage of bandwidth, this also makes some sense, since mobile devices are used in public and in houses, where unsolicited sound from random Web sites could be a nuisance.
However, in the later versions, this idea was over ruled and Chrome on Android started allowing autoplay of HTML audios and videos on it. Again after a set of reviews and discussions, this feature was reverted to what it was, making it mandatory for a user action to invoke HTML audios and videos on the Chrome for Android.
Here is something that I found more on the same. As it says, the reason stated was that "We're going to gather some data about how users react to autoplaying videos in order to decide whether to keep this restriction". And hence the playing option without a user action was reverted back.
You can also find more about the blocking of _autoplay of audio(s) and video(s) here on Forbes and The Verge.
However, this is something that I can suggest you to try which will help you achieve what you intend to. All you have to do is copy this code and paste in your Chrome for Android. This helps you reset the flag which is default set to not allowing to play HTML audios and videos without user interaction:
chrome://flags/#disable-gesture-requirement-for-media-playback
OR
about:flags/#disable-gesture-requirement-for-media-playback
If the above procedure doesn't help/work for you, you can do this:
Go into chrome://flags OR about:flags (this will direct you to chrome://flags) and Enable the "Disable gesture requirement for media playback" option (which is actually the same as the above URL specified).

Send music control keys from my app in android

Is there a simple way to tell the default media player to change track back or forward?
I want the ability to send commands to the system media player (Music) to change track back and forward from within my app.
Is there a simple way? Code examples or descriptive explanation please, I have not developed for Android before.
Update: Is it just the HTC Music that isn't part of the SDK or even the stock one? Either player would be fine if I could manage way to change tracks.
The HTC Lock screen has some method of changing tracks in the music player. Is it possible I could get hold of this and use it?
Baksmali?
I want the ability to send commands to
the system media player (Music) to
change track back and forward from
within my app.
The Music application is not part of the Android SDK, so there are no documented and supported Intents for moving from track to track.
Sorry!
by ACTION_MEDIA_BUTTON using intent ??
http://developer.android.com/reference/android/content/Intent.html#ACTION_MEDIA_BUTTON
Intent media_intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
media_intent.setPackage(DEFAULTPLAYER);
synchronized (this) {
media_intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, keycode));
mContext.sendOrderedBroadcast(media_intent, null);
media_intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, keycode));
mContext.sendOrderedBroadcast(media_intent, null);
}
however DEFAULTPLAYER needs to be assigned...
:S :S :S

Voice recognition on android with recorded sound clip?

I've used the voice recognition feature on Android and I love it. It's one of my customers' most praised features. However, the format is somewhat restrictive. You have to call the recognizer intent, have it send the recording for transcription to google, and wait for the text back.
Some of my ideas would require recording the audio within my app and then sending the clip to google for transcription.
Is there any way I can send an audio clip to be processed with speech to text?
I got a solution that is working well to have speech recognizing and audio recording. Here is the link to a simple Android project I created to show the solution's working. Also, I put some print screens inside the project to illustrate the app.
I'm gonna try to explain briefly the approach I used. I combined two features in that project: Google Speech API and Flac recording.
Google Speech API is called through HTTP connections. Mike Pultz gives more details about the API:
"(...) the new [Google] API is a full-duplex streaming API. What this means, is that it actually uses two HTTP connections- one POST request to upload the content as a “live” chunked stream, and a second GET request to access the results, which makes much more sense for longer audio samples, or for streaming audio."
However, this API needs to receive a FLAC sound file to work properly. That makes us to go to the second part: Flac recording
I implemented Flac recording in that project through extracting and adapting some pieces of code and libraries from an open source app called AudioBoo. AudioBoo uses native code to record and play flac format.
Thus, it's possible to record a flac sound, send it to Google Speech API, get the text, and play the sound that was just recorded.
The project I created has the basic principles to make it work and can be improved for specific situations. In order to make it work in a different scenario, it's necessary to get a Google Speech API key, which is obtained by being part of Google Chromium-dev group. I left one key in that project just to show it's working, but I'll remove it eventually. If someone needs more information about it, let me know cause I'm not able to put more than 2 links in this post.
Unfortunately not at this time. The only interface currently supported by Android's voice recognition service is the RecognizerIntent, which doesn't allow you to provide your own sound data.
If this is something you'd like to see, file a feature request at http://b.android.com. This is also tangentially related to existing issue 4541.
As far as I know there is still no way to directly send an audio clip to Google for transcription. However, Froyo (API level 8) introduced the SpeechRecognizer class, which provides direct access to the speech recognition service. So, for example, you can start playback of an audio clip and have your Activity start the speech recognizer listening in the background, which will return results after completion to a user-defined listener callback method.
The following sample code should be defined within an Activity since SpeechRecognizer's methods must be run in the main application thread. Also you will need to add the RECORD_AUDIO permission to your AndroidManifest.xml.
boolean available = SpeechRecognizer.isRecognitionAvailable(this);
if (available) {
SpeechRecognizer sr = SpeechRecognizer.createSpeechRecognizer(this);
sr.setRecognitionListener(new RecognitionListener() {
#Override
public void onResults(Bundle results) {
// process results here
}
// define your other overloaded listener methods here
});
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
// the following appears to be a requirement, but can be a "dummy" value
intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, "com.dummy");
// define any other intent extras you want
// start playback of audio clip here
// this will start the speech recognizer service in the background
// without starting a separate activity
sr.startListening(intent);
}
You can also define your own speech recognition service by extending RecognitionService, but that is beyond the scope of this answer :)

Receiving MP3 play actions in a BroadcastReceiver in Android

I am trying to build an Android Service that should get notified when the user starts playing an MP3. I checked LogCat when I start playing a song and saw that the following Intent is logged:
Intent { act=com.android.music.PLAYBACK_VIEWER flg=0x4000000 cmp=com.android.music/.MediaPlaybackActivity }
I couldn't figure out how to write an IntentFilter to let my Service know that this event has occurred and let me know the name of the song that will be played. I searched Android reference but could not find anything on PLAYBACK_VIEWER.
Thanks,
C
I would do neither. First, none of this is part of the SDK and so may change at any point. Second, this will only work for the built-in media player application, not any third-party or OEM-supplied media players, and I expect more people to gravitate to those.

Categories

Resources