mirror of
https://github.com/ultrasonic/ultrasonic
synced 2025-02-19 21:20:52 +01:00
We can now remove the deprecated Remote Control API
This commit is contained in:
parent
26ba022003
commit
19580cda8b
@ -300,7 +300,6 @@ public class MediaPlayerService extends Service
|
|||||||
{
|
{
|
||||||
nowPlayingEventDistributor.getValue().raiseHideNowPlayingEvent();
|
nowPlayingEventDistributor.getValue().raiseHideNowPlayingEvent();
|
||||||
stopForeground(true);
|
stopForeground(true);
|
||||||
localMediaPlayer.clearRemoteControl();
|
|
||||||
isInForeground = false;
|
isInForeground = false;
|
||||||
stopIfIdle();
|
stopIfIdle();
|
||||||
}
|
}
|
||||||
@ -520,7 +519,6 @@ public class MediaPlayerService extends Service
|
|||||||
{
|
{
|
||||||
nowPlayingEventDistributor.getValue().raiseHideNowPlayingEvent();
|
nowPlayingEventDistributor.getValue().raiseHideNowPlayingEvent();
|
||||||
stopForeground(true);
|
stopForeground(true);
|
||||||
localMediaPlayer.clearRemoteControl();
|
|
||||||
isInForeground = false;
|
isInForeground = false;
|
||||||
stopIfIdle();
|
stopIfIdle();
|
||||||
}
|
}
|
||||||
|
@ -7,17 +7,12 @@
|
|||||||
|
|
||||||
package org.moire.ultrasonic.service
|
package org.moire.ultrasonic.service
|
||||||
|
|
||||||
import android.app.PendingIntent
|
|
||||||
import android.content.ComponentName
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Context.AUDIO_SERVICE
|
|
||||||
import android.content.Context.POWER_SERVICE
|
import android.content.Context.POWER_SERVICE
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.media.AudioManager
|
import android.media.AudioManager
|
||||||
import android.media.MediaMetadataRetriever
|
|
||||||
import android.media.MediaPlayer
|
import android.media.MediaPlayer
|
||||||
import android.media.MediaPlayer.OnCompletionListener
|
import android.media.MediaPlayer.OnCompletionListener
|
||||||
import android.media.RemoteControlClient
|
|
||||||
import android.media.audiofx.AudioEffect
|
import android.media.audiofx.AudioEffect
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
@ -35,10 +30,8 @@ import org.moire.ultrasonic.audiofx.VisualizerController
|
|||||||
import org.moire.ultrasonic.data.ActiveServerProvider.Companion.isOffline
|
import org.moire.ultrasonic.data.ActiveServerProvider.Companion.isOffline
|
||||||
import org.moire.ultrasonic.domain.PlayerState
|
import org.moire.ultrasonic.domain.PlayerState
|
||||||
import org.moire.ultrasonic.fragment.PlayerFragment
|
import org.moire.ultrasonic.fragment.PlayerFragment
|
||||||
import org.moire.ultrasonic.receiver.MediaButtonIntentReceiver
|
|
||||||
import org.moire.ultrasonic.util.CancellableTask
|
import org.moire.ultrasonic.util.CancellableTask
|
||||||
import org.moire.ultrasonic.util.Constants
|
import org.moire.ultrasonic.util.Constants
|
||||||
import org.moire.ultrasonic.util.FileUtil
|
|
||||||
import org.moire.ultrasonic.util.StreamProxy
|
import org.moire.ultrasonic.util.StreamProxy
|
||||||
import org.moire.ultrasonic.util.Util
|
import org.moire.ultrasonic.util.Util
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
@ -84,8 +77,6 @@ class LocalMediaPlayer(
|
|||||||
private var mediaPlayerHandler: Handler? = null
|
private var mediaPlayerHandler: Handler? = null
|
||||||
private var cachedPosition = 0
|
private var cachedPosition = 0
|
||||||
private var proxy: StreamProxy? = null
|
private var proxy: StreamProxy? = null
|
||||||
private var audioManager: AudioManager = context.getSystemService(AUDIO_SERVICE) as AudioManager
|
|
||||||
private var remoteControlClient: RemoteControlClient? = null
|
|
||||||
private var bufferTask: CancellableTask? = null
|
private var bufferTask: CancellableTask? = null
|
||||||
private var positionCache: PositionCache? = null
|
private var positionCache: PositionCache? = null
|
||||||
private var secondaryProgress = -1
|
private var secondaryProgress = -1
|
||||||
@ -129,7 +120,6 @@ class LocalMediaPlayer(
|
|||||||
|
|
||||||
wakeLock.setReferenceCounted(false)
|
wakeLock.setReferenceCounted(false)
|
||||||
Util.registerMediaButtonEventReceiver(context, true)
|
Util.registerMediaButtonEventReceiver(context, true)
|
||||||
setUpRemoteControlClient()
|
|
||||||
Timber.i("LocalMediaPlayer created")
|
Timber.i("LocalMediaPlayer created")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,8 +146,6 @@ class LocalMediaPlayer(
|
|||||||
if (nextPlayingTask != null) {
|
if (nextPlayingTask != null) {
|
||||||
nextPlayingTask!!.cancel()
|
nextPlayingTask!!.cancel()
|
||||||
}
|
}
|
||||||
audioManager.unregisterRemoteControlClient(remoteControlClient)
|
|
||||||
clearRemoteControl()
|
|
||||||
Util.unregisterMediaButtonEventReceiver(context, true)
|
Util.unregisterMediaButtonEventReceiver(context, true)
|
||||||
wakeLock.release()
|
wakeLock.release()
|
||||||
} catch (exception: Throwable) {
|
} catch (exception: Throwable) {
|
||||||
@ -173,9 +161,7 @@ class LocalMediaPlayer(
|
|||||||
if (playerState === PlayerState.STARTED) {
|
if (playerState === PlayerState.STARTED) {
|
||||||
audioFocusHandler.requestAudioFocus()
|
audioFocusHandler.requestAudioFocus()
|
||||||
}
|
}
|
||||||
if (playerState === PlayerState.STARTED || playerState === PlayerState.PAUSED) {
|
|
||||||
updateRemoteControl()
|
|
||||||
}
|
|
||||||
if (onPlayerStateChanged != null) {
|
if (onPlayerStateChanged != null) {
|
||||||
val mainHandler = Handler(context.mainLooper)
|
val mainHandler = Handler(context.mainLooper)
|
||||||
val myRunnable = Runnable {
|
val myRunnable = Runnable {
|
||||||
@ -200,7 +186,6 @@ class LocalMediaPlayer(
|
|||||||
fun setCurrentPlaying(currentPlaying: DownloadFile?) {
|
fun setCurrentPlaying(currentPlaying: DownloadFile?) {
|
||||||
Timber.v("setCurrentPlaying %s", currentPlaying)
|
Timber.v("setCurrentPlaying %s", currentPlaying)
|
||||||
this.currentPlaying = currentPlaying
|
this.currentPlaying = currentPlaying
|
||||||
updateRemoteControl()
|
|
||||||
|
|
||||||
if (onCurrentPlayingChanged != null) {
|
if (onCurrentPlayingChanged != null) {
|
||||||
val mainHandler = Handler(context.mainLooper)
|
val mainHandler = Handler(context.mainLooper)
|
||||||
@ -296,140 +281,11 @@ class LocalMediaPlayer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* The remote control API is deprecated in API 21
|
|
||||||
*/
|
|
||||||
private fun updateRemoteControl() {
|
|
||||||
if (!Util.isLockScreenEnabled(context)) {
|
|
||||||
clearRemoteControl()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (remoteControlClient == null) {
|
|
||||||
remoteControlClient = createRemoteControlClient()
|
|
||||||
} else {
|
|
||||||
// This is probably needed only in API <=17
|
|
||||||
// "You must register your RemoteControlDisplay every time when the View which
|
|
||||||
// displays metadata is shown to the user. This is because 4.2.2 and lower
|
|
||||||
// versions support only one RemoteControlDisplay, and if system will
|
|
||||||
// decide to register it's own RCD, your RCD will be
|
|
||||||
// unregistered automatically.
|
|
||||||
// https://forum.xda-developers.com/t/guide-implement-your-own-lockscreen-like-music-controls.2401597/
|
|
||||||
audioManager.unregisterRemoteControlClient(remoteControlClient)
|
|
||||||
audioManager.registerRemoteControlClient(remoteControlClient)
|
|
||||||
}
|
|
||||||
|
|
||||||
Timber.i(
|
|
||||||
"In updateRemoteControl, playerState: %s [%d]",
|
|
||||||
playerState, playerPosition
|
|
||||||
)
|
|
||||||
|
|
||||||
if (playerState === PlayerState.STARTED) {
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
|
||||||
remoteControlClient!!.setPlaybackState(RemoteControlClient.PLAYSTATE_PLAYING)
|
|
||||||
} else {
|
|
||||||
remoteControlClient!!.setPlaybackState(
|
|
||||||
RemoteControlClient.PLAYSTATE_PLAYING,
|
|
||||||
playerPosition.toLong(), 1.0f
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
|
||||||
remoteControlClient!!.setPlaybackState(RemoteControlClient.PLAYSTATE_PAUSED)
|
|
||||||
} else {
|
|
||||||
remoteControlClient!!.setPlaybackState(
|
|
||||||
RemoteControlClient.PLAYSTATE_PAUSED,
|
|
||||||
playerPosition.toLong(), 1.0f
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentPlaying != null) {
|
|
||||||
val currentSong = currentPlaying!!.song
|
|
||||||
val lockScreenBitmap = FileUtil.getAlbumArtBitmap(
|
|
||||||
context, currentSong,
|
|
||||||
Util.getMinDisplayMetric(context), true
|
|
||||||
)
|
|
||||||
val artist = currentSong.artist
|
|
||||||
val album = currentSong.album
|
|
||||||
val title = currentSong.title
|
|
||||||
val currentSongDuration = currentSong.duration
|
|
||||||
var duration = 0L
|
|
||||||
if (currentSongDuration != null) duration = (currentSongDuration * 1000).toLong()
|
|
||||||
remoteControlClient!!.editMetadata(true)
|
|
||||||
.putString(MediaMetadataRetriever.METADATA_KEY_ARTIST, artist)
|
|
||||||
.putString(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST, artist)
|
|
||||||
.putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, album)
|
|
||||||
.putString(MediaMetadataRetriever.METADATA_KEY_TITLE, title)
|
|
||||||
.putLong(MediaMetadataRetriever.METADATA_KEY_DURATION, duration)
|
|
||||||
.putBitmap(RemoteControlClient.MetadataEditor.BITMAP_KEY_ARTWORK, lockScreenBitmap)
|
|
||||||
.apply()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun clearRemoteControl() {
|
|
||||||
if (remoteControlClient != null) {
|
|
||||||
remoteControlClient!!.setPlaybackState(RemoteControlClient.PLAYSTATE_STOPPED)
|
|
||||||
audioManager.unregisterRemoteControlClient(remoteControlClient)
|
|
||||||
remoteControlClient = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setUpRemoteControlClient() {
|
|
||||||
if (!Util.isLockScreenEnabled(context)) return
|
|
||||||
|
|
||||||
if (remoteControlClient == null) {
|
|
||||||
remoteControlClient = createRemoteControlClient()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createRemoteControlClient(): RemoteControlClient {
|
|
||||||
val componentName = ComponentName(
|
|
||||||
context.packageName,
|
|
||||||
MediaButtonIntentReceiver::class.java.name
|
|
||||||
)
|
|
||||||
|
|
||||||
val mediaButtonIntent = Intent(Intent.ACTION_MEDIA_BUTTON)
|
|
||||||
mediaButtonIntent.component = componentName
|
|
||||||
|
|
||||||
val broadcast = PendingIntent.getBroadcast(
|
|
||||||
context, 0,
|
|
||||||
mediaButtonIntent, PendingIntent.FLAG_UPDATE_CURRENT
|
|
||||||
)
|
|
||||||
|
|
||||||
val remoteControlClient = RemoteControlClient(broadcast)
|
|
||||||
audioManager.registerRemoteControlClient(remoteControlClient)
|
|
||||||
|
|
||||||
// Flags for the media transport control that this client supports.
|
|
||||||
var flags = RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS or
|
|
||||||
RemoteControlClient.FLAG_KEY_MEDIA_NEXT or
|
|
||||||
RemoteControlClient.FLAG_KEY_MEDIA_PLAY or
|
|
||||||
RemoteControlClient.FLAG_KEY_MEDIA_PAUSE or
|
|
||||||
RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE or
|
|
||||||
RemoteControlClient.FLAG_KEY_MEDIA_STOP
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
|
||||||
flags = flags or RemoteControlClient.FLAG_KEY_MEDIA_POSITION_UPDATE
|
|
||||||
remoteControlClient.setOnGetPlaybackPositionListener {
|
|
||||||
mediaPlayer.currentPosition.toLong()
|
|
||||||
}
|
|
||||||
remoteControlClient.setPlaybackPositionUpdateListener {
|
|
||||||
newPositionMs ->
|
|
||||||
seekTo(newPositionMs.toInt())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
remoteControlClient.setTransportControlFlags(flags)
|
|
||||||
|
|
||||||
return remoteControlClient
|
|
||||||
}
|
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun seekTo(position: Int) {
|
fun seekTo(position: Int) {
|
||||||
try {
|
try {
|
||||||
mediaPlayer.seekTo(position)
|
mediaPlayer.seekTo(position)
|
||||||
cachedPosition = position
|
cachedPosition = position
|
||||||
updateRemoteControl()
|
|
||||||
} catch (x: Exception) {
|
} catch (x: Exception) {
|
||||||
handleError(x)
|
handleError(x)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user