playback: fix headset focus autoplay issue

Fix an issue where headset focus would result in unexpected playback
whenever the service started.

AudioManager.ACTION_HEADSET_PLUG seems to always fire when the initial
BroadcastReceiver is set up, which results in a weird bug where if a
wired headset is connected while PlaybackService is started, playback
will start immediately, which was not user friendly.

I fear that this may result in an edge case that results in headset
focus not firing in an unrelated situation, which in that case I would
be forced to remove headset autoplay entirely (or at least relegate it
to a quirk option).
This commit is contained in:
OxygenCobalt 2022-03-03 18:47:55 -07:00
parent 1e39ceb9fc
commit 6d003c308b
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
8 changed files with 20 additions and 8 deletions

View file

@ -15,6 +15,7 @@ from the system theme was used [#80]
- Fixed music loading failure that would occur when certain paths were parsed [#84]
- Fixed incorrect track numbers when the tag was formatted as NN/TT [#88]
- Fixed years deliberately set as "0" showing up as "No Date"
- Fixed headset management unexpectedly starting audio when the app initially opens
#### What's Changed
- All cover art is now cropped to a 1:1 aspect ratio

View file

@ -29,6 +29,10 @@ import org.oxycblt.auxio.coil.GenreImageFetcher
import org.oxycblt.auxio.coil.MusicKeyer
import org.oxycblt.auxio.settings.SettingsManager
/**
* TODO: Phase out databinding
* TODO: Rework sealed classes to minimize whens and maximize overrides
*/
@Suppress("UNUSED")
class AuxioApp : Application(), ImageLoaderFactory {
override fun onCreate() {

View file

@ -43,7 +43,6 @@ import org.oxycblt.auxio.util.systemBarInsetsCompat
* TODO: Add a new view for crashes with a stack trace
* TODO: Custom language support
* TODO: Rework menus [perhaps add multi-select]
* TODO: Phase out databinding
*/
class MainActivity : AppCompatActivity() {
private val playbackModel: PlaybackViewModel by viewModels()

View file

@ -56,6 +56,7 @@ import org.oxycblt.auxio.util.logTraceOrThrow
* views for each respective item.
* @author OxygenCobalt
* TODO: Make tabs invisible when there is only one
* TODO: Add duration and song count sorts
*/
class HomeFragment : Fragment() {
private val playbackModel: PlaybackViewModel by activityViewModels()

View file

@ -149,7 +149,7 @@ data class Song(
*/
data class Album(
override val name: String,
/** The latest year of the songs in this album. */
/** The latest year of the songs in this album. Null if none of the songs had metadata. */
val year: Int?,
/** The URI for the cover art corresponding to this album. */
val albumCoverUri: Uri,

View file

@ -241,6 +241,7 @@ class MusicLoader {
// Use the song with the latest year as our metadata song.
// This allows us to replicate the LAST_YEAR field, which is useful as it means that
// weird years like "0" wont show up if there are alternatives.
// TODO: Weigh songs with null years lower than songs with zero years
val templateSong = requireNotNull(
albumSongs.maxByOrNull { it.internalMediaStoreYear ?: 0 }
)

View file

@ -69,7 +69,8 @@ class MusicStore private constructor() {
val start = System.currentTimeMillis()
val loader = MusicLoader()
val library = loader.load(context) ?: return Response.Err(ErrorKind.NO_MUSIC)
val library = loader.load(context)
?: return Response.Err(ErrorKind.NO_MUSIC)
mSongs = library.songs
mAlbums = library.albums
@ -78,7 +79,7 @@ class MusicStore private constructor() {
logD("Music load completed successfully in ${System.currentTimeMillis() - start}ms")
} catch (e: Exception) {
logE("Something went horribly wrong")
logE("Music loading failed.")
logE(e.stackTraceToString())
return Response.Err(ErrorKind.FAILED)
}

View file

@ -439,7 +439,6 @@ class PlaybackService : Service(), Player.Listener, PlaybackStateManager.Callbac
private fun stopForegroundAndNotification() {
stopForeground(true)
notificationManager.cancel(PlaybackNotification.NOTIFICATION_ID)
isForeground = false
}
@ -448,6 +447,8 @@ class PlaybackService : Service(), Player.Listener, PlaybackStateManager.Callbac
* TODO: Don't fire when the service initially starts?
*/
private inner class PlaybackReceiver : BroadcastReceiver() {
private var handledInitialHeadsetPlug = false
override fun onReceive(context: Context, intent: Intent) {
when (intent.action) {
// --- SYSTEM EVENTS ---
@ -461,10 +462,14 @@ class PlaybackService : Service(), Player.Listener, PlaybackStateManager.Callbac
AudioManager.ACTION_AUDIO_BECOMING_NOISY -> pauseFromPlug()
AudioManager.ACTION_HEADSET_PLUG -> {
when (intent.getIntExtra("state", -1)) {
0 -> pauseFromPlug()
1 -> resumeFromPlug()
if (handledInitialHeadsetPlug) {
when (intent.getIntExtra("state", -1)) {
0 -> pauseFromPlug()
1 -> resumeFromPlug()
}
}
handledInitialHeadsetPlug = true
}
// --- AUXIO EVENTS ---