From 8a940c3792d9eae3f666f34803abb1113f6db061 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Sat, 28 Mar 2015 11:06:16 -0700 Subject: #474 Cache album lists for use when no network --- .../dsub/service/CachedMusicService.java | 310 +++++++++++++-------- .../daneren2005/dsub/service/RESTMusicService.java | 56 ++-- 2 files changed, 229 insertions(+), 137 deletions(-) (limited to 'src/github') diff --git a/src/github/daneren2005/dsub/service/CachedMusicService.java b/src/github/daneren2005/dsub/service/CachedMusicService.java index 9d3444cb..c4552e18 100644 --- a/src/github/daneren2005/dsub/service/CachedMusicService.java +++ b/src/github/daneren2005/dsub/service/CachedMusicService.java @@ -19,6 +19,7 @@ package github.daneren2005.dsub.service; import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; @@ -358,112 +359,147 @@ public class CachedMusicService implements MusicService { @Override public MusicDirectory getAlbumList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception { - MusicDirectory dir = musicService.getAlbumList(type, size, offset, context, progressListener); - - // Do some serialization updates for changes to recently added - if("newest".equals(type) && offset == 0) { - String recentlyAddedFile = getCacheName(context, type); - ArrayList recents = FileUtil.deserialize(context, recentlyAddedFile, ArrayList.class); - if(recents == null) { - recents = new ArrayList(); - } - - // Add any new items - final int instance = musicService.getInstance(context); - isTagBrowsing = Util.isTagBrowsing(context, instance); - for(final Entry album: dir.getChildren()) { - if(!recents.contains(album.getId())) { - recents.add(album.getId()); - - String cacheName, parent; - if(isTagBrowsing) { - cacheName = "artist"; - parent = album.getArtistId(); - } else { - cacheName = "directory"; - parent = album.getParent(); - } - - // Add album to artist - if(parent != null) { - new MusicDirectoryUpdater(context, cacheName, parent) { - private boolean changed = false; - - @Override - public boolean checkResult(Entry check) { - return true; - } - - @Override - public void updateResult(List objects, Entry result) { - // Only add if it doesn't already exist in it! - if(!objects.contains(album)) { - objects.add(album); - changed = true; + try { + MusicDirectory dir = musicService.getAlbumList(type, size, offset, context, progressListener); + + // Do some serialization updates for changes to recently added + if ("newest".equals(type) && offset == 0) { + String recentlyAddedFile = getCacheName(context, type); + ArrayList recents = FileUtil.deserialize(context, recentlyAddedFile, ArrayList.class); + if (recents == null) { + recents = new ArrayList(); + } + + // Add any new items + final int instance = musicService.getInstance(context); + isTagBrowsing = Util.isTagBrowsing(context, instance); + for (final Entry album : dir.getChildren()) { + if (!recents.contains(album.getId())) { + recents.add(album.getId()); + + String cacheName, parent; + if (isTagBrowsing) { + cacheName = "artist"; + parent = album.getArtistId(); + } else { + cacheName = "directory"; + parent = album.getParent(); + } + + // Add album to artist + if (parent != null) { + new MusicDirectoryUpdater(context, cacheName, parent) { + private boolean changed = false; + + @Override + public boolean checkResult(Entry check) { + return true; } - } - - @Override - public void save(ArrayList objects) { - // Only save if actually added to artist - if(changed) { - musicDirectory.replaceChildren(objects); - // Reapply sort after addition - musicDirectory.sortChildren(context, instance); - FileUtil.serialize(context, musicDirectory, cacheName); + + @Override + public void updateResult(List objects, Entry result) { + // Only add if it doesn't already exist in it! + if (!objects.contains(album)) { + objects.add(album); + changed = true; + } } - } - }.execute(); - } else { - // If parent is null, then this is a root level album - final Artist artist = new Artist(); - artist.setId(album.getId()); - artist.setName(album.getTitle()); - - new IndexesUpdater(context, isTagBrowsing ? "artists" : "indexes") { - private boolean changed = false; - - @Override - public boolean checkResult(Artist check) { - return true; - } - - @Override - public void updateResult(List objects, Artist result) { - if(!objects.contains(artist)) { - objects.add(artist); - changed = true; + + @Override + public void save(ArrayList objects) { + // Only save if actually added to artist + if (changed) { + musicDirectory.replaceChildren(objects); + // Reapply sort after addition + musicDirectory.sortChildren(context, instance); + FileUtil.serialize(context, musicDirectory, cacheName); + } } - } - - @Override - public void save(ArrayList objects) { - if(changed) { - indexes.setArtists(objects); - // Reapply sort after addition - indexes.sortChildren(context); - FileUtil.serialize(context, indexes, cacheName); - cachedIndexes.set(indexes); + }.execute(); + } else { + // If parent is null, then this is a root level album + final Artist artist = new Artist(); + artist.setId(album.getId()); + artist.setName(album.getTitle()); + + new IndexesUpdater(context, isTagBrowsing ? "artists" : "indexes") { + private boolean changed = false; + + @Override + public boolean checkResult(Artist check) { + return true; } - } - }.execute(); + + @Override + public void updateResult(List objects, Artist result) { + if (!objects.contains(artist)) { + objects.add(artist); + changed = true; + } + } + + @Override + public void save(ArrayList objects) { + if (changed) { + indexes.setArtists(objects); + // Reapply sort after addition + indexes.sortChildren(context); + FileUtil.serialize(context, indexes, cacheName); + cachedIndexes.set(indexes); + } + } + }.execute(); + } } } + + // Keep list from growing into infinity + while (recents.size() > 0) { + recents.remove(0); + } + FileUtil.serialize(context, recents, recentlyAddedFile); } - - // Keep list from growing into infinity - while(recents.size() > 0) { - recents.remove(0); + + FileUtil.serialize(context, dir, getCacheName(context, type, Integer.toString(offset))); + return dir; + } catch(IOException e) { + MusicDirectory dir = FileUtil.deserialize(context, getCacheName(context, type, Integer.toString(offset)), MusicDirectory.class); + + if(dir == null) { + // If we are at start and no cache, throw error higher + if(offset == 0) { + throw e; + } else { + // Otherwise just pretend we are at the end of the list + return new MusicDirectory(); + } + } else { + return dir; } - FileUtil.serialize(context, recents, recentlyAddedFile); } - - return dir; } @Override public MusicDirectory getAlbumList(String type, String extra, int size, int offset, Context context, ProgressListener progressListener) throws Exception { - return musicService.getAlbumList(type, extra, size, offset, context, progressListener); + try { + MusicDirectory dir = musicService.getAlbumList(type, extra, size, offset, context, progressListener); + FileUtil.serialize(context, dir, getCacheName(context, type + extra, Integer.toString(offset))); + return dir; + } catch(IOException e) { + MusicDirectory dir = FileUtil.deserialize(context, getCacheName(context, type + extra, Integer.toString(offset)), MusicDirectory.class); + + if(dir == null) { + // If we are at start and no cache, throw error higher + if(offset == 0) { + throw e; + } else { + // Otherwise just pretend we are at the end of the list + return new MusicDirectory(); + } + } else { + return dir; + } + } } @Override @@ -473,35 +509,44 @@ public class CachedMusicService implements MusicService { @Override public MusicDirectory getStarredList(Context context, ProgressListener progressListener) throws Exception { - MusicDirectory dir = musicService.getStarredList(context, progressListener); + try { + MusicDirectory dir = musicService.getStarredList(context, progressListener); - MusicDirectory oldDir = FileUtil.deserialize(context, "starred", MusicDirectory.class); - if(oldDir != null) { - final List newList = new ArrayList(); - newList.addAll(dir.getChildren()); - final List oldList = oldDir.getChildren(); + MusicDirectory oldDir = FileUtil.deserialize(context, "starred", MusicDirectory.class); + if (oldDir != null) { + final List newList = new ArrayList(); + newList.addAll(dir.getChildren()); + final List oldList = oldDir.getChildren(); - for(Iterator it = oldList.iterator(); it.hasNext(); ) { - Entry oldEntry = it.next(); + for (Iterator it = oldList.iterator(); it.hasNext(); ) { + Entry oldEntry = it.next(); - // Remove entries from newList - if(newList.remove(oldEntry)) { - // If it was removed, then remove it from old list as well - it.remove(); - } else { - oldEntry.setStarred(false); + // Remove entries from newList + if (newList.remove(oldEntry)) { + // If it was removed, then remove it from old list as well + it.remove(); + } else { + oldEntry.setStarred(false); + } } - } - List totalList = new ArrayList(); - totalList.addAll(oldList); - totalList.addAll(newList); + List totalList = new ArrayList(); + totalList.addAll(oldList); + totalList.addAll(newList); - new StarUpdater(context, totalList).execute(); - } - FileUtil.serialize(context, dir, "starred"); + new StarUpdater(context, totalList).execute(); + } + FileUtil.serialize(context, dir, "starred"); - return dir; + return dir; + } catch(IOException e) { + MusicDirectory dir = FileUtil.deserialize(context, "starred", MusicDirectory.class); + if(dir == null) { + throw e; + } else { + return dir; + } + } } @Override @@ -641,7 +686,26 @@ public class CachedMusicService implements MusicService { @Override public MusicDirectory getSongsByGenre(String genre, int count, int offset, Context context, ProgressListener progressListener) throws Exception { - return musicService.getSongsByGenre(genre, count, offset, context, progressListener); + try { + MusicDirectory dir = musicService.getSongsByGenre(genre, count, offset, context, progressListener); + FileUtil.serialize(context, dir, getCacheName(context, "genreSongs", Integer.toString(offset))); + + return dir; + } catch(IOException e) { + MusicDirectory dir = FileUtil.deserialize(context, getCacheName(context, "genreSongs", Integer.toString(offset)), MusicDirectory.class); + + if(dir == null) { + // If we are at start and no cache, throw error higher + if(offset == 0) { + throw e; + } else { + // Otherwise just pretend we are at the end of the list + return new MusicDirectory(); + } + } else { + return dir; + } + } } @Override @@ -921,7 +985,19 @@ public class CachedMusicService implements MusicService { @Override public MusicDirectory getVideos(boolean refresh, Context context, ProgressListener progressListener) throws Exception { - return musicService.getVideos(refresh, context, progressListener); + try { + MusicDirectory dir = musicService.getVideos(refresh, context, progressListener); + FileUtil.serialize(context, dir, "videos"); + + return dir; + } catch(IOException e) { + MusicDirectory dir = FileUtil.deserialize(context, "videos", MusicDirectory.class); + if(dir == null) { + throw e; + } else { + return dir; + } + } } @Override diff --git a/src/github/daneren2005/dsub/service/RESTMusicService.java b/src/github/daneren2005/dsub/service/RESTMusicService.java index de60ae12..7def53c2 100644 --- a/src/github/daneren2005/dsub/service/RESTMusicService.java +++ b/src/github/daneren2005/dsub/service/RESTMusicService.java @@ -517,7 +517,7 @@ public class RESTMusicService implements MusicService { } Reader reader = getReader(context, progressListener, Util.isTagBrowsing(context, getInstance(context)) ? "getAlbumList2" : "getAlbumList", - null, names, values); + null, names, values, true); try { return new AlbumListParser(context, getInstance(context)).parse(reader, progressListener); } finally { @@ -566,7 +566,7 @@ public class RESTMusicService implements MusicService { } } - Reader reader = getReader(context, progressListener, Util.isTagBrowsing(context, instance) ? "getAlbumList2" : "getAlbumList", null, names, values); + Reader reader = getReader(context, progressListener, Util.isTagBrowsing(context, instance) ? "getAlbumList2" : "getAlbumList", null, names, values, true); try { return new AlbumListParser(context, instance).parse(reader, progressListener); } finally { @@ -622,7 +622,7 @@ public class RESTMusicService implements MusicService { } } - Reader reader = getReader(context, progressListener, Util.isTagBrowsing(context, instance) ? "getStarred2" : "getStarred", null, names, values); + Reader reader = getReader(context, progressListener, Util.isTagBrowsing(context, instance) ? "getStarred2" : "getStarred", null, names, values, true); try { return new StarredListParser(context, instance).parse(reader, progressListener); } finally { @@ -788,7 +788,7 @@ public class RESTMusicService implements MusicService { parameterValues.add("raw"); } } - HttpResponse response = getResponseForURL(context, url, params, parameterNames, parameterValues, headers, null, task); + HttpResponse response = getResponseForURL(context, url, params, parameterNames, parameterValues, headers, null, task, false); // If content type is XML, an error occurred. Get it. String contentType = Util.getContentType(response.getEntity()); @@ -1141,7 +1141,7 @@ public class RESTMusicService implements MusicService { } } - Reader reader = getReader(context, progressListener, "getSongsByGenre", params, parameterNames, parameterValues); + Reader reader = getReader(context, progressListener, "getSongsByGenre", params, parameterNames, parameterValues, true); try { return new RandomSongsParser(context, instance).parse(reader, progressListener); } finally { @@ -1541,7 +1541,7 @@ public class RESTMusicService implements MusicService { @Override public MusicDirectory getVideos(boolean refresh, Context context, ProgressListener progressListener) throws Exception { - Reader reader = getReader(context, progressListener, "getVideos", null); + Reader reader = getReader(context, progressListener, "getVideos", null, true); try { return new VideosParser(context, getInstance(context)).parse(reader, progressListener); } finally { @@ -1690,8 +1690,11 @@ public class RESTMusicService implements MusicService { this.instance = instance; } - private Reader getReader(Context context, ProgressListener progressListener, String method, HttpParams requestParams) throws Exception { - return getReader(context, progressListener, method, requestParams, Collections.emptyList(), Collections.emptyList()); + private Reader getReader(Context context, ProgressListener progressListener, String method, HttpParams requestParams) throws Exception { + return getReader(context, progressListener, method, requestParams, false); + } + private Reader getReader(Context context, ProgressListener progressListener, String method, HttpParams requestParams, boolean throwsError) throws Exception { + return getReader(context, progressListener, method, requestParams, Collections.emptyList(), Collections.emptyList(), throwsError); } private Reader getReader(Context context, ProgressListener progressListener, String method, @@ -1699,20 +1702,28 @@ public class RESTMusicService implements MusicService { return getReader(context, progressListener, method, requestParams, Arrays.asList(parameterName), Arrays.asList(parameterValue)); } + private Reader getReader(Context context, ProgressListener progressListener, String method, + HttpParams requestParams, List parameterNames, List parameterValues) throws Exception { + return getReader(context, progressListener, method, requestParams, parameterNames, parameterValues, false); + } private Reader getReader(Context context, ProgressListener progressListener, String method, - HttpParams requestParams, List parameterNames, List parameterValues) throws Exception { + HttpParams requestParams, List parameterNames, List parameterValues, boolean throwErrors) throws Exception { if (progressListener != null) { progressListener.updateProgress(R.string.service_connecting); } String url = getRestUrl(context, method); - return getReaderForURL(context, url, requestParams, parameterNames, parameterValues, progressListener); + return getReaderForURL(context, url, requestParams, parameterNames, parameterValues, progressListener, throwErrors); } + private Reader getReaderForURL(Context context, String url, HttpParams requestParams, List parameterNames, + List parameterValues, ProgressListener progressListener) throws Exception { + return getReaderForURL(context, url, requestParams, parameterNames, parameterValues, progressListener, true); + } private Reader getReaderForURL(Context context, String url, HttpParams requestParams, List parameterNames, - List parameterValues, ProgressListener progressListener) throws Exception { - HttpEntity entity = getEntityForURL(context, url, requestParams, parameterNames, parameterValues, progressListener); + List parameterValues, ProgressListener progressListener, boolean throwErrors) throws Exception { + HttpEntity entity = getEntityForURL(context, url, requestParams, parameterNames, parameterValues, progressListener, throwErrors); if (entity == null) { throw new RuntimeException("No entity received for URL " + url); } @@ -1726,18 +1737,23 @@ public class RESTMusicService implements MusicService { } private HttpEntity getEntityForURL(Context context, String url, HttpParams requestParams, List parameterNames, - List parameterValues, ProgressListener progressListener) throws Exception { + List parameterValues, ProgressListener progressListener, boolean throwErrors) throws Exception { - return getEntityForURL(context, url, requestParams, parameterNames, parameterValues, progressListener, null); + return getEntityForURL(context, url, requestParams, parameterNames, parameterValues, progressListener, null, throwErrors); + } + + private HttpEntity getEntityForURL(Context context, String url, HttpParams requestParams, List parameterNames, + List parameterValues, ProgressListener progressListener, SilentBackgroundTask task) throws Exception { + return getResponseForURL(context, url, requestParams, parameterNames, parameterValues, null, progressListener, task, false).getEntity(); } private HttpEntity getEntityForURL(Context context, String url, HttpParams requestParams, List parameterNames, - List parameterValues, ProgressListener progressListener, SilentBackgroundTask task) throws Exception { - return getResponseForURL(context, url, requestParams, parameterNames, parameterValues, null, progressListener, task).getEntity(); + List parameterValues, ProgressListener progressListener, SilentBackgroundTask task, boolean throwsError) throws Exception { + return getResponseForURL(context, url, requestParams, parameterNames, parameterValues, null, progressListener, task, throwsError).getEntity(); } private HttpResponse getResponseForURL(Context context, String url, HttpParams requestParams, List parameterNames, List parameterValues, - List
headers, ProgressListener progressListener, SilentBackgroundTask task) throws Exception { + List
headers, ProgressListener progressListener, SilentBackgroundTask task, boolean throwsErrors) throws Exception { // If not too many parameters, extract them to the URL rather than relying on the HTTP POST request being // received intact. Remember, HTTP POST requests are converted to GET requests during HTTP redirects, thus // loosing its entity. @@ -1755,12 +1771,12 @@ public class RESTMusicService implements MusicService { } String rewrittenUrl = rewriteUrlWithRedirect(context, url); - return executeWithRetry(context, rewrittenUrl, url, requestParams, parameterNames, parameterValues, headers, progressListener, task); + return executeWithRetry(context, rewrittenUrl, url, requestParams, parameterNames, parameterValues, headers, progressListener, task, throwsErrors); } private HttpResponse executeWithRetry(final Context context, String url, String originalUrl, HttpParams requestParams, List parameterNames, List parameterValues, - List
headers, ProgressListener progressListener, SilentBackgroundTask task) throws Exception { + List
headers, ProgressListener progressListener, SilentBackgroundTask task, boolean throwErrors) throws Exception { // Strip out sensitive information from log if(url.indexOf("scanstatus") == -1) { Log.i(TAG, stripUrlInfo(url)); @@ -1838,7 +1854,7 @@ public class RESTMusicService implements MusicService { return response; } catch (IOException x) { request.abort(); - if (attempts >= HTTP_REQUEST_MAX_ATTEMPTS || isCancelled.get()) { + if (attempts >= HTTP_REQUEST_MAX_ATTEMPTS || isCancelled.get() || throwErrors) { throw x; } if (progressListener != null) { -- cgit v1.2.3