Fixed headphones auto-play not working
This commit is contained in:
parent
88ccd667ab
commit
1edd4acd9c
5 changed files with 60 additions and 85 deletions
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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.
|
||||||
*
|
*
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue