mirror of
https://github.com/antebudimir/tempus.git
synced 2025-12-31 17:43:32 +00:00
feat: radio
This commit is contained in:
parent
1deb9ed3d7
commit
a1ee70c24f
16 changed files with 478 additions and 11 deletions
|
|
@ -31,4 +31,8 @@ public interface ClickCallback {
|
|||
default void onPodcastClick(Bundle bundle) {}
|
||||
|
||||
default void onPodcastLongClick(Bundle bundle) {}
|
||||
|
||||
default void onInternetRadioStationClick(Bundle bundle) {}
|
||||
|
||||
default void onInternetRadioStationLongClick(Bundle bundle) {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
package com.cappielloantonio.play.repository;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
|
||||
import com.cappielloantonio.play.App;
|
||||
import com.cappielloantonio.play.subsonic.base.ApiResponse;
|
||||
import com.cappielloantonio.play.subsonic.models.InternetRadioStation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
public class RadioRepository {
|
||||
public MutableLiveData<List<InternetRadioStation>> getInternetRadioStations() {
|
||||
MutableLiveData<List<InternetRadioStation>> radioStation = new MutableLiveData<>();
|
||||
|
||||
App.getSubsonicClientInstance(false)
|
||||
.getInternetRadioClient()
|
||||
.getInternetRadioStations()
|
||||
.enqueue(new Callback<ApiResponse>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
|
||||
if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getInternetRadioStations() != null) {
|
||||
radioStation.setValue(response.body().getSubsonicResponse().getInternetRadioStations().getInternetRadioStations());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
return radioStation;
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ import com.cappielloantonio.play.repository.ChronologyRepository;
|
|||
import com.cappielloantonio.play.repository.QueueRepository;
|
||||
import com.cappielloantonio.play.repository.SongRepository;
|
||||
import com.cappielloantonio.play.subsonic.models.Child;
|
||||
import com.cappielloantonio.play.subsonic.models.InternetRadioStation;
|
||||
import com.cappielloantonio.play.util.MappingUtil;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
|
|
@ -128,6 +129,23 @@ public class MediaManager {
|
|||
}
|
||||
}
|
||||
|
||||
public static void startRadio(ListenableFuture<MediaBrowser> mediaBrowserListenableFuture, InternetRadioStation internetRadioStation) {
|
||||
if (mediaBrowserListenableFuture != null) {
|
||||
mediaBrowserListenableFuture.addListener(() -> {
|
||||
try {
|
||||
if (mediaBrowserListenableFuture.isDone()) {
|
||||
mediaBrowserListenableFuture.get().clearMediaItems();
|
||||
mediaBrowserListenableFuture.get().setMediaItem(MappingUtil.mapInternetRadioStation(internetRadioStation));
|
||||
mediaBrowserListenableFuture.get().prepare();
|
||||
mediaBrowserListenableFuture.get().play();
|
||||
}
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, MoreExecutors.directExecutor());
|
||||
}
|
||||
}
|
||||
|
||||
public static void enqueue(ListenableFuture<MediaBrowser> mediaBrowserListenableFuture, List<Child> media, boolean playImmediatelyAfter) {
|
||||
if (mediaBrowserListenableFuture != null) {
|
||||
mediaBrowserListenableFuture.addListener(() -> {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.cappielloantonio.play.subsonic;
|
|||
import com.cappielloantonio.play.subsonic.api.albumsonglist.AlbumSongListClient;
|
||||
import com.cappielloantonio.play.subsonic.api.bookmarks.BookmarksClient;
|
||||
import com.cappielloantonio.play.subsonic.api.browsing.BrowsingClient;
|
||||
import com.cappielloantonio.play.subsonic.api.internetradio.InternetRadioClient;
|
||||
import com.cappielloantonio.play.subsonic.api.mediaannotation.MediaAnnotationClient;
|
||||
import com.cappielloantonio.play.subsonic.api.medialibraryscanning.MediaLibraryScanningClient;
|
||||
import com.cappielloantonio.play.subsonic.api.mediaretrieval.MediaRetrievalClient;
|
||||
|
|
@ -31,6 +32,7 @@ public class Subsonic {
|
|||
private PodcastClient podcastClient;
|
||||
private MediaLibraryScanningClient mediaLibraryScanningClient;
|
||||
private BookmarksClient bookmarksClient;
|
||||
private InternetRadioClient internetRadioClient;
|
||||
|
||||
public Subsonic(SubsonicPreferences preferences) {
|
||||
this.preferences = preferences;
|
||||
|
|
@ -110,6 +112,13 @@ public class Subsonic {
|
|||
return bookmarksClient;
|
||||
}
|
||||
|
||||
public InternetRadioClient getInternetRadioClient() {
|
||||
if (internetRadioClient == null) {
|
||||
internetRadioClient = new InternetRadioClient(this);
|
||||
}
|
||||
return internetRadioClient;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
String url = preferences.getServerUrl() + "/rest/";
|
||||
return url.replace("//rest", "/rest");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
package com.cappielloantonio.play.subsonic.api.internetradio;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.cappielloantonio.play.subsonic.RetrofitClient;
|
||||
import com.cappielloantonio.play.subsonic.Subsonic;
|
||||
import com.cappielloantonio.play.subsonic.base.ApiResponse;
|
||||
|
||||
import retrofit2.Call;
|
||||
|
||||
public class InternetRadioClient {
|
||||
private static final String TAG = "InternetRadioClient";
|
||||
|
||||
private final Subsonic subsonic;
|
||||
private final InternetRadioService internetRadioService;
|
||||
|
||||
public InternetRadioClient(Subsonic subsonic) {
|
||||
this.subsonic = subsonic;
|
||||
this.internetRadioService = new RetrofitClient(subsonic).getRetrofit().create(InternetRadioService.class);
|
||||
}
|
||||
|
||||
public Call<ApiResponse> getInternetRadioStations() {
|
||||
Log.d(TAG, "getInternetRadioStations()");
|
||||
return internetRadioService.getInternetRadioStations(subsonic.getParams());
|
||||
}
|
||||
|
||||
public Call<ApiResponse> createInternetRadioStation(String streamUrl, String name, String homepageUrl) {
|
||||
Log.d(TAG, "createInternetRadioStation()");
|
||||
return internetRadioService.createInternetRadioStation(subsonic.getParams(), streamUrl, name, homepageUrl);
|
||||
}
|
||||
|
||||
public Call<ApiResponse> updateInternetRadioStation(String id, String streamUrl, String name, String homepageUrl) {
|
||||
Log.d(TAG, "updateInternetRadioStation()");
|
||||
return internetRadioService.updateInternetRadioStation(subsonic.getParams(), id, streamUrl, name, homepageUrl);
|
||||
}
|
||||
|
||||
public Call<ApiResponse> deleteInternetRadioStation(String id) {
|
||||
Log.d(TAG, "deleteInternetRadioStation()");
|
||||
return internetRadioService.deleteInternetRadioStation(subsonic.getParams(), id);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package com.cappielloantonio.play.subsonic.api.internetradio;
|
||||
|
||||
import com.cappielloantonio.play.subsonic.base.ApiResponse;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.Query;
|
||||
import retrofit2.http.QueryMap;
|
||||
|
||||
public interface InternetRadioService {
|
||||
@GET("getInternetRadioStations")
|
||||
Call<ApiResponse> getInternetRadioStations(@QueryMap Map<String, String> params);
|
||||
|
||||
@GET("createInternetRadioStation")
|
||||
Call<ApiResponse> createInternetRadioStation(@QueryMap Map<String, String> params, @Query("streamUrl") String streamUrl, @Query("name") String name, @Query("homepageUrl") String homepageUrl);
|
||||
|
||||
@GET("updateInternetRadioStation")
|
||||
Call<ApiResponse> updateInternetRadioStation(@QueryMap Map<String, String> params, @Query("id") String id, @Query("streamUrl") String streamUrl, @Query("name") String name, @Query("homepageUrl") String homepageUrl);
|
||||
|
||||
@GET("deleteInternetRadioStation")
|
||||
Call<ApiResponse> deleteInternetRadioStation(@QueryMap Map<String, String> params, @Query("id") String id);
|
||||
}
|
||||
|
|
@ -1,6 +1,10 @@
|
|||
package com.cappielloantonio.play.subsonic.models
|
||||
|
||||
class InternetRadioStation {
|
||||
import android.os.Parcelable
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
class InternetRadioStation : Parcelable {
|
||||
var id: String? = null
|
||||
var name: String? = null
|
||||
var streamUrl: String? = null
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
package com.cappielloantonio.play.subsonic.models
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
class InternetRadioStations {
|
||||
@SerializedName("internetRadioStation")
|
||||
var internetRadioStations: List<InternetRadioStation>? = null
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
package com.cappielloantonio.play.ui.adapter;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.cappielloantonio.play.databinding.ItemHomeInternetRadioStationBinding;
|
||||
import com.cappielloantonio.play.glide.CustomGlideRequest;
|
||||
import com.cappielloantonio.play.interfaces.ClickCallback;
|
||||
import com.cappielloantonio.play.subsonic.models.InternetRadioStation;
|
||||
import com.cappielloantonio.play.util.Constants;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@UnstableApi
|
||||
public class InternetRadioStationAdapter extends RecyclerView.Adapter<InternetRadioStationAdapter.ViewHolder> {
|
||||
private final ClickCallback click;
|
||||
|
||||
private List<InternetRadioStation> internetRadioStations;
|
||||
|
||||
public InternetRadioStationAdapter(ClickCallback click) {
|
||||
this.click = click;
|
||||
this.internetRadioStations = Collections.emptyList();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
ItemHomeInternetRadioStationBinding view = ItemHomeInternetRadioStationBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||
InternetRadioStation internetRadioStation = internetRadioStations.get(position);
|
||||
|
||||
holder.item.internetRadioStationTitleTextView.setText(internetRadioStation.getName());
|
||||
holder.item.internetRadioStationSubtitleTextView.setText(internetRadioStation.getStreamUrl());
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), internetRadioStation.getStreamUrl())
|
||||
.build()
|
||||
.into(holder.item.internetRadioStationCoverImageView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return internetRadioStations.size();
|
||||
}
|
||||
|
||||
public void setItems(List<InternetRadioStation> internetRadioStations) {
|
||||
this.internetRadioStations = internetRadioStations;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public InternetRadioStation getItem(int position) {
|
||||
return internetRadioStations.get(position);
|
||||
}
|
||||
|
||||
public class ViewHolder extends RecyclerView.ViewHolder {
|
||||
ItemHomeInternetRadioStationBinding item;
|
||||
|
||||
ViewHolder(ItemHomeInternetRadioStationBinding item) {
|
||||
super(item.getRoot());
|
||||
|
||||
this.item = item;
|
||||
|
||||
item.internetRadioStationTitleTextView.setSelected(true);
|
||||
item.internetRadioStationSubtitleTextView.setSelected(true);
|
||||
|
||||
itemView.setOnClickListener(v -> onClick());
|
||||
itemView.setOnLongClickListener(v -> onLongClick());
|
||||
|
||||
item.internetRadioStationMoreButton.setOnClickListener(v -> onLongClick());
|
||||
}
|
||||
|
||||
public void onClick() {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(Constants.INTERNET_RADIO_STATION_OBJECT, internetRadioStations.get(getBindingAdapterPosition()));
|
||||
|
||||
click.onInternetRadioStationClick(bundle);
|
||||
}
|
||||
|
||||
private boolean onLongClick() {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(Constants.INTERNET_RADIO_STATION_OBJECT, internetRadioStations.get(getBindingAdapterPosition()));
|
||||
|
||||
click.onInternetRadioStationLongClick(bundle);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import android.os.Bundle;
|
|||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
|
@ -13,21 +14,27 @@ import androidx.lifecycle.ViewModelProvider;
|
|||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.session.MediaBrowser;
|
||||
import androidx.media3.session.SessionToken;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
||||
import com.cappielloantonio.play.databinding.FragmentHomeTabPodcastBinding;
|
||||
import com.cappielloantonio.play.databinding.FragmentHomeTabRadioBinding;
|
||||
import com.cappielloantonio.play.interfaces.ClickCallback;
|
||||
import com.cappielloantonio.play.service.MediaManager;
|
||||
import com.cappielloantonio.play.service.MediaService;
|
||||
import com.cappielloantonio.play.ui.activity.MainActivity;
|
||||
import com.cappielloantonio.play.viewmodel.HomeViewModel;
|
||||
import com.cappielloantonio.play.ui.adapter.InternetRadioStationAdapter;
|
||||
import com.cappielloantonio.play.util.Constants;
|
||||
import com.cappielloantonio.play.viewmodel.RadioViewModel;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
@UnstableApi
|
||||
public class HomeTabRadioFragment extends Fragment {
|
||||
public class HomeTabRadioFragment extends Fragment implements ClickCallback {
|
||||
private static final String TAG = "HomeTabRadioFragment";
|
||||
|
||||
private FragmentHomeTabRadioBinding bind;
|
||||
private MainActivity activity;
|
||||
private HomeViewModel homeViewModel;
|
||||
private RadioViewModel radioViewModel;
|
||||
|
||||
private InternetRadioStationAdapter internetRadioStationAdapter;
|
||||
|
||||
private ListenableFuture<MediaBrowser> mediaBrowserListenableFuture;
|
||||
|
||||
|
|
@ -38,11 +45,18 @@ public class HomeTabRadioFragment extends Fragment {
|
|||
|
||||
bind = FragmentHomeTabRadioBinding.inflate(inflater, container, false);
|
||||
View view = bind.getRoot();
|
||||
homeViewModel = new ViewModelProvider(requireActivity()).get(HomeViewModel.class);
|
||||
radioViewModel = new ViewModelProvider(requireActivity()).get(RadioViewModel.class);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
initRadioStationView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
|
@ -62,6 +76,28 @@ public class HomeTabRadioFragment extends Fragment {
|
|||
bind = null;
|
||||
}
|
||||
|
||||
private void initRadioStationView() {
|
||||
bind.internetRadioStationRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||
bind.internetRadioStationRecyclerView.setHasFixedSize(true);
|
||||
|
||||
internetRadioStationAdapter = new InternetRadioStationAdapter(this);
|
||||
bind.internetRadioStationRecyclerView.setAdapter(internetRadioStationAdapter);
|
||||
radioViewModel.getInternetRadioStations().observe(getViewLifecycleOwner(), internetRadioStations -> {
|
||||
if (internetRadioStations == null) {
|
||||
if (bind != null)
|
||||
bind.internetRadioStationPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
if (bind != null) bind.internetRadioStationSector.setVisibility(View.GONE);
|
||||
} else {
|
||||
if (bind != null)
|
||||
bind.internetRadioStationPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
if (bind != null)
|
||||
bind.internetRadioStationSector.setVisibility(!internetRadioStations.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
|
||||
internetRadioStationAdapter.setItems(internetRadioStations);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void initializeMediaBrowser() {
|
||||
mediaBrowserListenableFuture = new MediaBrowser.Builder(requireContext(), new SessionToken(requireContext(), new ComponentName(requireContext(), MediaService.class))).buildAsync();
|
||||
}
|
||||
|
|
@ -69,4 +105,15 @@ public class HomeTabRadioFragment extends Fragment {
|
|||
private void releaseMediaBrowser() {
|
||||
MediaBrowser.releaseFuture(mediaBrowserListenableFuture);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInternetRadioStationClick(Bundle bundle) {
|
||||
MediaManager.startRadio(mediaBrowserListenableFuture, bundle.getParcelable(Constants.INTERNET_RADIO_STATION_OBJECT));
|
||||
activity.setBottomSheetInPeek(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInternetRadioStationLongClick(Bundle bundle) {
|
||||
Toast.makeText(requireContext(), "Long click!", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
package com.cappielloantonio.play.ui.fragment;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.graphics.Point;
|
||||
import android.os.Bundle;
|
||||
import android.view.Display;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
|
@ -214,6 +212,17 @@ public class PlayerControllerFragment extends Fragment {
|
|||
bind.getRoot().findViewById(R.id.player_skip_silence_toggle_button).setVisibility(View.VISIBLE);
|
||||
setPlaybackParameters(mediaBrowser);
|
||||
break;
|
||||
case Constants.MEDIA_TYPE_RADIO:
|
||||
bind.getRoot().setShowShuffleButton(false);
|
||||
bind.getRoot().setShowRewindButton(false);
|
||||
bind.getRoot().setShowPreviousButton(false);
|
||||
bind.getRoot().setShowNextButton(false);
|
||||
bind.getRoot().setShowFastForwardButton(false);
|
||||
bind.getRoot().setRepeatToggleModes(RepeatModeUtil.REPEAT_TOGGLE_MODE_NONE);
|
||||
bind.getRoot().findViewById(R.id.player_playback_speed_button).setVisibility(View.GONE);
|
||||
bind.getRoot().findViewById(R.id.player_skip_silence_toggle_button).setVisibility(View.GONE);
|
||||
setPlaybackParameters(mediaBrowser);
|
||||
break;
|
||||
case Constants.MEDIA_TYPE_MUSIC:
|
||||
default:
|
||||
bind.getRoot().setShowShuffleButton(true);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ object Constants {
|
|||
const val GENRE_OBJECT = "GENRE_OBJECT"
|
||||
const val PLAYLIST_OBJECT = "PLAYLIST_OBJECT"
|
||||
const val PODCAST_OBJECT = "PODCAST_OBJECT"
|
||||
const val INTERNET_RADIO_STATION_OBJECT = "INTERNET_RADIO_STATION_OBJECT"
|
||||
|
||||
const val ALBUM_RECENTLY_PLAYED = "ALBUM_RECENTLY_PLAYED"
|
||||
const val ALBUM_MOST_PLAYED = "ALBUM_MOST_PLAYED"
|
||||
|
|
@ -42,6 +43,7 @@ object Constants {
|
|||
const val MEDIA_TYPE_PODCAST = "podcast"
|
||||
const val MEDIA_TYPE_AUDIOBOOK = "audiobook"
|
||||
const val MEDIA_TYPE_VIDEO = "video"
|
||||
const val MEDIA_TYPE_RADIO = "radio"
|
||||
|
||||
const val MEDIA_PLAYBACK_SPEED_080 = 0.8f
|
||||
const val MEDIA_PLAYBACK_SPEED_100 = 1.0f
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import androidx.media3.common.util.UnstableApi;
|
|||
|
||||
import com.cappielloantonio.play.App;
|
||||
import com.cappielloantonio.play.subsonic.models.Child;
|
||||
import com.cappielloantonio.play.subsonic.models.InternetRadioStation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
|
@ -121,6 +122,36 @@ public class MappingUtil {
|
|||
.build();
|
||||
}
|
||||
|
||||
public static MediaItem mapInternetRadioStation(InternetRadioStation internetRadioStation) {
|
||||
Uri uri = Uri.parse(internetRadioStation.getStreamUrl());
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("id", internetRadioStation.getId());
|
||||
bundle.putString("title", internetRadioStation.getName());
|
||||
bundle.putString("artist", uri.toString());
|
||||
bundle.putString("uri", uri.toString());
|
||||
bundle.putString("type", Constants.MEDIA_TYPE_RADIO);
|
||||
|
||||
return new MediaItem.Builder()
|
||||
.setMediaId(internetRadioStation.getId())
|
||||
.setMediaMetadata(
|
||||
new MediaMetadata.Builder()
|
||||
.setTitle(internetRadioStation.getName())
|
||||
.setArtist(internetRadioStation.getStreamUrl())
|
||||
.setExtras(bundle)
|
||||
.build()
|
||||
)
|
||||
.setRequestMetadata(
|
||||
new MediaItem.RequestMetadata.Builder()
|
||||
.setMediaUri(uri)
|
||||
.setExtras(bundle)
|
||||
.build()
|
||||
)
|
||||
.setMimeType(MimeTypes.BASE_TYPE_AUDIO)
|
||||
.setUri(uri)
|
||||
.build();
|
||||
}
|
||||
|
||||
private static Uri getUri(Child media) {
|
||||
return DownloadUtil.getDownloadTracker(App.getContext()).isDownloaded(media.getId())
|
||||
? MusicUtil.getDownloadUri(media.getId())
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
package com.cappielloantonio.play.viewmodel;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.AndroidViewModel;
|
||||
import androidx.lifecycle.LiveData;
|
||||
|
||||
import com.cappielloantonio.play.repository.RadioRepository;
|
||||
import com.cappielloantonio.play.subsonic.models.InternetRadioStation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class RadioViewModel extends AndroidViewModel {
|
||||
private final RadioRepository radioRepository;
|
||||
|
||||
public RadioViewModel(@NonNull Application application) {
|
||||
super(application);
|
||||
|
||||
radioRepository = new RadioRepository();
|
||||
}
|
||||
|
||||
public LiveData<List<InternetRadioStation>> getInternetRadioStations() {
|
||||
return radioRepository.getInternetRadioStations();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,47 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.core.widget.NestedScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/internet_radio_station_sector"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/global_padding_bottom">
|
||||
|
||||
<TextView
|
||||
style="@style/TitleLarge"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:text="@string/home_title_internet_radio_station" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/internet_radio_station_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:clipToPadding="false"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<include
|
||||
android:id="@+id/internet_radio_station_placeholder"
|
||||
layout="@layout/item_placeholder_horizontal"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
|
|
|||
71
app/src/main/res/layout/item_home_internet_radio_station.xml
Normal file
71
app/src/main/res/layout/item_home_internet_radio_station.xml
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clipChildren="false"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="3dp"
|
||||
android:paddingBottom="3dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/internet_radio_station_cover_image_view"
|
||||
android:layout_width="52dp"
|
||||
android:layout_height="52dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_margin="2dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<View
|
||||
android:id="@+id/cover_image_separator"
|
||||
android:layout_width="12dp"
|
||||
android:layout_height="52dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/internet_radio_station_cover_image_view"
|
||||
app:layout_constraintEnd_toStartOf="@+id/internet_radio_station_title_text_view"
|
||||
app:layout_constraintStart_toEndOf="@+id/internet_radio_station_cover_image_view"
|
||||
app:layout_constraintTop_toTopOf="@+id/internet_radio_station_cover_image_view" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/internet_radio_station_title_text_view"
|
||||
style="@style/LabelMedium"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="marquee"
|
||||
android:paddingEnd="12dp"
|
||||
android:singleLine="true"
|
||||
android:text="@string/label_placeholder"
|
||||
app:layout_constraintBottom_toTopOf="@id/internet_radio_station_subtitle_text_view"
|
||||
app:layout_constraintEnd_toStartOf="@+id/internet_radio_station_more_button"
|
||||
app:layout_constraintStart_toEndOf="@+id/cover_image_separator"
|
||||
app:layout_constraintTop_toTopOf="@+id/internet_radio_station_cover_image_view"
|
||||
app:layout_constraintVertical_chainStyle="packed" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/internet_radio_station_subtitle_text_view"
|
||||
style="@style/LabelSmall"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="marquee"
|
||||
android:paddingEnd="12dp"
|
||||
android:singleLine="true"
|
||||
android:text="@string/label_placeholder"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/internet_radio_station_cover_image_view"
|
||||
app:layout_constraintEnd_toStartOf="@+id/internet_radio_station_more_button"
|
||||
app:layout_constraintStart_toEndOf="@+id/cover_image_separator"
|
||||
app:layout_constraintTop_toBottomOf="@+id/internet_radio_station_title_text_view" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/internet_radio_station_more_button"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:background="@drawable/ic_more_vert"
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||
app:layout_constraintBottom_toBottomOf="@id/internet_radio_station_subtitle_text_view"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/internet_radio_station_cover_image_view" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
Loading…
Add table
Add a link
Reference in a new issue