diff --git a/app/src/main/java/com/cappielloantonio/play/database/AppDatabase.java b/app/src/main/java/com/cappielloantonio/play/database/AppDatabase.java index 7295d7a7..4e2f4506 100644 --- a/app/src/main/java/com/cappielloantonio/play/database/AppDatabase.java +++ b/app/src/main/java/com/cappielloantonio/play/database/AppDatabase.java @@ -6,13 +6,15 @@ import androidx.room.Database; import androidx.room.Room; import androidx.room.RoomDatabase; +import com.cappielloantonio.play.database.dao.DownloadDao; import com.cappielloantonio.play.database.dao.QueueDao; import com.cappielloantonio.play.database.dao.RecentSearchDao; +import com.cappielloantonio.play.model.Download; import com.cappielloantonio.play.model.Queue; import com.cappielloantonio.play.model.RecentSearch; import com.cappielloantonio.play.model.Song; -@Database(entities = {Queue.class, RecentSearch.class}, version = 3, exportSchema = false) +@Database(entities = {Queue.class, RecentSearch.class, Download.class}, version = 5, exportSchema = false) public abstract class AppDatabase extends RoomDatabase { private static final String TAG = "AppDatabase"; @@ -31,4 +33,6 @@ public abstract class AppDatabase extends RoomDatabase { public abstract QueueDao queueDao(); public abstract RecentSearchDao recentSearchDao(); + + public abstract DownloadDao downloadDao(); } diff --git a/app/src/main/java/com/cappielloantonio/play/database/dao/DownloadDao.java b/app/src/main/java/com/cappielloantonio/play/database/dao/DownloadDao.java new file mode 100644 index 00000000..5a3d377b --- /dev/null +++ b/app/src/main/java/com/cappielloantonio/play/database/dao/DownloadDao.java @@ -0,0 +1,32 @@ +package com.cappielloantonio.play.database.dao; + +import androidx.lifecycle.LiveData; +import androidx.room.Dao; +import androidx.room.Insert; +import androidx.room.OnConflictStrategy; +import androidx.room.Query; + +import com.cappielloantonio.play.model.Download; + +import java.util.List; + +@Dao +public interface DownloadDao { + @Query("SELECT * FROM download") + LiveData> getAll(); + + @Query("SELECT * FROM download LIMIT :size") + LiveData> getSample(int size); + + @Insert(onConflict = OnConflictStrategy.REPLACE) + void insert(Download download); + + @Insert(onConflict = OnConflictStrategy.REPLACE) + void insertAll(List downloads); + + @Query("DELETE FROM download WHERE id = :id") + void delete(String id); + + @Query("DELETE FROM download") + void deleteAll(); +} \ No newline at end of file diff --git a/app/src/main/java/com/cappielloantonio/play/model/Download.java b/app/src/main/java/com/cappielloantonio/play/model/Download.java new file mode 100644 index 00000000..ad5523c0 --- /dev/null +++ b/app/src/main/java/com/cappielloantonio/play/model/Download.java @@ -0,0 +1,121 @@ +package com.cappielloantonio.play.model; + +import androidx.annotation.NonNull; +import androidx.room.ColumnInfo; +import androidx.room.Entity; +import androidx.room.PrimaryKey; + +@Entity(tableName = "download") +public class Download { + @NonNull + @PrimaryKey + @ColumnInfo(name = "id") + private String songID; + + @ColumnInfo(name = "title") + private String title; + + @ColumnInfo(name = "albumId") + private String albumId; + + @ColumnInfo(name = "albumName") + private String albumName; + + @ColumnInfo(name = "artistId") + private String artistId; + + @ColumnInfo(name = "artistName") + private String artistName; + + @ColumnInfo(name = "primary") + private String primary; + + @ColumnInfo(name = "duration") + private long duration; + + public Download(String songID, String title, String albumId, String albumName, String artistId, String artistName, String primary, long duration) { + this.songID = songID; + this.title = title; + this.albumId = albumId; + this.albumName = albumName; + this.artistId = artistId; + this.artistName = artistName; + this.primary = primary; + this.duration = duration; + } + + public Download(Song song) { + this.songID = song.getId(); + this.title = song.getTitle(); + this.albumId = song.getAlbumId(); + this.albumName = song.getAlbumName(); + this.artistId = song.getArtistId(); + this.artistName = song.getArtistName(); + this.primary = song.getPrimary(); + this.duration = song.getDuration(); + } + + public String getSongID() { + return songID; + } + + public void setSongID(String songID) { + this.songID = songID; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getAlbumId() { + return albumId; + } + + public void setAlbumId(String albumId) { + this.albumId = albumId; + } + + public String getAlbumName() { + return albumName; + } + + public void setAlbumName(String albumName) { + this.albumName = albumName; + } + + public String getArtistId() { + return artistId; + } + + public void setArtistId(String artistId) { + this.artistId = artistId; + } + + public String getArtistName() { + return artistName; + } + + public void setArtistName(String artistName) { + this.artistName = artistName; + } + + public String getPrimary() { + return primary; + } + + public void setPrimary(String primary) { + this.primary = primary; + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } +} diff --git a/app/src/main/java/com/cappielloantonio/play/model/Song.java b/app/src/main/java/com/cappielloantonio/play/model/Song.java index 8fed53cb..8636e196 100644 --- a/app/src/main/java/com/cappielloantonio/play/model/Song.java +++ b/app/src/main/java/com/cappielloantonio/play/model/Song.java @@ -89,6 +89,17 @@ public class Song implements Parcelable { this.duration = queue.getDuration(); } + public Song(Download download) { + this.id = download.getSongID(); + this.title = download.getTitle(); + this.albumId = download.getAlbumId(); + this.albumName = download.getAlbumName(); + this.artistId = download.getArtistId(); + this.artistName = download.getArtistName(); + this.primary = download.getPrimary(); + this.duration = download.getDuration(); + } + public String getId() { return id; } diff --git a/app/src/main/java/com/cappielloantonio/play/repository/DownloadRepository.java b/app/src/main/java/com/cappielloantonio/play/repository/DownloadRepository.java new file mode 100644 index 00000000..545670d5 --- /dev/null +++ b/app/src/main/java/com/cappielloantonio/play/repository/DownloadRepository.java @@ -0,0 +1,122 @@ +package com.cappielloantonio.play.repository; + +import android.app.Application; + +import androidx.lifecycle.LiveData; + +import com.cappielloantonio.play.database.AppDatabase; +import com.cappielloantonio.play.database.dao.DownloadDao; +import com.cappielloantonio.play.database.dao.QueueDao; +import com.cappielloantonio.play.model.Download; +import com.cappielloantonio.play.model.Queue; +import com.cappielloantonio.play.model.Song; +import com.cappielloantonio.play.util.MappingUtil; +import com.cappielloantonio.play.util.QueueUtil; + +import java.util.ArrayList; +import java.util.List; + +public class DownloadRepository { + private static final String TAG = "QueueRepository"; + + private DownloadDao downloadDao; + private LiveData> listLiveDownload; + private LiveData> listLiveDownloadSample; + + public DownloadRepository(Application application) { + AppDatabase database = AppDatabase.getInstance(application); + downloadDao = database.downloadDao(); + } + + public LiveData> getLiveDownload() { + listLiveDownload = downloadDao.getAll(); + return listLiveDownload; + } + + public LiveData> getLiveDownloadSample(int size) { + listLiveDownloadSample = downloadDao.getSample(size); + return listLiveDownloadSample; + } + + public void insert(Download download) { + InsertThreadSafe insert = new InsertThreadSafe(downloadDao, download); + Thread thread = new Thread(insert); + thread.start(); + } + + private static class InsertThreadSafe implements Runnable { + private DownloadDao downloadDao; + private Download download; + + public InsertThreadSafe(DownloadDao downloadDao, Download download) { + this.downloadDao = downloadDao; + this.download = download; + } + + @Override + public void run() { + downloadDao.insert(download); + } + } + + public void insertAll(List downloads) { + InsertAllThreadSafe insertAll = new InsertAllThreadSafe(downloadDao, downloads); + Thread thread = new Thread(insertAll); + thread.start(); + } + + private static class InsertAllThreadSafe implements Runnable { + private DownloadDao downloadDao; + private List downloads; + + public InsertAllThreadSafe(DownloadDao downloadDao, List downloads) { + this.downloadDao = downloadDao; + this.downloads = downloads; + } + + @Override + public void run() { + downloadDao.insertAll(downloads); + } + } + + public void deleteAll() { + DeleteAllThreadSafe deleteAll = new DeleteAllThreadSafe(downloadDao); + Thread thread = new Thread(deleteAll); + thread.start(); + } + + private static class DeleteAllThreadSafe implements Runnable { + private DownloadDao downloadDao; + + public DeleteAllThreadSafe(DownloadDao downloadDao) { + this.downloadDao = downloadDao; + } + + @Override + public void run() { + downloadDao.deleteAll(); + } + } + + public void delete(Download download) { + DeleteThreadSafe delete = new DeleteThreadSafe(downloadDao, download); + Thread thread = new Thread(delete); + thread.start(); + } + + private static class DeleteThreadSafe implements Runnable { + private DownloadDao downloadDao; + private Download download; + + public DeleteThreadSafe(DownloadDao downloadDao, Download download) { + this.downloadDao = downloadDao; + this.download = download; + } + + @Override + public void run() { + downloadDao.delete(download.getSongID()); + } + } +} diff --git a/app/src/main/java/com/cappielloantonio/play/service/DownloadTracker.java b/app/src/main/java/com/cappielloantonio/play/service/DownloadTracker.java index 6f633972..4842bfb8 100644 --- a/app/src/main/java/com/cappielloantonio/play/service/DownloadTracker.java +++ b/app/src/main/java/com/cappielloantonio/play/service/DownloadTracker.java @@ -8,7 +8,9 @@ import androidx.annotation.Nullable; import com.cappielloantonio.play.App; import com.cappielloantonio.play.model.Song; +import com.cappielloantonio.play.repository.DownloadRepository; import com.cappielloantonio.play.repository.SongRepository; +import com.cappielloantonio.play.util.MappingUtil; import com.cappielloantonio.play.util.MusicUtil; import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.offline.Download; @@ -71,7 +73,7 @@ public class DownloadTracker { } public void toggleDownload(List songs) { - SongRepository songRepository = new SongRepository(App.getInstance()); + DownloadRepository downloadRepository = new DownloadRepository(App.getInstance()); for (Song song : songs) { MediaItem mediaItem = MusicUtil.getMediaItemFromSong(song); @@ -81,12 +83,12 @@ public class DownloadTracker { if (download != null && download.state != Download.STATE_FAILED) { song.setOffline(false); DownloadService.sendRemoveDownload(context, DownloaderService.class, download.request.id, false); + downloadRepository.delete(MappingUtil.mapToDownload(song)); } else { song.setOffline(true); DownloadService.sendAddDownload(context, DownloaderService.class, getDownloadRequest(song.getId(), mediaItem.playbackProperties.uri), false); + downloadRepository.insert(MappingUtil.mapToDownload(song)); } - - // songRepository.setOfflineStatus(song); } } diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/HomeFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/HomeFragment.java index 51bf5ac5..55024312 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/HomeFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/HomeFragment.java @@ -28,6 +28,7 @@ import com.cappielloantonio.play.databinding.FragmentHomeBinding; import com.cappielloantonio.play.interfaces.MediaCallback; import com.cappielloantonio.play.model.Song; import com.cappielloantonio.play.ui.activity.MainActivity; +import com.cappielloantonio.play.util.MappingUtil; import com.cappielloantonio.play.util.UIUtil; import com.cappielloantonio.play.viewmodel.HomeViewModel; @@ -254,9 +255,9 @@ public class HomeFragment extends Fragment { dowanloadedMusicAdapter = new RecentMusicAdapter(activity, requireContext(), getChildFragmentManager()); bind.downloadedTracksRecyclerView.setAdapter(dowanloadedMusicAdapter); - homeViewModel.getDownloaded().observe(requireActivity(), songs -> { - if(bind != null) bind.homeDownloadedTracksSector.setVisibility(!songs.isEmpty() ? View.VISIBLE : View.GONE); - dowanloadedMusicAdapter.setItems(songs); + homeViewModel.getDownloaded().observe(requireActivity(), downloads -> { + if(bind != null) bind.homeDownloadedTracksSector.setVisibility(!downloads.isEmpty() ? View.VISIBLE : View.GONE); + dowanloadedMusicAdapter.setItems(MappingUtil.mapDownload(downloads)); }); } diff --git a/app/src/main/java/com/cappielloantonio/play/util/MappingUtil.java b/app/src/main/java/com/cappielloantonio/play/util/MappingUtil.java index f2e2f246..36cc5e2c 100644 --- a/app/src/main/java/com/cappielloantonio/play/util/MappingUtil.java +++ b/app/src/main/java/com/cappielloantonio/play/util/MappingUtil.java @@ -2,6 +2,7 @@ package com.cappielloantonio.play.util; import com.cappielloantonio.play.model.Album; import com.cappielloantonio.play.model.Artist; +import com.cappielloantonio.play.model.Download; import com.cappielloantonio.play.model.Playlist; import com.cappielloantonio.play.model.Queue; import com.cappielloantonio.play.model.Song; @@ -68,4 +69,28 @@ public class MappingUtil { return playlist; } + + public static ArrayList mapDownload(List downloads) { + ArrayList songs = new ArrayList(); + + for(Download download : downloads){ + songs.add(new Song(download)); + } + + return songs; + } + + public static ArrayList mapToDownload(List songs) { + ArrayList downloads = new ArrayList(); + + for(Song song : songs){ + downloads.add(new Download(song)); + } + + return downloads; + } + + public static Download mapToDownload(Song song) { + return new Download(song); + } } diff --git a/app/src/main/java/com/cappielloantonio/play/viewmodel/HomeViewModel.java b/app/src/main/java/com/cappielloantonio/play/viewmodel/HomeViewModel.java index 5b0c03b0..00599d65 100644 --- a/app/src/main/java/com/cappielloantonio/play/viewmodel/HomeViewModel.java +++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/HomeViewModel.java @@ -10,9 +10,11 @@ import androidx.lifecycle.MutableLiveData; import com.cappielloantonio.play.interfaces.MediaCallback; import com.cappielloantonio.play.model.Album; import com.cappielloantonio.play.model.Artist; +import com.cappielloantonio.play.model.Download; import com.cappielloantonio.play.model.Song; import com.cappielloantonio.play.repository.AlbumRepository; import com.cappielloantonio.play.repository.ArtistRepository; +import com.cappielloantonio.play.repository.DownloadRepository; import com.cappielloantonio.play.repository.SongRepository; import java.util.ArrayList; @@ -23,8 +25,9 @@ public class HomeViewModel extends AndroidViewModel { private SongRepository songRepository; private AlbumRepository albumRepository; private ArtistRepository artistRepository; + private DownloadRepository downloadRepository; - private LiveData> downloadedSongSample; + private LiveData> downloadedSongSample; private List years; private MutableLiveData> dicoverSongSample; @@ -42,6 +45,7 @@ public class HomeViewModel extends AndroidViewModel { songRepository = new SongRepository(application); albumRepository = new AlbumRepository(application); artistRepository = new ArtistRepository(application); + downloadRepository = new DownloadRepository(application); // favoritesSongSample = songRepository.getListLiveFavoritesSampleSong(20); // downloadedSongSample = songRepository.getListLiveDownloadedSampleSong(20); @@ -49,7 +53,7 @@ public class HomeViewModel extends AndroidViewModel { setDicoverSongSample(); dicoverSongSample = new MutableLiveData<>(); - downloadedSongSample = new MutableLiveData<>(); + downloadedSongSample = downloadRepository.getLiveDownloadSample(10); years = new ArrayList<>(); mostPlayedAlbumSample = albumRepository.getAlbums("frequent", 20); @@ -85,7 +89,7 @@ public class HomeViewModel extends AndroidViewModel { return starredArtists; } - public LiveData> getDownloaded() { + public LiveData> getDownloaded() { return downloadedSongSample; }