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
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 123 additions and 114 deletions

View File

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

View File

@ -38,10 +38,10 @@ public class RemoveFromHistorySwipeAction implements SwipeAction {
@Override
public void performAction(FeedItem item, Fragment fragment, FeedItemFilter filter) {
Date playbackCompletionDate = item.getMedia().getPlaybackCompletionDate();
Date lastPlayedTimeHistory = item.getMedia().getLastPlayedTimeHistory();
DBWriter.deleteFromPlaybackHistory(item);
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)));
}

View File

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

View File

@ -38,12 +38,12 @@ public class FeedMedia implements Playable {
private long downloadDate;
private int duration;
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 long size; // File size in Byte
private String mimeType;
@Nullable private volatile FeedItem item;
private Date playbackCompletionDate;
private Date lastPlayedTimeHistory;
private int startPosition = -1;
private int playedDurationWhenStarted;
@ -66,8 +66,8 @@ public class FeedMedia implements Playable {
public FeedMedia(long id, FeedItem item, int duration, int position,
long size, String mimeType, String localFileUrl, String downloadUrl,
long downloadDate, Date playbackCompletionDate, int playedDuration,
long lastPlayedTime) {
long downloadDate, Date lastPlayedTimeHistory, int playedDuration,
long lastPlayedTimeStatistics) {
this.localFileUrl = localFileUrl;
this.downloadUrl = downloadUrl;
this.downloadDate = downloadDate;
@ -80,17 +80,17 @@ public class FeedMedia implements Playable {
this.playedDurationWhenStarted = playedDuration;
this.size = size;
this.mimeType = mimeType;
this.playbackCompletionDate = playbackCompletionDate == null
? null : (Date) playbackCompletionDate.clone();
this.lastPlayedTime = lastPlayedTime;
this.lastPlayedTimeHistory = lastPlayedTimeHistory == null
? null : (Date) lastPlayedTimeHistory.clone();
this.lastPlayedTimeStatistics = lastPlayedTimeStatistics;
}
public FeedMedia(long id, FeedItem item, int duration, int position,
long size, String mimeType, String localFileUrl, String downloadUrl,
long downloadDate, Date playbackCompletionDate, int playedDuration,
Boolean hasEmbeddedPicture, long lastPlayedTime) {
long downloadDate, Date lastPlayedTimeHistory, int playedDuration,
Boolean hasEmbeddedPicture, long lastPlayedTimeStatistics) {
this(id, item, duration, position, size, mimeType, localFileUrl, downloadUrl, downloadDate,
playbackCompletionDate, playedDuration, lastPlayedTime);
lastPlayedTimeHistory, playedDuration, lastPlayedTimeStatistics);
this.hasEmbeddedPicture = hasEmbeddedPicture;
}
@ -178,8 +178,8 @@ public class FeedMedia implements Playable {
}
@Override
public void setLastPlayedTime(long lastPlayedTime) {
this.lastPlayedTime = lastPlayedTime;
public void setLastPlayedTimeStatistics(long lastPlayedTimeStatistics) {
this.lastPlayedTimeStatistics = lastPlayedTimeStatistics;
}
public int getPlayedDuration() {
@ -199,8 +199,8 @@ public class FeedMedia implements Playable {
}
@Override
public long getLastPlayedTime() {
return lastPlayedTime;
public long getLastPlayedTimeStatistics() {
return lastPlayedTimeStatistics;
}
public void setPosition(int position) {
@ -260,14 +260,14 @@ public class FeedMedia implements Playable {
}
}
public Date getPlaybackCompletionDate() {
return playbackCompletionDate == null
? null : (Date) playbackCompletionDate.clone();
public Date getLastPlayedTimeHistory() {
return lastPlayedTimeHistory == null
? null : (Date) lastPlayedTimeHistory.clone();
}
public void setPlaybackCompletionDate(Date playbackCompletionDate) {
this.playbackCompletionDate = playbackCompletionDate == null
? null : (Date) playbackCompletionDate.clone();
public void setLastPlayedTimeHistory(Date lastPlayedTimeHistory) {
this.lastPlayedTimeHistory = lastPlayedTimeHistory == null
? null : (Date) lastPlayedTimeHistory.clone();
}
public boolean isInProgress() {
@ -298,9 +298,9 @@ public class FeedMedia implements Playable {
dest.writeString(localFileUrl);
dest.writeString(downloadUrl);
dest.writeLong(downloadDate);
dest.writeLong((playbackCompletionDate != null) ? playbackCompletionDate.getTime() : 0);
dest.writeLong((lastPlayedTimeHistory != null) ? lastPlayedTimeHistory.getTime() : 0);
dest.writeInt(playedDuration);
dest.writeLong(lastPlayedTime);
dest.writeLong(lastPlayedTimeStatistics);
}
@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
* if last played time is unknown.
*/
long getLastPlayedTime();
long getLastPlayedTimeStatistics();
/**
* Returns the description of the item, if available.
@ -100,7 +100,7 @@ public interface Playable extends Parcelable, Serializable {
/**
* @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.

View File

@ -40,7 +40,7 @@ public class RemoteMedia implements Playable {
private List<Chapter> chapters;
private int duration;
private int position;
private long lastPlayedTime;
private long lastPlayedTimeStatistics;
public RemoteMedia(String downloadUrl, String itemId, String feedUrl, String feedTitle,
String episodeTitle, String episodeLink, String feedAuthor,
@ -159,8 +159,8 @@ public class RemoteMedia implements Playable {
}
@Override
public long getLastPlayedTime() {
return lastPlayedTime;
public long getLastPlayedTimeStatistics() {
return lastPlayedTimeStatistics;
}
@Override
@ -194,8 +194,8 @@ public class RemoteMedia implements Playable {
}
@Override
public void setLastPlayedTime(long lastPlayedTimestamp) {
lastPlayedTime = lastPlayedTimestamp;
public void setLastPlayedTimeStatistics(long lastPlayedTimestamp) {
lastPlayedTimeStatistics = lastPlayedTimestamp;
}
@Override
@ -255,7 +255,7 @@ public class RemoteMedia implements Playable {
dest.writeString(notes);
dest.writeInt(duration);
dest.writeInt(position);
dest.writeLong(lastPlayedTime);
dest.writeLong(lastPlayedTimeStatistics);
}
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());
result.setDuration(in.readInt());
result.setPosition(in.readInt());
result.setLastPlayedTime(in.readLong());
result.setLastPlayedTimeStatistics(in.readLong());
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
* 'playbackCompletionDate'-value will be deleted first.
* 'lastPlayedTimeHistory'-value will be deleted first.
* <p/>
* This method should NOT be executed on the GUI thread.
*

View File

@ -47,8 +47,8 @@ public class APCleanupAlgorithm extends EpisodeCleanupAlgorithm {
List<FeedItem> delete;
Collections.sort(candidates, (lhs, rhs) -> {
Date l = lhs.getMedia().getPlaybackCompletionDate();
Date r = rhs.getMedia().getPlaybackCompletionDate();
Date l = lhs.getMedia().getLastPlayedTimeHistory();
Date r = rhs.getMedia().getLastPlayedTimeHistory();
if (l == null) {
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
// to now
if (media != null
&& media.getPlaybackCompletionDate() != null
&& media.getPlaybackCompletionDate().before(mostRecentDateForDeletion)) {
&& media.getLastPlayedTimeHistory() != null
&& media.getLastPlayedTimeHistory().before(mostRecentDateForDeletion)) {
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
* 'playbackCompletionDate'-value will be deleted first.
* 'lastPlayedTimeHistory'-value will be deleted first.
* <p/>
* This method should NOT be executed on the GUI thread.
*

View File

@ -130,9 +130,9 @@ public class DbCleanupTests {
boolean addToFavorites) throws IOException {
for (int i = 0; i < numItems; i++) {
Date itemDate = new Date(numItems - i);
Date playbackCompletionDate = null;
Date lastPlayedTimeHistory = null;
if (itemState == FeedItem.PLAYED) {
playbackCompletionDate = itemDate;
lastPlayedTimeHistory = itemDate;
}
FeedItem item = new FeedItem(0, "title", "id" + i, "link", itemDate, itemState, feed);
@ -140,7 +140,7 @@ public class DbCleanupTests {
assertTrue(f.createNewFile());
files.add(f);
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);
}

View File

@ -324,9 +324,9 @@ public class DbReaderTest {
adapter.open();
for (int i = 0; i < playedItems; ++i) {
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();
@ -506,8 +506,8 @@ public class DbReaderTest {
adapter.open();
for (int i = 0; i < playedItems; i++) {
FeedMedia m = feed.getItems().get(i).getMedia();
m.setPlaybackCompletionDate(new Date(i + 1));
adapter.setFeedMediaPlaybackCompletionDate(m);
m.setLastPlayedTimeHistory(new Date(i + 1));
adapter.setFeedMediaLastPlayedTimeHistory(m);
ids[ids.length - 1 - i] = m.getItem().getId();
}
adapter.close();
@ -520,7 +520,7 @@ public class DbReaderTest {
numReturnedItems, saved.size());
for (int i = 0; i < numReturnedItems; 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: ",
paramOffset, paramLimit),
item.getId(), ids[paramOffset + i]);

View File

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

View File

@ -19,12 +19,12 @@ public abstract class RewindAfterPauseUtils {
/**
* @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
*/
public static int calculatePositionWithRewind(int currentPosition, long lastPlayedTime) {
if (currentPosition > 0 && lastPlayedTime > 0) {
long elapsedTime = System.currentTimeMillis() - lastPlayedTime;
public static int calculatePositionWithRewind(int currentPosition, long lastPlayedTimeStatistics) {
if (currentPosition > 0 && lastPlayedTimeStatistics > 0) {
long elapsedTime = System.currentTimeMillis() - lastPlayedTimeStatistics;
long rewindTime = 0;
if (elapsedTime > ELAPSED_TIME_FOR_LONG_REWIND) {

View File

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

View File

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

View File

@ -1,5 +1,7 @@
package de.danoeh.antennapod.playback.service.internal;
import java.util.Date;
import de.danoeh.antennapod.storage.database.DBWriter;
import de.danoeh.antennapod.model.feed.FeedItem;
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) {
playable.setPosition(newPosition);
playable.setLastPlayedTime(timestamp);
playable.setLastPlayedTimeStatistics(timestamp);
if (playable instanceof FeedMedia) {
FeedMedia media = (FeedMedia) playable;
media.setLastPlayedTimeHistory(new Date(timestamp));
FeedItem item = media.getItem();
if (item != null && item.isNew()) {
DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.getId());

View File

@ -45,7 +45,7 @@ class DBUpgrader {
}
if (oldVersion <= 7) {
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");
}
if (oldVersion <= 8) {
@ -210,7 +210,7 @@ class DBUpgrader {
}
if (oldVersion < 1040002) {
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) {
db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_PUBDATE);

View File

@ -296,16 +296,16 @@ public class DBWriter {
* current date regardless of the current value.
*
* @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) {
return runOnDbThread(() -> {
Log.d(TAG, "Adding item to playback history");
media.setPlaybackCompletionDate(date);
media.setLastPlayedTimeHistory(date);
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setFeedMediaPlaybackCompletionDate(media);
adapter.setFeedMediaLastPlayedTimeHistory(media);
adapter.close();
EventBus.getDefault().post(PlaybackHistoryEvent.listUpdated());

View File

@ -79,8 +79,8 @@ public class FeedItemPermutors {
comparator = (f1, f2) -> Long.compare(size(f2), size(f1));
break;
case COMPLETION_DATE_NEW_OLD:
comparator = (f1, f2) -> f2.getMedia().getPlaybackCompletionDate()
.compareTo(f1.getMedia().getPlaybackCompletionDate());
comparator = (f1, f2) -> f2.getMedia().getLastPlayedTimeHistory()
.compareTo(f1.getMedia().getLastPlayedTimeHistory());
break;
default:
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_REASON_DETAILED = "reason_detailed";
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_KEEP_UPDATED = "keep_updated";
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_LAST_UPDATE_FAILED = "last_update_failed";
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_EXCLUDE_FILTER = "exclude_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
+ " TEXT," + KEY_DOWNLOAD_DATE + " INTEGER," + KEY_POSITION
+ " INTEGER," + KEY_SIZE + " INTEGER," + KEY_MIME_TYPE + " TEXT,"
+ KEY_PLAYBACK_COMPLETION_DATE + " INTEGER,"
+ KEY_LAST_PLAYED_TIME_HISTORY + " INTEGER,"
+ KEY_FEEDITEM + " INTEGER,"
+ KEY_PLAYED_DURATION + " 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 "
+ 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_SIZE + ", "
+ 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_PLAYED_DURATION + ", "
+ 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 =
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_FILE_URL, media.getLocalFileUrl());
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) {
values.put(KEY_PLAYBACK_COMPLETION_DATE, media.getPlaybackCompletionDate().getTime());
if (media.getLastPlayedTimeHistory() != null) {
values.put(KEY_LAST_PLAYED_TIME_HISTORY, media.getLastPlayedTimeHistory().getTime());
} else {
values.put(KEY_PLAYBACK_COMPLETION_DATE, 0);
values.put(KEY_LAST_PLAYED_TIME_HISTORY, 0);
}
if (media.getItem() != null) {
values.put(KEY_FEEDITEM, media.getItem().getId());
@ -548,7 +548,8 @@ public class PodDBAdapter {
values.put(KEY_POSITION, media.getPosition());
values.put(KEY_DURATION, media.getDuration());
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 + "=?",
new String[]{String.valueOf(media.getId())});
} else {
@ -556,15 +557,15 @@ public class PodDBAdapter {
}
}
public void setFeedMediaPlaybackCompletionDate(FeedMedia media) {
public void setFeedMediaLastPlayedTimeHistory(FeedMedia media) {
if (media.getId() != 0) {
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());
db.update(TABLE_NAME_FEED_MEDIA, values, KEY_ID + "=?",
new String[]{String.valueOf(media.getId())});
} 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() {
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);
}
@ -1061,7 +1062,7 @@ public class PodDBAdapter {
public final Cursor getPausedQueueCursor(int limit) {
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);
final String query = "SELECT " + KEYS_FEED_ITEM_WITHOUT_DESCRIPTION + ", " + KEYS_FEED_MEDIA
+ " FROM " + TABLE_NAME_QUEUE
@ -1069,7 +1070,7 @@ public class PodDBAdapter {
+ " ON " + SELECT_KEY_ITEM_ID + " = " + TABLE_NAME_QUEUE + "." + KEY_FEEDITEM
+ JOIN_FEED_ITEM_AND_MEDIA
+ " 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
+ " LIMIT " + limit;
return db.rawQuery(query, null);
@ -1124,13 +1125,14 @@ public class PodDBAdapter {
}
public Cursor getRandomEpisodesCursor(int limit, int seed) {
long oneHourAgo = System.currentTimeMillis() - 1000L * 3600L;
final String allItems = SELECT_FEED_ITEMS_AND_MEDIA
+ " 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
+ " AND " + KEY_PUBDATE + " > " + (System.currentTimeMillis() - 1000L * 3600L * 24L * 356L * 2)
// Hide episodes that have been played but not completed
+ " AND (" + KEY_LAST_PLAYED_TIME + " == 0"
+ " OR " + KEY_LAST_PLAYED_TIME + " > " + (System.currentTimeMillis() - 1000L * 3600L) + ")"
+ " AND (" + KEY_LAST_PLAYED_TIME_STATISTICS + " == 0"
+ " OR " + KEY_LAST_PLAYED_TIME_STATISTICS + " > " + oneHourAgo + ")"
+ " AND " + SELECT_WHERE_FEED_IS_SUBSCRIBED;
final String query = "SELECT MAX(" + randomEpisodeNumber(seed) + "), * FROM (" + allItems + ")"
+ " GROUP BY " + KEY_FEED
@ -1184,7 +1186,7 @@ public class PodDBAdapter {
}
final String query = SELECT_FEED_ITEMS_AND_MEDIA
+ " 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);
}
@ -1206,10 +1208,10 @@ public class PodDBAdapter {
public final Cursor getMonthlyStatisticsCursor() {
final String query = "SELECT SUM(" + KEY_PLAYED_DURATION + ") AS total_duration"
+ ", strftime('%m', datetime(" + KEY_LAST_PLAYED_TIME + "/1000, 'unixepoch')) AS month"
+ ", strftime('%Y', datetime(" + KEY_LAST_PLAYED_TIME + "/1000, 'unixepoch')) AS year"
+ ", strftime('%m', datetime(" + KEY_LAST_PLAYED_TIME_STATISTICS + "/1000, 'unixepoch')) AS month"
+ ", strftime('%Y', datetime(" + KEY_LAST_PLAYED_TIME_STATISTICS + "/1000, 'unixepoch')) AS year"
+ " 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"
+ " ORDER BY year, month";
return db.rawQuery(query, null);
@ -1217,16 +1219,16 @@ public class PodDBAdapter {
public final Cursor getFeedStatisticsCursor(boolean includeMarkedAsPlayed, long timeFilterFrom,
long timeFilterTo, long sixMonthsAgo) {
final String lastPlayedTime = TABLE_NAME_FEED_MEDIA + "." + KEY_LAST_PLAYED_TIME;
String wasStarted = TABLE_NAME_FEED_MEDIA + "." + KEY_PLAYBACK_COMPLETION_DATE + " > 0"
final String lastPlayedTimeStatistics = TABLE_NAME_FEED_MEDIA + "." + KEY_LAST_PLAYED_TIME_STATISTICS;
String wasStarted = TABLE_NAME_FEED_MEDIA + "." + KEY_LAST_PLAYED_TIME_HISTORY + " > 0"
+ " AND " + TABLE_NAME_FEED_MEDIA + "." + KEY_PLAYED_DURATION + " > 0";
if (includeMarkedAsPlayed) {
wasStarted = "(" + wasStarted + ") OR "
+ TABLE_NAME_FEED_ITEMS + "." + KEY_READ + "=" + FeedItem.PLAYED + " OR "
+ TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + "> 0";
}
final String timeFilter = lastPlayedTime + ">=" + timeFilterFrom
+ " AND " + lastPlayedTime + "<" + timeFilterTo;
final String timeFilter = lastPlayedTimeStatistics + ">=" + timeFilterFrom
+ " AND " + lastPlayedTimeStatistics + "<" + timeFilterTo;
String playedTime = TABLE_NAME_FEED_MEDIA + "." + KEY_PLAYED_DURATION;
if (includeMarkedAsPlayed) {
playedTime = "(CASE WHEN " + playedTime + " != 0"
@ -1238,8 +1240,9 @@ public class PodDBAdapter {
final String query = "SELECT " + KEYS_FEED + ", "
+ "COUNT(*) AS num_episodes, "
+ "MIN(CASE WHEN " + lastPlayedTime + " > 0"
+ " THEN " + lastPlayedTime + " ELSE " + Long.MAX_VALUE + " END) AS oldest_date, "
+ "MIN(CASE WHEN " + lastPlayedTimeStatistics + " > 0"
+ " THEN " + lastPlayedTimeStatistics
+ " ELSE " + Long.MAX_VALUE + " END) AS oldest_date, "
+ "SUM(CASE WHEN (" + wasStarted + ") THEN 1 ELSE 0 END) AS episodes_started, "
+ "IFNULL(SUM(CASE WHEN (" + timeFilter + ")"
+ " THEN (" + playedTime + ") ELSE 0 END), 0) AS played_time, "
@ -1263,10 +1266,10 @@ public class PodDBAdapter {
public final Cursor getTimeBetweenReleaseAndPlayback(long timeFilterFrom, long timeFilterTo) {
final String from = " FROM " + TABLE_NAME_FEED_ITEMS
+ 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_MEDIA + "." + KEY_LAST_PLAYED_TIME + "<" + timeFilterTo;
final String query = "SELECT " + TABLE_NAME_FEED_MEDIA + "." + KEY_LAST_PLAYED_TIME
+ " AND " + TABLE_NAME_FEED_MEDIA + "." + KEY_LAST_PLAYED_TIME_STATISTICS + "<" + timeFilterTo;
final String query = "SELECT " + TABLE_NAME_FEED_MEDIA + "." + KEY_LAST_PLAYED_TIME_STATISTICS
+ " - " + TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE + " AS diff"
+ from
+ " 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
String keyRead = PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_READ;
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 keyMediaId = PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + 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";
case COMPLETION_DATE_NEW_OLD:
return PodDBAdapter.TABLE_NAME_FEED_MEDIA + "."
+ PodDBAdapter.KEY_PLAYBACK_COMPLETION_DATE + " " + "DESC";
+ PodDBAdapter.KEY_LAST_PLAYED_TIME_HISTORY + " " + "DESC";
case DATE_OLD_NEW:
return PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_PUBDATE + " " + "ASC";
case EPISODE_FILENAME_A_Z:

View File

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