Add incompletely played episodes to playback history (#7815)

This commit is contained in:
dominikfill
2025-05-27 22:52:43 +02:00
committed by GitHub
parent 49e6da6727
commit c2f7dabc8b
23 changed files with 123 additions and 114 deletions

View File

@ -183,7 +183,7 @@ public class UITestUtils {
queue.add(feed.getItems().get(0)); queue.add(feed.getItems().get(0));
if (feed.getItems().get(1).hasMedia()) { if (feed.getItems().get(1).hasMedia()) {
feed.getItems().get(1).getMedia().setPlaybackCompletionDate(new Date()); feed.getItems().get(1).getMedia().setLastPlayedTimeHistory(new Date());
} }
} }
localFeedDataAdded = true; localFeedDataAdded = true;

View File

@ -38,10 +38,10 @@ public class RemoveFromHistorySwipeAction implements SwipeAction {
@Override @Override
public void performAction(FeedItem item, Fragment fragment, FeedItemFilter filter) { public void performAction(FeedItem item, Fragment fragment, FeedItemFilter filter) {
Date playbackCompletionDate = item.getMedia().getPlaybackCompletionDate(); Date lastPlayedTimeHistory = item.getMedia().getLastPlayedTimeHistory();
DBWriter.deleteFromPlaybackHistory(item); DBWriter.deleteFromPlaybackHistory(item);
EventBus.getDefault().post(new MessageEvent(fragment.getString(R.string.removed_history_label), EventBus.getDefault().post(new MessageEvent(fragment.getString(R.string.removed_history_label),
context -> DBWriter.addItemToPlaybackHistory(item.getMedia(), playbackCompletionDate), context -> DBWriter.addItemToPlaybackHistory(item.getMedia(), lastPlayedTimeHistory),
fragment.getString(R.string.undo))); fragment.getString(R.string.undo)));
} }

View File

@ -117,7 +117,7 @@ public class FeedItemFilter implements Serializable {
} else if (showNotFavorite && item.isTagged(FeedItem.TAG_FAVORITE)) { } else if (showNotFavorite && item.isTagged(FeedItem.TAG_FAVORITE)) {
return false; return false;
} else if (showInHistory && item.getMedia() != null } else if (showInHistory && item.getMedia() != null
&& item.getMedia().getPlaybackCompletionDate().getTime() == 0) { && item.getMedia().getLastPlayedTimeHistory().getTime() == 0) {
return false; return false;
} else if (!includeNotSubscribed && item.getFeed() != null } else if (!includeNotSubscribed && item.getFeed() != null
&& item.getFeed().getState() != Feed.STATE_SUBSCRIBED) { && item.getFeed().getState() != Feed.STATE_SUBSCRIBED) {

View File

@ -38,12 +38,12 @@ public class FeedMedia implements Playable {
private long downloadDate; private long downloadDate;
private int duration; private int duration;
private int position; // Current position in file private int position; // Current position in file
private long lastPlayedTime; // Last time this media was played (in ms) private long lastPlayedTimeStatistics; // Last time this media was played (in ms)
private int playedDuration; // How many ms of this file have been played private int playedDuration; // How many ms of this file have been played
private long size; // File size in Byte private long size; // File size in Byte
private String mimeType; private String mimeType;
@Nullable private volatile FeedItem item; @Nullable private volatile FeedItem item;
private Date playbackCompletionDate; private Date lastPlayedTimeHistory;
private int startPosition = -1; private int startPosition = -1;
private int playedDurationWhenStarted; private int playedDurationWhenStarted;
@ -66,8 +66,8 @@ public class FeedMedia implements Playable {
public FeedMedia(long id, FeedItem item, int duration, int position, public FeedMedia(long id, FeedItem item, int duration, int position,
long size, String mimeType, String localFileUrl, String downloadUrl, long size, String mimeType, String localFileUrl, String downloadUrl,
long downloadDate, Date playbackCompletionDate, int playedDuration, long downloadDate, Date lastPlayedTimeHistory, int playedDuration,
long lastPlayedTime) { long lastPlayedTimeStatistics) {
this.localFileUrl = localFileUrl; this.localFileUrl = localFileUrl;
this.downloadUrl = downloadUrl; this.downloadUrl = downloadUrl;
this.downloadDate = downloadDate; this.downloadDate = downloadDate;
@ -80,17 +80,17 @@ public class FeedMedia implements Playable {
this.playedDurationWhenStarted = playedDuration; this.playedDurationWhenStarted = playedDuration;
this.size = size; this.size = size;
this.mimeType = mimeType; this.mimeType = mimeType;
this.playbackCompletionDate = playbackCompletionDate == null this.lastPlayedTimeHistory = lastPlayedTimeHistory == null
? null : (Date) playbackCompletionDate.clone(); ? null : (Date) lastPlayedTimeHistory.clone();
this.lastPlayedTime = lastPlayedTime; this.lastPlayedTimeStatistics = lastPlayedTimeStatistics;
} }
public FeedMedia(long id, FeedItem item, int duration, int position, public FeedMedia(long id, FeedItem item, int duration, int position,
long size, String mimeType, String localFileUrl, String downloadUrl, long size, String mimeType, String localFileUrl, String downloadUrl,
long downloadDate, Date playbackCompletionDate, int playedDuration, long downloadDate, Date lastPlayedTimeHistory, int playedDuration,
Boolean hasEmbeddedPicture, long lastPlayedTime) { Boolean hasEmbeddedPicture, long lastPlayedTimeStatistics) {
this(id, item, duration, position, size, mimeType, localFileUrl, downloadUrl, downloadDate, this(id, item, duration, position, size, mimeType, localFileUrl, downloadUrl, downloadDate,
playbackCompletionDate, playedDuration, lastPlayedTime); lastPlayedTimeHistory, playedDuration, lastPlayedTimeStatistics);
this.hasEmbeddedPicture = hasEmbeddedPicture; this.hasEmbeddedPicture = hasEmbeddedPicture;
} }
@ -178,8 +178,8 @@ public class FeedMedia implements Playable {
} }
@Override @Override
public void setLastPlayedTime(long lastPlayedTime) { public void setLastPlayedTimeStatistics(long lastPlayedTimeStatistics) {
this.lastPlayedTime = lastPlayedTime; this.lastPlayedTimeStatistics = lastPlayedTimeStatistics;
} }
public int getPlayedDuration() { public int getPlayedDuration() {
@ -199,8 +199,8 @@ public class FeedMedia implements Playable {
} }
@Override @Override
public long getLastPlayedTime() { public long getLastPlayedTimeStatistics() {
return lastPlayedTime; return lastPlayedTimeStatistics;
} }
public void setPosition(int position) { public void setPosition(int position) {
@ -260,14 +260,14 @@ public class FeedMedia implements Playable {
} }
} }
public Date getPlaybackCompletionDate() { public Date getLastPlayedTimeHistory() {
return playbackCompletionDate == null return lastPlayedTimeHistory == null
? null : (Date) playbackCompletionDate.clone(); ? null : (Date) lastPlayedTimeHistory.clone();
} }
public void setPlaybackCompletionDate(Date playbackCompletionDate) { public void setLastPlayedTimeHistory(Date lastPlayedTimeHistory) {
this.playbackCompletionDate = playbackCompletionDate == null this.lastPlayedTimeHistory = lastPlayedTimeHistory == null
? null : (Date) playbackCompletionDate.clone(); ? null : (Date) lastPlayedTimeHistory.clone();
} }
public boolean isInProgress() { public boolean isInProgress() {
@ -298,9 +298,9 @@ public class FeedMedia implements Playable {
dest.writeString(localFileUrl); dest.writeString(localFileUrl);
dest.writeString(downloadUrl); dest.writeString(downloadUrl);
dest.writeLong(downloadDate); dest.writeLong(downloadDate);
dest.writeLong((playbackCompletionDate != null) ? playbackCompletionDate.getTime() : 0); dest.writeLong((lastPlayedTimeHistory != null) ? lastPlayedTimeHistory.getTime() : 0);
dest.writeInt(playedDuration); dest.writeInt(playedDuration);
dest.writeLong(lastPlayedTime); dest.writeLong(lastPlayedTimeStatistics);
} }
@Override @Override

View File

@ -61,7 +61,7 @@ public interface Playable extends Parcelable, Serializable {
* Returns last time (in ms) when this playable was played or 0 * Returns last time (in ms) when this playable was played or 0
* if last played time is unknown. * if last played time is unknown.
*/ */
long getLastPlayedTime(); long getLastPlayedTimeStatistics();
/** /**
* Returns the description of the item, if available. * Returns the description of the item, if available.
@ -100,7 +100,7 @@ public interface Playable extends Parcelable, Serializable {
/** /**
* @param lastPlayedTimestamp timestamp in ms * @param lastPlayedTimestamp timestamp in ms
*/ */
void setLastPlayedTime(long lastPlayedTimestamp); void setLastPlayedTimeStatistics(long lastPlayedTimestamp);
/** /**
* This method should be called every time playback starts on this object. * This method should be called every time playback starts on this object.

View File

@ -40,7 +40,7 @@ public class RemoteMedia implements Playable {
private List<Chapter> chapters; private List<Chapter> chapters;
private int duration; private int duration;
private int position; private int position;
private long lastPlayedTime; private long lastPlayedTimeStatistics;
public RemoteMedia(String downloadUrl, String itemId, String feedUrl, String feedTitle, public RemoteMedia(String downloadUrl, String itemId, String feedUrl, String feedTitle,
String episodeTitle, String episodeLink, String feedAuthor, String episodeTitle, String episodeLink, String feedAuthor,
@ -159,8 +159,8 @@ public class RemoteMedia implements Playable {
} }
@Override @Override
public long getLastPlayedTime() { public long getLastPlayedTimeStatistics() {
return lastPlayedTime; return lastPlayedTimeStatistics;
} }
@Override @Override
@ -194,8 +194,8 @@ public class RemoteMedia implements Playable {
} }
@Override @Override
public void setLastPlayedTime(long lastPlayedTimestamp) { public void setLastPlayedTimeStatistics(long lastPlayedTimestamp) {
lastPlayedTime = lastPlayedTimestamp; lastPlayedTimeStatistics = lastPlayedTimestamp;
} }
@Override @Override
@ -255,7 +255,7 @@ public class RemoteMedia implements Playable {
dest.writeString(notes); dest.writeString(notes);
dest.writeInt(duration); dest.writeInt(duration);
dest.writeInt(position); dest.writeInt(position);
dest.writeLong(lastPlayedTime); dest.writeLong(lastPlayedTimeStatistics);
} }
public static final Parcelable.Creator<RemoteMedia> CREATOR = new Parcelable.Creator<RemoteMedia>() { public static final Parcelable.Creator<RemoteMedia> CREATOR = new Parcelable.Creator<RemoteMedia>() {
@ -266,7 +266,7 @@ public class RemoteMedia implements Playable {
in.readString(), in.readString(), new Date(in.readLong()), in.readString()); in.readString(), in.readString(), new Date(in.readLong()), in.readString());
result.setDuration(in.readInt()); result.setDuration(in.readInt());
result.setPosition(in.readInt()); result.setPosition(in.readInt());
result.setLastPlayedTime(in.readLong()); result.setLastPlayedTimeStatistics(in.readLong());
return result; return result;
} }

View File

@ -29,7 +29,7 @@ public abstract class AutoDownloadManager {
/** /**
* Removed downloaded episodes outside of the queue if the episode cache is full. Episodes with a smaller * Removed downloaded episodes outside of the queue if the episode cache is full. Episodes with a smaller
* 'playbackCompletionDate'-value will be deleted first. * 'lastPlayedTimeHistory'-value will be deleted first.
* <p/> * <p/>
* This method should NOT be executed on the GUI thread. * This method should NOT be executed on the GUI thread.
* *

View File

@ -47,8 +47,8 @@ public class APCleanupAlgorithm extends EpisodeCleanupAlgorithm {
List<FeedItem> delete; List<FeedItem> delete;
Collections.sort(candidates, (lhs, rhs) -> { Collections.sort(candidates, (lhs, rhs) -> {
Date l = lhs.getMedia().getPlaybackCompletionDate(); Date l = lhs.getMedia().getLastPlayedTimeHistory();
Date r = rhs.getMedia().getPlaybackCompletionDate(); Date r = rhs.getMedia().getLastPlayedTimeHistory();
if (l == null) { if (l == null) {
l = new Date(); l = new Date();
@ -105,8 +105,8 @@ public class APCleanupAlgorithm extends EpisodeCleanupAlgorithm {
// make sure this candidate was played at least the proper amount of days prior // make sure this candidate was played at least the proper amount of days prior
// to now // to now
if (media != null if (media != null
&& media.getPlaybackCompletionDate() != null && media.getLastPlayedTimeHistory() != null
&& media.getPlaybackCompletionDate().before(mostRecentDateForDeletion)) { && media.getLastPlayedTimeHistory().before(mostRecentDateForDeletion)) {
candidates.add(item); candidates.add(item);
} }
} }

View File

@ -43,7 +43,7 @@ public class AutoDownloadManagerImpl extends AutoDownloadManager {
/** /**
* Removed downloaded episodes outside of the queue if the episode cache is full. Episodes with a smaller * Removed downloaded episodes outside of the queue if the episode cache is full. Episodes with a smaller
* 'playbackCompletionDate'-value will be deleted first. * 'lastPlayedTimeHistory'-value will be deleted first.
* <p/> * <p/>
* This method should NOT be executed on the GUI thread. * This method should NOT be executed on the GUI thread.
* *

View File

@ -130,9 +130,9 @@ public class DbCleanupTests {
boolean addToFavorites) throws IOException { boolean addToFavorites) throws IOException {
for (int i = 0; i < numItems; i++) { for (int i = 0; i < numItems; i++) {
Date itemDate = new Date(numItems - i); Date itemDate = new Date(numItems - i);
Date playbackCompletionDate = null; Date lastPlayedTimeHistory = null;
if (itemState == FeedItem.PLAYED) { if (itemState == FeedItem.PLAYED) {
playbackCompletionDate = itemDate; lastPlayedTimeHistory = itemDate;
} }
FeedItem item = new FeedItem(0, "title", "id" + i, "link", itemDate, itemState, feed); FeedItem item = new FeedItem(0, "title", "id" + i, "link", itemDate, itemState, feed);
@ -140,7 +140,7 @@ public class DbCleanupTests {
assertTrue(f.createNewFile()); assertTrue(f.createNewFile());
files.add(f); files.add(f);
item.setMedia(new FeedMedia(0, item, 1, 0, 1L, "m", item.setMedia(new FeedMedia(0, item, 1, 0, 1L, "m",
f.getAbsolutePath(), "url", System.currentTimeMillis(), playbackCompletionDate, 0, 0)); f.getAbsolutePath(), "url", System.currentTimeMillis(), lastPlayedTimeHistory, 0, 0));
items.add(item); items.add(item);
} }

View File

@ -324,9 +324,9 @@ public class DbReaderTest {
adapter.open(); adapter.open();
for (int i = 0; i < playedItems; ++i) { for (int i = 0; i < playedItems; ++i) {
FeedMedia m = feed.getItems().get(i).getMedia(); FeedMedia m = feed.getItems().get(i).getMedia();
m.setPlaybackCompletionDate(new Date(i + 1)); m.setLastPlayedTimeHistory(new Date(i + 1));
adapter.setFeedMediaPlaybackCompletionDate(m); adapter.setFeedMediaLastPlayedTimeHistory(m);
} }
adapter.close(); adapter.close();
@ -506,8 +506,8 @@ public class DbReaderTest {
adapter.open(); adapter.open();
for (int i = 0; i < playedItems; i++) { for (int i = 0; i < playedItems; i++) {
FeedMedia m = feed.getItems().get(i).getMedia(); FeedMedia m = feed.getItems().get(i).getMedia();
m.setPlaybackCompletionDate(new Date(i + 1)); m.setLastPlayedTimeHistory(new Date(i + 1));
adapter.setFeedMediaPlaybackCompletionDate(m); adapter.setFeedMediaLastPlayedTimeHistory(m);
ids[ids.length - 1 - i] = m.getItem().getId(); ids[ids.length - 1 - i] = m.getItem().getId();
} }
adapter.close(); adapter.close();
@ -520,7 +520,7 @@ public class DbReaderTest {
numReturnedItems, saved.size()); numReturnedItems, saved.size());
for (int i = 0; i < numReturnedItems; i++) { for (int i = 0; i < numReturnedItems; i++) {
FeedItem item = saved.get(i); FeedItem item = saved.get(i);
assertNotNull(item.getMedia().getPlaybackCompletionDate()); assertNotNull(item.getMedia().getLastPlayedTimeHistory());
assertEquals(String.format("Wrong sort order with offset %d and limit %d: ", assertEquals(String.format("Wrong sort order with offset %d and limit %d: ",
paramOffset, paramLimit), paramOffset, paramLimit),
item.getId(), ids[paramOffset + i]); item.getId(), ids[paramOffset + i]);

View File

@ -94,7 +94,8 @@ public class DbWriterTest {
@Test @Test
public void testSetFeedMediaPlaybackInformation() throws Exception { public void testSetFeedMediaPlaybackInformation() throws Exception {
final int position = 50; final int position = 50;
final long lastPlayedTime = 1000; final long lastPlayedTimeStatistics = 1000;
final Date lastPlayedTimeHistory = new Date();
final int playedDuration = 60; final int playedDuration = 60;
final int duration = 100; final int duration = 100;
@ -110,8 +111,9 @@ public class DbWriterTest {
DBWriter.setFeedItem(item).get(TIMEOUT, TimeUnit.SECONDS); DBWriter.setFeedItem(item).get(TIMEOUT, TimeUnit.SECONDS);
media.setPosition(position); media.setPosition(position);
media.setLastPlayedTime(lastPlayedTime); media.setLastPlayedTimeStatistics(lastPlayedTimeStatistics);
media.setPlayedDuration(playedDuration); media.setPlayedDuration(playedDuration);
media.setLastPlayedTimeHistory(lastPlayedTimeHistory);
DBWriter.setFeedMediaPlaybackInformation(item.getMedia()).get(TIMEOUT, TimeUnit.SECONDS); DBWriter.setFeedMediaPlaybackInformation(item.getMedia()).get(TIMEOUT, TimeUnit.SECONDS);
@ -119,7 +121,8 @@ public class DbWriterTest {
FeedMedia mediaFromDb = itemFromDb.getMedia(); FeedMedia mediaFromDb = itemFromDb.getMedia();
assertEquals(position, mediaFromDb.getPosition()); assertEquals(position, mediaFromDb.getPosition());
assertEquals(lastPlayedTime, mediaFromDb.getLastPlayedTime()); assertEquals(lastPlayedTimeStatistics, mediaFromDb.getLastPlayedTimeStatistics());
assertEquals(lastPlayedTimeHistory, mediaFromDb.getLastPlayedTimeHistory());
assertEquals(playedDuration, mediaFromDb.getPlayedDuration()); assertEquals(playedDuration, mediaFromDb.getPlayedDuration());
assertEquals(duration, mediaFromDb.getDuration()); assertEquals(duration, mediaFromDb.getDuration());
} }
@ -467,12 +470,12 @@ public class DbWriterTest {
adapter.close(); adapter.close();
} }
private FeedMedia playbackHistorySetup(Date playbackCompletionDate) { private FeedMedia playbackHistorySetup(Date lastPlayedTimeHistory) {
Feed feed = new Feed("url", null, "title"); Feed feed = new Feed("url", null, "title");
feed.setItems(new ArrayList<>()); feed.setItems(new ArrayList<>());
FeedItem item = new FeedItem(0, "title", "id", "link", new Date(), FeedItem.PLAYED, feed); FeedItem item = new FeedItem(0, "title", "id", "link", new Date(), FeedItem.PLAYED, feed);
FeedMedia media = new FeedMedia(0, item, 10, 0, 1, "mime", null, FeedMedia media = new FeedMedia(0, item, 10, 0, 1, "mime", null,
"url", 0, playbackCompletionDate, 0, 0); "url", 0, lastPlayedTimeHistory, 0, 0);
feed.getItems().add(item); feed.getItems().add(item);
item.setMedia(media); item.setMedia(media);
PodDBAdapter adapter = PodDBAdapter.getInstance(); PodDBAdapter adapter = PodDBAdapter.getInstance();
@ -493,7 +496,7 @@ public class DbWriterTest {
adapter.close(); adapter.close();
assertNotNull(media); assertNotNull(media);
assertNotNull(media.getPlaybackCompletionDate()); assertNotNull(media.getLastPlayedTimeHistory());
} }
@Test @Test
@ -508,8 +511,8 @@ public class DbWriterTest {
adapter.close(); adapter.close();
assertNotNull(media); assertNotNull(media);
assertNotNull(media.getPlaybackCompletionDate()); assertNotNull(media.getLastPlayedTimeHistory());
assertNotEquals(media.getPlaybackCompletionDate().getTime(), oldDate); assertNotEquals(media.getLastPlayedTimeHistory().getTime(), oldDate);
} }
@SuppressWarnings("SameParameterValue") @SuppressWarnings("SameParameterValue")

View File

@ -19,12 +19,12 @@ public abstract class RewindAfterPauseUtils {
/** /**
* @param currentPosition current position in a media file in ms * @param currentPosition current position in a media file in ms
* @param lastPlayedTime timestamp when was media paused * @param lastPlayedTimeStatistics timestamp when was media paused
* @return new rewinded position for playback in milliseconds * @return new rewinded position for playback in milliseconds
*/ */
public static int calculatePositionWithRewind(int currentPosition, long lastPlayedTime) { public static int calculatePositionWithRewind(int currentPosition, long lastPlayedTimeStatistics) {
if (currentPosition > 0 && lastPlayedTime > 0) { if (currentPosition > 0 && lastPlayedTimeStatistics > 0) {
long elapsedTime = System.currentTimeMillis() - lastPlayedTime; long elapsedTime = System.currentTimeMillis() - lastPlayedTimeStatistics;
long rewindTime = 0; long rewindTime = 0;
if (elapsedTime > ELAPSED_TIME_FOR_LONG_REWIND) { if (elapsedTime > ELAPSED_TIME_FOR_LONG_REWIND) {

View File

@ -334,7 +334,7 @@ public class CastPsmp extends PlaybackServiceMediaPlayer {
public void resume() { public void resume() {
int newPosition = RewindAfterPauseUtils.calculatePositionWithRewind( int newPosition = RewindAfterPauseUtils.calculatePositionWithRewind(
media.getPosition(), media.getPosition(),
media.getLastPlayedTime()); media.getLastPlayedTimeStatistics());
seekTo(newPosition); seekTo(newPosition);
remoteMediaClient.play(); remoteMediaClient.play();
} }
@ -353,7 +353,7 @@ public class CastPsmp extends PlaybackServiceMediaPlayer {
if (position > 0) { if (position > 0) {
position = RewindAfterPauseUtils.calculatePositionWithRewind( position = RewindAfterPauseUtils.calculatePositionWithRewind(
position, position,
media.getLastPlayedTime()); media.getLastPlayedTimeStatistics());
} }
remoteMediaClient.load(new MediaLoadRequestData.Builder() remoteMediaClient.load(new MediaLoadRequestData.Builder()
.setMediaInfo(remoteMedia) .setMediaInfo(remoteMedia)

View File

@ -233,7 +233,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer {
if (playerStatus == PlayerStatus.PREPARED && media.getPosition() > 0) { if (playerStatus == PlayerStatus.PREPARED && media.getPosition() > 0) {
int newPosition = RewindAfterPauseUtils.calculatePositionWithRewind( int newPosition = RewindAfterPauseUtils.calculatePositionWithRewind(
media.getPosition(), media.getLastPlayedTime()); media.getPosition(), media.getLastPlayedTimeStatistics());
seekTo(newPosition); seekTo(newPosition);
} }
mediaPlayer.start(); mediaPlayer.start();

View File

@ -1,5 +1,7 @@
package de.danoeh.antennapod.playback.service.internal; package de.danoeh.antennapod.playback.service.internal;
import java.util.Date;
import de.danoeh.antennapod.storage.database.DBWriter; import de.danoeh.antennapod.storage.database.DBWriter;
import de.danoeh.antennapod.model.feed.FeedItem; import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedMedia; import de.danoeh.antennapod.model.feed.FeedMedia;
@ -17,10 +19,11 @@ public abstract class PlayableUtils {
*/ */
public static void saveCurrentPosition(Playable playable, int newPosition, long timestamp) { public static void saveCurrentPosition(Playable playable, int newPosition, long timestamp) {
playable.setPosition(newPosition); playable.setPosition(newPosition);
playable.setLastPlayedTime(timestamp); playable.setLastPlayedTimeStatistics(timestamp);
if (playable instanceof FeedMedia) { if (playable instanceof FeedMedia) {
FeedMedia media = (FeedMedia) playable; FeedMedia media = (FeedMedia) playable;
media.setLastPlayedTimeHistory(new Date(timestamp));
FeedItem item = media.getItem(); FeedItem item = media.getItem();
if (item != null && item.isNew()) { if (item != null && item.isNew()) {
DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.getId()); DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.getId());

View File

@ -45,7 +45,7 @@ class DBUpgrader {
} }
if (oldVersion <= 7) { if (oldVersion <= 7) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ " ADD COLUMN " + PodDBAdapter.KEY_PLAYBACK_COMPLETION_DATE + " ADD COLUMN " + PodDBAdapter.KEY_LAST_PLAYED_TIME_HISTORY
+ " INTEGER"); + " INTEGER");
} }
if (oldVersion <= 8) { if (oldVersion <= 8) {
@ -210,7 +210,7 @@ class DBUpgrader {
} }
if (oldVersion < 1040002) { if (oldVersion < 1040002) {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ " ADD COLUMN " + PodDBAdapter.KEY_LAST_PLAYED_TIME + " INTEGER DEFAULT 0"); + " ADD COLUMN " + PodDBAdapter.KEY_LAST_PLAYED_TIME_STATISTICS + " INTEGER DEFAULT 0");
} }
if (oldVersion < 1040013) { if (oldVersion < 1040013) {
db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_PUBDATE); db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_PUBDATE);

View File

@ -296,16 +296,16 @@ public class DBWriter {
* current date regardless of the current value. * current date regardless of the current value.
* *
* @param media FeedMedia that should be added to the playback history. * @param media FeedMedia that should be added to the playback history.
* @param date PlaybackCompletionDate for <code>media</code> * @param date LastPlayedTimeHistory for <code>media</code>
*/ */
public static Future<?> addItemToPlaybackHistory(final FeedMedia media, Date date) { public static Future<?> addItemToPlaybackHistory(final FeedMedia media, Date date) {
return runOnDbThread(() -> { return runOnDbThread(() -> {
Log.d(TAG, "Adding item to playback history"); Log.d(TAG, "Adding item to playback history");
media.setPlaybackCompletionDate(date); media.setLastPlayedTimeHistory(date);
PodDBAdapter adapter = PodDBAdapter.getInstance(); PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open(); adapter.open();
adapter.setFeedMediaPlaybackCompletionDate(media); adapter.setFeedMediaLastPlayedTimeHistory(media);
adapter.close(); adapter.close();
EventBus.getDefault().post(PlaybackHistoryEvent.listUpdated()); EventBus.getDefault().post(PlaybackHistoryEvent.listUpdated());

View File

@ -79,8 +79,8 @@ public class FeedItemPermutors {
comparator = (f1, f2) -> Long.compare(size(f2), size(f1)); comparator = (f1, f2) -> Long.compare(size(f2), size(f1));
break; break;
case COMPLETION_DATE_NEW_OLD: case COMPLETION_DATE_NEW_OLD:
comparator = (f1, f2) -> f2.getMedia().getPlaybackCompletionDate() comparator = (f1, f2) -> f2.getMedia().getLastPlayedTimeHistory()
.compareTo(f1.getMedia().getPlaybackCompletionDate()); .compareTo(f1.getMedia().getLastPlayedTimeHistory());
break; break;
default: default:
throw new IllegalArgumentException("Permutor not implemented"); throw new IllegalArgumentException("Permutor not implemented");

View File

@ -95,7 +95,6 @@ public class PodDBAdapter {
public static final String KEY_FEED_IDENTIFIER = "feed_identifier"; public static final String KEY_FEED_IDENTIFIER = "feed_identifier";
public static final String KEY_REASON_DETAILED = "reason_detailed"; public static final String KEY_REASON_DETAILED = "reason_detailed";
public static final String KEY_DOWNLOADSTATUS_TITLE = "title"; public static final String KEY_DOWNLOADSTATUS_TITLE = "title";
public static final String KEY_PLAYBACK_COMPLETION_DATE = "playback_completion_date";
public static final String KEY_AUTO_DOWNLOAD_ENABLED = "auto_download"; // Both tables use the same key public static final String KEY_AUTO_DOWNLOAD_ENABLED = "auto_download"; // Both tables use the same key
public static final String KEY_KEEP_UPDATED = "keep_updated"; public static final String KEY_KEEP_UPDATED = "keep_updated";
public static final String KEY_AUTO_DELETE_ACTION = "auto_delete_action"; public static final String KEY_AUTO_DELETE_ACTION = "auto_delete_action";
@ -109,7 +108,8 @@ public class PodDBAdapter {
public static final String KEY_SORT_ORDER = "sort_order"; public static final String KEY_SORT_ORDER = "sort_order";
public static final String KEY_LAST_UPDATE_FAILED = "last_update_failed"; public static final String KEY_LAST_UPDATE_FAILED = "last_update_failed";
public static final String KEY_HAS_EMBEDDED_PICTURE = "has_embedded_picture"; public static final String KEY_HAS_EMBEDDED_PICTURE = "has_embedded_picture";
public static final String KEY_LAST_PLAYED_TIME = "last_played_time"; public static final String KEY_LAST_PLAYED_TIME_HISTORY = "playback_completion_date";
public static final String KEY_LAST_PLAYED_TIME_STATISTICS = "last_played_time";
public static final String KEY_INCLUDE_FILTER = "include_filter"; public static final String KEY_INCLUDE_FILTER = "include_filter";
public static final String KEY_EXCLUDE_FILTER = "exclude_filter"; public static final String KEY_EXCLUDE_FILTER = "exclude_filter";
public static final String KEY_MINIMAL_DURATION_FILTER = "minimal_duration_filter"; public static final String KEY_MINIMAL_DURATION_FILTER = "minimal_duration_filter";
@ -197,11 +197,11 @@ public class PodDBAdapter {
+ " INTEGER," + KEY_FILE_URL + " TEXT," + KEY_DOWNLOAD_URL + " INTEGER," + KEY_FILE_URL + " TEXT," + KEY_DOWNLOAD_URL
+ " TEXT," + KEY_DOWNLOAD_DATE + " INTEGER," + KEY_POSITION + " TEXT," + KEY_DOWNLOAD_DATE + " INTEGER," + KEY_POSITION
+ " INTEGER," + KEY_SIZE + " INTEGER," + KEY_MIME_TYPE + " TEXT," + " INTEGER," + KEY_SIZE + " INTEGER," + KEY_MIME_TYPE + " TEXT,"
+ KEY_PLAYBACK_COMPLETION_DATE + " INTEGER," + KEY_LAST_PLAYED_TIME_HISTORY + " INTEGER,"
+ KEY_FEEDITEM + " INTEGER," + KEY_FEEDITEM + " INTEGER,"
+ KEY_PLAYED_DURATION + " INTEGER," + KEY_PLAYED_DURATION + " INTEGER,"
+ KEY_HAS_EMBEDDED_PICTURE + " INTEGER," + KEY_HAS_EMBEDDED_PICTURE + " INTEGER,"
+ KEY_LAST_PLAYED_TIME + " INTEGER" + ")"; + KEY_LAST_PLAYED_TIME_STATISTICS + " INTEGER" + ")";
private static final String CREATE_TABLE_DOWNLOAD_LOG = "CREATE TABLE " private static final String CREATE_TABLE_DOWNLOAD_LOG = "CREATE TABLE "
+ TABLE_NAME_DOWNLOAD_LOG + " (" + TABLE_PRIMARY_KEY + KEY_FEEDFILE + TABLE_NAME_DOWNLOAD_LOG + " (" + TABLE_PRIMARY_KEY + KEY_FEEDFILE
@ -292,11 +292,11 @@ public class PodDBAdapter {
+ TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + ", " + TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + ", "
+ TABLE_NAME_FEED_MEDIA + "." + KEY_SIZE + ", " + TABLE_NAME_FEED_MEDIA + "." + KEY_SIZE + ", "
+ TABLE_NAME_FEED_MEDIA + "." + KEY_MIME_TYPE + ", " + TABLE_NAME_FEED_MEDIA + "." + KEY_MIME_TYPE + ", "
+ TABLE_NAME_FEED_MEDIA + "." + KEY_PLAYBACK_COMPLETION_DATE + ", " + TABLE_NAME_FEED_MEDIA + "." + KEY_LAST_PLAYED_TIME_HISTORY + ", "
+ TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM + ", " + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM + ", "
+ TABLE_NAME_FEED_MEDIA + "." + KEY_PLAYED_DURATION + ", " + TABLE_NAME_FEED_MEDIA + "." + KEY_PLAYED_DURATION + ", "
+ TABLE_NAME_FEED_MEDIA + "." + KEY_HAS_EMBEDDED_PICTURE + ", " + TABLE_NAME_FEED_MEDIA + "." + KEY_HAS_EMBEDDED_PICTURE + ", "
+ TABLE_NAME_FEED_MEDIA + "." + KEY_LAST_PLAYED_TIME; + TABLE_NAME_FEED_MEDIA + "." + KEY_LAST_PLAYED_TIME_STATISTICS;
private static final String KEYS_FEED = private static final String KEYS_FEED =
TABLE_NAME_FEEDS + "." + KEY_ID + " AS " + SELECT_KEY_FEED_ID + ", " TABLE_NAME_FEEDS + "." + KEY_ID + " AS " + SELECT_KEY_FEED_ID + ", "
@ -523,12 +523,12 @@ public class PodDBAdapter {
values.put(KEY_DOWNLOAD_DATE, media.getDownloadDate()); values.put(KEY_DOWNLOAD_DATE, media.getDownloadDate());
values.put(KEY_FILE_URL, media.getLocalFileUrl()); values.put(KEY_FILE_URL, media.getLocalFileUrl());
values.put(KEY_HAS_EMBEDDED_PICTURE, media.hasEmbeddedPicture()); values.put(KEY_HAS_EMBEDDED_PICTURE, media.hasEmbeddedPicture());
values.put(KEY_LAST_PLAYED_TIME, media.getLastPlayedTime()); values.put(KEY_LAST_PLAYED_TIME_STATISTICS, media.getLastPlayedTimeStatistics());
if (media.getPlaybackCompletionDate() != null) { if (media.getLastPlayedTimeHistory() != null) {
values.put(KEY_PLAYBACK_COMPLETION_DATE, media.getPlaybackCompletionDate().getTime()); values.put(KEY_LAST_PLAYED_TIME_HISTORY, media.getLastPlayedTimeHistory().getTime());
} else { } else {
values.put(KEY_PLAYBACK_COMPLETION_DATE, 0); values.put(KEY_LAST_PLAYED_TIME_HISTORY, 0);
} }
if (media.getItem() != null) { if (media.getItem() != null) {
values.put(KEY_FEEDITEM, media.getItem().getId()); values.put(KEY_FEEDITEM, media.getItem().getId());
@ -548,7 +548,8 @@ public class PodDBAdapter {
values.put(KEY_POSITION, media.getPosition()); values.put(KEY_POSITION, media.getPosition());
values.put(KEY_DURATION, media.getDuration()); values.put(KEY_DURATION, media.getDuration());
values.put(KEY_PLAYED_DURATION, media.getPlayedDuration()); values.put(KEY_PLAYED_DURATION, media.getPlayedDuration());
values.put(KEY_LAST_PLAYED_TIME, media.getLastPlayedTime()); values.put(KEY_LAST_PLAYED_TIME_STATISTICS, media.getLastPlayedTimeStatistics());
values.put(KEY_LAST_PLAYED_TIME_HISTORY, media.getLastPlayedTimeHistory().getTime());
db.update(TABLE_NAME_FEED_MEDIA, values, KEY_ID + "=?", db.update(TABLE_NAME_FEED_MEDIA, values, KEY_ID + "=?",
new String[]{String.valueOf(media.getId())}); new String[]{String.valueOf(media.getId())});
} else { } else {
@ -556,15 +557,15 @@ public class PodDBAdapter {
} }
} }
public void setFeedMediaPlaybackCompletionDate(FeedMedia media) { public void setFeedMediaLastPlayedTimeHistory(FeedMedia media) {
if (media.getId() != 0) { if (media.getId() != 0) {
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put(KEY_PLAYBACK_COMPLETION_DATE, media.getPlaybackCompletionDate().getTime()); values.put(KEY_LAST_PLAYED_TIME_HISTORY, media.getLastPlayedTimeHistory().getTime());
values.put(KEY_PLAYED_DURATION, media.getPlayedDuration()); values.put(KEY_PLAYED_DURATION, media.getPlayedDuration());
db.update(TABLE_NAME_FEED_MEDIA, values, KEY_ID + "=?", db.update(TABLE_NAME_FEED_MEDIA, values, KEY_ID + "=?",
new String[]{String.valueOf(media.getId())}); new String[]{String.valueOf(media.getId())});
} else { } else {
Log.e(TAG, "setFeedMediaPlaybackCompletionDate: ID of media was 0"); Log.e(TAG, "setFeedMediaLastPlayedTimeHistory: ID of media was 0");
} }
} }
@ -954,7 +955,7 @@ public class PodDBAdapter {
public void clearPlaybackHistory() { public void clearPlaybackHistory() {
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put(KEY_PLAYBACK_COMPLETION_DATE, 0); values.put(KEY_LAST_PLAYED_TIME_HISTORY, 0);
db.update(TABLE_NAME_FEED_MEDIA, values, null, null); db.update(TABLE_NAME_FEED_MEDIA, values, null, null);
} }
@ -1061,7 +1062,7 @@ public class PodDBAdapter {
public final Cursor getPausedQueueCursor(int limit) { public final Cursor getPausedQueueCursor(int limit) {
final String hasPositionOrRecentlyPlayed = TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + " >= 1000" final String hasPositionOrRecentlyPlayed = TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + " >= 1000"
+ " OR " + TABLE_NAME_FEED_MEDIA + "." + KEY_LAST_PLAYED_TIME + " OR " + TABLE_NAME_FEED_MEDIA + "." + KEY_LAST_PLAYED_TIME_STATISTICS
+ " >= " + (System.currentTimeMillis() - 30000); + " >= " + (System.currentTimeMillis() - 30000);
final String query = "SELECT " + KEYS_FEED_ITEM_WITHOUT_DESCRIPTION + ", " + KEYS_FEED_MEDIA final String query = "SELECT " + KEYS_FEED_ITEM_WITHOUT_DESCRIPTION + ", " + KEYS_FEED_MEDIA
+ " FROM " + TABLE_NAME_QUEUE + " FROM " + TABLE_NAME_QUEUE
@ -1069,7 +1070,7 @@ public class PodDBAdapter {
+ " ON " + SELECT_KEY_ITEM_ID + " = " + TABLE_NAME_QUEUE + "." + KEY_FEEDITEM + " ON " + SELECT_KEY_ITEM_ID + " = " + TABLE_NAME_QUEUE + "." + KEY_FEEDITEM
+ JOIN_FEED_ITEM_AND_MEDIA + JOIN_FEED_ITEM_AND_MEDIA
+ " ORDER BY (CASE WHEN " + hasPositionOrRecentlyPlayed + " THEN " + " ORDER BY (CASE WHEN " + hasPositionOrRecentlyPlayed + " THEN "
+ TABLE_NAME_FEED_MEDIA + "." + KEY_LAST_PLAYED_TIME + " ELSE 0 END) DESC , " + TABLE_NAME_FEED_MEDIA + "." + KEY_LAST_PLAYED_TIME_STATISTICS + " ELSE 0 END) DESC , "
+ TABLE_NAME_QUEUE + "." + KEY_ID + TABLE_NAME_QUEUE + "." + KEY_ID
+ " LIMIT " + limit; + " LIMIT " + limit;
return db.rawQuery(query, null); return db.rawQuery(query, null);
@ -1124,13 +1125,14 @@ public class PodDBAdapter {
} }
public Cursor getRandomEpisodesCursor(int limit, int seed) { public Cursor getRandomEpisodesCursor(int limit, int seed) {
long oneHourAgo = System.currentTimeMillis() - 1000L * 3600L;
final String allItems = SELECT_FEED_ITEMS_AND_MEDIA final String allItems = SELECT_FEED_ITEMS_AND_MEDIA
+ " WHERE (" + KEY_READ + " = " + FeedItem.NEW + " OR " + KEY_READ + " = " + FeedItem.UNPLAYED + ") " + " WHERE (" + KEY_READ + " = " + FeedItem.NEW + " OR " + KEY_READ + " = " + FeedItem.UNPLAYED + ") "
// Only from the last two years. Older episodes often contain broken covers and stuff like that // Only from the last two years. Older episodes often contain broken covers and stuff like that
+ " AND " + KEY_PUBDATE + " > " + (System.currentTimeMillis() - 1000L * 3600L * 24L * 356L * 2) + " AND " + KEY_PUBDATE + " > " + (System.currentTimeMillis() - 1000L * 3600L * 24L * 356L * 2)
// Hide episodes that have been played but not completed // Hide episodes that have been played but not completed
+ " AND (" + KEY_LAST_PLAYED_TIME + " == 0" + " AND (" + KEY_LAST_PLAYED_TIME_STATISTICS + " == 0"
+ " OR " + KEY_LAST_PLAYED_TIME + " > " + (System.currentTimeMillis() - 1000L * 3600L) + ")" + " OR " + KEY_LAST_PLAYED_TIME_STATISTICS + " > " + oneHourAgo + ")"
+ " AND " + SELECT_WHERE_FEED_IS_SUBSCRIBED; + " AND " + SELECT_WHERE_FEED_IS_SUBSCRIBED;
final String query = "SELECT MAX(" + randomEpisodeNumber(seed) + "), * FROM (" + allItems + ")" final String query = "SELECT MAX(" + randomEpisodeNumber(seed) + "), * FROM (" + allItems + ")"
+ " GROUP BY " + KEY_FEED + " GROUP BY " + KEY_FEED
@ -1184,7 +1186,7 @@ public class PodDBAdapter {
} }
final String query = SELECT_FEED_ITEMS_AND_MEDIA final String query = SELECT_FEED_ITEMS_AND_MEDIA
+ " WHERE " + KEY_DOWNLOAD_URL + " IN (" + urlsString + ")" + " WHERE " + KEY_DOWNLOAD_URL + " IN (" + urlsString + ")"
+ " ORDER BY " + KEY_PLAYBACK_COMPLETION_DATE + " DESC"; + " ORDER BY " + KEY_LAST_PLAYED_TIME_HISTORY + " DESC";
return db.rawQuery(query, null); return db.rawQuery(query, null);
} }
@ -1206,10 +1208,10 @@ public class PodDBAdapter {
public final Cursor getMonthlyStatisticsCursor() { public final Cursor getMonthlyStatisticsCursor() {
final String query = "SELECT SUM(" + KEY_PLAYED_DURATION + ") AS total_duration" final String query = "SELECT SUM(" + KEY_PLAYED_DURATION + ") AS total_duration"
+ ", strftime('%m', datetime(" + KEY_LAST_PLAYED_TIME + "/1000, 'unixepoch')) AS month" + ", strftime('%m', datetime(" + KEY_LAST_PLAYED_TIME_STATISTICS + "/1000, 'unixepoch')) AS month"
+ ", strftime('%Y', datetime(" + KEY_LAST_PLAYED_TIME + "/1000, 'unixepoch')) AS year" + ", strftime('%Y', datetime(" + KEY_LAST_PLAYED_TIME_STATISTICS + "/1000, 'unixepoch')) AS year"
+ " FROM " + TABLE_NAME_FEED_MEDIA + " FROM " + TABLE_NAME_FEED_MEDIA
+ " WHERE " + KEY_LAST_PLAYED_TIME + " > 0 AND " + KEY_PLAYED_DURATION + " > 0" + " WHERE " + KEY_LAST_PLAYED_TIME_STATISTICS + " > 0 AND " + KEY_PLAYED_DURATION + " > 0"
+ " GROUP BY year, month" + " GROUP BY year, month"
+ " ORDER BY year, month"; + " ORDER BY year, month";
return db.rawQuery(query, null); return db.rawQuery(query, null);
@ -1217,16 +1219,16 @@ public class PodDBAdapter {
public final Cursor getFeedStatisticsCursor(boolean includeMarkedAsPlayed, long timeFilterFrom, public final Cursor getFeedStatisticsCursor(boolean includeMarkedAsPlayed, long timeFilterFrom,
long timeFilterTo, long sixMonthsAgo) { long timeFilterTo, long sixMonthsAgo) {
final String lastPlayedTime = TABLE_NAME_FEED_MEDIA + "." + KEY_LAST_PLAYED_TIME; final String lastPlayedTimeStatistics = TABLE_NAME_FEED_MEDIA + "." + KEY_LAST_PLAYED_TIME_STATISTICS;
String wasStarted = TABLE_NAME_FEED_MEDIA + "." + KEY_PLAYBACK_COMPLETION_DATE + " > 0" String wasStarted = TABLE_NAME_FEED_MEDIA + "." + KEY_LAST_PLAYED_TIME_HISTORY + " > 0"
+ " AND " + TABLE_NAME_FEED_MEDIA + "." + KEY_PLAYED_DURATION + " > 0"; + " AND " + TABLE_NAME_FEED_MEDIA + "." + KEY_PLAYED_DURATION + " > 0";
if (includeMarkedAsPlayed) { if (includeMarkedAsPlayed) {
wasStarted = "(" + wasStarted + ") OR " wasStarted = "(" + wasStarted + ") OR "
+ TABLE_NAME_FEED_ITEMS + "." + KEY_READ + "=" + FeedItem.PLAYED + " OR " + TABLE_NAME_FEED_ITEMS + "." + KEY_READ + "=" + FeedItem.PLAYED + " OR "
+ TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + "> 0"; + TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + "> 0";
} }
final String timeFilter = lastPlayedTime + ">=" + timeFilterFrom final String timeFilter = lastPlayedTimeStatistics + ">=" + timeFilterFrom
+ " AND " + lastPlayedTime + "<" + timeFilterTo; + " AND " + lastPlayedTimeStatistics + "<" + timeFilterTo;
String playedTime = TABLE_NAME_FEED_MEDIA + "." + KEY_PLAYED_DURATION; String playedTime = TABLE_NAME_FEED_MEDIA + "." + KEY_PLAYED_DURATION;
if (includeMarkedAsPlayed) { if (includeMarkedAsPlayed) {
playedTime = "(CASE WHEN " + playedTime + " != 0" playedTime = "(CASE WHEN " + playedTime + " != 0"
@ -1238,8 +1240,9 @@ public class PodDBAdapter {
final String query = "SELECT " + KEYS_FEED + ", " final String query = "SELECT " + KEYS_FEED + ", "
+ "COUNT(*) AS num_episodes, " + "COUNT(*) AS num_episodes, "
+ "MIN(CASE WHEN " + lastPlayedTime + " > 0" + "MIN(CASE WHEN " + lastPlayedTimeStatistics + " > 0"
+ " THEN " + lastPlayedTime + " ELSE " + Long.MAX_VALUE + " END) AS oldest_date, " + " THEN " + lastPlayedTimeStatistics
+ " ELSE " + Long.MAX_VALUE + " END) AS oldest_date, "
+ "SUM(CASE WHEN (" + wasStarted + ") THEN 1 ELSE 0 END) AS episodes_started, " + "SUM(CASE WHEN (" + wasStarted + ") THEN 1 ELSE 0 END) AS episodes_started, "
+ "IFNULL(SUM(CASE WHEN (" + timeFilter + ")" + "IFNULL(SUM(CASE WHEN (" + timeFilter + ")"
+ " THEN (" + playedTime + ") ELSE 0 END), 0) AS played_time, " + " THEN (" + playedTime + ") ELSE 0 END), 0) AS played_time, "
@ -1263,10 +1266,10 @@ public class PodDBAdapter {
public final Cursor getTimeBetweenReleaseAndPlayback(long timeFilterFrom, long timeFilterTo) { public final Cursor getTimeBetweenReleaseAndPlayback(long timeFilterFrom, long timeFilterTo) {
final String from = " FROM " + TABLE_NAME_FEED_ITEMS final String from = " FROM " + TABLE_NAME_FEED_ITEMS
+ JOIN_FEED_ITEM_AND_MEDIA + JOIN_FEED_ITEM_AND_MEDIA
+ " WHERE " + TABLE_NAME_FEED_MEDIA + "." + KEY_LAST_PLAYED_TIME + ">=" + timeFilterFrom + " WHERE " + TABLE_NAME_FEED_MEDIA + "." + KEY_LAST_PLAYED_TIME_STATISTICS + ">=" + timeFilterFrom
+ " AND " + TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE + ">=" + timeFilterFrom + " AND " + TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE + ">=" + timeFilterFrom
+ " AND " + TABLE_NAME_FEED_MEDIA + "." + KEY_LAST_PLAYED_TIME + "<" + timeFilterTo; + " AND " + TABLE_NAME_FEED_MEDIA + "." + KEY_LAST_PLAYED_TIME_STATISTICS + "<" + timeFilterTo;
final String query = "SELECT " + TABLE_NAME_FEED_MEDIA + "." + KEY_LAST_PLAYED_TIME final String query = "SELECT " + TABLE_NAME_FEED_MEDIA + "." + KEY_LAST_PLAYED_TIME_STATISTICS
+ " - " + TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE + " AS diff" + " - " + TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE + " AS diff"
+ from + from
+ " ORDER BY diff ASC" + " ORDER BY diff ASC"

View File

@ -22,7 +22,7 @@ public class FeedItemFilterQuery {
// The keys used within this method, but explicitly combined with their table // The keys used within this method, but explicitly combined with their table
String keyRead = PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_READ; String keyRead = PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_READ;
String keyPosition = PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + PodDBAdapter.KEY_POSITION; String keyPosition = PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + PodDBAdapter.KEY_POSITION;
String keyCompletionDate = PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + PodDBAdapter.KEY_PLAYBACK_COMPLETION_DATE; String keyCompletionDate = PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + PodDBAdapter.KEY_LAST_PLAYED_TIME_HISTORY;
String keyDownloaded = PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + PodDBAdapter.KEY_DOWNLOAD_DATE; String keyDownloaded = PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + PodDBAdapter.KEY_DOWNLOAD_DATE;
String keyMediaId = PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + PodDBAdapter.KEY_ID; String keyMediaId = PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + PodDBAdapter.KEY_ID;
String keyItemId = PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_ID; String keyItemId = PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_ID;

View File

@ -23,7 +23,7 @@ public class FeedItemSortQuery {
return PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + PodDBAdapter.KEY_SIZE + " " + "DESC"; return PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + PodDBAdapter.KEY_SIZE + " " + "DESC";
case COMPLETION_DATE_NEW_OLD: case COMPLETION_DATE_NEW_OLD:
return PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." return PodDBAdapter.TABLE_NAME_FEED_MEDIA + "."
+ PodDBAdapter.KEY_PLAYBACK_COMPLETION_DATE + " " + "DESC"; + PodDBAdapter.KEY_LAST_PLAYED_TIME_HISTORY + " " + "DESC";
case DATE_OLD_NEW: case DATE_OLD_NEW:
return PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_PUBDATE + " " + "ASC"; return PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_PUBDATE + " " + "ASC";
case EPISODE_FILENAME_A_Z: case EPISODE_FILENAME_A_Z:

View File

@ -13,7 +13,7 @@ import java.util.Date;
*/ */
public class FeedMediaCursor extends CursorWrapper { public class FeedMediaCursor extends CursorWrapper {
private final int indexId; private final int indexId;
private final int indexPlaybackCompletionDate; private final int indexLastPlayedTimeHistory;
private final int indexDuration; private final int indexDuration;
private final int indexPosition; private final int indexPosition;
private final int indexSize; private final int indexSize;
@ -22,13 +22,13 @@ public class FeedMediaCursor extends CursorWrapper {
private final int indexDownloadUrl; private final int indexDownloadUrl;
private final int indexDownloadDate; private final int indexDownloadDate;
private final int indexPlayedDuration; private final int indexPlayedDuration;
private final int indexLastPlayedTime; private final int indexLastPlayedTimeStatistics;
private final int indexHasEmbeddedPicture; private final int indexHasEmbeddedPicture;
public FeedMediaCursor(Cursor cursor) { public FeedMediaCursor(Cursor cursor) {
super(cursor); super(cursor);
indexId = cursor.getColumnIndexOrThrow(PodDBAdapter.SELECT_KEY_MEDIA_ID); indexId = cursor.getColumnIndexOrThrow(PodDBAdapter.SELECT_KEY_MEDIA_ID);
indexPlaybackCompletionDate = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_PLAYBACK_COMPLETION_DATE); indexLastPlayedTimeHistory = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_LAST_PLAYED_TIME_HISTORY);
indexDuration = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_DURATION); indexDuration = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_DURATION);
indexPosition = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_POSITION); indexPosition = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_POSITION);
indexSize = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_SIZE); indexSize = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_SIZE);
@ -37,7 +37,7 @@ public class FeedMediaCursor extends CursorWrapper {
indexDownloadUrl = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_DOWNLOAD_URL); indexDownloadUrl = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_DOWNLOAD_URL);
indexDownloadDate = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_DOWNLOAD_DATE); indexDownloadDate = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_DOWNLOAD_DATE);
indexPlayedDuration = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_PLAYED_DURATION); indexPlayedDuration = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_PLAYED_DURATION);
indexLastPlayedTime = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_LAST_PLAYED_TIME); indexLastPlayedTimeStatistics = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_LAST_PLAYED_TIME_STATISTICS);
indexHasEmbeddedPicture = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE); indexHasEmbeddedPicture = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE);
} }
@ -46,8 +46,8 @@ public class FeedMediaCursor extends CursorWrapper {
*/ */
@NonNull @NonNull
public FeedMedia getFeedMedia() { public FeedMedia getFeedMedia() {
long playbackCompletionTime = getLong(indexPlaybackCompletionDate); long lastPlayedTimeHistoryTime = getLong(indexLastPlayedTimeHistory);
Date playbackCompletionDate = playbackCompletionTime > 0 ? new Date(playbackCompletionTime) : null; Date lastPlayedTimeHistory = lastPlayedTimeHistoryTime > 0 ? new Date(lastPlayedTimeHistoryTime) : null;
Boolean hasEmbeddedPicture; Boolean hasEmbeddedPicture;
switch (getInt(indexHasEmbeddedPicture)) { switch (getInt(indexHasEmbeddedPicture)) {
@ -72,10 +72,10 @@ public class FeedMediaCursor extends CursorWrapper {
getString(indexFileUrl), getString(indexFileUrl),
getString(indexDownloadUrl), getString(indexDownloadUrl),
getLong(indexDownloadDate), getLong(indexDownloadDate),
playbackCompletionDate, lastPlayedTimeHistory,
getInt(indexPlayedDuration), getInt(indexPlayedDuration),
hasEmbeddedPicture, hasEmbeddedPicture,
getLong(indexLastPlayedTime) getLong(indexLastPlayedTimeStatistics)
); );
} }
} }