Fixed headphones auto-play not working

This commit is contained in:
Prathamesh More 2022-05-30 14:53:41 +05:30
parent 88ccd667ab
commit 1edd4acd9c
5 changed files with 60 additions and 85 deletions

View file

@ -33,7 +33,7 @@ abstract class AbsMainActivityFragment(@LayoutRes layout: Int) : AbsMusicService
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val menuHost: MenuHost = requireActivity() val menuHost: MenuHost = requireActivity() as MenuHost
menuHost.addMenuProvider(this, viewLifecycleOwner, Lifecycle.State.STARTED) menuHost.addMenuProvider(this, viewLifecycleOwner, Lifecycle.State.STARTED)
} }
} }

View file

@ -2,13 +2,9 @@ package code.name.monkey.retromusic.service
import android.animation.Animator import android.animation.Animator
import android.content.Context import android.content.Context
import android.media.AudioAttributes
import android.media.AudioManager
import android.media.MediaPlayer import android.media.MediaPlayer
import android.media.PlaybackParams import android.media.PlaybackParams
import android.os.PowerManager import android.os.PowerManager
import android.util.Log
import androidx.core.net.toUri
import code.name.monkey.appthemehelper.util.VersionUtils.hasMarshmallow import code.name.monkey.appthemehelper.util.VersionUtils.hasMarshmallow
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.extensions.showToast import code.name.monkey.retromusic.extensions.showToast
@ -18,6 +14,7 @@ import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.service.AudioFader.Companion.createFadeAnimator import code.name.monkey.retromusic.service.AudioFader.Companion.createFadeAnimator
import code.name.monkey.retromusic.service.playback.Playback.PlaybackCallbacks import code.name.monkey.retromusic.service.playback.Playback.PlaybackCallbacks
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.logE
import kotlinx.coroutines.* import kotlinx.coroutines.*
/** @author Prathamesh M */ /** @author Prathamesh M */
@ -29,8 +26,7 @@ import kotlinx.coroutines.*
* play but with decreasing volume and start the player with the next song with increasing volume * play but with decreasing volume and start the player with the next song with increasing volume
* and vice versa for upcoming song and so on. * and vice versa for upcoming song and so on.
*/ */
class CrossFadePlayer(context: Context) : LocalPlayback(context), MediaPlayer.OnCompletionListener, class CrossFadePlayer(context: Context) : LocalPlayback(context) {
MediaPlayer.OnErrorListener {
private var currentPlayer: CurrentPlayer = CurrentPlayer.NOT_SET private var currentPlayer: CurrentPlayer = CurrentPlayer.NOT_SET
private var player1 = MediaPlayer() private var player1 = MediaPlayer()
@ -144,39 +140,6 @@ class CrossFadePlayer(context: Context) : LocalPlayback(context), MediaPlayer.On
override fun setNextDataSource(path: String?) {} override fun setNextDataSource(path: String?) {}
/**
* @param player The {@link MediaPlayer} to use
* @param path The path of the file, or the http/rtsp URL of the stream you want to play
* @return True if the <code>player</code> has been prepared and is ready to play, false otherwise
*/
private fun setDataSourceImpl(
player: MediaPlayer,
path: String,
completion: (success: Boolean) -> Unit,
) {
player.reset()
try {
if (path.startsWith("content://")) {
player.setDataSource(context, path.toUri())
} else {
player.setDataSource(path)
}
player.setAudioAttributes(
AudioAttributes.Builder().setLegacyStreamType(AudioManager.STREAM_MUSIC).build()
)
player.setOnPreparedListener {
player.setOnPreparedListener(null)
completion(true)
}
player.prepareAsync()
} catch (e: Exception) {
completion(false)
e.printStackTrace()
}
player.setOnCompletionListener(this)
player.setOnErrorListener(this)
}
override fun setAudioSessionId(sessionId: Int): Boolean { override fun setAudioSessionId(sessionId: Int): Boolean {
return try { return try {
getCurrentPlayer()?.audioSessionId = sessionId getCurrentPlayer()?.audioSessionId = sessionId
@ -287,7 +250,7 @@ class CrossFadePlayer(context: Context) : LocalPlayback(context), MediaPlayer.On
mIsInitialized = true mIsInitialized = true
mp?.setWakeMode(context, PowerManager.PARTIAL_WAKE_LOCK) mp?.setWakeMode(context, PowerManager.PARTIAL_WAKE_LOCK)
context.showToast(R.string.unplayable_file) context.showToast(R.string.unplayable_file)
Log.e(TAG, what.toString() + extra) logE(what.toString() + extra)
return false return false
} }

View file

@ -4,9 +4,12 @@ import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.media.AudioAttributes
import android.media.AudioManager import android.media.AudioManager
import android.media.MediaPlayer
import androidx.annotation.CallSuper import androidx.annotation.CallSuper
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import androidx.core.net.toUri
import androidx.media.AudioAttributesCompat import androidx.media.AudioAttributesCompat
import androidx.media.AudioFocusRequestCompat import androidx.media.AudioFocusRequestCompat
import androidx.media.AudioManagerCompat import androidx.media.AudioManagerCompat
@ -15,7 +18,8 @@ import code.name.monkey.retromusic.extensions.showToast
import code.name.monkey.retromusic.service.playback.Playback import code.name.monkey.retromusic.service.playback.Playback
import code.name.monkey.retromusic.util.PreferenceUtil.isAudioFocusEnabled import code.name.monkey.retromusic.util.PreferenceUtil.isAudioFocusEnabled
abstract class LocalPlayback(val context: Context) : Playback { abstract class LocalPlayback(val context: Context) : Playback, MediaPlayer.OnErrorListener,
MediaPlayer.OnCompletionListener {
private val becomingNoisyReceiverIntentFilter = private val becomingNoisyReceiverIntentFilter =
IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY) IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)
@ -100,6 +104,41 @@ abstract class LocalPlayback(val context: Context) : Playback {
return true return true
} }
/**
* @param player The [MediaPlayer] to use
* @param path The path of the file, or the http/rtsp URL of the stream you want to play
* @return True if the <code>player</code> has been prepared and is ready to play, false otherwise
*/
fun setDataSourceImpl(
player: MediaPlayer,
path: String,
completion: (success: Boolean) -> Unit,
) {
player.reset()
try {
if (path.startsWith("content://")) {
player.setDataSource(context, path.toUri())
} else {
player.setDataSource(path)
}
player.setAudioAttributes(AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build()
)
player.setOnPreparedListener {
player.setOnPreparedListener(null)
completion(true)
}
player.prepareAsync()
} catch (e: Exception) {
completion(false)
e.printStackTrace()
}
player.setOnCompletionListener(this)
player.setOnErrorListener(this)
}
private fun unregisterBecomingNoisyReceiver() { private fun unregisterBecomingNoisyReceiver() {
if (becomingNoisyReceiverRegistered) { if (becomingNoisyReceiverRegistered) {
context.unregisterReceiver(becomingNoisyReceiver) context.unregisterReceiver(becomingNoisyReceiver)

View file

@ -14,10 +14,7 @@
package code.name.monkey.retromusic.service package code.name.monkey.retromusic.service
import android.content.Context import android.content.Context
import android.media.AudioAttributes
import android.media.MediaPlayer import android.media.MediaPlayer
import android.media.MediaPlayer.OnCompletionListener
import android.net.Uri
import android.os.PowerManager import android.os.PowerManager
import android.util.Log import android.util.Log
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
@ -30,8 +27,7 @@ import code.name.monkey.retromusic.util.PreferenceUtil.isGapLessPlayback
/** /**
* @author Andrew Neal, Karim Abou Zeid (kabouzeid) * @author Andrew Neal, Karim Abou Zeid (kabouzeid)
*/ */
class MultiPlayer(context: Context) : LocalPlayback(context), class MultiPlayer(context: Context) : LocalPlayback(context) {
MediaPlayer.OnErrorListener, OnCompletionListener {
private var mCurrentMediaPlayer = MediaPlayer() private var mCurrentMediaPlayer = MediaPlayer()
private var mNextMediaPlayer: MediaPlayer? = null private var mNextMediaPlayer: MediaPlayer? = null
override var callbacks: PlaybackCallbacks? = null override var callbacks: PlaybackCallbacks? = null
@ -65,42 +61,6 @@ class MultiPlayer(context: Context) : LocalPlayback(context),
} }
} }
/**
* @param player The [MediaPlayer] to use
* @param path The path of the file, or the http/rtsp URL of the stream you want to play
* @return True if the `player` has been prepared and is ready to play, false otherwise
*/
private fun setDataSourceImpl(
player: MediaPlayer,
path: String,
completion: (success: Boolean) -> Unit,
) {
try {
player.reset()
player.setOnPreparedListener(null)
if (path.startsWith("content://")) {
player.setDataSource(context, Uri.parse(path))
} else {
player.setDataSource(path)
}
player.setAudioAttributes(AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build()
)
player.setOnPreparedListener {
player.setOnPreparedListener(null)
completion(true)
}
player.prepareAsync()
} catch (e: Exception) {
completion(false)
e.printStackTrace()
}
player.setOnCompletionListener(this)
player.setOnErrorListener(this)
}
/** /**
* Set the MediaPlayer to start when this MediaPlayer finishes playback. * Set the MediaPlayer to start when this MediaPlayer finishes playback.
* *

View file

@ -235,6 +235,7 @@ class MusicService : MediaBrowserServiceCompat(),
} }
} }
private var receivedHeadsetConnected = false
private val headsetReceiver = object : BroadcastReceiver() { private val headsetReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
val action = intent.action val action = intent.action
@ -242,7 +243,12 @@ class MusicService : MediaBrowserServiceCompat(),
if (Intent.ACTION_HEADSET_PLUG == action) { if (Intent.ACTION_HEADSET_PLUG == action) {
when (intent.getIntExtra("state", -1)) { when (intent.getIntExtra("state", -1)) {
0 -> pause() 0 -> pause()
1 -> play() // Check whether the current song is empty which means the playing queue hasn't restored yet
1 -> if (currentSong != emptySong) {
play()
} else {
receivedHeadsetConnected = true
}
} }
} }
} }
@ -921,6 +927,10 @@ class MusicService : MediaBrowserServiceCompat(),
notHandledMetaChangedForCurrentTrack = true notHandledMetaChangedForCurrentTrack = true
sendChangeInternal(META_CHANGED) sendChangeInternal(META_CHANGED)
} }
if (receivedHeadsetConnected) {
play()
receivedHeadsetConnected = false
}
} }
sendChangeInternal(QUEUE_CHANGED) sendChangeInternal(QUEUE_CHANGED)
@ -1250,9 +1260,12 @@ class MusicService : MediaBrowserServiceCompat(),
) )
handleAndSendChangeInternal(SHUFFLE_MODE_CHANGED) handleAndSendChangeInternal(SHUFFLE_MODE_CHANGED)
handleAndSendChangeInternal(REPEAT_MODE_CHANGED) handleAndSendChangeInternal(REPEAT_MODE_CHANGED)
serviceScope.launch { val start= System.currentTimeMillis()
serviceScope.launch(start = CoroutineStart.DEFAULT) {
restoreQueuesAndPositionIfNecessary() restoreQueuesAndPositionIfNecessary()
println("Time completion: ${System.currentTimeMillis() - start}")
} }
println("Time: ${System.currentTimeMillis() - start}")
} }
private fun savePosition() { private fun savePosition() {