From 13ad47fa37ea73d25dae39a890ed0149da111607 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Sat, 23 Nov 2013 22:46:15 -0800 Subject: Added playlist sync management logic --- res/menu/select_playlist_context.xml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'res/menu') diff --git a/res/menu/select_playlist_context.xml b/res/menu/select_playlist_context.xml index 0ec94e02..7cdc0c79 100644 --- a/res/menu/select_playlist_context.xml +++ b/res/menu/select_playlist_context.xml @@ -22,10 +22,13 @@ android:title="@string/common.download" /> - + + + Date: Sun, 24 Nov 2013 22:52:50 -0800 Subject: Moved sync to SyncUtil, added podcast logic --- res/menu/select_podcasts_context.xml | 10 +- .../dsub/fragments/SelectPlaylistFragment.java | 9 +- .../dsub/fragments/SelectPodcastsFragment.java | 44 +++++++ src/github/daneren2005/dsub/service/SyncUtil.java | 138 +++++++++++++++++++++ .../dsub/service/sync/PlaylistSyncAdapter.java | 5 +- .../dsub/service/sync/PodcastSyncAdapter.java | 35 ++++-- src/github/daneren2005/dsub/util/Util.java | 46 ------- src/github/daneren2005/dsub/view/PlaylistView.java | 7 +- .../daneren2005/dsub/view/PodcastChannelView.java | 16 ++- 9 files changed, 241 insertions(+), 69 deletions(-) create mode 100644 src/github/daneren2005/dsub/service/SyncUtil.java (limited to 'res/menu') diff --git a/res/menu/select_podcasts_context.xml b/res/menu/select_podcasts_context.xml index c9785b92..3a2a1c60 100644 --- a/res/menu/select_podcasts_context.xml +++ b/res/menu/select_podcasts_context.xml @@ -6,5 +6,13 @@ android:title="@string/common.info"/> + android:title="@string/common.delete"/> + + + + \ No newline at end of file diff --git a/src/github/daneren2005/dsub/fragments/SelectPlaylistFragment.java b/src/github/daneren2005/dsub/fragments/SelectPlaylistFragment.java index b3bab6e3..3f84a4f6 100644 --- a/src/github/daneren2005/dsub/fragments/SelectPlaylistFragment.java +++ b/src/github/daneren2005/dsub/fragments/SelectPlaylistFragment.java @@ -23,6 +23,7 @@ import github.daneren2005.dsub.service.MusicService; import github.daneren2005.dsub.service.MusicServiceFactory; import github.daneren2005.dsub.service.OfflineException; import github.daneren2005.dsub.service.ServerTooOldException; +import github.daneren2005.dsub.service.SyncUtil; import github.daneren2005.dsub.util.BackgroundTask; import github.daneren2005.dsub.util.CacheCleaner; import github.daneren2005.dsub.util.Constants; @@ -109,7 +110,7 @@ public class SelectPlaylistFragment extends SubsonicFragment implements AdapterV AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; Playlist playlist = (Playlist) list.getItemAtPosition(info.position); - if(Util.isSyncedPlaylist(context, playlist.getId())) { + if(SyncUtil.isSyncedPlaylist(context, playlist.getId())) { menu.removeItem(R.id.playlist_menu_sync); } else { menu.removeItem(R.id.playlist_menu_stop_sync); @@ -228,7 +229,7 @@ public class SelectPlaylistFragment extends SubsonicFragment implements AdapterV protected Void doInBackground() throws Throwable { MusicService musicService = MusicServiceFactory.getMusicService(context); musicService.deletePlaylist(playlist.getId(), context, null); - Util.removeSyncedPlaylist(context, playlist.getId()); + SyncUtil.removeSyncedPlaylist(context, playlist.getId()); return null; } @@ -320,11 +321,11 @@ public class SelectPlaylistFragment extends SubsonicFragment implements AdapterV } private void syncPlaylist(Playlist playlist) { - Util.addSyncedPlaylist(context, playlist.getId()); + SyncUtil.addSyncedPlaylist(context, playlist.getId()); downloadPlaylist(playlist.getId(), playlist.getName(), true, true, false, false, true); } private void stopSyncPlaylist(Playlist playlist) { - Util.removeSyncedPlaylist(context, playlist.getId()); + SyncUtil.removeSyncedPlaylist(context, playlist.getId()); } } diff --git a/src/github/daneren2005/dsub/fragments/SelectPodcastsFragment.java b/src/github/daneren2005/dsub/fragments/SelectPodcastsFragment.java index 143ff229..461a613c 100644 --- a/src/github/daneren2005/dsub/fragments/SelectPodcastsFragment.java +++ b/src/github/daneren2005/dsub/fragments/SelectPodcastsFragment.java @@ -36,11 +36,13 @@ import android.widget.AdapterView; import android.widget.ListView; import android.widget.TextView; import github.daneren2005.dsub.R; +import github.daneren2005.dsub.domain.MusicDirectory; import github.daneren2005.dsub.domain.PodcastChannel; import github.daneren2005.dsub.service.MusicService; import github.daneren2005.dsub.service.MusicServiceFactory; import github.daneren2005.dsub.service.OfflineException; import github.daneren2005.dsub.service.ServerTooOldException; +import github.daneren2005.dsub.service.SyncUtil; import github.daneren2005.dsub.util.BackgroundTask; import github.daneren2005.dsub.util.Constants; import github.daneren2005.dsub.util.LoadingTask; @@ -134,6 +136,14 @@ public class SelectPodcastsFragment extends SubsonicFragment implements AdapterV if(!Util.isOffline(context)) { android.view.MenuInflater inflater = context.getMenuInflater(); inflater.inflate(R.menu.select_podcasts_context, menu); + + AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; + PodcastChannel podcast = (PodcastChannel) podcastListView.getItemAtPosition(info.position); + if(SyncUtil.isSyncedPodcast(context, podcast.getId())) { + menu.removeItem(R.id.podcast_menu_sync); + } else { + menu.removeItem(R.id.podcast_menu_stop_sync); + } } } @@ -147,6 +157,12 @@ public class SelectPodcastsFragment extends SubsonicFragment implements AdapterV PodcastChannel channel = (PodcastChannel) podcastListView.getItemAtPosition(info.position); switch (menuItem.getItemId()) { + case R.id.podcast_menu_sync: + syncPodcast(channel); + break; + case R.id.podcast_menu_stop_sync: + stopSyncPodcast(channel); + break; case R.id.podcast_channel_info: displayPodcastInfo(channel); break; @@ -305,6 +321,7 @@ public class SelectPodcastsFragment extends SubsonicFragment implements AdapterV protected Void doInBackground() throws Throwable { MusicService musicService = MusicServiceFactory.getMusicService(context); musicService.deletePodcastChannel(channel.getId(), context, null); + stopSyncPodcast(channel); return null; } @@ -330,4 +347,31 @@ public class SelectPodcastsFragment extends SubsonicFragment implements AdapterV } }); } + + private void syncPodcast(final PodcastChannel podcast) { + new LoadingTask(context, false) { + @Override + protected MusicDirectory doInBackground() throws Throwable { + MusicService musicService = MusicServiceFactory.getMusicService(context); + return musicService.getPodcastEpisodes(true, podcast.getId(), context, this); + } + + @Override + protected void done(MusicDirectory result) { + List existingEpisodes = new ArrayList(); + for(MusicDirectory.Entry entry: result.getChildren()) { + String id = entry.getId(); + if(id != null) { + existingEpisodes.add(entry.getId()); + } + } + + SyncUtil.addSyncedPodcast(context, podcast.getId(), existingEpisodes); + } + }.execute(); + } + + private void stopSyncPodcast(PodcastChannel podcast) { + SyncUtil.removeSyncedPodcast(context, podcast.getId()); + } } diff --git a/src/github/daneren2005/dsub/service/SyncUtil.java b/src/github/daneren2005/dsub/service/SyncUtil.java new file mode 100644 index 00000000..40da78c1 --- /dev/null +++ b/src/github/daneren2005/dsub/service/SyncUtil.java @@ -0,0 +1,138 @@ +package github.daneren2005.dsub.service; + +import android.content.Context; +import android.util.Log; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import github.daneren2005.dsub.util.FileUtil; +import github.daneren2005.dsub.util.Util; + +/** + * Created by Scott on 11/24/13. + */ +public final class SyncUtil { + private static String TAG = SyncUtil.class.getSimpleName(); + private static ArrayList syncedPlaylists; + private static ArrayList syncedPodcasts; + + // Playlist sync + public static boolean isSyncedPlaylist(Context context, String playlistId) { + if(syncedPlaylists == null) { + syncedPlaylists = getSyncedPlaylists(context); + } + return syncedPlaylists.contains(playlistId); + } + public static ArrayList getSyncedPlaylists(Context context) { + return getSyncedPlaylists(context, Util.getActiveServer(context)); + } + public static ArrayList getSyncedPlaylists(Context context, int instance) { + ArrayList playlists = FileUtil.deserialize(context, getPlaylistSyncFile(context, instance), ArrayList.class); + if(playlists == null) { + playlists = new ArrayList(); + } + return playlists; + } + public static void addSyncedPlaylist(Context context, String playlistId) { + String playlistFile = getPlaylistSyncFile(context); + ArrayList playlists = getSyncedPlaylists(context); + if(!playlists.contains(playlistId)) { + playlists.add(playlistId); + } + FileUtil.serialize(context, playlists, playlistFile); + syncedPlaylists = playlists; + } + public static void removeSyncedPlaylist(Context context, String playlistId) { + String playlistFile = getPlaylistSyncFile(context); + ArrayList playlists = getSyncedPlaylists(context); + if(playlists.contains(playlistId)) { + playlists.remove(playlistId); + FileUtil.serialize(context, playlists, playlistFile); + syncedPlaylists = playlists; + } + } + public static String getPlaylistSyncFile(Context context) { + int instance = Util.getActiveServer(context); + return getPlaylistSyncFile(context, instance); + } + public static String getPlaylistSyncFile(Context context, int instance) { + return "sync-playlist-" + (Util.getRestUrl(context, null, instance)).hashCode() + ".ser"; + } + + // Podcast sync + public static boolean isSyncedPodcast(Context context, String podcastId) { + if(syncedPodcasts == null) { + syncedPodcasts = getSyncedPodcasts(context); + } + return syncedPodcasts.contains(new SyncSet(podcastId)); + } + public static ArrayList getSyncedPodcasts(Context context) { + return getSyncedPodcasts(context, Util.getActiveServer(context)); + } + public static ArrayList getSyncedPodcasts(Context context, int instance) { + ArrayList podcasts = FileUtil.deserialize(context, getPodcastSyncFile(context, instance), ArrayList.class); + if(podcasts == null) { + podcasts = new ArrayList(); + } + return podcasts; + } + public static void addSyncedPodcast(Context context, String podcastId, List synced) { + String podcastFile = getPodcastSyncFile(context); + ArrayList podcasts = getSyncedPodcasts(context); + SyncSet set = new SyncSet(podcastId, synced); + if(!podcasts.contains(set)) { + podcasts.add(set); + } + FileUtil.serialize(context, podcasts, podcastFile); + syncedPodcasts = podcasts; + } + public static void removeSyncedPodcast(Context context, String podcastId) { + String podcastFile = getPodcastSyncFile(context); + ArrayList podcasts = getSyncedPodcasts(context); + SyncSet set = new SyncSet(podcastId); + if(podcasts.contains(set)) { + podcasts.remove(set); + FileUtil.serialize(context, podcasts, podcastFile); + syncedPodcasts = podcasts; + } + } + public static String getPodcastSyncFile(Context context) { + int instance = Util.getActiveServer(context); + return getPodcastSyncFile(context, instance); + } + public static String getPodcastSyncFile(Context context, int instance) { + return "sync-podcast-" + (Util.getRestUrl(context, null, instance)).hashCode() + ".ser"; + } + + public static class SyncSet implements Serializable { + public String id; + public List synced; + + protected SyncSet() { + + } + public SyncSet(String id) { + this.id = id; + } + public SyncSet(String id, List synced) { + this.id = id; + this.synced = synced; + } + + @Override + public boolean equals(Object obj) { + if(obj instanceof SyncSet) { + return this.id.equals(((SyncSet)obj).id); + } else { + return false; + } + } + + @Override + public int hashCode() { + return id.hashCode(); + } + } +} diff --git a/src/github/daneren2005/dsub/service/sync/PlaylistSyncAdapter.java b/src/github/daneren2005/dsub/service/sync/PlaylistSyncAdapter.java index 680f8e3e..48bc9161 100644 --- a/src/github/daneren2005/dsub/service/sync/PlaylistSyncAdapter.java +++ b/src/github/daneren2005/dsub/service/sync/PlaylistSyncAdapter.java @@ -23,12 +23,11 @@ import android.annotation.TargetApi; import android.content.Context; import android.util.Log; -import java.util.ArrayList; import java.util.List; import github.daneren2005.dsub.domain.MusicDirectory; import github.daneren2005.dsub.service.DownloadFile; -import github.daneren2005.dsub.util.FileUtil; +import github.daneren2005.dsub.service.SyncUtil; import github.daneren2005.dsub.util.Util; /** @@ -49,7 +48,7 @@ public class PlaylistSyncAdapter extends SubsonicSyncAdapter { @Override public void onExecuteSync(Context context, int instance) { String serverName = Util.getServerName(context, instance); - List playlistList = Util.getSyncedPlaylists(context, instance); + List playlistList = SyncUtil.getSyncedPlaylists(context, instance); for(int i = 0; i < playlistList.size(); i++) { String id = playlistList.get(i); try { diff --git a/src/github/daneren2005/dsub/service/sync/PodcastSyncAdapter.java b/src/github/daneren2005/dsub/service/sync/PodcastSyncAdapter.java index c5779c48..b5807e92 100644 --- a/src/github/daneren2005/dsub/service/sync/PodcastSyncAdapter.java +++ b/src/github/daneren2005/dsub/service/sync/PodcastSyncAdapter.java @@ -23,12 +23,15 @@ import android.annotation.TargetApi; import android.content.Context; import android.util.Log; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; import github.daneren2005.dsub.domain.MusicDirectory; import github.daneren2005.dsub.domain.PodcastEpisode; import github.daneren2005.dsub.service.DownloadFile; +import github.daneren2005.dsub.service.SyncUtil; +import github.daneren2005.dsub.service.SyncUtil.SyncSet; import github.daneren2005.dsub.util.FileUtil; import github.daneren2005.dsub.util.Util; @@ -49,24 +52,38 @@ public class PodcastSyncAdapter extends SubsonicSyncAdapter { @Override public void onExecuteSync(Context context, int instance) { - String serverName = Util.getServerName(context, instance); - String podcastListFile = "sync-podcast-" + (Util.getRestUrl(context, null, instance)).hashCode() + ".ser"; - List podcastList = FileUtil.deserialize(context, podcastListFile, ArrayList.class); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + + ArrayList podcastList = SyncUtil.getSyncedPodcasts(context, instance); + boolean updated = false; for(int i = 0; i < podcastList.size(); i++) { - String id = Integer.toString(podcastList.get(i)); + SyncSet set = podcastList.get(i); + String id = set.id; + List existingEpisodes = set.synced; try { MusicDirectory podcasts = musicService.getPodcastEpisodes(true, id, context, null); - // TODO: Only grab most recent podcasts! for(MusicDirectory.Entry entry: podcasts.getChildren()) { - DownloadFile file = new DownloadFile(context, entry, true); - while(!file.isSaved() && !file.isFailedMax()) { - file.downloadNow(); + // Make sure podcast is valid and not already synced + if(entry.getId() != null && "completed".equals(((PodcastEpisode)entry).getStatus()) && !existingEpisodes.contains(entry.getId())) { + DownloadFile file = new DownloadFile(context, entry, true); + while(!file.isSaved() && !file.isFailedMax()) { + file.downloadNow(); + } + // Only add if actualy downloaded correctly + if(file.isSaved()) { + existingEpisodes.add(entry.getId()); + } } } } catch(Exception e) { - Log.e(TAG, "Failed to get playlist for " + serverName); + Log.e(TAG, "Failed to get podcasts for " + Util.getServerName(context, instance)); } } + + // Make sure there are is at least one change before re-syncing + if(updated) { + FileUtil.serialize(context, podcastList, SyncUtil.getPodcastSyncFile(context, instance)); + } } } diff --git a/src/github/daneren2005/dsub/util/Util.java b/src/github/daneren2005/dsub/util/Util.java index 28b350be..895e2b6a 100644 --- a/src/github/daneren2005/dsub/util/Util.java +++ b/src/github/daneren2005/dsub/util/Util.java @@ -107,7 +107,6 @@ public final class Util { public static final String AVRCP_PLAYSTATE_CHANGED = "com.android.music.playstatechanged"; public static final String AVRCP_METADATA_CHANGED = "com.android.music.metachanged"; - private static List syncedPlaylists; private static boolean hasFocus = false; private static boolean pauseFocus = false; private static boolean lowerFocus = false; @@ -432,51 +431,6 @@ public final class Util { return name; } - public static boolean isSyncedPlaylist(Context context, String playlistId) { - if(syncedPlaylists == null) { - syncedPlaylists = getSyncedPlaylists(context); - } - return syncedPlaylists.contains(playlistId); - } - public static ArrayList getSyncedPlaylists(Context context) { - return getSyncedPlaylists(context, Util.getActiveServer(context)); - } - public static ArrayList getSyncedPlaylists(Context context, int instance) { - ArrayList playlists = FileUtil.deserialize(context, getPlaylistSyncFile(context, instance), ArrayList.class); - if(playlists == null) { - playlists = new ArrayList(); - } - return playlists; - } - public static void addSyncedPlaylist(Context context, String playlistId) { - String playlistFile = getPlaylistSyncFile(context); - ArrayList playlists = getSyncedPlaylists(context); - if(!playlists.contains(playlistId)) { - playlists.add(playlistId); - } - for(String str: playlists) { - Log.d(TAG, str); - } - FileUtil.serialize(context, playlists, playlistFile); - syncedPlaylists = playlists; - } - public static void removeSyncedPlaylist(Context context, String playlistId) { - String playlistFile = getPlaylistSyncFile(context); - ArrayList playlists = getSyncedPlaylists(context); - if(playlists.contains(playlistId)) { - playlists.remove(playlistId); - FileUtil.serialize(context, playlists, playlistFile); - syncedPlaylists = playlists; - } - } - private static String getPlaylistSyncFile(Context context) { - int instance = Util.getActiveServer(context); - return getPlaylistSyncFile(context, instance); - } - private static String getPlaylistSyncFile(Context context, int instance) { - return "sync-playlist-" + (Util.getRestUrl(context, null, instance)).hashCode() + ".ser"; - } - public static String getContentType(HttpEntity entity) { if (entity == null || entity.getContentType() == null) { return null; diff --git a/src/github/daneren2005/dsub/view/PlaylistView.java b/src/github/daneren2005/dsub/view/PlaylistView.java index 7a0c1f34..63ba4f5c 100644 --- a/src/github/daneren2005/dsub/view/PlaylistView.java +++ b/src/github/daneren2005/dsub/view/PlaylistView.java @@ -19,7 +19,6 @@ package github.daneren2005.dsub.view; import android.content.Context; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageButton; @@ -27,9 +26,7 @@ import android.widget.ImageView; import android.widget.TextView; import github.daneren2005.dsub.R; import github.daneren2005.dsub.domain.Playlist; -import github.daneren2005.dsub.util.FileUtil; -import github.daneren2005.dsub.util.Util; -import java.io.File; +import github.daneren2005.dsub.service.SyncUtil; /** * Used to display albums in a {@code ListView}. @@ -67,6 +64,6 @@ public class PlaylistView extends UpdateView { @Override protected void updateBackground() { - pinned = Util.isSyncedPlaylist(context, playlist.getId()); + pinned = SyncUtil.isSyncedPlaylist(context, playlist.getId()); } } diff --git a/src/github/daneren2005/dsub/view/PodcastChannelView.java b/src/github/daneren2005/dsub/view/PodcastChannelView.java index 9ad78d1c..8b0f4b84 100644 --- a/src/github/daneren2005/dsub/view/PodcastChannelView.java +++ b/src/github/daneren2005/dsub/view/PodcastChannelView.java @@ -19,6 +19,7 @@ package github.daneren2005.dsub.view; import android.content.Context; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageButton; @@ -26,6 +27,7 @@ import android.widget.ImageView; import android.widget.TextView; import github.daneren2005.dsub.R; import github.daneren2005.dsub.domain.PodcastChannel; +import github.daneren2005.dsub.service.SyncUtil; import github.daneren2005.dsub.util.FileUtil; import java.io.File; @@ -66,6 +68,18 @@ public class PodcastChannelView extends UpdateView { @Override protected void updateBackground() { - exists = file.exists(); + if(SyncUtil.isSyncedPodcast(context, channel.getId())) { + if(exists) { + shaded = false; + exists = false; + } + pinned = true; + } else if(file.exists()) { + if(pinned) { + shaded = false; + pinned = false; + } + exists = true; + } } } -- cgit v1.2.3