From 36167e5ab99ab683b7bb19ce6e576988a5c2c2f7 Mon Sep 17 00:00:00 2001 From: Joshua Bahnsen Date: Sun, 26 Jan 2014 16:47:13 -0700 Subject: [PATCH] Add years to album header, determine album name based on entries in album header, make thread collection in ImageLoader concurrent --- res/layout/select_album_header.xml | 29 ++++++++++----- res/values-fr/strings.xml | 1 + res/values-hu/strings.xml | 1 + res/values/strings.xml | 1 + .../androidapp/activity/DownloadActivity.java | 2 +- .../activity/SelectAlbumActivity.java | 14 ++++++-- .../androidapp/util/AlbumHeader.java | 25 +++++++++++++ .../androidapp/util/CacheCleaner.java | 35 ++++++++++--------- .../androidapp/util/ImageLoader.java | 6 ++-- 9 files changed, 83 insertions(+), 31 deletions(-) diff --git a/res/layout/select_album_header.xml b/res/layout/select_album_header.xml index d631e19b..91be0aa1 100644 --- a/res/layout/select_album_header.xml +++ b/res/layout/select_album_header.xml @@ -1,7 +1,7 @@ + a:layout_width="fill_parent" + a:layout_height="wrap_content"> + a:src="@drawable/unknown_album_large"/> + a:textAppearance="?android:attr/textAppearanceMedium"/> + a:textAppearance="?android:attr/textAppearanceSmall"/> + a:textAppearance="?android:attr/textAppearanceSmall"/> + + + a:textAppearance="?android:attr/textAppearanceSmall"/> + a:textAppearance="?android:attr/textAppearanceSmall"/> \ No newline at end of file diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index 4f6d90ba..ae667164 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -388,6 +388,7 @@ 11 12 albumArt + Multiple Years Aucun titre diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml index bc3d5c3d..e81083b0 100644 --- a/res/values-hu/strings.xml +++ b/res/values-hu/strings.xml @@ -388,6 +388,7 @@ 11 12 albumArt + Multiple Years Nincsenek dalok diff --git a/res/values/strings.xml b/res/values/strings.xml index 2a68266f..9a142f56 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -388,6 +388,7 @@ 11 12 albumArt + Multiple Years No songs diff --git a/src/com/thejoshwa/ultrasonic/androidapp/activity/DownloadActivity.java b/src/com/thejoshwa/ultrasonic/androidapp/activity/DownloadActivity.java index ab1bae84..b27565e4 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/activity/DownloadActivity.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/activity/DownloadActivity.java @@ -1325,7 +1325,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi artistTextView.setText(null); downloadTrackTextView.setText(null); downloadTotalDurationTextView.setText(null); - getImageLoader().loadImage(albumArtImageView, null, true, 0, false, false); + getImageLoader().loadImage(albumArtImageView, null, true, 0, false, true); } } diff --git a/src/com/thejoshwa/ultrasonic/androidapp/activity/SelectAlbumActivity.java b/src/com/thejoshwa/ultrasonic/androidapp/activity/SelectAlbumActivity.java index 56b8217c..8591de5d 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/activity/SelectAlbumActivity.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/activity/SelectAlbumActivity.java @@ -1196,11 +1196,12 @@ public class SelectAlbumActivity extends SubsonicTabActivity int artworkSelection = random.nextInt(entries.size()); getImageLoader().loadImage(coverArtView, entries.get(artworkSelection), false, Util.getAlbumImageSize(SelectAlbumActivity.this), false, true); - TextView titleView = (TextView) header.findViewById(R.id.select_album_title); - titleView.setText(name != null ? name : getActionBarSubtitle()); - AlbumHeader albumHeader = AlbumHeader.processEntries(SelectAlbumActivity.this, entries); + TextView titleView = (TextView) header.findViewById(R.id.select_album_title); + name = albumHeader.getAlbumNames().size() == 1 ? albumHeader.getAlbumNames().iterator().next() : name; + titleView.setText(name != null ? name : getActionBarSubtitle()); + // Don't show a header if all entries are videos if (albumHeader.getIsAllVideo()) { @@ -1221,6 +1222,13 @@ public class SelectAlbumActivity extends SubsonicTabActivity genreView.setText(genre); + TextView yearView = (TextView) header.findViewById(R.id.select_album_year); + String year; + + year = albumHeader.getYears().size() == 1 ? albumHeader.getYears().iterator().next().toString() : getResources().getString(R.string.common_multiple_years); + + yearView.setText(year); + TextView songCountView = (TextView) header.findViewById(R.id.select_album_song_count); String songs = getResources().getQuantityString(R.plurals.select_album_n_songs, songCount, songCount); songCountView.setText(songs); diff --git a/src/com/thejoshwa/ultrasonic/androidapp/util/AlbumHeader.java b/src/com/thejoshwa/ultrasonic/androidapp/util/AlbumHeader.java index 6b6c68fc..d1570c33 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/util/AlbumHeader.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/util/AlbumHeader.java @@ -14,6 +14,8 @@ public class AlbumHeader private Set artists; private Set grandParents; private Set genres; + private Set albumNames; + private Set years; public boolean getIsAllVideo() { @@ -40,11 +42,24 @@ public class AlbumHeader return this.genres; } + public Set getAlbumNames() + { + return this.albumNames; + } + + public Set getYears() + { + return this.years; + } + public AlbumHeader() { this.artists = new HashSet(); this.grandParents = new HashSet(); this.genres = new HashSet(); + this.albumNames = new HashSet(); + this.years = new HashSet(); + this.isAllVideo = true; this.totalDuration = 0; } @@ -83,6 +98,16 @@ public class AlbumHeader { albumHeader.genres.add(entry.getGenre()); } + + if (entry.getAlbum() != null) + { + albumHeader.albumNames.add(entry.getAlbum()); + } + + if (entry.getYear() != null) + { + albumHeader.years.add(entry.getYear()); + } } } diff --git a/src/com/thejoshwa/ultrasonic/androidapp/util/CacheCleaner.java b/src/com/thejoshwa/ultrasonic/androidapp/util/CacheCleaner.java index 48961d59..2cb38216 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/util/CacheCleaner.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/util/CacheCleaner.java @@ -77,11 +77,11 @@ public class CacheCleaner } } - private static void deleteEmptyDirs(Iterable dirs, Collection undeletable) + private static void deleteEmptyDirs(Iterable dirs, Collection doNotDelete) { for (File dir : dirs) { - if (undeletable.contains(dir)) + if (doNotDelete.contains(dir)) { continue; } @@ -114,8 +114,8 @@ public class CacheCleaner } long cacheSizeBytes = Util.getCacheSizeMB(context) * 1024L * 1024L; - long bytesUsedBySubsonic = 0L; + for (File file : files) { bytesUsedBySubsonic += file.length(); @@ -140,7 +140,7 @@ public class CacheCleaner return bytesToDelete; } - private static void deleteFiles(Collection files, Collection undeletable, long bytesToDelete, boolean deletePartials) + private static void deleteFiles(Collection files, Collection doNotDelete, long bytesToDelete, boolean deletePartials) { if (files.isEmpty()) { @@ -154,9 +154,10 @@ public class CacheCleaner if (bytesToDelete > bytesDeleted || (deletePartials && (file.getName().endsWith(".partial") || file.getName().contains(".partial.")))) { - if (!undeletable.contains(file) && !file.getName().equals(Constants.ALBUM_ART_FILE)) + if (!doNotDelete.contains(file) && !file.getName().equals(Constants.ALBUM_ART_FILE)) { long size = file.length(); + if (Util.delete(file)) { bytesDeleted += size; @@ -174,6 +175,7 @@ public class CacheCleaner { String name = file.getName(); boolean isCacheFile = name.endsWith(".partial") || name.contains(".partial.") || name.endsWith(".complete") || name.contains(".complete."); + if (isCacheFile) { files.add(file); @@ -186,6 +188,7 @@ public class CacheCleaner { findCandidatesForDeletion(child, files, dirs); } + dirs.add(file); } } @@ -212,18 +215,18 @@ public class CacheCleaner }); } - private Set findUndeletableFiles() + private Set findFilesToNotDelete() { - Set undeletable = new HashSet(5); + Set filesToNotDelete = new HashSet(5); for (DownloadFile downloadFile : downloadService.getDownloads()) { - undeletable.add(downloadFile.getPartialFile()); - undeletable.add(downloadFile.getCompleteFile()); + filesToNotDelete.add(downloadFile.getPartialFile()); + filesToNotDelete.add(downloadFile.getCompleteFile()); } - undeletable.add(FileUtil.getMusicDirectory(context)); - return undeletable; + filesToNotDelete.add(FileUtil.getMusicDirectory(context)); + return filesToNotDelete; } private class BackgroundCleanup extends AsyncTask @@ -246,10 +249,10 @@ public class CacheCleaner findCandidatesForDeletion(FileUtil.getMusicDirectory(context), files, dirs); sortByAscendingModificationTime(files); - Set undeletable = findUndeletableFiles(); + Set filesToNotDelete = findFilesToNotDelete(); - deleteFiles(files, undeletable, getMinimumDelete(files), true); - deleteEmptyDirs(dirs, undeletable); + deleteFiles(files, filesToNotDelete, getMinimumDelete(files), true); + deleteEmptyDirs(dirs, filesToNotDelete); } catch (RuntimeException x) { @@ -282,8 +285,8 @@ public class CacheCleaner if (bytesToDelete > 0L) { sortByAscendingModificationTime(files); - Set undeletable = findUndeletableFiles(); - deleteFiles(files, undeletable, bytesToDelete, false); + Set filesToNotDelete = findFilesToNotDelete(); + deleteFiles(files, filesToNotDelete, bytesToDelete, false); } } catch (RuntimeException x) diff --git a/src/com/thejoshwa/ultrasonic/androidapp/util/ImageLoader.java b/src/com/thejoshwa/ultrasonic/androidapp/util/ImageLoader.java index d433b5f5..43b0e819 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/util/ImageLoader.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/util/ImageLoader.java @@ -38,6 +38,7 @@ import com.thejoshwa.ultrasonic.androidapp.service.MusicServiceFactory; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.atomic.AtomicBoolean; @@ -98,7 +99,7 @@ public class ImageLoader implements Runnable { running.set(true); - threads = new ArrayList(this.concurrency); + threads = Collections.synchronizedCollection(new ArrayList(this.concurrency)); for (int i = 0; i < this.concurrency; i++) { @@ -209,9 +210,10 @@ public class ImageLoader implements Runnable MusicDirectory.Entry tagEntry = (MusicDirectory.Entry) view.getTag(); + // Only apply image to the view if the view is intended for this entry if (entry != null && tagEntry != null && !entry.equals(tagEntry)) { - Log.i(TAG, "Skipping entry"); + Log.i(TAG, "View is no longer valid, not setting ImageBitmap"); return; }