From 4c865e199d85e67efdf25f7163bd1ed3653d019f Mon Sep 17 00:00:00 2001 From: pca006132 Date: Thu, 30 Oct 2025 18:01:07 +0800 Subject: [PATCH 1/9] feat: sort artists by album count --- .../tempo/ui/adapter/ArtistCatalogueAdapter.java | 3 +++ .../tempo/ui/fragment/ArtistCatalogueFragment.java | 3 +++ app/src/main/java/com/cappielloantonio/tempo/util/Constants.kt | 1 + app/src/main/res/menu/sort_artist_popup_menu.xml | 3 +++ app/src/main/res/values/strings.xml | 1 + 5 files changed, 11 insertions(+) diff --git a/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/ArtistCatalogueAdapter.java b/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/ArtistCatalogueAdapter.java index 77c3169a..b1defe42 100644 --- a/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/ArtistCatalogueAdapter.java +++ b/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/ArtistCatalogueAdapter.java @@ -151,6 +151,9 @@ public class ArtistCatalogueAdapter extends RecyclerView.Adapter + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c5b35a88..b06c81c0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -200,6 +200,7 @@ Artist Name Random + Album Count Recently added Recently played Most played From 5d5113292119e020ac5443d621bcfdb88a8dc6c3 Mon Sep 17 00:00:00 2001 From: pca006132 Date: Thu, 30 Oct 2025 19:55:52 +0800 Subject: [PATCH 2/9] feat: add preference to sort artists by album count --- .../tempo/ui/fragment/ArtistCatalogueFragment.java | 6 +++++- .../com/cappielloantonio/tempo/util/Preferences.kt | 11 +++++++++++ app/src/main/res/values/strings.xml | 2 ++ app/src/main/res/xml/global_preferences.xml | 6 ++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/ArtistCatalogueFragment.java b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/ArtistCatalogueFragment.java index 208ef4d7..7e7ce759 100644 --- a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/ArtistCatalogueFragment.java +++ b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/ArtistCatalogueFragment.java @@ -34,6 +34,7 @@ import com.cappielloantonio.tempo.interfaces.ClickCallback; import com.cappielloantonio.tempo.ui.activity.MainActivity; import com.cappielloantonio.tempo.ui.adapter.ArtistCatalogueAdapter; import com.cappielloantonio.tempo.util.Constants; +import com.cappielloantonio.tempo.util.Preferences; import com.cappielloantonio.tempo.viewmodel.ArtistCatalogueViewModel; import com.cappielloantonio.tempo.subsonic.models.ArtistID3; @@ -114,7 +115,10 @@ public class ArtistCatalogueFragment extends Fragment implements ClickCallback { artistAdapter = new ArtistCatalogueAdapter(this); artistAdapter.setStateRestorationPolicy(RecyclerView.Adapter.StateRestorationPolicy.PREVENT_WHEN_EMPTY); bind.artistCatalogueRecyclerView.setAdapter(artistAdapter); - artistCatalogueViewModel.getArtistList().observe(getViewLifecycleOwner(), artistList -> artistAdapter.setItems(artistList)); + artistCatalogueViewModel.getArtistList().observe(getViewLifecycleOwner(), artistList -> { + artistAdapter.setItems(artistList); + artistAdapter.sort(Preferences.getArtistSortOrder()); + }); bind.artistCatalogueRecyclerView.setOnTouchListener((v, event) -> { hideKeyboard(v); diff --git a/app/src/main/java/com/cappielloantonio/tempo/util/Preferences.kt b/app/src/main/java/com/cappielloantonio/tempo/util/Preferences.kt index 4815fb83..42ffa524 100644 --- a/app/src/main/java/com/cappielloantonio/tempo/util/Preferences.kt +++ b/app/src/main/java/com/cappielloantonio/tempo/util/Preferences.kt @@ -79,6 +79,7 @@ object Preferences { private const val ALBUM_DETAIL = "album_detail" private const val ALBUM_SORT_ORDER = "album_sort_order" private const val DEFAULT_ALBUM_SORT_ORDER = Constants.ALBUM_ORDER_BY_NAME + private const val ARTIST_SORT_BY_ALBUM_COUNT= "artist_sort_by_album_count" @JvmStatic fun getServer(): String? { @@ -656,4 +657,14 @@ object Preferences { fun setAlbumSortOrder(sortOrder: String) { App.getInstance().preferences.edit().putString(ALBUM_SORT_ORDER, sortOrder).apply() } + + @JvmStatic + fun getArtistSortOrder(): String { + val sort_by_album_count = App.getInstance().preferences.getBoolean(ARTIST_SORT_BY_ALBUM_COUNT, false) + Log.d("Preferences", "getSortOrder") + if (sort_by_album_count) + return Constants.ARTIST_ORDER_BY_ALBUM_COUNT + else + return Constants.ARTIST_ORDER_BY_NAME + } } \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b06c81c0..2dafec49 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -528,4 +528,6 @@ Show album detail If enabled, show the album details like genre, song count etc. on the album page + Sort artists by album count + If enabled, sort the artists by album count. Sort by name if disabled. diff --git a/app/src/main/res/xml/global_preferences.xml b/app/src/main/res/xml/global_preferences.xml index 4610e255..a8caeb8b 100644 --- a/app/src/main/res/xml/global_preferences.xml +++ b/app/src/main/res/xml/global_preferences.xml @@ -116,6 +116,12 @@ android:summary="@string/settings_album_detail_summary" android:key="album_detail" /> + + From 7f661246141b19bc97af340aec13c35c73dcfcbd Mon Sep 17 00:00:00 2001 From: pca006132 Date: Fri, 31 Oct 2025 20:16:01 +0800 Subject: [PATCH 3/9] fix: download tab performance --- .../tempo/ui/fragment/DownloadFragment.java | 2 - app/src/main/res/layout/fragment_download.xml | 150 ++++++++---------- 2 files changed, 69 insertions(+), 83 deletions(-) diff --git a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/DownloadFragment.java b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/DownloadFragment.java index be2b3eb0..12ca2434 100644 --- a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/DownloadFragment.java +++ b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/DownloadFragment.java @@ -117,14 +117,12 @@ public class DownloadFragment extends Fragment implements ClickCallback { if (songs.isEmpty()) { if (bind != null) { bind.emptyDownloadLayout.setVisibility(View.VISIBLE); - bind.fragmentDownloadNestedScrollView.setVisibility(View.GONE); bind.downloadDownloadedSector.setVisibility(View.GONE); bind.downloadedGroupByImageView.setVisibility(View.GONE); } } else { if (bind != null) { bind.emptyDownloadLayout.setVisibility(View.GONE); - bind.fragmentDownloadNestedScrollView.setVisibility(View.VISIBLE); bind.downloadDownloadedSector.setVisibility(View.VISIBLE); bind.downloadedGroupByImageView.setVisibility(View.VISIBLE); diff --git a/app/src/main/res/layout/fragment_download.xml b/app/src/main/res/layout/fragment_download.xml index 68d3f84b..47fd92e0 100644 --- a/app/src/main/res/layout/fragment_download.xml +++ b/app/src/main/res/layout/fragment_download.xml @@ -1,9 +1,10 @@ - + android:layout_height="match_parent" + android:orientation="vertical"> - + tools:visibility="visible"> - + + + android:text="@string/download_shuffle_all_subtitle" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/downloaded_text_view_refreshable" /> - + - + - + + - - - - - - - - - + + From 52b2ca8fa7b5d59224dfc418c825bdae1a26fd47 Mon Sep 17 00:00:00 2001 From: pca006132 Date: Sat, 1 Nov 2025 11:43:30 +0800 Subject: [PATCH 4/9] chore: update media3 dependencies --- app/build.gradle | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 2cc90af4..53758756 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -110,12 +110,12 @@ dependencies { implementation 'com.github.bumptech.glide:annotations:4.16.0' // Media3 - implementation 'androidx.media3:media3-session:1.5.1' - implementation 'androidx.media3:media3-common:1.5.1' - implementation 'androidx.media3:media3-exoplayer:1.5.1' - implementation 'androidx.media3:media3-ui:1.5.1' - implementation 'androidx.media3:media3-exoplayer-hls:1.5.1' - tempusImplementation 'androidx.media3:media3-cast:1.5.1' + implementation 'androidx.media3:media3-session:1.8.0' + implementation 'androidx.media3:media3-common:1.8.0' + implementation 'androidx.media3:media3-exoplayer:1.8.0' + implementation 'androidx.media3:media3-ui:1.8.0' + implementation 'androidx.media3:media3-exoplayer-hls:1.8.0' + tempusImplementation 'androidx.media3:media3-cast:1.8.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0' From 0abdfc6b19e7486678df6bad59fef52ea38b3294 Mon Sep 17 00:00:00 2001 From: pca006132 Date: Sat, 1 Nov 2025 10:33:14 +0800 Subject: [PATCH 5/9] fix: remove NestedScrollViews for fragment_album_page --- .../main/res/layout/fragment_album_page.xml | 73 +++++-------------- 1 file changed, 17 insertions(+), 56 deletions(-) diff --git a/app/src/main/res/layout/fragment_album_page.xml b/app/src/main/res/layout/fragment_album_page.xml index 411d5c1c..1cf81bc3 100644 --- a/app/src/main/res/layout/fragment_album_page.xml +++ b/app/src/main/res/layout/fragment_album_page.xml @@ -14,22 +14,21 @@ app:layout_collapseMode="pin" app:navigationIcon="@drawable/ic_arrow_back" /> - - - + + android:layout_height="wrap_content"> + android:paddingTop="8dp" + app:layout_scrollFlags="scroll|exitUntilCollapsed"> + - - - - - - - - - - - - - - + + \ No newline at end of file From 77c0b86dace004b532aeeca7621611f8e7ae879f Mon Sep 17 00:00:00 2001 From: pca006132 Date: Sat, 1 Nov 2025 13:34:47 +0800 Subject: [PATCH 6/9] fix: playlist page should not snap --- app/src/main/res/layout/fragment_playlist_page.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/layout/fragment_playlist_page.xml b/app/src/main/res/layout/fragment_playlist_page.xml index d409601a..87d7e858 100644 --- a/app/src/main/res/layout/fragment_playlist_page.xml +++ b/app/src/main/res/layout/fragment_playlist_page.xml @@ -27,7 +27,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/colorSurface" - app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"> + app:layout_scrollFlags="scroll|exitUntilCollapsed"> Date: Sat, 1 Nov 2025 22:43:09 +0300 Subject: [PATCH 7/9] Update USAGE.md with instant mix details Follow up of https://github.com/eddyizm/tempus/issues/184#issuecomment-3475333928 --- USAGE.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/USAGE.md b/USAGE.md index e9711875..b045b9b1 100644 --- a/USAGE.md +++ b/USAGE.md @@ -78,6 +78,9 @@ On the main player control screen, tapping on the artwork will reveal a small co 1. Downloads the track (there is a notification if the android screen but not a pop toast currently ) 2. Adds track to playlist - pops up playlist dialog. 3. Adds tracks to the queue via instant mix function + * TBD: what is the _instant mix function_? + * Uses [getSimilarSongs](https://opensubsonic.netlify.app/docs/endpoints/getsimilarsongs/) of OpenSubsonic API. + Which tracks to be mixed depends on the server implementation. For example, Navidrome gets 15 similar artists from LastFM, then 20 top songs from each. 4. Saves play queue (if the feature is enabled in the settings) * if the setting is not enabled, it toggles a view of the lyrics if available (slides to the right) @@ -163,4 +166,4 @@ For additional help: --- -*Note: This app requires a pre-existing Subsonic-compatible server with music content.* \ No newline at end of file +*Note: This app requires a pre-existing Subsonic-compatible server with music content.* From d35146dba3a2d2dd10ca76519a3b610ebcc20a53 Mon Sep 17 00:00:00 2001 From: pca006132 Date: Sun, 2 Nov 2025 14:50:12 +0800 Subject: [PATCH 8/9] fix: do not override itemType and itemId --- .../tempo/ui/adapter/AlbumCatalogueAdapter.java | 10 ---------- .../tempo/ui/adapter/ArtistAdapter.java | 10 ---------- .../tempo/ui/adapter/ArtistCatalogueAdapter.java | 10 ---------- .../tempo/ui/adapter/ArtistHorizontalAdapter.java | 10 ---------- .../tempo/ui/adapter/ArtistSimilarAdapter.java | 10 ---------- .../tempo/ui/adapter/DownloadHorizontalAdapter.java | 10 ---------- .../ui/adapter/PodcastChannelCatalogueAdapter.java | 10 ---------- .../tempo/ui/adapter/PodcastEpisodeAdapter.java | 10 ---------- .../tempo/ui/adapter/SongHorizontalAdapter.java | 10 ---------- 9 files changed, 90 deletions(-) diff --git a/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/AlbumCatalogueAdapter.java b/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/AlbumCatalogueAdapter.java index e2d0563e..ba663c37 100644 --- a/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/AlbumCatalogueAdapter.java +++ b/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/AlbumCatalogueAdapter.java @@ -105,16 +105,6 @@ public class AlbumCatalogueAdapter extends RecyclerView.Adapter groupSong(List songs) { switch (view) { case Constants.DOWNLOAD_TYPE_TRACK: diff --git a/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/PodcastChannelCatalogueAdapter.java b/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/PodcastChannelCatalogueAdapter.java index 3eb6bc02..f3784175 100644 --- a/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/PodcastChannelCatalogueAdapter.java +++ b/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/PodcastChannelCatalogueAdapter.java @@ -95,16 +95,6 @@ public class PodcastChannelCatalogueAdapter extends RecyclerView.Adapter Date: Sun, 2 Nov 2025 16:37:01 +0800 Subject: [PATCH 9/9] fix: update MediaItems after network change --- .../tempo/service/MediaService.kt | 51 ++++++++++++++++++- .../tempo/util/MappingUtil.java | 16 ++++++ .../tempo/util/MusicUtil.java | 23 +++++++++ .../tempo/service/MediaService.kt | 49 ++++++++++++++++++ 4 files changed, 137 insertions(+), 2 deletions(-) diff --git a/app/src/degoogled/java/com/cappielloantonio/tempo/service/MediaService.kt b/app/src/degoogled/java/com/cappielloantonio/tempo/service/MediaService.kt index c669a7d3..bb237c62 100644 --- a/app/src/degoogled/java/com/cappielloantonio/tempo/service/MediaService.kt +++ b/app/src/degoogled/java/com/cappielloantonio/tempo/service/MediaService.kt @@ -5,18 +5,20 @@ import android.app.PendingIntent.FLAG_IMMUTABLE import android.app.PendingIntent.FLAG_UPDATE_CURRENT import android.app.TaskStackBuilder import android.content.Intent +import android.net.ConnectivityManager +import android.net.Network +import android.net.NetworkCapabilities import android.os.Binder import android.os.Bundle import android.os.IBinder import android.os.Handler import android.os.Looper +import android.util.Log import androidx.media3.common.* import androidx.media3.common.util.UnstableApi import androidx.media3.exoplayer.DefaultLoadControl import androidx.media3.exoplayer.ExoPlayer 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.MediaSession.ControllerInfo import com.cappielloantonio.tempo.R @@ -43,6 +45,7 @@ class MediaService : MediaLibraryService() { private lateinit var mediaLibrarySession: MediaLibrarySession private lateinit var shuffleCommands: List private lateinit var repeatCommands: List + private lateinit var networkCallback: CustomNetworkCallback lateinit var equalizerManager: EqualizerManager private var customLayout = ImmutableList.of() @@ -81,6 +84,38 @@ class MediaService : MediaLibraryService() { 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() { super.onCreate() @@ -90,6 +125,7 @@ class MediaService : MediaLibraryService() { restorePlayerFromQueue() initializePlayerListener() initializeEqualizerManager() + initializeNetworkListener() setPlayer(player) } @@ -99,6 +135,7 @@ class MediaService : MediaLibraryService() { } override fun onDestroy() { + releaseNetworkCallback() equalizerManager.release() stopWidgetUpdates() releasePlayer() @@ -275,6 +312,12 @@ class MediaService : MediaLibraryService() { } } + private fun initializeNetworkListener() { + networkCallback = CustomNetworkCallback() + getSystemService(ConnectivityManager::class.java).registerDefaultNetworkCallback(networkCallback) + updateMediaItems() + } + private fun restorePlayerFromQueue() { if (player.mediaItemCount > 0) return @@ -398,6 +441,10 @@ class MediaService : MediaLibraryService() { mediaLibrarySession.release() } + private fun releaseNetworkCallback() { + getSystemService(ConnectivityManager::class.java).unregisterNetworkCallback(networkCallback) + } + @SuppressLint("PrivateResource") private fun getShuffleCommandButton(sessionCommand: SessionCommand): CommandButton { val isOn = sessionCommand.customAction == CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_ON diff --git a/app/src/main/java/com/cappielloantonio/tempo/util/MappingUtil.java b/app/src/main/java/com/cappielloantonio/tempo/util/MappingUtil.java index 558aa218..1222804b 100644 --- a/app/src/main/java/com/cappielloantonio/tempo/util/MappingUtil.java +++ b/app/src/main/java/com/cappielloantonio/tempo/util/MappingUtil.java @@ -115,6 +115,22 @@ public class MappingUtil { .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 mapDownloads(List items) { ArrayList downloads = new ArrayList<>(); diff --git a/app/src/main/java/com/cappielloantonio/tempo/util/MusicUtil.java b/app/src/main/java/com/cappielloantonio/tempo/util/MusicUtil.java index 696b5b9d..cd2c7a36 100644 --- a/app/src/main/java/com/cappielloantonio/tempo/util/MusicUtil.java +++ b/app/src/main/java/com/cappielloantonio/tempo/util/MusicUtil.java @@ -21,11 +21,16 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; public class 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) { Map params = App.getSubsonicClientInstance(false).getParams(); @@ -61,6 +66,24 @@ public class MusicUtil { 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) { StringBuilder uri = new StringBuilder(); diff --git a/app/src/tempus/java/com/cappielloantonio/tempo/service/MediaService.kt b/app/src/tempus/java/com/cappielloantonio/tempo/service/MediaService.kt index 2ff81ac4..36ea5b26 100644 --- a/app/src/tempus/java/com/cappielloantonio/tempo/service/MediaService.kt +++ b/app/src/tempus/java/com/cappielloantonio/tempo/service/MediaService.kt @@ -4,10 +4,14 @@ import android.app.PendingIntent.FLAG_IMMUTABLE import android.app.PendingIntent.FLAG_UPDATE_CURRENT import android.app.TaskStackBuilder import android.content.Intent +import android.net.ConnectivityManager +import android.net.Network +import android.net.NetworkCapabilities import android.os.Binder import android.os.IBinder import android.os.Handler import android.os.Looper +import android.util.Log import androidx.core.content.ContextCompat import androidx.media3.cast.CastPlayer import androidx.media3.cast.SessionAvailabilityListener @@ -43,6 +47,7 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener { private lateinit var castPlayer: CastPlayer private lateinit var mediaLibrarySession: MediaLibrarySession private lateinit var librarySessionCallback: MediaLibrarySessionCallback + private lateinit var networkCallback: CustomNetworkCallback lateinit var equalizerManager: EqualizerManager 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() { super.onCreate() @@ -79,6 +116,7 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener { initializePlayerListener() initializeCastPlayer() initializeEqualizerManager() + initializeNetworkListener() setPlayer( null, @@ -99,6 +137,7 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener { } override fun onDestroy() { + releaseNetworkCallback() equalizerManager.release() stopWidgetUpdates() releasePlayer() @@ -178,6 +217,12 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener { .build() } + private fun initializeNetworkListener() { + networkCallback = CustomNetworkCallback() + getSystemService(ConnectivityManager::class.java).registerDefaultNetworkCallback(networkCallback) + updateMediaItems() + } + private fun restorePlayerFromQueue() { if (player.mediaItemCount > 0) return @@ -374,6 +419,10 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener { automotiveRepository.deleteMetadata() } + private fun releaseNetworkCallback() { + getSystemService(ConnectivityManager::class.java).unregisterNetworkCallback(networkCallback) + } + private fun getRenderersFactory() = DownloadUtil.buildRenderersFactory(this, false) override fun onCastSessionAvailable() {