Android ExoPlayer demo: continue playback with screen locked - android

I want to modify the ExoPlayer demo to allow audio playback to continue when the screen gets locked (this should work regardless of whether the media being played is audio or video). Based on some hints (e.g. 1, 2) this is what I came up with so far:
https://github.com/google/ExoPlayer/compare/release-v2...sedubois:background-playback
This is directly based on the ExoPlayer demo code, currently in version 2.12.1. It adds a "foreground" permission, registers a service, and creates a notification in that service (according to the documentation this notification is required for background playback). The service is started when initializing the player.
I can start the player and the demo looks as illustrated below with an audio stream. At this point the notification gets created properly, it shows the player details (title, description, progress bar) and control buttons (see picture below), which work (I can play/pause, restart from the beginning and skip backwards/forwards).
However the playback still stops when I minimize the application or when I lock the screen by pressing the power button. What is the proper way to make this work?

Just to make sure we are on same page. I'm testing on dev-v2 branch of exoplayer repo here
onStop() method in PlayerActivity.java is releasing player, So when app goes in background then onStop() is being called and it is releasing player with method releasePlayer.
If you'll comment out that method i.e. dont release player in onStop(), then player will play in background.

Related

Use MediaButton to control foreground app (no audio) with audio in background

I want to use the media buttons to control a foreground app, but not for audio use.
So the goal is to detect button clicks to do certain things in the app.
I can achieve that by using MediaSession and the MediaButtonReceiver. see here
The problem is that when the app is used, often users play music in the background, so the audio focus of the background app takes over the MediaSession and i cannot control my app anymore.
Is there a way to achieve that? Directly listening for button clicks with onKeyDown does not seem to work.
sadly there is no way for two active MediaSessions at the same time. if another app is playing music and run MediaSession then yours doesn't have focus and isn't active... this is made for purpose - better UX - only one "player" app can play music (or video). if this wouldn't work like that and you could play music by few apps at once then how should work media button on e.g. headphones? pasuing/resuming all players? this is just not user-friendly, so Android team introduced MediaSession pattern with option for calling "focus on me now" by any app, but then another app/MediaSession pauses and doesn't get any inputs (this active session does)
if you need physical buttons presses then onKeyDown should work (inside Activity or eventually using AccessibilityService, which would work "globally" in whole system). if you need some on-screen notification buttons presses then just make custom layout for your notification with as much buttons as you like, even styled as a player
note that in Android 11 active MediaSessions notification is stickied to top of notification section when you drop down status bar. your custom notification will be somewhere below between all others (you can manipulate position a bit using priority param for notification/channel)

How to get rid of "media playing" notification shown by Chrome on Android?

My HTML5 game has some background music that uses Howler.js in "html5" mode, which apparently triggers Chrome for Android's media playback notifications. This means a notification appears while the user has my game open in any tab:
The game is a good citizen and pauses the music while the tab is not in focus, so there is no need for this notification. It's even actively confusing, because the user can pause and resume the game's background music without being in the game. But I can't find a way to get rid of the notification.
I tried calling stop() instead of pause() or mute() on the music object, but this doesn't remove the notification.
Looking a bit deeper, I discovered the experimental MediaSession API (W3C draft) which supposedly can be used to control the notification. But, if I understand correctly, it offers no way to disable it outright!
I tried this at the start of my application:
if (typeof navigator.mediaSession == 'object') {
navigator.mediaSession.playbackState = 'none'
}
However, this only sets the declared playback state (in spec terminology). And setting that to 'none' has no effect:
The actual playback state is computed in the following way:
If the declared playback state is "playing", return "playing".
Otherwise, return the guessed playback state.
And the guessed playback state is something I have no control over; it's derived by the browser based on the state of <audio> elements on the page.
Is there a possibility that I'm overlooking, or is this just an oversight in the current MediaSession specification?
This may be what you are looking for.
If you can make the music loop within 5 second (like in NES days), notification won't show it said.
Else, use Web Audio API without "audio" element. So, use a stream.
Otherwise, "Dismiss media notifications with audio.src = ''." reference

how to detect when Music is played using Native Music Player?

I am making an app in which I've made a Service which plays Music from URLs. The thing is that my music Service is playing music correctly BUT when user plays any song with Native music player then BOTH(Native Player and My Music Service) are playing music simultaneously. I want to stop My Music Service when user started playing music with native player.
Is there any Broadcast Intent which i can register to Detect the
music player is started?
Is it possible to detect Music player Started?
Any Other Solution?
Any suggestions would appreciated.
I'll suggest a different approach, that I believe it's the correct approach.
the issue on your approach is that you're suggesting to check for one specific app. And there're tons of different music players, plus radio players, plus video players, plus games... and all of those should stop your music in case they want to play something.
So how you do it?
It's all explained in the Android Developers website.
You have to register an OnAudioFocusChangeListener, so, whenever a different app request to have the audio focus, your app can stop the music.
Step 1: Detect if the user has opened native music app. For this , you need to know the package name of your native music app.
Then refer to my answer here: Android how to know an app has been started and range apps priority according the starting times
Using that , the list taskinfo will have the list of all running activities, and as explained there, the first element of the list will be the activity in the foreground.
STEP 2: Once you detect native music app being activated using STEP 1 (by polling for it in the background) , then stop your app's service.
NOTE: You should do this in a background (using asynctask) or another service.
NOTE 2: The limitation of this method is that you can't actually stop the music player when the user clicks play in the native music app, since this method will help you detect only if the native music app is opened or not.

