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?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
val menuHost: MenuHost = requireActivity()
|
||||
val menuHost: MenuHost = requireActivity() as MenuHost
|
||||
menuHost.addMenuProvider(this, viewLifecycleOwner, Lifecycle.State.STARTED)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,9 @@ package code.name.monkey.retromusic.service
|
|||
|
||||
import android.animation.Animator
|
||||
import android.content.Context
|
||||
import android.media.AudioAttributes
|
||||
import android.media.AudioManager
|
||||
import android.media.MediaPlayer
|
||||
import android.media.PlaybackParams
|
||||
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.retromusic.R
|
||||
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.playback.Playback.PlaybackCallbacks
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.logE
|
||||
import kotlinx.coroutines.*
|
||||
|
||||
/** @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
|
||||
* and vice versa for upcoming song and so on.
|
||||
*/
|
||||
class CrossFadePlayer(context: Context) : LocalPlayback(context), MediaPlayer.OnCompletionListener,
|
||||
MediaPlayer.OnErrorListener {
|
||||
class CrossFadePlayer(context: Context) : LocalPlayback(context) {
|
||||
|
||||
private var currentPlayer: CurrentPlayer = CurrentPlayer.NOT_SET
|
||||
private var player1 = MediaPlayer()
|
||||
|
@ -144,39 +140,6 @@ class CrossFadePlayer(context: Context) : LocalPlayback(context), MediaPlayer.On
|
|||
|
||||
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 {
|
||||
return try {
|
||||
getCurrentPlayer()?.audioSessionId = sessionId
|
||||
|
@ -287,7 +250,7 @@ class CrossFadePlayer(context: Context) : LocalPlayback(context), MediaPlayer.On
|
|||
mIsInitialized = true
|
||||
mp?.setWakeMode(context, PowerManager.PARTIAL_WAKE_LOCK)
|
||||
context.showToast(R.string.unplayable_file)
|
||||
Log.e(TAG, what.toString() + extra)
|
||||
logE(what.toString() + extra)
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
|
@ -4,9 +4,12 @@ import android.content.BroadcastReceiver
|
|||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.media.AudioAttributes
|
||||
import android.media.AudioManager
|
||||
import android.media.MediaPlayer
|
||||
import androidx.annotation.CallSuper
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.core.net.toUri
|
||||
import androidx.media.AudioAttributesCompat
|
||||
import androidx.media.AudioFocusRequestCompat
|
||||
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.util.PreferenceUtil.isAudioFocusEnabled
|
||||
|
||||
abstract class LocalPlayback(val context: Context) : Playback {
|
||||
abstract class LocalPlayback(val context: Context) : Playback, MediaPlayer.OnErrorListener,
|
||||
MediaPlayer.OnCompletionListener {
|
||||
|
||||
private val becomingNoisyReceiverIntentFilter =
|
||||
IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)
|
||||
|
@ -100,6 +104,41 @@ abstract class LocalPlayback(val context: Context) : Playback {
|
|||
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() {
|
||||
if (becomingNoisyReceiverRegistered) {
|
||||
context.unregisterReceiver(becomingNoisyReceiver)
|
||||
|
|
|
@ -14,10 +14,7 @@
|
|||
package code.name.monkey.retromusic.service
|
||||
|
||||
import android.content.Context
|
||||
import android.media.AudioAttributes
|
||||
import android.media.MediaPlayer
|
||||
import android.media.MediaPlayer.OnCompletionListener
|
||||
import android.net.Uri
|
||||
import android.os.PowerManager
|
||||
import android.util.Log
|
||||
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)
|
||||
*/
|
||||
class MultiPlayer(context: Context) : LocalPlayback(context),
|
||||
MediaPlayer.OnErrorListener, OnCompletionListener {
|
||||
class MultiPlayer(context: Context) : LocalPlayback(context) {
|
||||
private var mCurrentMediaPlayer = MediaPlayer()
|
||||
private var mNextMediaPlayer: MediaPlayer? = 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.
|
||||
*
|
||||
|
|
|
@ -235,6 +235,7 @@ class MusicService : MediaBrowserServiceCompat(),
|
|||
}
|
||||
}
|
||||
|
||||
private var receivedHeadsetConnected = false
|
||||
private val headsetReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
val action = intent.action
|
||||
|
@ -242,7 +243,12 @@ class MusicService : MediaBrowserServiceCompat(),
|
|||
if (Intent.ACTION_HEADSET_PLUG == action) {
|
||||
when (intent.getIntExtra("state", -1)) {
|
||||
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
|
||||
sendChangeInternal(META_CHANGED)
|
||||
}
|
||||
if (receivedHeadsetConnected) {
|
||||
play()
|
||||
receivedHeadsetConnected = false
|
||||
}
|
||||
}
|
||||
|
||||
sendChangeInternal(QUEUE_CHANGED)
|
||||
|
@ -1250,9 +1260,12 @@ class MusicService : MediaBrowserServiceCompat(),
|
|||
)
|
||||
handleAndSendChangeInternal(SHUFFLE_MODE_CHANGED)
|
||||
handleAndSendChangeInternal(REPEAT_MODE_CHANGED)
|
||||
serviceScope.launch {
|
||||
val start= System.currentTimeMillis()
|
||||
serviceScope.launch(start = CoroutineStart.DEFAULT) {
|
||||
restoreQueuesAndPositionIfNecessary()
|
||||
println("Time completion: ${System.currentTimeMillis() - start}")
|
||||
}
|
||||
println("Time: ${System.currentTimeMillis() - start}")
|
||||
}
|
||||
|
||||
private fun savePosition() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue