diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 2e6a599f1..e319d132e 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -23,6 +23,7 @@
+
+
+
+
+
+
diff --git a/res/layout/external_itemlist_item.xml b/res/layout/external_itemlist_item.xml
index fe1c29a19..6f2405abc 100644
--- a/res/layout/external_itemlist_item.xml
+++ b/res/layout/external_itemlist_item.xml
@@ -32,8 +32,8 @@
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginLeft="8dp"
- android:layout_marginTop="8dp"
android:layout_marginRight="4dp"
+ android:layout_marginTop="8dp"
android:layout_toLeftOf="@id/butAction"
android:layout_toRightOf="@id/imgvFeedimage"
android:ellipsize="end"
@@ -81,21 +81,15 @@
android:layout_marginTop="4dp"
android:layout_toLeftOf="@id/butAction" />
-
+
-
-
\ No newline at end of file
diff --git a/res/layout/feeditemlist_item.xml b/res/layout/feeditemlist_item.xml
index 2cc7ee703..4fbddbbac 100644
--- a/res/layout/feeditemlist_item.xml
+++ b/res/layout/feeditemlist_item.xml
@@ -87,6 +87,19 @@
android:textColor="?android:attr/textColorTertiary"
android:textSize="@dimen/text_size_micro" />
+
+
-
-
\ No newline at end of file
diff --git a/res/menu/feeditem.xml b/res/menu/feeditem.xml
index a76f2c658..09b7fa6b0 100644
--- a/res/menu/feeditem.xml
+++ b/res/menu/feeditem.xml
@@ -1,7 +1,7 @@
\ No newline at end of file
diff --git a/res/menu/mediaplayer.xml b/res/menu/mediaplayer.xml
index 4f3a55114..2cde6d58a 100644
--- a/res/menu/mediaplayer.xml
+++ b/res/menu/mediaplayer.xml
@@ -1,7 +1,18 @@
\ No newline at end of file
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 17a94c29f..aebc74b33 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -21,6 +21,23 @@
- 24
+
+ - 10
+ - 20
+ - 40
+ - 60
+ - 80
+ - 100
+
+
+
+ - N/A
+
+
+
+ - 0
+
+
- Light
- Dark
diff --git a/res/values/ids.xml b/res/values/ids.xml
index 476969668..4d393e675 100644
--- a/res/values/ids.xml
+++ b/res/values/ids.xml
@@ -14,5 +14,6 @@
+
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 906d530d7..5bc40db54 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -7,6 +7,7 @@
PODCASTS
EPISODES
New
+ Waiting list
Settings
Add a new Feed
Downloads
@@ -70,6 +71,7 @@
Flattr this
Enqueue all
Download all
+ Skip episode
Download successful
@@ -165,15 +167,16 @@
Support the development of AntennaPod by flattring it. Thanks!
Revoke access
Revoke the access permission to your flattr account for this app.
- Auto-enqueue
- Add an episode to the queue when you start to download it.
Display only episodes
Display only items which also have an episode.
User Interface
- Auto-delete
- Delete an episode when playback completes or when it is removed from the queue.
Select theme
Change the appearance of AntennaPod.
+ Automatic download
+ Configure the automatic download of episodes.
+ Enable Wi-Fi filter
+ Allow automatic download only for selected Wi-Fi networks.
+ Episode cache
Search for Feeds or Episodes
diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml
index ccde3097f..c8c947797 100644
--- a/res/xml/preferences.xml
+++ b/res/xml/preferences.xml
@@ -17,7 +17,6 @@
android:key="prefFollowQueue"
android:summary="@string/pref_followQueue_sum"
android:title="@string/pref_followQueue_title" />
-
@@ -35,7 +34,10 @@
android:key="prefMobileUpdate"
android:summary="@string/pref_mobileUpdate_sum"
android:title="@string/pref_mobileUpdate_title" />
-
+
+
+
+
networks = wifiservice.getConfiguredNetworks();
+
+ if (networks != null) {
+ selectedNetworks = new CheckBoxPreference[networks.size()];
+ List prefValues = Arrays.asList(UserPreferences
+ .getAutodownloadSelectedNetworks());
+ PreferenceScreen prefScreen = (PreferenceScreen) findPreference(AUTO_DL_PREF_SCREEN);
+ OnPreferenceClickListener clickListener = new OnPreferenceClickListener() {
+
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ if (preference instanceof CheckBoxPreference) {
+ String key = preference.getKey();
+ ArrayList prefValuesList = new ArrayList(
+ Arrays.asList(UserPreferences
+ .getAutodownloadSelectedNetworks()));
+ boolean newValue = ((CheckBoxPreference) preference)
+ .isChecked();
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Selected network " + key
+ + ". New state: " + newValue);
+
+ int index = prefValuesList.indexOf(key);
+ if (index >= 0 && newValue == false) {
+ // remove network
+ prefValuesList.remove(index);
+ } else if (index < 0 && newValue == true) {
+ prefValuesList.add(key);
+ }
+
+ UserPreferences.setAutodownloadSelectedNetworks(
+ PreferenceActivity.this, prefValuesList
+ .toArray(new String[prefValuesList
+ .size()]));
+ return true;
+ } else {
+ return false;
+ }
+ }
+ };
+ // create preference for each known network. attach listener and set
+ // value
+ for (int i = 0; i < networks.size(); i++) {
+ WifiConfiguration config = networks.get(i);
+
+ CheckBoxPreference pref = new CheckBoxPreference(this);
+ String key = Integer.toString(config.networkId);
+ pref.setTitle(config.SSID);
+ pref.setKey(key);
+ pref.setOnPreferenceClickListener(clickListener);
+ pref.setPersistent(false);
+ pref.setChecked(prefValues.contains(key));
+ selectedNetworks[i] = pref;
+ prefScreen.addPreference(pref);
+ }
+ } else {
+ Log.e(TAG, "Couldn't get list of configure Wi-Fi networks");
+ }
+ }
+
+ private void clearAutodownloadSelectedNetworsPreference() {
+ if (selectedNetworks != null) {
+ PreferenceScreen prefScreen = (PreferenceScreen) findPreference(AUTO_DL_PREF_SCREEN);
+
+ for (int i = 0; i < selectedNetworks.length; i++) {
+ if (selectedNetworks[i] != null) {
+ prefScreen.removePreference(selectedNetworks[i]);
+ }
+ }
+ }
+ }
}
diff --git a/src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java b/src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java
index db716c66e..5005b25b4 100644
--- a/src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java
+++ b/src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java
@@ -9,6 +9,7 @@ import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
+import android.widget.ProgressBar;
import android.widget.TextView;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.asynctask.ImageLoader;
@@ -89,10 +90,8 @@ public class ExternalEpisodesListAdapter extends BaseExpandableListAdapter {
.findViewById(R.id.butAction);
holder.statusPlaying = (View) convertView
.findViewById(R.id.statusPlaying);
- holder.statusUnread = (View) convertView
- .findViewById(R.id.statusUnread);
- holder.statusInProgress = (TextView) convertView
- .findViewById(R.id.statusInProgress);
+ holder.episodeProgress = (ProgressBar) convertView
+ .findViewById(R.id.pbar_episode_progress);
convertView.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
@@ -100,41 +99,53 @@ public class ExternalEpisodesListAdapter extends BaseExpandableListAdapter {
holder.title.setText(item.getTitle());
holder.feedTitle.setText(item.getFeed().getTitle());
+ FeedItem.State state = item.getState();
if (groupPosition == GROUP_POS_QUEUE) {
- FeedItem.State state = item.getState();
switch (state) {
case PLAYING:
holder.statusPlaying.setVisibility(View.VISIBLE);
- holder.statusUnread.setVisibility(View.GONE);
- holder.statusInProgress.setVisibility(View.GONE);
+ holder.episodeProgress.setVisibility(View.VISIBLE);
break;
case IN_PROGRESS:
holder.statusPlaying.setVisibility(View.GONE);
- holder.statusUnread.setVisibility(View.GONE);
- holder.statusInProgress.setVisibility(View.VISIBLE);
- holder.statusInProgress.setText(Converter
- .getDurationStringLong(item.getMedia().getPosition()));
+ holder.episodeProgress.setVisibility(View.VISIBLE);
break;
case NEW:
holder.statusPlaying.setVisibility(View.GONE);
- holder.statusUnread.setVisibility(View.VISIBLE);
- holder.statusInProgress.setVisibility(View.GONE);
+ holder.episodeProgress.setVisibility(View.GONE);
break;
default:
holder.statusPlaying.setVisibility(View.GONE);
- holder.statusUnread.setVisibility(View.GONE);
- holder.statusInProgress.setVisibility(View.GONE);
+ holder.episodeProgress.setVisibility(View.GONE);
break;
}
} else {
holder.statusPlaying.setVisibility(View.GONE);
- holder.statusUnread.setVisibility(View.GONE);
- holder.statusInProgress.setVisibility(View.GONE);
+ holder.episodeProgress.setVisibility(View.GONE);
}
FeedMedia media = item.getMedia();
if (media != null) {
+
+ if (state == FeedItem.State.PLAYING
+ || state == FeedItem.State.IN_PROGRESS) {
+ if (media.getDuration() > 0) {
+ holder.episodeProgress.setProgress((int) (((double) media
+ .getPosition()) / media.getDuration() * 100));
+ holder.lenSize.setText(Converter
+ .getDurationStringLong(media.getDuration()
+ - media.getPosition()));
+ }
+ } else if (!media.isDownloaded()) {
+ holder.lenSize.setText(context.getString(R.string.size_prefix)
+ + Converter.byteToString(media.getSize()));
+ } else {
+ holder.lenSize.setText(context
+ .getString(R.string.length_prefix)
+ + Converter.getDurationStringLong(media.getDuration()));
+ }
+
TypedArray drawables = context.obtainStyledAttributes(new int[] {
R.attr.av_download, R.attr.navigation_refresh });
holder.lenSize.setVisibility(View.VISIBLE);
@@ -144,20 +155,15 @@ public class ExternalEpisodesListAdapter extends BaseExpandableListAdapter {
holder.downloadStatus.setImageDrawable(drawables
.getDrawable(1));
} else {
- holder.downloadStatus.setVisibility(View.GONE);
+ holder.downloadStatus.setVisibility(View.INVISIBLE);
}
- holder.lenSize.setText(context.getString(R.string.size_prefix)
- + Converter.byteToString(media.getSize()));
} else {
holder.downloadStatus.setVisibility(View.VISIBLE);
holder.downloadStatus
.setImageDrawable(drawables.getDrawable(0));
- holder.lenSize.setText(context
- .getString(R.string.length_prefix)
- + Converter.getDurationStringLong(media.getDuration()));
}
} else {
- holder.downloadStatus.setVisibility(View.GONE);
+ holder.downloadStatus.setVisibility(View.INVISIBLE);
holder.lenSize.setVisibility(View.INVISIBLE);
}
@@ -188,9 +194,8 @@ public class ExternalEpisodesListAdapter extends BaseExpandableListAdapter {
ImageView downloadStatus;
ImageView feedImage;
ImageButton butAction;
- View statusUnread;
View statusPlaying;
- TextView statusInProgress;
+ ProgressBar episodeProgress;
}
@Override
@@ -230,7 +235,7 @@ public class ExternalEpisodesListAdapter extends BaseExpandableListAdapter {
headerString += " (" + getChildrenCount(GROUP_POS_QUEUE) + ")";
}
} else {
- headerString = context.getString(R.string.new_label);
+ headerString = context.getString(R.string.waiting_list_label);
if (manager.getUnreadItemsSize(true) > 0) {
headerString += " (" + getChildrenCount(GROUP_POS_UNREAD) + ")";
}
diff --git a/src/de/danoeh/antennapod/adapter/InternalFeedItemlistAdapter.java b/src/de/danoeh/antennapod/adapter/InternalFeedItemlistAdapter.java
index c8d41b10e..7b898385e 100644
--- a/src/de/danoeh/antennapod/adapter/InternalFeedItemlistAdapter.java
+++ b/src/de/danoeh/antennapod/adapter/InternalFeedItemlistAdapter.java
@@ -12,10 +12,12 @@ import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.ImageButton;
import android.widget.ImageView;
+import android.widget.ProgressBar;
import android.widget.TextView;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.feed.FeedItem;
import de.danoeh.antennapod.feed.FeedManager;
+import de.danoeh.antennapod.feed.FeedMedia;
import de.danoeh.antennapod.feed.MediaType;
import de.danoeh.antennapod.storage.DownloadRequester;
import de.danoeh.antennapod.util.Converter;
@@ -72,8 +74,8 @@ public class InternalFeedItemlistAdapter extends DefaultFeedItemlistAdapter {
.findViewById(R.id.statusPlaying);
holder.statusUnread = (View) convertView
.findViewById(R.id.statusUnread);
- holder.statusInProgress = (TextView) convertView
- .findViewById(R.id.statusInProgress);
+ holder.episodeProgress = (ProgressBar) convertView
+ .findViewById(R.id.pbar_episode_progress);
convertView.setTag(holder);
} else {
@@ -99,24 +101,22 @@ public class InternalFeedItemlistAdapter extends DefaultFeedItemlistAdapter {
case PLAYING:
holder.statusPlaying.setVisibility(View.VISIBLE);
holder.statusUnread.setVisibility(View.GONE);
- holder.statusInProgress.setVisibility(View.GONE);
+ holder.episodeProgress.setVisibility(View.VISIBLE);
break;
case IN_PROGRESS:
holder.statusPlaying.setVisibility(View.GONE);
holder.statusUnread.setVisibility(View.GONE);
- holder.statusInProgress.setVisibility(View.VISIBLE);
- holder.statusInProgress.setText(Converter
- .getDurationStringLong(item.getMedia().getPosition()));
+ holder.episodeProgress.setVisibility(View.VISIBLE);
break;
case NEW:
holder.statusPlaying.setVisibility(View.GONE);
holder.statusUnread.setVisibility(View.VISIBLE);
- holder.statusInProgress.setVisibility(View.GONE);
+ holder.episodeProgress.setVisibility(View.GONE);
break;
default:
holder.statusPlaying.setVisibility(View.GONE);
holder.statusUnread.setVisibility(View.GONE);
- holder.statusInProgress.setVisibility(View.GONE);
+ holder.episodeProgress.setVisibility(View.GONE);
break;
}
@@ -126,13 +126,36 @@ public class InternalFeedItemlistAdapter extends DefaultFeedItemlistAdapter {
System.currentTimeMillis(), DateFormat.MEDIUM,
DateFormat.SHORT));
- if (item.getMedia() == null) {
+ FeedMedia media = item.getMedia();
+ if (media == null) {
holder.downloaded.setVisibility(View.GONE);
holder.downloading.setVisibility(View.GONE);
holder.inPlaylist.setVisibility(View.GONE);
holder.type.setVisibility(View.GONE);
holder.lenSize.setVisibility(View.GONE);
} else {
+
+ if (state == FeedItem.State.PLAYING
+ || state == FeedItem.State.IN_PROGRESS) {
+ if (media.getDuration() > 0) {
+ holder.episodeProgress
+ .setProgress((int) (((double) media
+ .getPosition()) / media.getDuration() * 100));
+ holder.lenSize.setText(Converter
+ .getDurationStringLong(media.getDuration()
+ - media.getPosition()));
+ }
+ } else if (!media.isDownloaded()) {
+ holder.lenSize.setText(getContext().getString(
+ R.string.size_prefix)
+ + Converter.byteToString(media.getSize()));
+ } else {
+ holder.lenSize.setText(getContext().getString(
+ R.string.length_prefix)
+ + Converter.getDurationStringLong(media
+ .getDuration()));
+ }
+
holder.lenSize.setVisibility(View.VISIBLE);
if (FeedManager.getInstance().isInQueue(item)) {
holder.inPlaylist.setVisibility(View.VISIBLE);
@@ -140,17 +163,8 @@ public class InternalFeedItemlistAdapter extends DefaultFeedItemlistAdapter {
holder.inPlaylist.setVisibility(View.GONE);
}
if (item.getMedia().isDownloaded()) {
- holder.lenSize.setText(convertView.getResources()
- .getString(R.string.length_prefix)
- + Converter.getDurationStringLong(item.getMedia()
- .getDuration()));
holder.downloaded.setVisibility(View.VISIBLE);
} else {
- holder.lenSize
- .setText(convertView.getResources().getString(
- R.string.size_prefix)
- + Converter.byteToString(item.getMedia()
- .getSize()));
holder.downloaded.setVisibility(View.GONE);
}
@@ -200,7 +214,7 @@ public class InternalFeedItemlistAdapter extends DefaultFeedItemlistAdapter {
ImageButton butAction;
View statusUnread;
View statusPlaying;
- TextView statusInProgress;
+ ProgressBar episodeProgress;
}
public int getSelectedItemIndex() {
diff --git a/src/de/danoeh/antennapod/feed/FeedItem.java b/src/de/danoeh/antennapod/feed/FeedItem.java
index bb176c411..87cea0a1e 100644
--- a/src/de/danoeh/antennapod/feed/FeedItem.java
+++ b/src/de/danoeh/antennapod/feed/FeedItem.java
@@ -213,9 +213,7 @@ public class FeedItem extends FeedComponent {
private boolean isPlaying() {
if (media != null) {
- if (PlaybackPreferences.getCurrentlyPlayingFeedMediaId() == media.getId()) {
- return true;
- }
+ return media.isPlaying();
}
return false;
}
diff --git a/src/de/danoeh/antennapod/feed/FeedManager.java b/src/de/danoeh/antennapod/feed/FeedManager.java
index e984da46a..e558b34ff 100644
--- a/src/de/danoeh/antennapod/feed/FeedManager.java
+++ b/src/de/danoeh/antennapod/feed/FeedManager.java
@@ -29,6 +29,7 @@ import de.danoeh.antennapod.storage.PodDBAdapter;
import de.danoeh.antennapod.util.DownloadError;
import de.danoeh.antennapod.util.EpisodeFilter;
import de.danoeh.antennapod.util.FeedtitleComparator;
+import de.danoeh.antennapod.util.NetworkUtils;
import de.danoeh.antennapod.util.comparator.DownloadStatusComparator;
import de.danoeh.antennapod.util.comparator.FeedItemPubdateComparator;
import de.danoeh.antennapod.util.comparator.PlaybackCompletionDateComparator;
@@ -111,7 +112,8 @@ public class FeedManager {
/**
* Play FeedMedia and start the playback service + launch Mediaplayer
- * Activity.
+ * Activity. The FeedItem belonging to the media is moved to the top of the
+ * queue.
*
* @param context
* for starting the playbackservice
@@ -149,9 +151,14 @@ public class FeedManager {
context.startActivity(PlaybackService.getPlayerActivityIntent(
context, media));
}
+ if (queue.contains(media.getItem())) {
+ moveQueueItem(context, queue.indexOf(media.getItem()), 0, true);
+ } else {
+ addQueueItemAt(context, media.getItem(), 0);
+ }
} catch (MediaFileNotFoundException e) {
e.printStackTrace();
- if (PlaybackPreferences.getLastPlayedId() == media.getId()) {
+ if (media.isPlaying()) {
context.sendBroadcast(new Intent(
PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE));
}
@@ -173,14 +180,20 @@ public class FeedManager {
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(context);
- if (media.getId() == PlaybackPreferences.getLastPlayedId()) {
- SharedPreferences.Editor editor = prefs.edit();
- editor.putBoolean(PlaybackPreferences.PREF_LAST_IS_STREAM, true);
- editor.commit();
- }
- if (PlaybackPreferences.getLastPlayedId() == media.getId()) {
- context.sendBroadcast(new Intent(
- PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE));
+ if (PlaybackPreferences.getCurrentlyPlayingMedia() == FeedMedia.PLAYABLE_TYPE_FEEDMEDIA) {
+ if (media.getId() == PlaybackPreferences
+ .getCurrentlyPlayingFeedMediaId()) {
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putBoolean(
+ PlaybackPreferences.PREF_CURRENT_EPISODE_IS_STREAM,
+ true);
+ editor.commit();
+ }
+ if (PlaybackPreferences.getCurrentlyPlayingFeedMediaId() == media
+ .getId()) {
+ context.sendBroadcast(new Intent(
+ PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE));
+ }
}
}
if (AppConfig.DEBUG)
@@ -192,12 +205,13 @@ public class FeedManager {
public void deleteFeed(final Context context, final Feed feed) {
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(context.getApplicationContext());
- if (PlaybackPreferences.getLastPlayedFeedId() == feed.getId()) {
+ if (PlaybackPreferences.getCurrentlyPlayingMedia() == FeedMedia.PLAYABLE_TYPE_FEEDMEDIA
+ && PlaybackPreferences.getLastPlayedFeedId() == feed.getId()) {
context.sendBroadcast(new Intent(
PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE));
SharedPreferences.Editor editor = prefs.edit();
- editor.putLong(PlaybackPreferences.PREF_LAST_PLAYED_ID, -1);
- editor.putLong(PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID, -1);
+ editor.putLong(PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID,
+ -1);
editor.commit();
}
@@ -560,11 +574,26 @@ public class FeedManager {
}
}
- /** Downloads FeedItems if they have not been downloaded yet. */
public void downloadFeedItem(final Context context, FeedItem... items)
throws DownloadRequestException {
- List addToQueue = new ArrayList();
+ downloadFeedItem(true, context, items);
+ }
+ /** Downloads FeedItems if they have not been downloaded yet. */
+ private void downloadFeedItem(boolean performAutoCleanup,
+ final Context context, final FeedItem... items)
+ throws DownloadRequestException {
+ if (performAutoCleanup) {
+ new Thread() {
+
+ @Override
+ public void run() {
+ performAutoCleanup(context,
+ getPerformAutoCleanupArgs(items.length));
+ }
+
+ }.start();
+ }
for (FeedItem item : items) {
if (item.getMedia() != null
&& !requester.isDownloadingFile(item.getMedia())
@@ -584,15 +613,165 @@ public class FeedManager {
} else {
requester.downloadMedia(context, item.getMedia());
}
- addToQueue.add(item);
}
}
- if (UserPreferences.isAutoQueue()) {
- addQueueItem(context,
- addToQueue.toArray(new FeedItem[addToQueue.size()]));
+ }
+
+ /**
+ * This method will try to download undownloaded items in the queue or the
+ * unread items list. If not enough space is available, an episode cleanup
+ * will be performed first.
+ */
+ public void autodownloadUndownloadedItems(Context context) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Performing auto-dl of undownloaded episodes");
+ if (NetworkUtils.autodownloadNetworkAvailable(context)) {
+ int undownloadedEpisodes = getNumberOfUndownloadedEpisodes();
+ int downloadedEpisodes = getNumberOfDownloadedEpisodes();
+ int deletedEpisodes = performAutoCleanup(context,
+ getPerformAutoCleanupArgs(undownloadedEpisodes));
+ int episodeSpaceLeft = undownloadedEpisodes;
+ if (UserPreferences.getEpisodeCacheSize() < downloadedEpisodes
+ + undownloadedEpisodes) {
+ episodeSpaceLeft = UserPreferences.getEpisodeCacheSize()
+ - (downloadedEpisodes - deletedEpisodes);
+ }
+
+ List itemsToDownload = new ArrayList();
+ if (episodeSpaceLeft > 0 && undownloadedEpisodes > 0) {
+ for (FeedItem item : queue) {
+ if (item.hasMedia() && !item.getMedia().isDownloaded()) {
+ itemsToDownload.add(item);
+ episodeSpaceLeft--;
+ undownloadedEpisodes--;
+ if (episodeSpaceLeft == 0 || undownloadedEpisodes == 0) {
+ break;
+ }
+ }
+ }
+ }
+ if (episodeSpaceLeft > 0 && undownloadedEpisodes > 0) {
+ for (FeedItem item : unreadItems) {
+ if (item.hasMedia() && !item.getMedia().isDownloaded()) {
+ itemsToDownload.add(item);
+ episodeSpaceLeft--;
+ undownloadedEpisodes--;
+ if (episodeSpaceLeft == 0 || undownloadedEpisodes == 0) {
+ break;
+ }
+ }
+ }
+ }
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Enqueueing " + itemsToDownload.size()
+ + " items for download");
+
+ try {
+ downloadFeedItem(false, context,
+ itemsToDownload.toArray(new FeedItem[itemsToDownload
+ .size()]));
+ } catch (DownloadRequestException e) {
+ e.printStackTrace();
+ }
+
}
}
+ /**
+ * This method will determine the number of episodes that have to be deleted
+ * depending on a given number of episodes.
+ *
+ * @return The argument that has to be passed to performAutoCleanup() so
+ * that the number of episodes fits into the episode cache.
+ * */
+ private int getPerformAutoCleanupArgs(final int episodeNumber) {
+ if (episodeNumber >= 0) {
+ int downloadedEpisodes = getNumberOfDownloadedEpisodes();
+ if (downloadedEpisodes + episodeNumber >= UserPreferences
+ .getEpisodeCacheSize()) {
+
+ return downloadedEpisodes + episodeNumber
+ - UserPreferences.getEpisodeCacheSize();
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Performs an auto-cleanup so that the number of downloaded episodes is
+ * below or equal to the episode cache size. The method will be executed in
+ * the caller's thread.
+ */
+ public void performAutoCleanup(Context context) {
+ performAutoCleanup(context, getPerformAutoCleanupArgs(0));
+ }
+
+ /**
+ * This method will try to delete a given number of episodes. An episode
+ * will only be deleted if it is not in the queue.
+ *
+ * @return The number of episodes that were actually deleted
+ * */
+ private int performAutoCleanup(Context context, final int episodeNumber) {
+ int counter = 0;
+ int episodesLeft = episodeNumber;
+ feedloop: for (Feed feed : feeds) {
+ for (FeedItem item : feed.getItems()) {
+ if (item.hasMedia() && item.getMedia().isDownloaded()) {
+ if (!isInQueue(item) && item.isRead()) {
+ deleteFeedMedia(context, item.getMedia());
+ counter++;
+ episodesLeft--;
+ if (episodesLeft == 0) {
+ break feedloop;
+ }
+ }
+ }
+ }
+ }
+ if (AppConfig.DEBUG)
+ Log.d(TAG, String.format(
+ "Auto-delete deleted %d episodes (%d requested)", counter,
+ episodeNumber));
+
+ return counter;
+ }
+
+ /**
+ * Counts items in the queue and the unread items list which haven't been
+ * downloaded yet.
+ */
+ private int getNumberOfUndownloadedEpisodes() {
+ int counter = 0;
+ for (FeedItem item : queue) {
+ if (item.hasMedia() && !item.getMedia().isDownloaded()) {
+ counter++;
+ }
+ }
+ for (FeedItem item : unreadItems) {
+ if (item.hasMedia() && !item.getMedia().isDownloaded()) {
+ counter++;
+ }
+ }
+ return counter;
+
+ }
+
+ /** Counts all downloaded items. */
+ private int getNumberOfDownloadedEpisodes() {
+ int counter = 0;
+ for (Feed feed : feeds) {
+ for (FeedItem item : feed.getItems()) {
+ if (item.hasMedia() && item.getMedia().isDownloaded()) {
+ counter++;
+ }
+ }
+ }
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Number of downloaded episodes: " + counter);
+ return counter;
+ }
+
/**
* Enqueues all items that are currently in the unreadItems list and marks
* them as 'read'.
@@ -605,7 +784,49 @@ public class FeedManager {
}
}
- /** Adds FeedItems to the queue if they are not in the queue yet. */
+ /**
+ * Adds a feeditem to the queue at the specified index if it is not in the
+ * queue yet. The item is marked as 'read'.
+ */
+ public void addQueueItemAt(final Context context, final FeedItem item,
+ final int index) {
+ contentChanger.post(new Runnable() {
+
+ @Override
+ public void run() {
+ if (!queue.contains(item)) {
+ queue.add(index, item);
+ if (!item.isRead()) {
+ markItemRead(context, item, true, false);
+ }
+ }
+ eventDist.sendQueueUpdateBroadcast();
+
+ dbExec.execute(new Runnable() {
+
+ @Override
+ public void run() {
+ PodDBAdapter adapter = new PodDBAdapter(context);
+ adapter.open();
+ adapter.setQueue(queue);
+ adapter.close();
+ }
+ });
+ new Thread() {
+ @Override
+ public void run() {
+ autodownloadUndownloadedItems(context);
+ }
+ }.start();
+ }
+ });
+
+ }
+
+ /**
+ * Adds FeedItems to the queue if they are not in the queue yet. The items
+ * are marked as 'read'.
+ */
public void addQueueItem(final Context context, final FeedItem... items) {
if (items.length > 0) {
contentChanger.post(new Runnable() {
@@ -615,6 +836,9 @@ public class FeedManager {
for (FeedItem item : items) {
if (!queue.contains(item)) {
queue.add(item);
+ if (!item.isRead()) {
+ markItemRead(context, item, true, false);
+ }
}
}
eventDist.sendQueueUpdateBroadcast();
@@ -628,6 +852,12 @@ public class FeedManager {
adapter.close();
}
});
+ new Thread() {
+ @Override
+ public void run() {
+ autodownloadUndownloadedItems(context);
+ }
+ }.start();
}
});
}
@@ -673,14 +903,12 @@ public class FeedManager {
if (removed) {
adapter.setQueue(queue);
}
-
}
/** Removes a FeedItem from the queue. */
public void removeQueueItem(final Context context, FeedItem item) {
boolean removed = queue.remove(item);
if (removed) {
- autoDeleteIfPossible(context, item.getMedia());
dbExec.execute(new Runnable() {
@Override
@@ -693,45 +921,13 @@ public class FeedManager {
});
}
- eventDist.sendQueueUpdateBroadcast();
- }
-
- /**
- * Delete the episode of this FeedMedia object if auto-delete is enabled and
- * it is not the last played media or it is the last played media and
- * playback has been completed.
- */
- public void autoDeleteIfPossible(Context context, FeedMedia media) {
- if (media != null) {
- SharedPreferences prefs = PreferenceManager
- .getDefaultSharedPreferences(context
- .getApplicationContext());
- if (UserPreferences.isAutoDelete()) {
-
- if ((media.getId() != PlaybackPreferences.getLastPlayedId())
- && ((media.getId() != PlaybackPreferences
- .getAutoDeleteMediaId()) || (media.getId() == PlaybackPreferences
- .getAutoDeleteMediaId() && PlaybackPreferences
- .isAutoDeleteMediaPlaybackCompleted()))) {
- if (AppConfig.DEBUG)
- Log.d(TAG, "Performing auto-cleanup");
- deleteFeedMedia(context, media);
-
- SharedPreferences.Editor editor = prefs.edit();
- editor.putLong(
- PlaybackPreferences.PREF_AUTODELETE_MEDIA_ID, -1);
- editor.commit();
- } else {
- if (AppConfig.DEBUG)
- Log.d(TAG, "Didn't do auto-cleanup");
- }
- } else {
- if (AppConfig.DEBUG)
- Log.d(TAG, "Auto-delete preference is disabled");
+ new Thread() {
+ @Override
+ public void run() {
+ autodownloadUndownloadedItems(context);
}
- } else {
- Log.e(TAG, "Could not do auto-cleanup: media was null");
- }
+ }.start();
+ eventDist.sendQueueUpdateBroadcast();
}
/**
@@ -806,7 +1002,7 @@ public class FeedManager {
*
* @return The saved Feed with a database ID
*/
- public Feed updateFeed(Context context, final Feed newFeed) {
+ public Feed updateFeed(final Context context, final Feed newFeed) {
// Look up feed in the feedslist
final Feed savedFeed = searchFeedByIdentifyingValue(newFeed
.getIdentifyingValue());
@@ -853,6 +1049,12 @@ public class FeedManager {
savedFeed.setLastUpdate(newFeed.getLastUpdate());
savedFeed.setType(newFeed.getType());
setCompleteFeed(context, savedFeed);
+ new Thread() {
+ @Override
+ public void run() {
+ autodownloadUndownloadedItems(context);
+ }
+ }.start();
return savedFeed;
}
@@ -1520,6 +1722,22 @@ public class FeedManager {
}
}
+ /**
+ * Returns true if the first item in the queue is currently being played or
+ * false otherwise. If the queue is empty, this method will also return
+ * false.
+ * */
+ public boolean firstQueueItemIsPlaying() {
+ FeedManager manager = FeedManager.getInstance();
+ int queueSize = manager.getQueueSize(true);
+ if (queueSize == 0) {
+ return false;
+ } else {
+ FeedItem item = getQueueItemAtIndex(0, true);
+ return item.getState() == FeedItem.State.PLAYING;
+ }
+ }
+
/**
* Returns the number of unread items.
*
diff --git a/src/de/danoeh/antennapod/feed/FeedMedia.java b/src/de/danoeh/antennapod/feed/FeedMedia.java
index de87c63a1..fd3d2ebb0 100644
--- a/src/de/danoeh/antennapod/feed/FeedMedia.java
+++ b/src/de/danoeh/antennapod/feed/FeedMedia.java
@@ -8,6 +8,7 @@ import android.content.SharedPreferences.Editor;
import android.os.Parcel;
import android.os.Parcelable;
import de.danoeh.antennapod.PodcastApp;
+import de.danoeh.antennapod.preferences.PlaybackPreferences;
import de.danoeh.antennapod.util.ChapterUtils;
import de.danoeh.antennapod.util.playback.Playable;
@@ -103,6 +104,15 @@ public class FeedMedia extends FeedFile implements Playable {
return false;
}
+ /**
+ * Reads playback preferences to determine whether this FeedMedia object is
+ * currently being played.
+ */
+ public boolean isPlaying() {
+ return PlaybackPreferences.getCurrentlyPlayingMedia() == FeedMedia.PLAYABLE_TYPE_FEEDMEDIA
+ && PlaybackPreferences.getCurrentlyPlayingFeedMediaId() == id;
+ }
+
@Override
public int getTypeAsInt() {
return FEEDFILETYPE_FEEDMEDIA;
@@ -257,10 +267,6 @@ public class FeedMedia extends FeedFile implements Playable {
@Override
public void onPlaybackStart() {
- if (getItem().isRead() == false) {
- FeedManager.getInstance().markItemRead(PodcastApp.getInstance(),
- getItem(), true, false);
- }
}
@Override
diff --git a/src/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java b/src/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java
index 94aa2b0fc..1b7d77193 100644
--- a/src/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java
+++ b/src/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java
@@ -162,6 +162,18 @@ public class ExternalPlayerFragment extends SherlockFragment {
}
}
+
+ @Override
+ public void onPlaybackEnd() {
+ if (fragmentLayout != null) {
+ fragmentLayout.setVisibility(View.GONE);
+ }
+ controller = setupPlaybackController();
+ if (butPlay != null) {
+ butPlay.setOnClickListener(controller
+ .newOnPlayButtonClickListener());
+ }
+ }
};
}
diff --git a/src/de/danoeh/antennapod/preferences/PlaybackPreferences.java b/src/de/danoeh/antennapod/preferences/PlaybackPreferences.java
index b93b2e07c..c6a431541 100644
--- a/src/de/danoeh/antennapod/preferences/PlaybackPreferences.java
+++ b/src/de/danoeh/antennapod/preferences/PlaybackPreferences.java
@@ -17,9 +17,6 @@ public class PlaybackPreferences implements
SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = "PlaybackPreferences";
- /** Contains the type of the media that was played last. */
- public static final String PREF_LAST_PLAYED_ID = "de.danoeh.antennapod.preferences.lastPlayedId";
-
/**
* Contains the feed id of the currently playing item if it is a FeedMedia
* object.
@@ -40,31 +37,19 @@ public class PlaybackPreferences implements
public static final String PREF_CURRENTLY_PLAYING_MEDIA = "de.danoeh.antennapod.preferences.currentlyPlayingMedia";
/** True if last played media was streamed. */
- public static final String PREF_LAST_IS_STREAM = "de.danoeh.antennapod.preferences.lastIsStream";
+ public static final String PREF_CURRENT_EPISODE_IS_STREAM = "de.danoeh.antennapod.preferences.lastIsStream";
/** True if last played media was a video. */
- public static final String PREF_LAST_IS_VIDEO = "de.danoeh.antennapod.preferences.lastIsVideo";
-
- /** True if playback of last played media has been completed. */
- public static final String PREF_AUTO_DELETE_MEDIA_PLAYBACK_COMPLETED = "de.danoeh.antennapod.preferences.lastPlaybackCompleted";
-
- /**
- * ID of the last played media which should be auto-deleted as soon as
- * PREF_LAST_PLAYED_ID changes.
- */
- public static final String PREF_AUTODELETE_MEDIA_ID = "de.danoeh.antennapod.preferences.autoDeleteMediaId";
+ public static final String PREF_CURRENT_EPISODE_IS_VIDEO = "de.danoeh.antennapod.preferences.lastIsVideo";
/** Value of PREF_CURRENTLY_PLAYING_MEDIA if no media is playing. */
public static final long NO_MEDIA_PLAYING = -1;
- private long lastPlayedId;
private long currentlyPlayingFeedId;
private long currentlyPlayingFeedMediaId;
private long currentlyPlayingMedia;
- private boolean lastIsStream;
- private boolean lastIsVideo;
- private boolean autoDeleteMediaPlaybackCompleted;
- private long autoDeleteMediaId;
+ private boolean currentEpisodeIsStream;
+ private boolean currentEpisodeIsVideo;
private static PlaybackPreferences instance;
private Context context;
@@ -94,33 +79,18 @@ public class PlaybackPreferences implements
private void loadPreferences() {
SharedPreferences sp = PreferenceManager
.getDefaultSharedPreferences(context);
- lastPlayedId = sp.getLong(PREF_LAST_PLAYED_ID, -1);
currentlyPlayingFeedId = sp.getLong(PREF_CURRENTLY_PLAYING_FEED_ID, -1);
currentlyPlayingFeedMediaId = sp.getLong(
PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID, NO_MEDIA_PLAYING);
currentlyPlayingMedia = sp.getLong(PREF_CURRENTLY_PLAYING_MEDIA,
NO_MEDIA_PLAYING);
- lastIsStream = sp.getBoolean(PREF_LAST_IS_STREAM, true);
- lastIsVideo = sp.getBoolean(PREF_LAST_IS_VIDEO, false);
- autoDeleteMediaPlaybackCompleted = sp.getBoolean(
- PREF_AUTO_DELETE_MEDIA_PLAYBACK_COMPLETED, false);
- autoDeleteMediaId = sp.getLong(PREF_AUTODELETE_MEDIA_ID, -1);
+ currentEpisodeIsStream = sp.getBoolean(PREF_CURRENT_EPISODE_IS_STREAM, true);
+ currentEpisodeIsVideo = sp.getBoolean(PREF_CURRENT_EPISODE_IS_VIDEO, false);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sp, String key) {
- if (key.equals(PREF_LAST_PLAYED_ID)) {
- lastPlayedId = sp.getLong(PREF_LAST_PLAYED_ID, -1);
- long mediaId = sp.getLong(
- PlaybackPreferences.PREF_AUTODELETE_MEDIA_ID, -1);
- if (mediaId != -1) {
- FeedManager manager = FeedManager.getInstance();
- FeedMedia media = manager.getFeedMedia(mediaId);
- if (media != null) {
- manager.autoDeleteIfPossible(context, media);
- }
- }
- } else if (key.equals(PREF_CURRENTLY_PLAYING_FEED_ID)) {
+ if (key.equals(PREF_CURRENTLY_PLAYING_FEED_ID)) {
currentlyPlayingFeedId = sp.getLong(PREF_CURRENTLY_PLAYING_FEED_ID,
-1);
@@ -128,17 +98,12 @@ public class PlaybackPreferences implements
currentlyPlayingMedia = sp
.getLong(PREF_CURRENTLY_PLAYING_MEDIA, -1);
- } else if (key.equals(PREF_LAST_IS_STREAM)) {
- lastIsStream = sp.getBoolean(PREF_LAST_IS_STREAM, true);
+ } else if (key.equals(PREF_CURRENT_EPISODE_IS_STREAM)) {
+ currentEpisodeIsStream = sp.getBoolean(PREF_CURRENT_EPISODE_IS_STREAM, true);
- } else if (key.equals(PREF_LAST_IS_VIDEO)) {
- lastIsVideo = sp.getBoolean(PREF_LAST_IS_VIDEO, false);
+ } else if (key.equals(PREF_CURRENT_EPISODE_IS_VIDEO)) {
+ currentEpisodeIsVideo = sp.getBoolean(PREF_CURRENT_EPISODE_IS_VIDEO, false);
- } else if (key.equals(PREF_AUTO_DELETE_MEDIA_PLAYBACK_COMPLETED)) {
- autoDeleteMediaPlaybackCompleted = sp.getBoolean(
- PREF_AUTODELETE_MEDIA_ID, false);
- } else if (key.equals(PREF_AUTODELETE_MEDIA_ID)) {
- autoDeleteMediaId = sp.getLong(PREF_AUTODELETE_MEDIA_ID, -1);
} else if (key.equals(PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID)) {
currentlyPlayingFeedMediaId = sp.getLong(
PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID, NO_MEDIA_PLAYING);
@@ -152,14 +117,6 @@ public class PlaybackPreferences implements
}
}
- public static long getLastPlayedId() {
- instanceAvailable();
- return instance.lastPlayedId;
- }
-
- public static long getAutoDeleteMediaId() {
- return instance.autoDeleteMediaId;
- }
public static long getLastPlayedFeedId() {
instanceAvailable();
@@ -175,19 +132,14 @@ public class PlaybackPreferences implements
return instance.currentlyPlayingFeedMediaId;
}
- public static boolean isLastIsStream() {
+ public static boolean getCurrentEpisodeIsStream() {
instanceAvailable();
- return instance.lastIsStream;
+ return instance.currentEpisodeIsStream;
}
- public static boolean isLastIsVideo() {
+ public static boolean getCurrentEpisodeIsVideo() {
instanceAvailable();
- return instance.lastIsVideo;
- }
-
- public static boolean isAutoDeleteMediaPlaybackCompleted() {
- instanceAvailable();
- return instance.autoDeleteMediaPlaybackCompleted;
+ return instance.currentEpisodeIsVideo;
}
}
diff --git a/src/de/danoeh/antennapod/preferences/UserPreferences.java b/src/de/danoeh/antennapod/preferences/UserPreferences.java
index f4c0b94b0..09fb49623 100644
--- a/src/de/danoeh/antennapod/preferences/UserPreferences.java
+++ b/src/de/danoeh/antennapod/preferences/UserPreferences.java
@@ -2,8 +2,11 @@ package de.danoeh.antennapod.preferences;
import java.io.File;
import java.io.IOException;
+import java.util.Set;
import java.util.concurrent.TimeUnit;
+import org.apache.commons.lang3.StringUtils;
+
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
@@ -31,11 +34,13 @@ public class UserPreferences implements
public static final String PREF_DOWNLOAD_MEDIA_ON_WIFI_ONLY = "prefDownloadMediaOnWifiOnly";
public static final String PREF_UPDATE_INTERVAL = "prefAutoUpdateIntervall";
public static final String PREF_MOBILE_UPDATE = "prefMobileUpdate";
- public static final String PREF_AUTO_QUEUE = "prefAutoQueue";
public static final String PREF_DISPLAY_ONLY_EPISODES = "prefDisplayOnlyEpisodes";
public static final String PREF_AUTO_DELETE = "prefAutoDelete";
public static final String PREF_THEME = "prefTheme";
public static final String PREF_DATA_FOLDER = "prefDataFolder";
+ public static final String PREF_ENABLE_AUTODL_WIFI_FILTER = "prefEnableAutoDownloadWifiFilter";
+ private static final String PREF_AUTODL_SELECTED_NETWORKS = "prefAutodownloadSelectedNetworks";
+ public static final String PREF_EPISODE_CACHE_SIZE = "prefEpisodeCacheSize";
private static UserPreferences instance;
private Context context;
@@ -46,10 +51,12 @@ public class UserPreferences implements
private boolean downloadMediaOnWifiOnly;
private long updateInterval;
private boolean allowMobileUpdate;
- private boolean autoQueue;
private boolean displayOnlyEpisodes;
private boolean autoDelete;
private int theme;
+ private boolean enableAutodownloadWifiFilter;
+ private String[] autodownloadSelectedNetworks;
+ private int episodeCacheSize;
private UserPreferences(Context context) {
this.context = context;
@@ -86,10 +93,15 @@ public class UserPreferences implements
updateInterval = readUpdateInterval(sp.getString(PREF_UPDATE_INTERVAL,
"0"));
allowMobileUpdate = sp.getBoolean(PREF_MOBILE_UPDATE, false);
- autoQueue = sp.getBoolean(PREF_AUTO_QUEUE, true);
displayOnlyEpisodes = sp.getBoolean(PREF_DISPLAY_ONLY_EPISODES, false);
autoDelete = sp.getBoolean(PREF_AUTO_DELETE, false);
theme = readThemeValue(sp.getString(PREF_THEME, "0"));
+ enableAutodownloadWifiFilter = sp.getBoolean(
+ PREF_ENABLE_AUTODL_WIFI_FILTER, false);
+ autodownloadSelectedNetworks = StringUtils.split(
+ sp.getString(PREF_AUTODL_SELECTED_NETWORKS, ""), ',');
+ episodeCacheSize = Integer.valueOf(sp.getString(
+ PREF_EPISODE_CACHE_SIZE, "20"));
}
private int readThemeValue(String valueFromPrefs) {
@@ -140,11 +152,6 @@ public class UserPreferences implements
return instance.allowMobileUpdate;
}
- public static boolean isAutoQueue() {
- instanceAvailable();
- return instance.autoQueue;
- }
-
public static boolean isDisplayOnlyEpisodes() {
instanceAvailable();
return instance.displayOnlyEpisodes;
@@ -160,6 +167,21 @@ public class UserPreferences implements
return instance.theme;
}
+ public static boolean isEnableAutodownloadWifiFilter() {
+ instanceAvailable();
+ return instance.enableAutodownloadWifiFilter;
+ }
+
+ public static String[] getAutodownloadSelectedNetworks() {
+ instanceAvailable();
+ return instance.autodownloadSelectedNetworks;
+ }
+
+ public static int getEpisodeCacheSize() {
+ instanceAvailable();
+ return instance.episodeCacheSize;
+ }
+
@Override
public void onSharedPreferenceChanged(SharedPreferences sp, String key) {
if (AppConfig.DEBUG)
@@ -196,17 +218,33 @@ public class UserPreferences implements
} else if (key.equals(PREF_AUTO_DELETE)) {
autoDelete = sp.getBoolean(PREF_AUTO_DELETE, false);
- } else if (key.equals(PREF_AUTO_QUEUE)) {
- autoQueue = sp.getBoolean(PREF_AUTO_QUEUE, true);
-
} else if (key.equals(PREF_DISPLAY_ONLY_EPISODES)) {
displayOnlyEpisodes = sp.getBoolean(PREF_DISPLAY_ONLY_EPISODES,
false);
} else if (key.equals(PREF_THEME)) {
theme = readThemeValue(sp.getString(PREF_THEME, ""));
+ } else if (key.equals(PREF_ENABLE_AUTODL_WIFI_FILTER)) {
+ enableAutodownloadWifiFilter = sp.getBoolean(
+ PREF_ENABLE_AUTODL_WIFI_FILTER, false);
+ } else if (key.equals(PREF_AUTODL_SELECTED_NETWORKS)) {
+ autodownloadSelectedNetworks = StringUtils.split(
+ sp.getString(PREF_AUTODL_SELECTED_NETWORKS, ""), ',');
+ } else if (key.equals(PREF_EPISODE_CACHE_SIZE)) {
+ episodeCacheSize = Integer.valueOf(sp.getString(
+ PREF_EPISODE_CACHE_SIZE, "20"));
}
}
+ public static void setAutodownloadSelectedNetworks(Context context,
+ String[] value) {
+ SharedPreferences.Editor editor = PreferenceManager
+ .getDefaultSharedPreferences(context.getApplicationContext())
+ .edit();
+ editor.putString(PREF_AUTODL_SELECTED_NETWORKS,
+ StringUtils.join(value, ','));
+ editor.commit();
+ }
+
/**
* Return the folder where the app stores all of its data. This method will
* return the standard data folder if none has been set by the user.
diff --git a/src/de/danoeh/antennapod/receiver/ConnectivityActionReceiver.java b/src/de/danoeh/antennapod/receiver/ConnectivityActionReceiver.java
new file mode 100644
index 000000000..5c898384a
--- /dev/null
+++ b/src/de/danoeh/antennapod/receiver/ConnectivityActionReceiver.java
@@ -0,0 +1,49 @@
+package de.danoeh.antennapod.receiver;
+
+import de.danoeh.antennapod.AppConfig;
+import de.danoeh.antennapod.feed.FeedManager;
+import de.danoeh.antennapod.storage.DownloadRequester;
+import de.danoeh.antennapod.util.NetworkUtils;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.util.Log;
+
+public class ConnectivityActionReceiver extends BroadcastReceiver {
+ private static final String TAG = "ConnectivityActionReceiver";
+
+ @Override
+ public void onReceive(final Context context, Intent intent) {
+ if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Received intent");
+
+ if (NetworkUtils.autodownloadNetworkAvailable(context)) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG,
+ "auto-dl network available, starting auto-download");
+ new Thread() {
+ @Override
+ public void run() {
+ FeedManager.getInstance()
+ .autodownloadUndownloadedItems(context);
+ }
+ }.start();
+ } else { // if new network is Wi-Fi, finish ongoing downloads,
+ // otherwise cancel all downloads
+ ConnectivityManager cm = (ConnectivityManager) context
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo ni = cm.getActiveNetworkInfo();
+ if (ni == null || ni.getType() != ConnectivityManager.TYPE_WIFI) {
+ if (AppConfig.DEBUG)
+ Log.i(TAG,
+ "Device is no longer connected to Wi-Fi. Cancelling ongoing downloads");
+ DownloadRequester.getInstance().cancelAllDownloads(context);
+ }
+
+ }
+ }
+ }
+}
diff --git a/src/de/danoeh/antennapod/service/PlaybackService.java b/src/de/danoeh/antennapod/service/PlaybackService.java
index 450f7f65d..811b02535 100644
--- a/src/de/danoeh/antennapod/service/PlaybackService.java
+++ b/src/de/danoeh/antennapod/service/PlaybackService.java
@@ -85,6 +85,12 @@ public class PlaybackService extends Service {
*/
public static final String ACTION_SHUTDOWN_PLAYBACK_SERVICE = "action.de.danoeh.antennapod.service.actionShutdownPlaybackService";
+ /**
+ * If the PlaybackService receives this action, it will end playback of the
+ * current episode and load the next episode if there is one available.
+ * */
+ public static final String ACTION_SKIP_CURRENT_EPISODE = "action.de.danoeh.antennapod.service.skipCurrentEpisode";
+
/** Used in NOTIFICATION_TYPE_RELOAD. */
public static final int EXTRA_CODE_AUDIO = 1;
public static final int EXTRA_CODE_VIDEO = 2;
@@ -97,6 +103,8 @@ public class PlaybackService extends Service {
public static final int NOTIFICATION_TYPE_SLEEPTIMER_UPDATE = 4;
public static final int NOTIFICATION_TYPE_BUFFER_START = 5;
public static final int NOTIFICATION_TYPE_BUFFER_END = 6;
+ /** No more episodes are going to be played. */
+ public static final int NOTIFICATION_TYPE_PLAYBACK_END = 7;
/**
* Returned by getPositionSafe() or getDurationSafe() if the playbackService
@@ -173,7 +181,7 @@ public class PlaybackService extends Service {
return new Intent(context, AudioplayerActivity.class);
}
} else {
- if (PlaybackPreferences.isLastIsVideo()) {
+ if (PlaybackPreferences.getCurrentEpisodeIsVideo()) {
return new Intent(context, VideoplayerActivity.class);
} else {
return new Intent(context, AudioplayerActivity.class);
@@ -194,35 +202,6 @@ public class PlaybackService extends Service {
}
}
- /** Get last played FeedMedia object or null if it doesn't exist. */
- public static FeedMedia getLastPlayedMediaFromPreferences(Context context) {
- SharedPreferences prefs = PreferenceManager
- .getDefaultSharedPreferences(context.getApplicationContext());
- long mediaId = PlaybackPreferences.getLastPlayedId();
- long feedId = PlaybackPreferences.getLastPlayedFeedId();
- FeedManager manager = FeedManager.getInstance();
- if (mediaId != -1 && feedId != -1) {
- Feed feed = manager.getFeed(feedId);
- if (feed != null) {
- return manager.getFeedMedia(mediaId, feed);
- }
- }
- return null;
- }
-
- private void setLastPlayedMediaId(long mediaId) {
- SharedPreferences prefs = PreferenceManager
- .getDefaultSharedPreferences(getApplicationContext());
- long autoDeleteId = PlaybackPreferences.getAutoDeleteMediaId();
- SharedPreferences.Editor editor = prefs.edit();
- if (mediaId == autoDeleteId) {
- editor.putBoolean(
- PlaybackPreferences.PREF_AUTO_DELETE_MEDIA_PLAYBACK_COMPLETED,
- false);
- }
- editor.commit();
- }
-
@SuppressLint("NewApi")
@Override
public void onCreate() {
@@ -266,6 +245,8 @@ public class PlaybackService extends Service {
ACTION_SHUTDOWN_PLAYBACK_SERVICE));
registerReceiver(audioBecomingNoisy, new IntentFilter(
AudioManager.ACTION_AUDIO_BECOMING_NOISY));
+ registerReceiver(skipCurrentEpisodeReceiver, new IntentFilter(
+ ACTION_SKIP_CURRENT_EPISODE));
}
@@ -296,6 +277,7 @@ public class PlaybackService extends Service {
unregisterReceiver(headsetDisconnected);
unregisterReceiver(shutdownReceiver);
unregisterReceiver(audioBecomingNoisy);
+ unregisterReceiver(skipCurrentEpisodeReceiver);
if (android.os.Build.VERSION.SDK_INT >= 14) {
audioManager.unregisterRemoteControlClient(remoteControlClient);
}
@@ -460,25 +442,28 @@ public class PlaybackService extends Service {
@Override
protected void onPostExecute(Playable result) {
- if (result != null) {
- try {
- if (shouldStream) {
- player.setDataSource(media.getStreamUrl());
- setStatus(PlayerStatus.PREPARING);
- player.prepareAsync();
- } else {
- player.setDataSource(media
- .getLocalMediaUrl());
- setStatus(PlayerStatus.PREPARING);
- player.prepareAsync();
+ if (status == PlayerStatus.INITIALIZING) {
+ if (result != null) {
+ try {
+ if (shouldStream) {
+ player.setDataSource(media
+ .getStreamUrl());
+ setStatus(PlayerStatus.PREPARING);
+ player.prepareAsync();
+ } else {
+ player.setDataSource(media
+ .getLocalMediaUrl());
+ setStatus(PlayerStatus.PREPARING);
+ player.prepareAsync();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
}
- } catch (IOException e) {
- e.printStackTrace();
+ } else {
+ setStatus(PlayerStatus.ERROR);
+ sendBroadcast(new Intent(
+ ACTION_SHUTDOWN_PLAYBACK_SERVICE));
}
- } else {
- setStatus(PlayerStatus.ERROR);
- sendBroadcast(new Intent(
- ACTION_SHUTDOWN_PLAYBACK_SERVICE));
}
}
@@ -510,7 +495,9 @@ public class PlaybackService extends Service {
player.release();
player = createMediaPlayer();
status = PlayerStatus.STOPPED;
- initMediaplayer();
+ if (media != null) {
+ initMediaplayer();
+ }
}
public void notifyVideoSurfaceAbandoned() {
@@ -531,35 +518,45 @@ public class PlaybackService extends Service {
@Override
protected void onPostExecute(Playable result) {
- if (result != null) {
- playingVideo = false;
- try {
- if (shouldStream) {
- player.setDataSource(media.getStreamUrl());
- } else if (media.localFileAvailable()) {
- player.setDataSource(media
- .getLocalMediaUrl());
- }
+ // check if state of service has changed. If it has
+ // changed, assume that loaded metadata is not needed
+ // anymore.
+ if (status == PlayerStatus.INITIALIZING) {
+ if (result != null) {
+ playingVideo = false;
+ try {
+ if (shouldStream) {
+ player.setDataSource(media
+ .getStreamUrl());
+ } else if (media.localFileAvailable()) {
+ player.setDataSource(media
+ .getLocalMediaUrl());
+ }
- if (prepareImmediately) {
- setStatus(PlayerStatus.PREPARING);
- player.prepareAsync();
- } else {
- setStatus(PlayerStatus.INITIALIZED);
+ if (prepareImmediately) {
+ setStatus(PlayerStatus.PREPARING);
+ player.prepareAsync();
+ } else {
+ setStatus(PlayerStatus.INITIALIZED);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ media = null;
+ setStatus(PlayerStatus.ERROR);
+ sendBroadcast(new Intent(
+ ACTION_SHUTDOWN_PLAYBACK_SERVICE));
}
- } catch (IOException e) {
- e.printStackTrace();
+ } else {
+ Log.e(TAG, "InitTask could not load metadata");
media = null;
setStatus(PlayerStatus.ERROR);
sendBroadcast(new Intent(
ACTION_SHUTDOWN_PLAYBACK_SERVICE));
}
} else {
- Log.e(TAG, "InitTask could not load metadata");
- media = null;
- setStatus(PlayerStatus.ERROR);
- sendBroadcast(new Intent(
- ACTION_SHUTDOWN_PLAYBACK_SERVICE));
+ if (AppConfig.DEBUG)
+ Log.d(TAG,
+ "Status of player has changed during initialization. Stopping init process.");
}
}
@@ -673,78 +670,7 @@ public class PlaybackService extends Service {
@Override
public void onCompletion(MediaPlayer mp) {
- if (AppConfig.DEBUG)
- Log.d(TAG, "Playback completed");
- audioManager.abandonAudioFocus(audioFocusChangeListener);
- SharedPreferences prefs = PreferenceManager
- .getDefaultSharedPreferences(getApplicationContext());
- SharedPreferences.Editor editor = prefs.edit();
-
- // Save state
- cancelPositionSaver();
-
- boolean isInQueue = false;
- FeedItem nextItem = null;
-
- if (media instanceof FeedMedia) {
- FeedItem item = ((FeedMedia) media).getItem();
- ((FeedMedia) media).setPlaybackCompletionDate(new Date());
- manager.markItemRead(PlaybackService.this, item, true, true);
- nextItem = manager.getQueueSuccessorOfItem(item);
- isInQueue = media instanceof FeedMedia
- && manager.isInQueue(((FeedMedia) media).getItem());
- if (isInQueue) {
- manager.removeQueueItem(PlaybackService.this, item);
- }
- manager.addItemToPlaybackHistory(PlaybackService.this, item);
- manager.setFeedMedia(PlaybackService.this, (FeedMedia) media);
- long autoDeleteMediaId = ((FeedComponent) media).getId();
- if (shouldStream) {
- autoDeleteMediaId = -1;
- }
- editor.putLong(PlaybackPreferences.PREF_AUTODELETE_MEDIA_ID,
- autoDeleteMediaId);
- }
- editor.putLong(PlaybackPreferences.PREF_CURRENTLY_PLAYING_MEDIA,
- PlaybackPreferences.NO_MEDIA_PLAYING);
- editor.putBoolean(
- PlaybackPreferences.PREF_AUTO_DELETE_MEDIA_PLAYBACK_COMPLETED,
- true);
- editor.putLong(
- PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID,
- PlaybackPreferences.NO_MEDIA_PLAYING);
- editor.putLong(PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID,
- PlaybackPreferences.NO_MEDIA_PLAYING);
- editor.commit();
-
- // Prepare for playing next item
- boolean playNextItem = isInQueue && UserPreferences.isFollowQueue()
- && nextItem != null;
- if (playNextItem) {
- if (AppConfig.DEBUG)
- Log.d(TAG, "Loading next item in queue");
- media = nextItem.getMedia();
- shouldStream = !media.localFileAvailable();
- prepareImmediately = startWhenPrepared = true;
- } else {
- if (AppConfig.DEBUG)
- Log.d(TAG,
- "No more episodes available to play; Reloading current episode");
- prepareImmediately = startWhenPrepared = false;
- stopForeground(true);
- stopWidgetUpdater();
- }
- int notificationCode = 0;
- if (media.getMediaType() == MediaType.AUDIO) {
- notificationCode = EXTRA_CODE_AUDIO;
- playingVideo = false;
- } else if (media.getMediaType() == MediaType.VIDEO) {
- notificationCode = EXTRA_CODE_VIDEO;
- }
- resetVideoSurface();
- refreshRemoteControlClientState();
- sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD,
- notificationCode);
+ endPlayback(true);
}
};
@@ -757,6 +683,82 @@ public class PlaybackService extends Service {
}
};
+ private void endPlayback(boolean playNextEpisode) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Playback ended");
+ audioManager.abandonAudioFocus(audioFocusChangeListener);
+
+ // Save state
+ cancelPositionSaver();
+
+ boolean isInQueue = false;
+ FeedItem nextItem = null;
+
+ if (media instanceof FeedMedia) {
+ FeedItem item = ((FeedMedia) media).getItem();
+ ((FeedMedia) media).setPlaybackCompletionDate(new Date());
+ manager.markItemRead(PlaybackService.this, item, true, true);
+ nextItem = manager.getQueueSuccessorOfItem(item);
+ isInQueue = media instanceof FeedMedia
+ && manager.isInQueue(((FeedMedia) media).getItem());
+ if (isInQueue) {
+ manager.removeQueueItem(PlaybackService.this, item);
+ }
+ manager.addItemToPlaybackHistory(PlaybackService.this, item);
+ manager.setFeedMedia(PlaybackService.this, (FeedMedia) media);
+ long autoDeleteMediaId = ((FeedComponent) media).getId();
+ if (shouldStream) {
+ autoDeleteMediaId = -1;
+ }
+ }
+
+ // Load next episode if previous episode was in the queue and if there
+ // is an episode in the queue left.
+ // Start playback immediately if continuous playback is enabled
+ boolean loadNextItem = isInQueue && nextItem != null;
+ playNextEpisode = playNextEpisode && loadNextItem
+ && UserPreferences.isFollowQueue();
+ if (loadNextItem) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Loading next item in queue");
+ media = nextItem.getMedia();
+ }
+
+ if (playNextEpisode) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Playback of next episode will start immediately.");
+ prepareImmediately = startWhenPrepared = true;
+ } else {
+ if (AppConfig.DEBUG)
+ Log.d(TAG,
+ "No more episodes available to play");
+ media = null;
+ prepareImmediately = startWhenPrepared = false;
+ stopForeground(true);
+ stopWidgetUpdater();
+ }
+
+ int notificationCode = 0;
+ if (media != null) {
+ shouldStream = !media.localFileAvailable();
+ if (media.getMediaType() == MediaType.AUDIO) {
+ notificationCode = EXTRA_CODE_AUDIO;
+ playingVideo = false;
+ } else if (media.getMediaType() == MediaType.VIDEO) {
+ notificationCode = EXTRA_CODE_VIDEO;
+ }
+ }
+ writePlaybackPreferences();
+ if (media != null) {
+ resetVideoSurface();
+ refreshRemoteControlClientState();
+ sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD, notificationCode);
+ } else {
+ sendNotificationBroadcast(NOTIFICATION_TYPE_PLAYBACK_END, 0);
+ stopSelf();
+ }
+ }
+
public void setSleepTimer(long waitingTime) {
if (AppConfig.DEBUG)
Log.d(TAG, "Setting sleep timer to " + Long.toString(waitingTime)
@@ -856,40 +858,8 @@ public class PlaybackService extends Service {
Log.d(TAG, "Audiofocus successfully requested");
if (AppConfig.DEBUG)
Log.d(TAG, "Resuming/Starting playback");
- SharedPreferences.Editor editor = PreferenceManager
- .getDefaultSharedPreferences(getApplicationContext())
- .edit();
- editor.putLong(
- PlaybackPreferences.PREF_CURRENTLY_PLAYING_MEDIA,
- media.getPlayableType());
- editor.putBoolean(PlaybackPreferences.PREF_LAST_IS_STREAM,
- shouldStream);
- editor.putBoolean(PlaybackPreferences.PREF_LAST_IS_VIDEO,
- playingVideo);
- editor.putLong(PlaybackPreferences.PREF_LAST_PLAYED_ID,
- media.getPlayableType());
- if (media instanceof FeedMedia) {
- FeedMedia fMedia = (FeedMedia) media;
- editor.putLong(
- PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID,
- fMedia.getItem().getFeed().getId());
- editor.putLong(
- PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID,
- fMedia.getId());
- } else {
- editor.putLong(
- PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID,
- PlaybackPreferences.NO_MEDIA_PLAYING);
- editor.putLong(
- PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID,
- PlaybackPreferences.NO_MEDIA_PLAYING);
- }
- media.writeToPreferences(editor);
+ writePlaybackPreferences();
- editor.commit();
- if (media instanceof FeedMedia) {
- setLastPlayedMediaId(((FeedMedia) media).getId());
- }
player.start();
if (status != PlayerStatus.PAUSED) {
player.seekTo((int) media.getPosition());
@@ -913,6 +883,51 @@ public class PlaybackService extends Service {
}
}
+ private void writePlaybackPreferences() {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Writing playback preferences");
+
+ SharedPreferences.Editor editor = PreferenceManager
+ .getDefaultSharedPreferences(getApplicationContext()).edit();
+ if (media != null) {
+ editor.putLong(PlaybackPreferences.PREF_CURRENTLY_PLAYING_MEDIA,
+ media.getPlayableType());
+ editor.putBoolean(
+ PlaybackPreferences.PREF_CURRENT_EPISODE_IS_STREAM,
+ shouldStream);
+ editor.putBoolean(
+ PlaybackPreferences.PREF_CURRENT_EPISODE_IS_VIDEO,
+ playingVideo);
+ if (media instanceof FeedMedia) {
+ FeedMedia fMedia = (FeedMedia) media;
+ editor.putLong(
+ PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID,
+ fMedia.getItem().getFeed().getId());
+ editor.putLong(
+ PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID,
+ fMedia.getId());
+ } else {
+ editor.putLong(
+ PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID,
+ PlaybackPreferences.NO_MEDIA_PLAYING);
+ editor.putLong(
+ PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID,
+ PlaybackPreferences.NO_MEDIA_PLAYING);
+ }
+ media.writeToPreferences(editor);
+ } else {
+ editor.putLong(PlaybackPreferences.PREF_CURRENTLY_PLAYING_MEDIA,
+ PlaybackPreferences.NO_MEDIA_PLAYING);
+ editor.putLong(PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID,
+ PlaybackPreferences.NO_MEDIA_PLAYING);
+ editor.putLong(
+ PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID,
+ PlaybackPreferences.NO_MEDIA_PLAYING);
+ }
+
+ editor.commit();
+ }
+
private void setStatus(PlayerStatus newStatus) {
if (AppConfig.DEBUG)
Log.d(TAG, "Setting status to " + newStatus);
@@ -1005,7 +1020,9 @@ public class PlaybackService extends Service {
public void seek(int i) {
saveCurrentPosition();
- if (status == PlayerStatus.INITIALIZED) {
+ if (status == PlayerStatus.INITIALIZED
+ || status == PlayerStatus.INITIALIZING
+ || status == PlayerStatus.PREPARING) {
media.setPosition(i);
setStartWhenPrepared(true);
prepare();
@@ -1201,6 +1218,22 @@ public class PlaybackService extends Service {
};
+ private BroadcastReceiver skipCurrentEpisodeReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction().equals(ACTION_SKIP_CURRENT_EPISODE)) {
+
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Received SKIP_CURRENT_EPISODE intent");
+ if (media != null) {
+ setStatus(PlayerStatus.STOPPED);
+ player.reset();
+ endPlayback(false);
+ }
+ }
+ }
+ };
+
/** Periodically saves the position of the media file */
class PositionSaver implements Runnable {
public static final int WAITING_INTERVALL = 5000;
diff --git a/src/de/danoeh/antennapod/service/download/DownloadService.java b/src/de/danoeh/antennapod/service/download/DownloadService.java
index 986491fb5..d72e3704b 100644
--- a/src/de/danoeh/antennapod/service/download/DownloadService.java
+++ b/src/de/danoeh/antennapod/service/download/DownloadService.java
@@ -58,6 +58,7 @@ import de.danoeh.antennapod.feed.FeedImage;
import de.danoeh.antennapod.feed.FeedItem;
import de.danoeh.antennapod.feed.FeedManager;
import de.danoeh.antennapod.feed.FeedMedia;
+import de.danoeh.antennapod.preferences.UserPreferences;
import de.danoeh.antennapod.storage.DownloadRequestException;
import de.danoeh.antennapod.storage.DownloadRequester;
import de.danoeh.antennapod.syndication.handler.FeedHandler;
@@ -831,7 +832,7 @@ public class DownloadService extends Service {
} finally {
mediaplayer.release();
}
-
+
if (media.getItem().getChapters() == null) {
ChapterUtils.loadChaptersFromFileUrl(media);
if (media.getItem().getChapters() != null) {
@@ -847,6 +848,11 @@ public class DownloadService extends Service {
manager.setFeedMedia(DownloadService.this, media);
}
+ if (!FeedManager.getInstance().isInQueue(media.getItem())) {
+ FeedManager.getInstance().addQueueItem(DownloadService.this,
+ media.getItem());
+ }
+
downloadsBeingHandled -= 1;
handler.post(new Runnable() {
diff --git a/src/de/danoeh/antennapod/util/NetworkUtils.java b/src/de/danoeh/antennapod/util/NetworkUtils.java
new file mode 100644
index 000000000..6064f3f91
--- /dev/null
+++ b/src/de/danoeh/antennapod/util/NetworkUtils.java
@@ -0,0 +1,63 @@
+package de.danoeh.antennapod.util;
+
+import java.util.Arrays;
+import java.util.List;
+
+import de.danoeh.antennapod.AppConfig;
+import de.danoeh.antennapod.preferences.UserPreferences;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.util.Log;
+
+public class NetworkUtils {
+ private static final String TAG = "NetworkUtils";
+
+ private NetworkUtils() {
+
+ }
+
+ /**
+ * Returns true if the device is connected to Wi-Fi and the Wi-Fi filter for
+ * automatic downloads is disabled or the device is connected to a Wi-Fi
+ * network that is on the 'selected networks' list of the Wi-Fi filter for
+ * automatic downloads and false otherwise.
+ * */
+ public static boolean autodownloadNetworkAvailable(Context context) {
+ ConnectivityManager cm = (ConnectivityManager) context
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo networkInfo = cm.getActiveNetworkInfo();
+ if (networkInfo != null) {
+ if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Device is connected to Wi-Fi");
+ if (networkInfo.isConnected()) {
+ if (!UserPreferences.isEnableAutodownloadWifiFilter()) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Auto-dl filter is disabled");
+ return true;
+ } else {
+ WifiManager wm = (WifiManager) context
+ .getSystemService(Context.WIFI_SERVICE);
+ WifiInfo wifiInfo = wm.getConnectionInfo();
+ List selectedNetworks = Arrays
+ .asList(UserPreferences
+ .getAutodownloadSelectedNetworks());
+ if (selectedNetworks.contains(Integer.toString(wifiInfo
+ .getNetworkId()))) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG,
+ "Current network is on the selected networks list");
+ return true;
+ }
+ }
+ }
+ }
+ }
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Network for auto-dl is not available");
+ return false;
+ }
+}
diff --git a/src/de/danoeh/antennapod/util/menuhandler/FeedItemMenuHandler.java b/src/de/danoeh/antennapod/util/menuhandler/FeedItemMenuHandler.java
index 9cdf8eec2..b1bc5a8e2 100644
--- a/src/de/danoeh/antennapod/util/menuhandler/FeedItemMenuHandler.java
+++ b/src/de/danoeh/antennapod/util/menuhandler/FeedItemMenuHandler.java
@@ -3,10 +3,12 @@ package de.danoeh.antennapod.util.menuhandler;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+import de.danoeh.antennapod.AppConfig;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.asynctask.FlattrClickWorker;
import de.danoeh.antennapod.feed.FeedItem;
import de.danoeh.antennapod.feed.FeedManager;
+import de.danoeh.antennapod.service.PlaybackService;
import de.danoeh.antennapod.storage.DownloadRequestException;
import de.danoeh.antennapod.storage.DownloadRequester;
import de.danoeh.antennapod.util.ShareUtils;
@@ -55,16 +57,22 @@ public class FeedItemMenuHandler {
&& requester.isDownloadingFile(selectedItem.getMedia());
boolean notLoadedAndNotLoading = hasMedia && (!downloaded)
&& (!downloading);
+ boolean isPlaying = hasMedia
+ && selectedItem.getState() == FeedItem.State.PLAYING;
+
FeedItem.State state = selectedItem.getState();
- if (!downloaded) {
+ if (!isPlaying) {
+ mi.setItemVisibility(R.id.skip_episode_item, false);
+ }
+ if (!downloaded || isPlaying) {
mi.setItemVisibility(R.id.play_item, false);
mi.setItemVisibility(R.id.remove_item, false);
}
if (!notLoadedAndNotLoading) {
mi.setItemVisibility(R.id.download_item, false);
}
- if (!(notLoadedAndNotLoading | downloading)) {
+ if (!(notLoadedAndNotLoading | downloading) | isPlaying) {
mi.setItemVisibility(R.id.stream_item, false);
}
if (!downloading) {
@@ -82,7 +90,8 @@ public class FeedItemMenuHandler {
mi.setItemVisibility(R.id.share_link_item, false);
}
- if (!(state == FeedItem.State.IN_PROGRESS || state == FeedItem.State.READ)) {
+ if (!AppConfig.DEBUG
+ || !(state == FeedItem.State.IN_PROGRESS || state == FeedItem.State.READ)) {
mi.setItemVisibility(R.id.mark_unread_item, false);
}
if (!(state == FeedItem.State.NEW || state == FeedItem.State.IN_PROGRESS)) {
@@ -104,6 +113,10 @@ public class FeedItemMenuHandler {
DownloadRequester requester = DownloadRequester.getInstance();
FeedManager manager = FeedManager.getInstance();
switch (menuItemId) {
+ case R.id.skip_episode_item:
+ context.sendBroadcast(new Intent(
+ PlaybackService.ACTION_SKIP_CURRENT_EPISODE));
+ break;
case R.id.download_item:
manager.downloadFeedItem(context, selectedItem);
break;
diff --git a/src/de/danoeh/antennapod/util/playback/PlaybackController.java b/src/de/danoeh/antennapod/util/playback/PlaybackController.java
index 699ff6699..331e2bf0c 100644
--- a/src/de/danoeh/antennapod/util/playback/PlaybackController.java
+++ b/src/de/danoeh/antennapod/util/playback/PlaybackController.java
@@ -188,9 +188,9 @@ public abstract class PlaybackController {
Log.d(TAG, "Trying to restore last played media");
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(activity.getApplicationContext());
- long lastPlayedId = PlaybackPreferences.getLastPlayedId();
- if (lastPlayedId != PlaybackPreferences.NO_MEDIA_PLAYING) {
- Playable media = PlayableUtils.createInstanceFromPreferences((int) lastPlayedId, prefs);
+ long currentlyPlayingMedia = PlaybackPreferences.getCurrentlyPlayingMedia();
+ if (currentlyPlayingMedia != PlaybackPreferences.NO_MEDIA_PLAYING) {
+ Playable media = PlayableUtils.createInstanceFromPreferences((int) currentlyPlayingMedia, prefs);
if (media != null) {
Intent serviceIntent = new Intent(activity,
PlaybackService.class);
@@ -200,7 +200,7 @@ public abstract class PlaybackController {
serviceIntent.putExtra(
PlaybackService.EXTRA_PREPARE_IMMEDIATELY, false);
boolean fileExists = media.localFileAvailable();
- boolean lastIsStream = PlaybackPreferences.isLastIsStream();
+ boolean lastIsStream = PlaybackPreferences.getCurrentEpisodeIsStream();
if (!fileExists && !lastIsStream && media instanceof FeedMedia) {
FeedManager.getInstance().notifyMissingFeedMediaFile(
activity, (FeedMedia) media);
@@ -320,6 +320,9 @@ public abstract class PlaybackController {
case PlaybackService.NOTIFICATION_TYPE_BUFFER_END:
onBufferEnd();
break;
+ case PlaybackService.NOTIFICATION_TYPE_PLAYBACK_END:
+ onPlaybackEnd();
+ break;
}
} else {
@@ -357,6 +360,8 @@ public abstract class PlaybackController {
public abstract void onSleepTimerUpdate();
public abstract void handleError(int code);
+
+ public abstract void onPlaybackEnd();
/**
* Is called whenever the PlaybackService changes it's status. This method