how to know when audio is started playing in android

In my application I want to get start time of music player when user started and end time when it stops.I don't want to start any music player in my app. I just want to track user activity in device. So i want my application to get any notification when user started the music .
Do I get any intent for music player started and it stopped.Or do I get any intent for when user opens music files.
Is there any other method other than intent to capture the start time and and time when user starts music player.
Well you can implement the interface 'AudioManager.OnAudioFocusChangeListener' in which there is a method 'onAudioFocusChange' which lets you know if audio focus has been changed, and it can also tell if focus was gained or lost.
See this link, it explains the Audio Focus in detail. An application must gain audio focus through a request, and you can implement the 'AudioManager.OnAudioFocusChangeListener' and if there is focus gain, you can detect if the media player is running, (because some other application such as you tube may gain focus to play its audio), see this to see how to detect which application or service is currently running. You can find if audio has started to play, and if it was the media player or not.
Hope this helps. It was interesting question and I have learned some new things while searching for the answer!

Any guidelines for handling the Headset and Bluetooth AVRC transport controls in Android 2.2

I am trying to figure out what is the correct (new) approach for handling the Intent.ACTION_MEDIA_BUTTON in Froyo. In pre 2.2 days we had to register a BroadcastReceiver (either permanently or at run-time) and the Media Button events would arrive, as long as no other application intercepts them and aborts the broadcast.
Froyo seems to still somewhat support that model (at least for the wired headset), but it also introduces the registerMediaButtonEventReceiver, and unregisterMediaButtonEventReceiver methods that seem to control the "transport focus" between applications.
During my experiments, using registerMediaButtonEventReceiver does cause both the bluetooth and the wired headset button presses to be routed to the application's broadcast receiver (the app gets the "transport focus"), but it looks like any change in the audio routing (for example unplugging the headset) shits the focus back to the default media player.
What is the logic behind the implementation in Android 2.2? What is correct way to handle transport controls? Do we have to detect the change in the audio routing and try to re-gain the focus?
This is an issue that any 3rd party media player on the Android platform has to deal with, so I hope that somebody (probably a Google Engineer) can provide some guidelines that we can all follow. Having a standard approach may make headset button controls a bit more predictable for the end users.
Stefan
Google has a detailed blog post on implementing the newer 2.2 AudioManager media button event receiver while maintaining backwards compatibility with older devices.
http://android-developers.blogspot.com/2010/06/allowing-applications-to-play-nicer.html
After some experiments, I was able to get a working solution with the new transport and audio focus infrastructure in Android 2.2.
What I end up doing is requesting both the Audio Focus (using AudioManager.requestAudioFocus) and the Trasport Focus (using AudioManagter.registerMediaButtonEventReceiver) every time my application starts playback.
requestAudioFocus takes a callback that is called when the audio focus is taken away from you (for example the internal player starts a playback). In my case I just pause the playback in my application if the focus is taken permanently. Same callback also now tells you that the focus is taken only temporary (for example the Nav system is talking) so you can "duck" your playback - lower the volume or pause and resume after it is done talking.
The only issue remaining is that the built in Music Player takes the transport focus every time you connect a Bluetooth headset. This has the effect where the first press of the Play button on the headset after connecting it, always starts the playback in the default Music Player.
There is probably a way to detect the headset connection and "hijack" the transport focus. In my case, I decided to not "fight" the default player, and get the transport focus back when the user manually starts the playback in my application.
If somebody has more insight or knows of a better way of handling the transport/audio focus, please share it.
I also have this same issue with the media button registration.
Periodically the Android returns the media button registration to the default music player. I have not been able to figure out why. This can happen while may application is actively playing as well as while my application playback is paused.
After a number of users complained that their Bluetooth pause and play control buttons would periodically stop working to control my application, I implemented code that re-registers my application by calling registerMediaButtonEventReceiver every 2 seconds. This allows me to get the button registration back and for the most part avoids the time window where where the user presses a Bluetooth media button and the default media player ends up responding.
My application is holding the audio focus during this entire time period, but still loses the Bluetooth button events periodically while it has audio focus. My application always unregisters the media button event receiver if it is called with a notification that it is losing the audio focus, and then registers again if it is later called when a temporary audio focus loss returns the audio focus.
The work around to keep the 2 second timer running and re-registering has been working, but I would like to get rid of this 2 second timer if someone has found a work around for the media button registration periodically switching back to the default media player.

Categories

Resources