mirror of
https://github.com/antebudimir/tempus.git
synced 2025-12-31 09:33:33 +00:00
fix: update MediaItems after network change
This commit is contained in:
parent
9930537486
commit
4b7f60bb8c
4 changed files with 137 additions and 2 deletions
|
|
@ -5,18 +5,20 @@ import android.app.PendingIntent.FLAG_IMMUTABLE
|
||||||
import android.app.PendingIntent.FLAG_UPDATE_CURRENT
|
import android.app.PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
import android.app.TaskStackBuilder
|
import android.app.TaskStackBuilder
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.net.ConnectivityManager
|
||||||
|
import android.net.Network
|
||||||
|
import android.net.NetworkCapabilities
|
||||||
import android.os.Binder
|
import android.os.Binder
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
|
import android.util.Log
|
||||||
import androidx.media3.common.*
|
import androidx.media3.common.*
|
||||||
import androidx.media3.common.util.UnstableApi
|
import androidx.media3.common.util.UnstableApi
|
||||||
import androidx.media3.exoplayer.DefaultLoadControl
|
import androidx.media3.exoplayer.DefaultLoadControl
|
||||||
import androidx.media3.exoplayer.ExoPlayer
|
import androidx.media3.exoplayer.ExoPlayer
|
||||||
import androidx.media3.exoplayer.source.MediaSource
|
import androidx.media3.exoplayer.source.MediaSource
|
||||||
import androidx.media3.exoplayer.source.TrackGroupArray
|
|
||||||
import androidx.media3.exoplayer.trackselection.TrackSelectionArray
|
|
||||||
import androidx.media3.session.*
|
import androidx.media3.session.*
|
||||||
import androidx.media3.session.MediaSession.ControllerInfo
|
import androidx.media3.session.MediaSession.ControllerInfo
|
||||||
import com.cappielloantonio.tempo.R
|
import com.cappielloantonio.tempo.R
|
||||||
|
|
@ -43,6 +45,7 @@ class MediaService : MediaLibraryService() {
|
||||||
private lateinit var mediaLibrarySession: MediaLibrarySession
|
private lateinit var mediaLibrarySession: MediaLibrarySession
|
||||||
private lateinit var shuffleCommands: List<CommandButton>
|
private lateinit var shuffleCommands: List<CommandButton>
|
||||||
private lateinit var repeatCommands: List<CommandButton>
|
private lateinit var repeatCommands: List<CommandButton>
|
||||||
|
private lateinit var networkCallback: CustomNetworkCallback
|
||||||
lateinit var equalizerManager: EqualizerManager
|
lateinit var equalizerManager: EqualizerManager
|
||||||
|
|
||||||
private var customLayout = ImmutableList.of<CommandButton>()
|
private var customLayout = ImmutableList.of<CommandButton>()
|
||||||
|
|
@ -81,6 +84,38 @@ class MediaService : MediaLibraryService() {
|
||||||
const val ACTION_BIND_EQUALIZER = "com.cappielloantonio.tempo.service.BIND_EQUALIZER"
|
const val ACTION_BIND_EQUALIZER = "com.cappielloantonio.tempo.service.BIND_EQUALIZER"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateMediaItems() {
|
||||||
|
Log.d("MediaService", "update items");
|
||||||
|
val n = player.mediaItemCount
|
||||||
|
val k = player.currentMediaItemIndex
|
||||||
|
val current = player.currentPosition
|
||||||
|
val items = (0 .. n-1).map{i -> MappingUtil.mapMediaItem(player.getMediaItemAt(i))}
|
||||||
|
player.clearMediaItems()
|
||||||
|
player.setMediaItems(items, k, current)
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class CustomNetworkCallback : ConnectivityManager.NetworkCallback() {
|
||||||
|
var wasWifi = false
|
||||||
|
|
||||||
|
init {
|
||||||
|
val manager = getSystemService(ConnectivityManager::class.java)
|
||||||
|
val network = manager.activeNetwork
|
||||||
|
val capabilities = manager.getNetworkCapabilities(network)
|
||||||
|
if (capabilities != null)
|
||||||
|
wasWifi = capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCapabilitiesChanged(network : Network, networkCapabilities : NetworkCapabilities) {
|
||||||
|
val isWifi = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
|
||||||
|
if (isWifi != wasWifi) {
|
||||||
|
wasWifi = isWifi
|
||||||
|
widgetUpdateHandler.post(Runnable {
|
||||||
|
updateMediaItems()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
|
||||||
|
|
@ -90,6 +125,7 @@ class MediaService : MediaLibraryService() {
|
||||||
restorePlayerFromQueue()
|
restorePlayerFromQueue()
|
||||||
initializePlayerListener()
|
initializePlayerListener()
|
||||||
initializeEqualizerManager()
|
initializeEqualizerManager()
|
||||||
|
initializeNetworkListener()
|
||||||
|
|
||||||
setPlayer(player)
|
setPlayer(player)
|
||||||
}
|
}
|
||||||
|
|
@ -99,6 +135,7 @@ class MediaService : MediaLibraryService() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
|
releaseNetworkCallback()
|
||||||
equalizerManager.release()
|
equalizerManager.release()
|
||||||
stopWidgetUpdates()
|
stopWidgetUpdates()
|
||||||
releasePlayer()
|
releasePlayer()
|
||||||
|
|
@ -275,6 +312,12 @@ class MediaService : MediaLibraryService() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun initializeNetworkListener() {
|
||||||
|
networkCallback = CustomNetworkCallback()
|
||||||
|
getSystemService(ConnectivityManager::class.java).registerDefaultNetworkCallback(networkCallback)
|
||||||
|
updateMediaItems()
|
||||||
|
}
|
||||||
|
|
||||||
private fun restorePlayerFromQueue() {
|
private fun restorePlayerFromQueue() {
|
||||||
if (player.mediaItemCount > 0) return
|
if (player.mediaItemCount > 0) return
|
||||||
|
|
||||||
|
|
@ -398,6 +441,10 @@ class MediaService : MediaLibraryService() {
|
||||||
mediaLibrarySession.release()
|
mediaLibrarySession.release()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun releaseNetworkCallback() {
|
||||||
|
getSystemService(ConnectivityManager::class.java).unregisterNetworkCallback(networkCallback)
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("PrivateResource")
|
@SuppressLint("PrivateResource")
|
||||||
private fun getShuffleCommandButton(sessionCommand: SessionCommand): CommandButton {
|
private fun getShuffleCommandButton(sessionCommand: SessionCommand): CommandButton {
|
||||||
val isOn = sessionCommand.customAction == CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_ON
|
val isOn = sessionCommand.customAction == CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_ON
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,22 @@ public class MappingUtil {
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static MediaItem mapMediaItem(MediaItem old) {
|
||||||
|
Uri uri = old.requestMetadata.mediaUri == null ? null : MusicUtil.updateStreamUri(old.requestMetadata.mediaUri);
|
||||||
|
return new MediaItem.Builder()
|
||||||
|
.setMediaId(old.mediaId)
|
||||||
|
.setMediaMetadata(old.mediaMetadata)
|
||||||
|
.setRequestMetadata(
|
||||||
|
new MediaItem.RequestMetadata.Builder()
|
||||||
|
.setMediaUri(uri)
|
||||||
|
.setExtras(old.requestMetadata.extras)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.setMimeType(MimeTypes.BASE_TYPE_AUDIO)
|
||||||
|
.setUri(uri)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
public static List<MediaItem> mapDownloads(List<Child> items) {
|
public static List<MediaItem> mapDownloads(List<Child> items) {
|
||||||
ArrayList<MediaItem> downloads = new ArrayList<>();
|
ArrayList<MediaItem> downloads = new ArrayList<>();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,16 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class MusicUtil {
|
public class MusicUtil {
|
||||||
private static final String TAG = "MusicUtil";
|
private static final String TAG = "MusicUtil";
|
||||||
|
|
||||||
|
private static final Pattern BITRATE_PATTERN = Pattern.compile("&maxBitRate=\\d+");
|
||||||
|
private static final Pattern FORMAT_PATTERN = Pattern.compile("&format=\\w+");
|
||||||
|
|
||||||
public static Uri getStreamUri(String id) {
|
public static Uri getStreamUri(String id) {
|
||||||
Map<String, String> params = App.getSubsonicClientInstance(false).getParams();
|
Map<String, String> params = App.getSubsonicClientInstance(false).getParams();
|
||||||
|
|
||||||
|
|
@ -61,6 +66,24 @@ public class MusicUtil {
|
||||||
return Uri.parse(uri.toString());
|
return Uri.parse(uri.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Uri updateStreamUri(Uri uri) {
|
||||||
|
String s = uri.toString();
|
||||||
|
Matcher m1 = BITRATE_PATTERN.matcher(s);
|
||||||
|
s = m1.replaceAll("");
|
||||||
|
Matcher m2 = FORMAT_PATTERN.matcher(s);
|
||||||
|
s = m2.replaceAll("");
|
||||||
|
s = s.replace("&estimateContentLength=true", "");
|
||||||
|
|
||||||
|
if (!Preferences.isServerPrioritized())
|
||||||
|
s += "&maxBitRate=" + getBitratePreference();
|
||||||
|
if (!Preferences.isServerPrioritized())
|
||||||
|
s += "&format=" + getTranscodingFormatPreference();
|
||||||
|
if (Preferences.askForEstimateContentLength())
|
||||||
|
s += "&estimateContentLength=true";
|
||||||
|
|
||||||
|
return Uri.parse(s);
|
||||||
|
}
|
||||||
|
|
||||||
public static Uri getDownloadUri(String id) {
|
public static Uri getDownloadUri(String id) {
|
||||||
StringBuilder uri = new StringBuilder();
|
StringBuilder uri = new StringBuilder();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,14 @@ import android.app.PendingIntent.FLAG_IMMUTABLE
|
||||||
import android.app.PendingIntent.FLAG_UPDATE_CURRENT
|
import android.app.PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
import android.app.TaskStackBuilder
|
import android.app.TaskStackBuilder
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.net.ConnectivityManager
|
||||||
|
import android.net.Network
|
||||||
|
import android.net.NetworkCapabilities
|
||||||
import android.os.Binder
|
import android.os.Binder
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
|
import android.util.Log
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.media3.cast.CastPlayer
|
import androidx.media3.cast.CastPlayer
|
||||||
import androidx.media3.cast.SessionAvailabilityListener
|
import androidx.media3.cast.SessionAvailabilityListener
|
||||||
|
|
@ -43,6 +47,7 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener {
|
||||||
private lateinit var castPlayer: CastPlayer
|
private lateinit var castPlayer: CastPlayer
|
||||||
private lateinit var mediaLibrarySession: MediaLibrarySession
|
private lateinit var mediaLibrarySession: MediaLibrarySession
|
||||||
private lateinit var librarySessionCallback: MediaLibrarySessionCallback
|
private lateinit var librarySessionCallback: MediaLibrarySessionCallback
|
||||||
|
private lateinit var networkCallback: CustomNetworkCallback
|
||||||
lateinit var equalizerManager: EqualizerManager
|
lateinit var equalizerManager: EqualizerManager
|
||||||
|
|
||||||
inner class LocalBinder : Binder() {
|
inner class LocalBinder : Binder() {
|
||||||
|
|
@ -69,6 +74,38 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateMediaItems() {
|
||||||
|
Log.d("MediaService", "update items");
|
||||||
|
val n = player.mediaItemCount
|
||||||
|
val k = player.currentMediaItemIndex
|
||||||
|
val current = player.currentPosition
|
||||||
|
val items = (0 .. n-1).map{i -> MappingUtil.mapMediaItem(player.getMediaItemAt(i))}
|
||||||
|
player.clearMediaItems()
|
||||||
|
player.setMediaItems(items, k, current)
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class CustomNetworkCallback : ConnectivityManager.NetworkCallback() {
|
||||||
|
var wasWifi = false
|
||||||
|
|
||||||
|
init {
|
||||||
|
val manager = getSystemService(ConnectivityManager::class.java)
|
||||||
|
val network = manager.activeNetwork
|
||||||
|
val capabilities = manager.getNetworkCapabilities(network)
|
||||||
|
if (capabilities != null)
|
||||||
|
wasWifi = capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCapabilitiesChanged(network : Network, networkCapabilities : NetworkCapabilities) {
|
||||||
|
val isWifi = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
|
||||||
|
if (isWifi != wasWifi) {
|
||||||
|
wasWifi = isWifi
|
||||||
|
widgetUpdateHandler.post(Runnable {
|
||||||
|
updateMediaItems()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
|
||||||
|
|
@ -79,6 +116,7 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener {
|
||||||
initializePlayerListener()
|
initializePlayerListener()
|
||||||
initializeCastPlayer()
|
initializeCastPlayer()
|
||||||
initializeEqualizerManager()
|
initializeEqualizerManager()
|
||||||
|
initializeNetworkListener()
|
||||||
|
|
||||||
setPlayer(
|
setPlayer(
|
||||||
null,
|
null,
|
||||||
|
|
@ -99,6 +137,7 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
|
releaseNetworkCallback()
|
||||||
equalizerManager.release()
|
equalizerManager.release()
|
||||||
stopWidgetUpdates()
|
stopWidgetUpdates()
|
||||||
releasePlayer()
|
releasePlayer()
|
||||||
|
|
@ -178,6 +217,12 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener {
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun initializeNetworkListener() {
|
||||||
|
networkCallback = CustomNetworkCallback()
|
||||||
|
getSystemService(ConnectivityManager::class.java).registerDefaultNetworkCallback(networkCallback)
|
||||||
|
updateMediaItems()
|
||||||
|
}
|
||||||
|
|
||||||
private fun restorePlayerFromQueue() {
|
private fun restorePlayerFromQueue() {
|
||||||
if (player.mediaItemCount > 0) return
|
if (player.mediaItemCount > 0) return
|
||||||
|
|
||||||
|
|
@ -374,6 +419,10 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener {
|
||||||
automotiveRepository.deleteMetadata()
|
automotiveRepository.deleteMetadata()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun releaseNetworkCallback() {
|
||||||
|
getSystemService(ConnectivityManager::class.java).unregisterNetworkCallback(networkCallback)
|
||||||
|
}
|
||||||
|
|
||||||
private fun getRenderersFactory() = DownloadUtil.buildRenderersFactory(this, false)
|
private fun getRenderersFactory() = DownloadUtil.buildRenderersFactory(this, false)
|
||||||
|
|
||||||
override fun onCastSessionAvailable() {
|
override fun onCastSessionAvailable() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue