From 4f84ceff734889748dc9d846bdf117db5fac4dce Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Fri, 3 Jul 2015 18:21:20 +0200 Subject: [PATCH 1/6] Determine media file size if feed doesn't report it correctly --- .../java/de/danoeh/antennapod/PodcastApp.java | 4 ++ .../antennapod/adapter/AdapterUtils.java | 15 +++--- .../antennapod/adapter/QueueListAdapter.java | 6 ++- core/src/main/AndroidManifest.xml | 3 ++ .../core/service/FeedMediaSizeService.java | 47 +++++++++++++++++++ .../antennapod/core/storage/DBReader.java | 22 +++++++++ .../antennapod/core/storage/DBTasks.java | 10 +++- .../antennapod/core/storage/PodDBAdapter.java | 7 +++ 8 files changed, 104 insertions(+), 10 deletions(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java diff --git a/app/src/main/java/de/danoeh/antennapod/PodcastApp.java b/app/src/main/java/de/danoeh/antennapod/PodcastApp.java index f79ac49ed..4b709ab74 100644 --- a/app/src/main/java/de/danoeh/antennapod/PodcastApp.java +++ b/app/src/main/java/de/danoeh/antennapod/PodcastApp.java @@ -1,12 +1,14 @@ package de.danoeh.antennapod; import android.app.Application; +import android.content.Intent; import android.content.res.Configuration; import de.danoeh.antennapod.core.asynctask.PicassoProvider; import de.danoeh.antennapod.core.feed.EventDistributor; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.core.service.FeedMediaSizeService; import de.danoeh.antennapod.spa.SPAUtil; /** Main application class. */ @@ -43,6 +45,8 @@ public class PodcastApp extends Application { EventDistributor.getInstance(); SPAUtil.sendSPAppsQueryFeedsIntent(this); + + startService(new Intent(this, FeedMediaSizeService.class)); } public static float getLogicalDensity() { diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java b/app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java index e22b31361..d3ee08546 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java @@ -36,18 +36,19 @@ public class AdapterUtils { || state == FeedItem.State.IN_PROGRESS) { if (media.getDuration() > 0) { episodeProgress.setVisibility(View.VISIBLE); - episodeProgress - .setProgress((int) (((double) media + episodeProgress.setProgress((int) (((double) media .getPosition()) / media.getDuration() * 100)); - txtvPos.setText(Converter - .getDurationStringLong(media.getDuration() + txtvPos.setText(Converter.getDurationStringLong(media.getDuration() - media.getPosition())); } } else if (!media.isDownloaded()) { - txtvPos.setText(Converter.byteToString(media.getSize())); + if(media.getSize() > 0) { + txtvPos.setText(Converter.byteToString(media.getSize())); + } else { + txtvPos.setText(""); + } } else { - txtvPos.setText(Converter.getDurationStringLong(media - .getDuration())); + txtvPos.setText(Converter.getDurationStringLong(media.getDuration())); } } } diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/QueueListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/QueueListAdapter.java index bba5a00a9..431b645c6 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/QueueListAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/QueueListAdapter.java @@ -129,7 +129,11 @@ public class QueueListAdapter extends BaseAdapter { holder.progressRight.setText(Converter.getDurationStringLong(media.getDuration())); } } else { - holder.progressLeft.setText(Converter.byteToString(media.getSize())); + if(media.getSize() > 0) { + holder.progressLeft.setText(Converter.byteToString(media.getSize())); + } else { + holder.progressLeft.setText(""); + } holder.progressRight.setText(Converter.getDurationStringLong(media.getDuration())); holder.progress.setVisibility(View.GONE); } diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml index 3ec519844..17dcb4ad8 100644 --- a/core/src/main/AndroidManifest.xml +++ b/core/src/main/AndroidManifest.xml @@ -23,6 +23,9 @@ + list = DBReader.getFeedMediaUnknownSize(this); + for (FeedMedia media : list) { + long size = -1; + try { + URL url = new URL(media.getDownload_url()); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + size = conn.getContentLength(); + conn.disconnect(); + } catch (IOException e) { + e.printStackTrace(); + } + media.setSize(size); + DBWriter.setFeedMedia(this, media); + } + } + +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index 93aec54c8..1af0fa0a9 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -550,6 +550,28 @@ public final class DBReader { return itemIds; } + /** + * Loads the IDs of the FeedItems whose 'read'-attribute is set to false. + * + * @param context A context that is used for opening a database connection. + * @return A list of IDs of the FeedItems whose 'read'-attribute is set to false. This method should be preferred + * over {@link #getUnreadItemsList(android.content.Context)} if the FeedItems in the UnreadItems list are not used. + */ + public static List getFeedMediaUnknownSize(Context context) { + PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + Cursor cursor = adapter.getFeedMediaUnknownSizeCursor(); + List result = new ArrayList<>(cursor.getCount()); + if (cursor.moveToFirst()) { + do { + FeedMedia media = extractFeedMediaFromCursorRow(cursor); + result.add(media); + } while (cursor.moveToNext()); + } + cursor.close(); + return result; + } + /** * Loads a list of FeedItems sorted by pubDate in descending order. diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java index 9273cf11e..1f6d0abd8 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java @@ -5,6 +5,9 @@ import android.content.Intent; import android.database.Cursor; import android.util.Log; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -29,6 +32,7 @@ import de.danoeh.antennapod.core.feed.FeedImage; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.core.service.FeedMediaSizeService; import de.danoeh.antennapod.core.service.GpodnetSyncService; import de.danoeh.antennapod.core.service.download.DownloadStatus; import de.danoeh.antennapod.core.service.playback.PlaybackService; @@ -595,15 +599,15 @@ public final class DBTasks { item.getIdentifyingValue()); if (oldItem == null) { // item is new - final int i = idx; item.setFeed(savedFeed); item.setAutoDownload(savedFeed.getPreferences().getAutoDownload()); - savedFeed.getItems().add(i, item); + savedFeed.getItems().add(item); if (markNewItems) { item.setNew(); } } else { oldItem.updateFromOther(item); + savedFeed.getItems().add(oldItem); } } // update attributes @@ -629,6 +633,8 @@ public final class DBTasks { EventDistributor.getInstance().sendFeedUpdateBroadcast(); + context.startService(new Intent(context, FeedMediaSizeService.class)); + return resultFeeds; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index 2be53047d..d42b67459 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -1105,6 +1105,13 @@ public class PodDBAdapter { return db.rawQuery(query, null); } + public final Cursor getFeedMediaUnknownSizeCursor() { + final String query = "SELECT * " + + " FROM " + TABLE_NAME_FEED_MEDIA + + " WHERE " + KEY_SIZE + "=0"; + return db.rawQuery(query, null); + } + /** * Returns a cursor which contains all items of a feed that are considered new. * The returned cursor uses the FEEDITEM_SEL_FI_SMALL selection. From 23a3e7c766a4dfbba9101672d8628b65ad16c855 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Fri, 3 Jul 2015 23:59:40 +0200 Subject: [PATCH 2/6] Check network for every media file, manually check suspiciously low file sizes --- .../antennapod/core/service/FeedMediaSizeService.java | 9 ++++++++- .../java/de/danoeh/antennapod/core/storage/DBReader.java | 6 +++--- .../de/danoeh/antennapod/core/storage/PodDBAdapter.java | 2 +- .../antennapod/core/syndication/namespace/NSRSS20.java | 4 ++++ 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java index b4542aae8..1f7dfa386 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java @@ -30,13 +30,20 @@ public class FeedMediaSizeService extends IntentService { } List list = DBReader.getFeedMediaUnknownSize(this); for (FeedMedia media : list) { - long size = -1; + if(false == NetworkUtils.networkAvailable(this)) { + return; + } + long size = Integer.MIN_VALUE; + Log.d(TAG, media.getDownload_url()); try { URL url = new URL(media.getDownload_url()); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestProperty( "Accept-Encoding", "" ); + conn.setRequestMethod("HEAD"); size = conn.getContentLength(); conn.disconnect(); } catch (IOException e) { + Log.d(TAG, media.getDownload_url()); e.printStackTrace(); } media.setSize(size); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index 1af0fa0a9..26a974616 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -551,11 +551,11 @@ public final class DBReader { } /** - * Loads the IDs of the FeedItems whose 'read'-attribute is set to false. + * Loads FeedMedia whose file size is unknown * * @param context A context that is used for opening a database connection. - * @return A list of IDs of the FeedItems whose 'read'-attribute is set to false. This method should be preferred - * over {@link #getUnreadItemsList(android.content.Context)} if the FeedItems in the UnreadItems list are not used. + * @return A list of FeedMedia items whose size is 0 (unknown and never tried to + * determine the correct size) */ public static List getFeedMediaUnknownSize(Context context) { PodDBAdapter adapter = new PodDBAdapter(context); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index d42b67459..319987cb2 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -1108,7 +1108,7 @@ public class PodDBAdapter { public final Cursor getFeedMediaUnknownSizeCursor() { final String query = "SELECT * " + " FROM " + TABLE_NAME_FEED_MEDIA - + " WHERE " + KEY_SIZE + "=0"; + + " WHERE " + KEY_SIZE + ">" + Integer.MIN_VALUE; return db.rawQuery(query, null); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java index 6455332be..31eb2efd6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java @@ -57,6 +57,10 @@ public class NSRSS20 extends Namespace { long size = 0; try { size = Long.parseLong(attributes.getValue(ENC_LEN)); + if(size < 16384) { + // less than 16kb is suspicious, check manually + size = 0; + } } catch (NumberFormatException e) { if (BuildConfig.DEBUG) Log.d(TAG, "Length attribute could not be parsed."); From be1fde6f8e416cd6ddc4be9d7b01de0e718fed55 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 4 Jul 2015 11:31:32 +0200 Subject: [PATCH 3/6] Post FeedMedia event --- .../antennapod/core/event/FeedMediaEvent.java | 24 +++++++++++++++++++ .../core/service/FeedMediaSizeService.java | 3 +++ 2 files changed, 27 insertions(+) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/event/FeedMediaEvent.java diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/FeedMediaEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/FeedMediaEvent.java new file mode 100644 index 000000000..94e186b7a --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/event/FeedMediaEvent.java @@ -0,0 +1,24 @@ +package de.danoeh.antennapod.core.event; + +import de.danoeh.antennapod.core.feed.FeedMedia; + +public class FeedMediaEvent { + + public enum Action { + UPDATE + } + + public final Action action; + public final FeedMedia media; + + private FeedMediaEvent(Action action, FeedMedia media) { + this.action = action; + this.media = media; + } + + public static FeedMediaEvent update(FeedMedia media) { + return new FeedMediaEvent(Action.UPDATE, media); + } + + +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java index 1f7dfa386..ad047f10a 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java @@ -9,10 +9,12 @@ import java.net.HttpURLConnection; import java.net.URL; import java.util.List; +import de.danoeh.antennapod.core.event.FeedMediaEvent; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.NetworkUtils; +import de.greenrobot.event.EventBus; public class FeedMediaSizeService extends IntentService { @@ -48,6 +50,7 @@ public class FeedMediaSizeService extends IntentService { } media.setSize(size); DBWriter.setFeedMedia(this, media); + EventBus.getDefault().post(FeedMediaEvent.update(media)); } } From 5608d228be2da4e06cfc07d9a133235298da8a68 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 5 Jul 2015 15:33:10 +0200 Subject: [PATCH 4/6] Close URL connection --- .../antennapod/core/service/FeedMediaSizeService.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java index ad047f10a..d6a1ce62c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java @@ -36,10 +36,10 @@ public class FeedMediaSizeService extends IntentService { return; } long size = Integer.MIN_VALUE; - Log.d(TAG, media.getDownload_url()); + HttpURLConnection conn = null; try { URL url = new URL(media.getDownload_url()); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn = (HttpURLConnection) url.openConnection(); conn.setRequestProperty( "Accept-Encoding", "" ); conn.setRequestMethod("HEAD"); size = conn.getContentLength(); @@ -47,6 +47,10 @@ public class FeedMediaSizeService extends IntentService { } catch (IOException e) { Log.d(TAG, media.getDownload_url()); e.printStackTrace(); + } finally { + if(conn != null) { + conn.disconnect(); + } } media.setSize(size); DBWriter.setFeedMedia(this, media); From 65611129e15f6a8b8f1a260f373bb6e89fc0c3ea Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 12 Jul 2015 21:17:22 +0200 Subject: [PATCH 5/6] Use local file size if episode is downloaded --- .../core/service/FeedMediaSizeService.java | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java index d6a1ce62c..e64a38901 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java @@ -4,6 +4,7 @@ import android.app.IntentService; import android.content.Intent; import android.util.Log; +import java.io.File; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; @@ -36,20 +37,27 @@ public class FeedMediaSizeService extends IntentService { return; } long size = Integer.MIN_VALUE; - HttpURLConnection conn = null; - try { - URL url = new URL(media.getDownload_url()); - conn = (HttpURLConnection) url.openConnection(); - conn.setRequestProperty( "Accept-Encoding", "" ); - conn.setRequestMethod("HEAD"); - size = conn.getContentLength(); - conn.disconnect(); - } catch (IOException e) { - Log.d(TAG, media.getDownload_url()); - e.printStackTrace(); - } finally { - if(conn != null) { + if(media.isDownloaded()) { + File mediaFile = new File(media.getLocalMediaUrl()); + if(mediaFile.exists()) { + size = mediaFile.length(); + } + } else { + HttpURLConnection conn = null; + try { + URL url = new URL(media.getDownload_url()); + conn = (HttpURLConnection) url.openConnection(); + conn.setRequestProperty("Accept-Encoding", ""); + conn.setRequestMethod("HEAD"); + size = conn.getContentLength(); conn.disconnect(); + } catch (IOException e) { + Log.d(TAG, media.getDownload_url()); + e.printStackTrace(); + } finally { + if (conn != null) { + conn.disconnect(); + } } } media.setSize(size); From 97827cde2d822fca93f6900527e3bda56076a0d5 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 12 Jul 2015 22:07:45 +0200 Subject: [PATCH 6/6] Fixed tests and bug --- .../java/de/test/antennapod/handler/FeedHandlerTest.java | 2 +- .../java/de/test/antennapod/storage/DBTasksTest.java | 5 +++-- .../main/java/de/danoeh/antennapod/core/storage/DBTasks.java | 3 +-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/androidTest/java/de/test/antennapod/handler/FeedHandlerTest.java b/app/src/androidTest/java/de/test/antennapod/handler/FeedHandlerTest.java index 738ec488f..13a0e3f78 100644 --- a/app/src/androidTest/java/de/test/antennapod/handler/FeedHandlerTest.java +++ b/app/src/androidTest/java/de/test/antennapod/handler/FeedHandlerTest.java @@ -172,7 +172,7 @@ public class FeedHandlerTest extends InstrumentationTestCase { "http://example.com/items/" + i, new Date(i*60000), FeedItem.UNPLAYED, feed); feed.getItems().add(item); if (withFeedMedia) { - item.setMedia(new FeedMedia(0, item, 4711, 0, 100, "audio/mp3", null, "http://example.com/media-" + i, + item.setMedia(new FeedMedia(0, item, 4711, 0, 1024*1024, "audio/mp3", null, "http://example.com/media-" + i, false, null, 0)); } } diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java b/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java index a176ef69a..ac4a709d7 100644 --- a/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java +++ b/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java @@ -67,6 +67,8 @@ public class DBTasksTest extends InstrumentationTestCase { SharedPreferences.Editor prefEdit = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()).edit(); prefEdit.putString(UserPreferences.PREF_EPISODE_CACHE_SIZE, Integer.toString(EPISODE_CACHE_SIZE)); prefEdit.commit(); + + UserPreferences.init(context); } @FlakyTest(tolerance = 3) @@ -261,7 +263,7 @@ public class DBTasksTest extends InstrumentationTestCase { } for (int i = NUM_ITEMS_OLD; i < NUM_ITEMS_NEW + NUM_ITEMS_OLD; i++) { - feed.getItems().add(0, new FeedItem(0, "item " + i, "id " + i, "link " + i, new Date(i), FeedItem.PLAYED, feed)); + feed.getItems().add(0, new FeedItem(0, "item " + i, "id " + i, "link " + i, new Date(i), FeedItem.UNPLAYED, feed)); } final Feed newFeed = DBTasks.updateFeed(context, feed)[0]; @@ -275,7 +277,6 @@ public class DBTasksTest extends InstrumentationTestCase { updatedFeedTest(feedFromDB, feedID, itemIDs, NUM_ITEMS_OLD, NUM_ITEMS_NEW); } - @FlakyTest(tolerance = 3) private void updatedFeedTest(final Feed newFeed, long feedID, List itemIDs, final int NUM_ITEMS_OLD, final int NUM_ITEMS_NEW) { assertTrue(newFeed.getId() == feedID); assertTrue(newFeed.getItems().size() == NUM_ITEMS_NEW + NUM_ITEMS_OLD); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java index 1f6d0abd8..a90df433e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java @@ -601,13 +601,12 @@ public final class DBTasks { // item is new item.setFeed(savedFeed); item.setAutoDownload(savedFeed.getPreferences().getAutoDownload()); - savedFeed.getItems().add(item); + savedFeed.getItems().add(idx, item); if (markNewItems) { item.setNew(); } } else { oldItem.updateFromOther(item); - savedFeed.getItems().add(oldItem); } } // update attributes