summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/build.gradle4
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java5
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java5
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java13
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java5
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java5
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java7
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java25
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java22
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java3
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java3
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java9
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java3
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java17
-rw-r--r--app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java5
-rw-r--r--app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java86
-rw-r--r--app/src/main/res/layout/queue_listitem.xml2
-rw-r--r--app/src/main/res/xml/preferences.xml14
-rw-r--r--build.gradle2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java44
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java13
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java7
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java27
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java8
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java15
-rw-r--r--core/src/main/res/values/arrays.xml3
-rw-r--r--core/src/main/res/values/strings.xml23
32 files changed, 307 insertions, 92 deletions
diff --git a/app/build.gradle b/app/build.gradle
index 7025d46ad..f2888cf2f 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -32,8 +32,8 @@ dependencies {
compile "io.reactivex:rxjava:$rxJavaVersion"
// And ProGuard rules for RxJava!
compile "com.artemzin.rxjava:proguard-rules:$rxJavaRulesVersion"
- compile "com.joanzapata.iconify:android-iconify-fontawesome:$iconifyFontawesomeVersion"
- compile "com.joanzapata.iconify:android-iconify-material:$iconifyFontawesomeVersion"
+ compile "com.joanzapata.iconify:android-iconify-fontawesome:$iconifyVersion"
+ compile "com.joanzapata.iconify:android-iconify-material:$iconifyVersion"
compile("com.github.afollestad.material-dialogs:commons:$materialDialogsVersion") {
transitive = true
}
diff --git a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java
index d65925703..d4994fb1a 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java
@@ -49,10 +49,11 @@ public class PlaybackSonicTest extends ActivityInstrumentationTestCase2<MainActi
public void setUp() throws Exception {
super.setUp();
- PodDBAdapter.deleteDatabase();
-
context = getInstrumentation().getTargetContext();
+ PodDBAdapter.init(context);
+ PodDBAdapter.deleteDatabase();
+
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
prefs.edit()
.clear()
diff --git a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java
index 016c868b4..5ce495f9a 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java
@@ -46,10 +46,11 @@ public class PlaybackTest extends ActivityInstrumentationTestCase2<MainActivity>
public void setUp() throws Exception {
super.setUp();
- PodDBAdapter.deleteDatabase();
-
context = getInstrumentation().getTargetContext();
+ PodDBAdapter.init(context);
+ PodDBAdapter.deleteDatabase();
+
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
prefs.edit()
.clear()
diff --git a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java
index 897098c00..b70336a30 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java
@@ -223,6 +223,8 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
String[] values = res.getStringArray(R.array.episode_cache_size_values);
String entry = entries[entries.length/2];
final int value = Integer.valueOf(values[values.length/2]);
+ solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
+ solo.waitForText(solo.getString(R.string.pref_automatic_download_title));
solo.clickOnText(solo.getString(R.string.pref_episode_cache_title));
solo.waitForDialogToOpen();
solo.clickOnText(entry);
@@ -234,6 +236,11 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
String[] values = res.getStringArray(R.array.episode_cache_size_values);
String minEntry = entries[0];
final int minValue = Integer.valueOf(values[0]);
+ solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
+ solo.waitForText(solo.getString(R.string.pref_automatic_download_title));
+ if(!UserPreferences.isEnableAutodownload()) {
+ solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
+ }
solo.clickOnText(solo.getString(R.string.pref_episode_cache_title));
solo.waitForDialogToOpen(1000);
solo.scrollUp();
@@ -241,12 +248,16 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
assertTrue(solo.waitForCondition(() -> UserPreferences.getEpisodeCacheSize() == minValue, Timeout.getLargeTimeout()));
}
-
public void testSetEpisodeCacheMax() {
String[] entries = res.getStringArray(R.array.episode_cache_size_entries);
String[] values = res.getStringArray(R.array.episode_cache_size_values);
String maxEntry = entries[entries.length-1];
final int maxValue = Integer.valueOf(values[values.length-1]);
+ solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
+ solo.waitForText(solo.getString(R.string.pref_automatic_download_title));
+ if(!UserPreferences.isEnableAutodownload()) {
+ solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
+ }
solo.clickOnText(solo.getString(R.string.pref_episode_cache_title));
solo.waitForDialogToOpen();
solo.clickOnText(maxEntry);
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java
index 014c65e11..50d557735 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java
@@ -499,6 +499,11 @@ public class AudioplayerActivity extends MediaplayerActivity implements NavDrawe
}
@Override
+ public int getNumberOfDownloadedItems() {
+ return (navDrawerData != null) ? navDrawerData.numDownloadedItems : 0;
+ }
+
+ @Override
public int getFeedCounter(long feedId) {
return navDrawerData != null ? navDrawerData.feedCounters.get(feedId) : 0;
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
index 17cd5ace3..2181e7d2d 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
@@ -636,6 +636,11 @@ public class MainActivity extends AppCompatActivity implements NavDrawerActivity
}
@Override
+ public int getNumberOfDownloadedItems() {
+ return (navDrawerData != null) ? navDrawerData.numDownloadedItems : 0;
+ }
+
+ @Override
public int getFeedCounter(long feedId) {
return navDrawerData != null ? navDrawerData.feedCounters.get(feedId) : 0;
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java
index f120aa1d5..1fa4b7c48 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java
@@ -4,7 +4,6 @@ import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
-import android.text.format.DateUtils;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
@@ -15,7 +14,6 @@ import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
-import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
@@ -36,6 +34,7 @@ import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.Converter;
+import de.danoeh.antennapod.core.util.DateUtils;
import de.danoeh.antennapod.core.util.NetworkUtils;
import de.danoeh.antennapod.fragment.ItemFragment;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
@@ -118,8 +117,8 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
holder.placeholder.setVisibility(View.VISIBLE);
holder.placeholder.setText(item.getFeed().getTitle());
holder.title.setText(item.getTitle());
- holder.pubDate.setText(DateUtils.formatDateTime(mainActivityRef.get(),
- item.getPubDate().getTime(), DateUtils.FORMAT_ABBREV_ALL));
+ String pubDateStr = DateUtils.formatAbbrev(mainActivityRef.get(), item.getPubDate());
+ holder.pubDate.setText(pubDateStr);
if (showOnlyNewEpisodes || false == item.isNew()) {
holder.statusUnread.setVisibility(View.INVISIBLE);
} else {
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java
index 2b1eccea5..ca747b9b0 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java
@@ -1,7 +1,6 @@
package de.danoeh.antennapod.adapter;
import android.content.Context;
-import android.text.format.DateUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -11,12 +10,12 @@ import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
-import com.bumptech.glide.load.engine.DiskCacheStrategy;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.util.Converter;
+import de.danoeh.antennapod.core.util.DateUtils;
/**
* Shows a list of downloaded episodes
@@ -75,7 +74,8 @@ public class DownloadedEpisodesListAdapter extends BaseAdapter {
}
holder.title.setText(item.getTitle());
- holder.pubDate.setText(DateUtils.formatDateTime(context, item.getPubDate().getTime(), DateUtils.FORMAT_ABBREV_ALL));
+ String pubDateStr = DateUtils.formatAbbrev(context, item.getPubDate());
+ holder.pubDate.setText(pubDateStr);
holder.txtvSize.setText(Converter.byteToString(item.getMedia().getSize()));
FeedItem.State state = item.getState();
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java
index e1d158d6a..e483738b4 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java
@@ -2,7 +2,6 @@ package de.danoeh.antennapod.adapter;
import android.content.Context;
import android.content.res.TypedArray;
-import android.text.format.DateUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
@@ -23,6 +22,7 @@ import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.MediaType;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DownloadRequester;
+import de.danoeh.antennapod.core.util.DateUtils;
import de.danoeh.antennapod.core.util.ThemeUtils;
/**
@@ -143,8 +143,8 @@ public class FeedItemlistAdapter extends BaseAdapter {
ViewHelper.setAlpha(convertView, 1.0f);
}
- holder.published.setText(DateUtils.formatDateTime(context, item.getPubDate().getTime(), DateUtils.FORMAT_ABBREV_ALL));
-
+ String pubDateStr = DateUtils.formatAbbrev(context, item.getPubDate());
+ holder.published.setText(pubDateStr);
FeedMedia media = item.getMedia();
if (media == null) {
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java
index 183c1a44e..d43e30d8f 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java
@@ -6,6 +6,7 @@ import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.preference.PreferenceManager;
+import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -15,7 +16,7 @@ import android.widget.RelativeLayout;
import android.widget.TextView;
import com.bumptech.glide.Glide;
-import com.bumptech.glide.load.engine.DiskCacheStrategy;
+import com.joanzapata.iconify.Iconify;
import com.joanzapata.iconify.widget.IconTextView;
import org.apache.commons.lang3.ArrayUtils;
@@ -208,7 +209,8 @@ public class NavListAdapter extends BaseAdapter
holder.title.setText(title);
- if (tags.get(position).equals(QueueFragment.TAG)) {
+ String tag = tags.get(position);
+ if (tag.equals(QueueFragment.TAG)) {
int queueSize = itemAccess.getQueueSize();
if (queueSize > 0) {
holder.count.setVisibility(View.VISIBLE);
@@ -216,7 +218,7 @@ public class NavListAdapter extends BaseAdapter
} else {
holder.count.setVisibility(View.GONE);
}
- } else if (tags.get(position).equals(EpisodesFragment.TAG)) {
+ } else if (tag.equals(EpisodesFragment.TAG)) {
int unreadItems = itemAccess.getNumberOfNewItems();
if (unreadItems > 0) {
holder.count.setVisibility(View.VISIBLE);
@@ -224,6 +226,22 @@ public class NavListAdapter extends BaseAdapter
} else {
holder.count.setVisibility(View.GONE);
}
+ } else if(tag.equals(DownloadsFragment.TAG) && UserPreferences.isEnableAutodownload()) {
+ int epCacheSize = UserPreferences.getEpisodeCacheSize();
+ if(itemAccess.getNumberOfDownloadedItems() >= epCacheSize) {
+ holder.count.setText("{md-disc-full 150%}");
+ Iconify.addIcons(holder.count);
+ holder.count.setVisibility(View.VISIBLE);
+ holder.count.setOnClickListener(v -> {
+ new AlertDialog.Builder(context)
+ .setTitle(R.string.episode_cache_full_title)
+ .setMessage(R.string.episode_cache_full_message)
+ .setPositiveButton(android.R.string.ok, (dialog, which) -> {})
+ .show();
+ });
+ } else {
+ holder.count.setVisibility(View.GONE);
+ }
} else {
holder.count.setVisibility(View.GONE);
}
@@ -316,6 +334,7 @@ public class NavListAdapter extends BaseAdapter
int getSelectedItemIndex();
int getQueueSize();
int getNumberOfNewItems();
+ int getNumberOfDownloadedItems();
int getFeedCounter(long feedId);
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java
index 3e4dd4deb..ca1f59e8d 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java
@@ -6,7 +6,6 @@ import android.support.annotation.Nullable;
import android.support.v4.view.MotionEventCompat;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
-import android.text.format.DateUtils;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
@@ -28,6 +27,8 @@ import com.bumptech.glide.request.target.GlideDrawableImageViewTarget;
import com.joanzapata.iconify.Iconify;
import com.nineoldandroids.view.ViewHelper;
+import org.apache.commons.lang3.StringUtils;
+
import java.lang.ref.WeakReference;
import de.danoeh.antennapod.R;
@@ -38,6 +39,7 @@ import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.Converter;
+import de.danoeh.antennapod.core.util.DateUtils;
import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.core.util.NetworkUtils;
import de.danoeh.antennapod.fragment.ItemFragment;
@@ -209,9 +211,21 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
FeedMedia media = item.getMedia();
title.setText(item.getTitle());
- String pubDateStr = DateUtils.formatDateTime(mainActivity.get(),
- item.getPubDate().getTime(), DateUtils.FORMAT_ABBREV_ALL);
- pubDate.setText(pubDateStr.replace(" ", "\n"));
+ String pubDateStr = DateUtils.formatAbbrev(mainActivity.get(), item.getPubDate());
+ int index = 0;
+ if(StringUtils.countMatches(pubDateStr, ' ') == 1 || StringUtils.countMatches(pubDateStr, ' ') == 2) {
+ index = pubDateStr.lastIndexOf(' ');
+ } else if(StringUtils.countMatches(pubDateStr, '.') == 2) {
+ index = pubDateStr.lastIndexOf('.');
+ } else if(StringUtils.countMatches(pubDateStr, '-') == 2) {
+ index = pubDateStr.lastIndexOf('-');
+ } else if(StringUtils.countMatches(pubDateStr, '/') == 2) {
+ index = pubDateStr.lastIndexOf('/');
+ }
+ if(index > 0) {
+ pubDateStr = pubDateStr.substring(0, index+1).trim() + "\n" + pubDateStr.substring(index+1);
+ }
+ pubDate.setText(pubDateStr);
if (media != null) {
final boolean isDownloadingMedia = DownloadRequester.getInstance().isDownloadingFile(media);
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
index 9ccb0fbe3..2bc4e9ded 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
@@ -190,6 +190,9 @@ public class AllEpisodesFragment extends Fragment {
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ if(!isAdded()) {
+ return;
+ }
super.onCreateOptionsMenu(menu, inflater);
if (itemsLoaded) {
inflater.inflate(R.menu.new_episodes, menu);
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java
index 47ed9676a..b470d379a 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java
@@ -111,6 +111,9 @@ public class DownloadLogFragment extends ListFragment {
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ if(!isAdded()) {
+ return;
+ }
super.onCreateOptionsMenu(menu, inflater);
if (itemsLoaded) {
MenuItem clearHistory = menu.add(Menu.NONE, R.id.clear_history_item, Menu.CATEGORY_CONTAINER, R.string.clear_history_label);
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
index f71b90570..bbffd2dea 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
@@ -11,7 +11,6 @@ import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.util.Pair;
import android.text.TextUtils;
-import android.text.format.DateUtils;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
@@ -55,6 +54,7 @@ import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.Converter;
+import de.danoeh.antennapod.core.util.DateUtils;
import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.core.util.ShareUtils;
@@ -243,7 +243,7 @@ public class ItemFragment extends Fragment {
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- if(item == null) {
+ if(!isAdded() || item == null) {
return;
}
inflater.inflate(R.menu.feeditem_options, menu);
@@ -297,7 +297,8 @@ public class ItemFragment extends Fragment {
txtvTitle.setText(item.getTitle());
if (item.getPubDate() != null) {
- txtvPublished.setText(DateUtils.formatDateTime(getActivity(), item.getPubDate().getTime(), DateUtils.FORMAT_ABBREV_ALL));
+ String pubDateStr = DateUtils.formatAbbrev(getActivity(), item.getPubDate());
+ txtvPublished.setText(pubDateStr);
}
Glide.with(getActivity())
@@ -331,7 +332,7 @@ public class ItemFragment extends Fragment {
butAction1Text = R.string.mark_read_label;
}
if (item.getLink() != null) {
- butAction2Icon = "{ma-web 24sp}";
+ butAction2Icon = "{md-web 24sp}";
butAction2Text = R.string.visit_website_label;
}
} else {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java
index bc5024426..97c446fab 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java
@@ -194,6 +194,9 @@ public class ItemlistFragment extends ListFragment {
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ if(!isAdded()) {
+ return;
+ }
super.onCreateOptionsMenu(menu, inflater);
if (itemsLoaded) {
@@ -370,6 +373,9 @@ public class ItemlistFragment extends ListFragment {
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
+ if(adapter == null) {
+ return;
+ }
FeedItem selection = adapter.getItem(position - l.getHeaderViewsCount());
if (selection != null) {
MainActivity activity = (MainActivity) getActivity();
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java
index 64e3a7da7..c5b77fae2 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java
@@ -148,6 +148,9 @@ public class PlaybackHistoryFragment extends ListFragment {
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ if(!isAdded()) {
+ return;
+ }
super.onCreateOptionsMenu(menu, inflater);
if (itemsLoaded) {
MenuItem clearHistory = menu.add(Menu.NONE, R.id.clear_history_item, Menu.CATEGORY_CONTAINER, R.string.clear_history_label);
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
index cc6b44f6a..43f22a587 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
@@ -68,6 +68,7 @@ public class QueueFragment extends Fragment {
public static final String TAG = "QueueFragment";
private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED |
+ EventDistributor.UNREAD_ITEMS_UPDATE | // sent when playback position is reset
EventDistributor.PLAYER_STATUS_UPDATE;
private TextView infoBar;
@@ -235,6 +236,9 @@ public class QueueFragment extends Fragment {
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ if(!isAdded()) {
+ return;
+ }
super.onCreateOptionsMenu(menu, inflater);
if (queue != null) {
inflater.inflate(R.menu.queue, menu);
@@ -268,10 +272,17 @@ public class QueueFragment extends Fragment {
if (!super.onOptionsItemSelected(item)) {
switch (item.getItemId()) {
case R.id.queue_lock:
- boolean locked = !UserPreferences.isQueueLocked();
- UserPreferences.setQueueLocked(locked);
+ boolean newLockState = !UserPreferences.isQueueLocked();
+ UserPreferences.setQueueLocked(newLockState);
getActivity().supportInvalidateOptionsMenu();
- recyclerAdapter.setLocked(locked);
+ recyclerAdapter.setLocked(newLockState);
+ if (newLockState) {
+ Snackbar.make(getActivity().findViewById(R.id.content), R.string
+ .queue_locked, Snackbar.LENGTH_SHORT).show();
+ } else {
+ Snackbar.make(getActivity().findViewById(R.id.content), R.string
+ .queue_unlocked, Snackbar.LENGTH_SHORT).show();
+ }
return true;
case R.id.refresh_item:
List<Feed> feeds = ((MainActivity) getActivity()).getFeeds();
diff --git a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java
index 06dbe4963..0224d2c7e 100644
--- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java
+++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java
@@ -72,7 +72,10 @@ public class FeedItemMenuHandler {
mi.setItemVisibility(R.id.skip_episode_item, false);
}
- boolean isInQueue = selectedItem.isTagged(FeedItem.TAG_QUEUE);
+ boolean isInQueue = false;
+ if(queueAccess != null) {
+ isInQueue = queueAccess.contains(selectedItem.getId());
+ }
if(queueAccess == null || queueAccess.size() == 0 || queueAccess.get(0) == selectedItem.getId()) {
mi.setItemVisibility(R.id.move_to_top_item, false);
}
diff --git a/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java
index cfc540fd6..0d2ff8a75 100644
--- a/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java
+++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java
@@ -34,10 +34,10 @@ public class MenuItemUtils extends de.danoeh.antennapod.core.menuhandler.MenuIte
TypedArray ta = context.obtainStyledAttributes(lockIcons);
if (UserPreferences.isQueueLocked()) {
queueLock.setTitle(de.danoeh.antennapod.R.string.unlock_queue);
- queueLock.setIcon(ta.getDrawable(1));
+ queueLock.setIcon(ta.getDrawable(0));
} else {
queueLock.setTitle(de.danoeh.antennapod.R.string.lock_queue);
- queueLock.setIcon(ta.getDrawable(0));
+ queueLock.setIcon(ta.getDrawable(1));
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java
index a872039f9..083ac5202 100644
--- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java
+++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java
@@ -30,10 +30,15 @@ import android.widget.Toast;
import com.afollestad.materialdialogs.MaterialDialog;
+import org.apache.commons.lang3.ArrayUtils;
+
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
import java.util.List;
+import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.CrashReportWriter;
import de.danoeh.antennapod.R;
@@ -216,17 +221,16 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
}
});
- ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL)
- .setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- if (newValue instanceof Boolean) {
- ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER).setEnabled((Boolean) newValue);
- setSelectedNetworksEnabled((Boolean) newValue && UserPreferences.isEnableAutodownloadWifiFilter());
- ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_ON_BATTERY).setEnabled((Boolean) newValue);
- }
- return true;
+ ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL).setOnPreferenceChangeListener(
+ (preference, newValue) -> {
+ if (newValue instanceof Boolean) {
+ boolean enabled = (Boolean) newValue;
+ ui.findPreference(UserPreferences.PREF_EPISODE_CACHE_SIZE).setEnabled(enabled);
+ ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_ON_BATTERY).setEnabled(enabled);
+ ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER).setEnabled(enabled);
+ setSelectedNetworksEnabled(enabled && UserPreferences.isEnableAutodownloadWifiFilter());
}
+ return true;
});
ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER)
.setOnPreferenceChangeListener(
@@ -411,6 +415,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
public void onResume() {
checkItemVisibility();
+ setUpdateIntervalText();
setParallelDownloadsText(UserPreferences.getParallelDownloads());
setEpisodeCacheSizeText(UserPreferences.getEpisodeCacheSize());
setDataFolderText();
@@ -503,15 +508,19 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
final Resources res = ui.getActivity().getResources();
ListPreference pref = (ListPreference) ui.findPreference(UserPreferences.PREF_SMART_MARK_AS_PLAYED_SECS);
- String[] values = res.getStringArray(
- R.array.smart_mark_as_played_values);
+ String[] values = res.getStringArray(R.array.smart_mark_as_played_values);
String[] entries = new String[values.length];
for (int x = 0; x < values.length; x++) {
if(x == 0) {
entries[x] = res.getString(R.string.pref_smart_mark_as_played_disabled);
} else {
Integer v = Integer.parseInt(values[x]);
- entries[x] = res.getQuantityString(R.plurals.time_seconds_quantified, v, v);
+ if(v < 60) {
+ entries[x] = res.getQuantityString(R.plurals.time_seconds_quantified, v, v);
+ } else {
+ v /= 60;
+ entries[x] = res.getQuantityString(R.plurals.time_minutes_quantified, v, v);
+ }
}
}
pref.setEntries(entries);
@@ -527,21 +536,17 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
@SuppressWarnings("deprecation")
private void checkItemVisibility() {
-
boolean hasFlattrToken = FlattrUtils.hasToken();
-
ui.findPreference(PreferenceController.PREF_FLATTR_SETTINGS).setEnabled(FlattrUtils.hasAPICredentials());
ui.findPreference(PreferenceController.PREF_FLATTR_AUTH).setEnabled(!hasFlattrToken);
ui.findPreference(PreferenceController.PREF_FLATTR_REVOKE).setEnabled(hasFlattrToken);
ui.findPreference(PreferenceController.PREF_AUTO_FLATTR_PREFS).setEnabled(hasFlattrToken);
- ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER)
- .setEnabled(UserPreferences.isEnableAutodownload());
- setSelectedNetworksEnabled(UserPreferences.isEnableAutodownload()
- && UserPreferences.isEnableAutodownloadWifiFilter());
-
- ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_ON_BATTERY)
- .setEnabled(UserPreferences.isEnableAutodownload());
+ boolean autoDownload = UserPreferences.isEnableAutodownload();
+ ui.findPreference(UserPreferences.PREF_EPISODE_CACHE_SIZE).setEnabled(autoDownload);
+ ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_ON_BATTERY).setEnabled(autoDownload);
+ ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER).setEnabled(autoDownload);
+ setSelectedNetworksEnabled(autoDownload && UserPreferences.isEnableAutodownloadWifiFilter());
ui.findPreference("prefSendCrashReport").setEnabled(CrashReportWriter.getFile().exists());
@@ -553,6 +558,32 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
}
}
+ private void setUpdateIntervalText() {
+ Context context = ui.getActivity().getApplicationContext();
+ String val;
+ long interval = UserPreferences.getUpdateInterval();
+ if(interval > 0) {
+ int hours = (int) TimeUnit.MILLISECONDS.toHours(interval);
+ String hoursStr = context.getResources().getQuantityString(R.plurals.time_hours_quantified, hours, hours);
+ val = String.format(context.getString(R.string.pref_autoUpdateIntervallOrTime_every), hoursStr);
+ } else {
+ int[] timeOfDay = UserPreferences.getUpdateTimeOfDay();
+ if(timeOfDay.length == 2) {
+ Calendar cal = new GregorianCalendar();
+ cal.set(Calendar.HOUR_OF_DAY, timeOfDay[0]);
+ cal.set(Calendar.MINUTE, timeOfDay[1]);
+ String timeOfDayStr = DateFormat.getTimeFormat(context).format(cal.getTime());
+ val = String.format(context.getString(R.string.pref_autoUpdateIntervallOrTime_at),
+ timeOfDayStr);
+ } else {
+ val = context.getString(R.string.pref_smart_mark_as_played_disabled);
+ }
+ }
+ String summary = context.getString(R.string.pref_autoUpdateIntervallOrTime_sum) + "\n"
+ + String.format(context.getString(R.string.pref_current_value), val);
+ ui.findPreference(UserPreferences.PREF_UPDATE_INTERVAL).setSummary(summary);
+ }
+
private void setParallelDownloadsText(int downloads) {
final Resources res = ui.getActivity().getResources();
@@ -772,10 +803,17 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
builder.setTitle(context.getString(R.string.pref_autoUpdateIntervallOrTime_Interval));
final String[] values = context.getResources().getStringArray(R.array.update_intervall_values);
final String[] entries = getUpdateIntervalEntries(values);
- builder.setSingleChoiceItems(entries, -1, (dialog1, which) -> {
+ long currInterval = UserPreferences.getUpdateInterval();
+ int checkedItem = -1;
+ if(currInterval > 0) {
+ String currIntervalStr = String.valueOf(TimeUnit.MILLISECONDS.toHours(currInterval));
+ checkedItem = ArrayUtils.indexOf(values, currIntervalStr);
+ }
+ builder.setSingleChoiceItems(entries, checkedItem, (dialog1, which) -> {
int hours = Integer.valueOf(values[which]);
UserPreferences.setUpdateInterval(hours);
dialog1.dismiss();
+ setUpdateIntervalText();
});
builder.setNegativeButton(context.getString(R.string.cancel_label), null);
builder.show();
@@ -794,6 +832,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
if (view.getTag() == null) { // onTimeSet() may get called twice!
view.setTag("TAGGED");
UserPreferences.setUpdateTimeOfDay(selectedHourOfDay, selectedMinute);
+ setUpdateIntervalText();
}
}, hourOfDay, minute, DateFormat.is24HourFormat(context));
timePickerDialog.setTitle(context.getString(R.string.pref_autoUpdateIntervallOrTime_TimeOfDay));
@@ -803,6 +842,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
@Override
public void onNeutral(MaterialDialog dialog) {
UserPreferences.setUpdateInterval(0);
+ setUpdateIntervalText();
}
});
builder.forceStacking(true);
diff --git a/app/src/main/res/layout/queue_listitem.xml b/app/src/main/res/layout/queue_listitem.xml
index e55b254f3..99e96c9fb 100644
--- a/app/src/main/res/layout/queue_listitem.xml
+++ b/app/src/main/res/layout/queue_listitem.xml
@@ -77,7 +77,7 @@
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="8dp"
- android:gravity="right|bottom"
+ android:gravity="right|top"
android:text="Feb\n12"
tools:background="@android:color/holo_blue_light" />
diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml
index cdb582898..b2a28e871 100644
--- a/app/src/main/res/xml/preferences.xml
+++ b/app/src/main/res/xml/preferences.xml
@@ -170,13 +170,6 @@
android:key="prefParallelDownloads"
android:title="@string/pref_parallel_downloads_title"
app:useStockLayout="true"/>
- <com.afollestad.materialdialogs.prefs.MaterialListPreference
- android:defaultValue="20"
- android:entries="@array/episode_cache_size_entries"
- android:key="prefEpisodeCacheSize"
- android:title="@string/pref_episode_cache_title"
- android:entryValues="@array/episode_cache_size_values"
- app:useStockLayout="true"/>
<PreferenceScreen
android:summary="@string/pref_automatic_download_sum"
android:key="prefAutoDownloadSettings"
@@ -185,6 +178,13 @@
android:key="prefEnableAutoDl"
android:title="@string/pref_automatic_download_title"
android:defaultValue="false"/>
+ <com.afollestad.materialdialogs.prefs.MaterialListPreference
+ android:defaultValue="20"
+ android:entries="@array/episode_cache_size_entries"
+ android:key="prefEpisodeCacheSize"
+ android:title="@string/pref_episode_cache_title"
+ android:entryValues="@array/episode_cache_size_values"
+ app:useStockLayout="true"/>
<de.danoeh.antennapod.preferences.SwitchCompatPreference
android:key="prefEnableAutoDownloadOnBattery"
android:title="@string/pref_automatic_download_on_battery_title"
diff --git a/build.gradle b/build.gradle
index 0d2cf9dfb..b2e6cd902 100644
--- a/build.gradle
+++ b/build.gradle
@@ -47,8 +47,8 @@ project.ext {
eventbusVersion = "2.4.0"
flattr4jVersion = "2.12"
glideVersion = "3.6.1"
+ iconifyVersion = "2.1.1"
jsoupVersion = "1.7.3"
- iconifyFontawesomeVersion = "2.1.1"
materialDialogsVersion = "0.8.5.3@aar"
okhttpVersion = "2.7.2"
okioVersion = "1.6.0"
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java
index c54cc1d5b..00b32de5f 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java
@@ -11,6 +11,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.core.asynctask.ImageResource;
import de.danoeh.antennapod.core.storage.DBReader;
@@ -75,7 +76,13 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
private List<Chapter> chapters;
private FeedImage image;
- private boolean autoDownload = true;
+ /*
+ * 0: auto download disabled
+ * 1: auto download enabled
+ * > 1: auto download enabled, (approx.) timestamp of the last failed attempt
+ * where last digit denotes the number of failed attempts
+ */
+ private long autoDownload = 0;
/**
* Any tags assigned to this item
@@ -93,7 +100,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
* */
public FeedItem(long id, String title, String link, Date pubDate, String paymentLink, long feedId,
FlattrStatus flattrStatus, boolean hasChapters, FeedImage image, int state,
- String itemIdentifier, boolean autoDownload) {
+ String itemIdentifier, long autoDownload) {
this.id = id;
this.title = title;
this.link = link;
@@ -162,7 +169,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
FlattrStatus flattrStatus = new FlattrStatus(cursor.getLong(indexFlattrStatus));
int state = cursor.getInt(indexRead);
String itemIdentifier = cursor.getString(indexItemIdentifier);
- boolean autoDownload = cursor.getInt(indexAutoDownload) > 0;
+ long autoDownload = cursor.getLong(indexAutoDownload);
FeedItem item = new FeedItem(id, title, link, pubDate, paymentLink, feedId, flattrStatus,
hasChapters, null, state, itemIdentifier, autoDownload);
@@ -449,18 +456,37 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
}
public void setAutoDownload(boolean autoDownload) {
- this.autoDownload = autoDownload;
+ this.autoDownload = autoDownload ? 1 : 0;
}
public boolean getAutoDownload() {
- return this.autoDownload;
+ return this.autoDownload > 0;
+ }
+
+ public int getFailedAutoDownloadAttempts() {
+ if (autoDownload <= 1) {
+ return 0;
+ }
+ int failedAttempts = (int)(autoDownload % 10);
+ if (failedAttempts == 0) {
+ failedAttempts = 10;
+ }
+ return failedAttempts;
}
public boolean isAutoDownloadable() {
- return this.hasMedia() &&
- false == this.getMedia().isPlaying() &&
- false == this.getMedia().isDownloaded() &&
- this.getAutoDownload();
+ if (media == null || media.isPlaying() || media.isDownloaded() || autoDownload == 0) {
+ return false;
+ }
+ if (autoDownload == 1) {
+ return true;
+ }
+ int failedAttempts = getFailedAutoDownloadAttempts();
+ double magicValue = 1.767; // 1.767^(10[=#maxNumAttempts]-1) = 168 hours / 7 days
+ int millisecondsInHour = 3600000;
+ long waitingTime = (long) (Math.pow(magicValue, failedAttempts - 1) * millisecondsInHour);
+ long grace = TimeUnit.MINUTES.toMillis(5);
+ return System.currentTimeMillis() > (autoDownload + waitingTime - grace);
}
/**
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java
index 29c44207d..c3afff276 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java
@@ -26,6 +26,7 @@ import org.xml.sax.SAXException;
import java.io.File;
import java.io.IOException;
+import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
@@ -196,11 +197,19 @@ public class DownloadService extends Service {
saveDownloadStatus(status);
handleFailedDownload(status, downloader.getDownloadRequest());
- // to make lists reload the failed item, we fake an item update
if(type == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
long id = status.getFeedfileId();
FeedMedia media = DBReader.getFeedMedia(id);
- EventBus.getDefault().post(FeedItemEvent.updated(media.getItem()));
+ if(media == null || media.getItem() == null) {
+ return;
+ }
+ FeedItem item = media.getItem();
+ if (status.getReason() == DownloadError.ERROR_HTTP_DATA_ERROR &&
+ Integer.valueOf(status.getReasonDetailed()) == HttpURLConnection.HTTP_NOT_FOUND) {
+ DBWriter.saveFeedItemAutoDownloadFailed(item).get();
+ }
+ // to make lists reload the failed item, we fake an item update
+ EventBus.getDefault().post(FeedItemEvent.updated(item));
}
}
} else {
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 fe5b177ab..16e65f9f3 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
@@ -1015,7 +1015,9 @@ public final class DBReader {
Collections.sort(feeds, comparator);
int queueSize = adapter.getQueueSize();
int numNewItems = adapter.getNumberOfNewItems();
- NavDrawerData result = new NavDrawerData(feeds, queueSize, numNewItems, feedCounters);
+ int numDownloadedItems = adapter.getNumberOfDownloadedEpisodes();
+
+ NavDrawerData result = new NavDrawerData(feeds, queueSize, numNewItems, numDownloadedItems, feedCounters);
adapter.close();
return result;
}
@@ -1024,15 +1026,18 @@ public final class DBReader {
public List<Feed> feeds;
public int queueSize;
public int numNewItems;
+ public int numDownloadedItems;
public LongIntMap feedCounters;
public NavDrawerData(List<Feed> feeds,
int queueSize,
int numNewItems,
+ int numDownloadedItems,
LongIntMap feedIndicatorValues) {
this.feeds = feeds;
this.queueSize = queueSize;
this.numNewItems = numNewItems;
+ this.numDownloadedItems = numDownloadedItems;
this.feedCounters = feedIndicatorValues;
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
index f74064cfc..d1d6bd750 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
@@ -977,13 +977,35 @@ public class DBWriter {
* Sets the 'auto_download'-attribute of specific FeedItem.
*
* @param feedItem FeedItem.
+ * @param autoDownload true enables auto download, false disables it
*/
public static Future<?> setFeedItemAutoDownload(final FeedItem feedItem,
final boolean autoDownload) {
- Log.d(TAG, "FeedItem[id=" + feedItem.getId() + "] SET auto_download " + autoDownload);
return dbExec.submit(() -> {
final PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
+ adapter.setFeedItemAutoDownload(feedItem, autoDownload ? 1 : 0);
+ adapter.close();
+ EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast();
+ });
+ }
+
+ public static Future<?> saveFeedItemAutoDownloadFailed(final FeedItem feedItem) {
+ return dbExec.submit(() -> {
+ int failedAttempts = feedItem.getFailedAutoDownloadAttempts() + 1;
+ Log.d(TAG, "failedAttempts: " + failedAttempts);
+ long autoDownload;
+ if(!feedItem.getAutoDownload() || failedAttempts >= 10) {
+ autoDownload = 0; // giving up, disable auto download
+ feedItem.setAutoDownload(false);
+ } else {
+ long now = System.currentTimeMillis();
+ autoDownload = (now / 10) * 10 + failedAttempts;
+ Log.d(TAG, "now: " + now);
+ Log.d(TAG, "autoDownload: " + autoDownload);
+ }
+ final PodDBAdapter adapter = PodDBAdapter.getInstance();
+ adapter.open();
adapter.setFeedItemAutoDownload(feedItem, autoDownload);
adapter.close();
EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast();
@@ -992,7 +1014,8 @@ public class DBWriter {
/**
* Sets the 'auto_download'-attribute of specific FeedItem.
- * @param feed This feed's episodes will be processed.
+ *
+ * @param feed This feed's episodes will be processed.
* @param autoDownload If true, auto download will be enabled for the feed's episodes. Else,
*/
public static Future<?> setFeedsItemsAutoDownload(final Feed feed,
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 629b73668..915ca14c7 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
@@ -794,7 +794,7 @@ public class PodDBAdapter {
return status.getId();
}
- public void setFeedItemAutoDownload(FeedItem feedItem, boolean autoDownload) {
+ public void setFeedItemAutoDownload(FeedItem feedItem, long autoDownload) {
ContentValues values = new ContentValues();
values.put(KEY_AUTO_DOWNLOAD, autoDownload);
db.update(TABLE_NAME_FEED_ITEMS, values, KEY_ID + "=?",
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java
index 6406295c1..9b9849c49 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java
@@ -1,5 +1,7 @@
package de.danoeh.antennapod.core.syndication.namespace;
+import android.text.TextUtils;
+
import org.xml.sax.Attributes;
import java.util.concurrent.TimeUnit;
@@ -36,8 +38,10 @@ public class NSITunes extends Namespace {
} else {
// this is the feed image
// prefer to all other images
- image.setOwner(state.getFeed());
- state.getFeed().setImage(image);
+ if(!TextUtils.isEmpty(image.getDownload_url())) {
+ image.setOwner(state.getFeed());
+ state.getFeed().setImage(image);
+ }
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java
index 1a148673c..4b4201b50 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java
@@ -1,5 +1,6 @@
package de.danoeh.antennapod.core.util;
+import android.content.Context;
import android.util.Log;
import org.apache.commons.lang3.StringUtils;
@@ -7,6 +8,7 @@ import org.apache.commons.lang3.StringUtils;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
+import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
@@ -141,4 +143,17 @@ public class DateUtils {
format.setTimeZone(defaultTimezone);
return format.format(date);
}
+
+ public static String formatAbbrev(final Context context, final Date date) {
+ GregorianCalendar cal = new GregorianCalendar();
+ cal.add(GregorianCalendar.YEAR, -1);
+ // some padding, because no one really remembers what day of the month it is
+ cal.add(GregorianCalendar.DAY_OF_MONTH, 10);
+ boolean withinLastYear = date.after(cal.getTime());
+ int format = android.text.format.DateUtils.FORMAT_ABBREV_ALL;
+ if(withinLastYear) {
+ format |= android.text.format.DateUtils.FORMAT_NO_YEAR;
+ }
+ return android.text.format.DateUtils.formatDateTime(context, date.getTime(), format);
+ }
}
diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml
index 80e3d57f5..55da0ee04 100644
--- a/core/src/main/res/values/arrays.xml
+++ b/core/src/main/res/values/arrays.xml
@@ -11,8 +11,9 @@
<item>0</item>
<item>15</item>
<item>30</item>
- <item>45</item>
<item>60</item>
+ <item>120</item>
+ <item>300</item>
</string-array>
diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml
index fa54ad22e..91a77e6e2 100644
--- a/core/src/main/res/values/strings.xml
+++ b/core/src/main/res/values/strings.xml
@@ -26,6 +26,8 @@
<string name="gpodnet_main_label">gpodder.net</string>
<string name="gpodnet_auth_label">gpodder.net Login</string>
<string name="free_space_label">%1$s free</string>
+ <string name="episode_cache_full_title">Episode cache full</string>
+ <string name="episode_cache_full_message">The episode cache limit has been reached. You can increase the cache size in the Settings.</string>
<!-- New episodes fragment -->
<string name="recently_published_episodes_label">Recently published</string>
@@ -75,7 +77,7 @@
<string name="length_prefix">Length:\u0020</string>
<string name="size_prefix">Size:\u0020</string>
<string name="processing_label">Processing</string>
- <string name="loading_label">Loading...</string>
+ <string name="loading_label">Loading&#8230;</string>
<string name="save_username_password_label">Save username and password</string>
<string name="close_label">Close</string>
<string name="retry_label">Retry</string>
@@ -87,7 +89,7 @@
<string name="feed_auto_download_global">Global</string>
<string name="feed_auto_download_always">Always</string>
<string name="feed_auto_download_never">Never</string>
- <string name="send_label">Send...</string>
+ <string name="send_label">Send&#8230;</string>
<string name="episode_cleanup_never">Never</string>
<string name="episode_cleanup_queue_removal">When not in queue</string>
<string name="episode_cleanup_after_listening">After finishing</string>
@@ -112,7 +114,7 @@
<string name="mark_all_seen_label">Mark all as seen</string>
<string name="show_info_label">Show information</string>
<string name="remove_feed_label">Remove Podcast</string>
- <string name="share_label">Share...</string>
+ <string name="share_label">Share&#8230;</string>
<string name="share_link_label">Share Link</string>
<string name="share_link_with_position_label">Share Link with Position</string>
<string name="share_feed_url_label">Share Feed URL</string>
@@ -219,6 +221,8 @@
<!-- Queue operations -->
<string name="lock_queue">Lock Queue</string>
<string name="unlock_queue">Unlock Queue</string>
+ <string name="queue_locked">Queue locked</string>
+ <string name="queue_unlocked">Queue unlocked</string>
<string name="clear_queue_label">Clear Queue</string>
<string name="undo">Undo</string>
<string name="removed_from_queue">Item removed</string>
@@ -300,6 +304,8 @@
<string name="pref_autoUpdateIntervallOrTime_Disable">Disable</string>
<string name="pref_autoUpdateIntervallOrTime_Interval">Set Interval</string>
<string name="pref_autoUpdateIntervallOrTime_TimeOfDay">Set Time of Day</string>
+ <string name="pref_autoUpdateIntervallOrTime_every">every %1$s</string>
+ <string name="pref_autoUpdateIntervallOrTime_at">at %1$s</string>
<string name="pref_downloadMediaOnWifiOnly_sum">Download media files only over WiFi</string>
<string name="pref_followQueue_title">Continuous Playback</string>
<string name="pref_downloadMediaOnWifiOnly_title">WiFi media download</string>
@@ -375,6 +381,7 @@
<string name="experimental_pref">Experimental</string>
<string name="pref_sonic_title">Sonic media player</string>
<string name="pref_sonic_message">Use built-in sonic media player as a replacement for Prestissimo</string>
+ <string name="pref_current_value">Current value: %1$s</string>
<!-- Auto-Flattr dialog -->
<string name="auto_flattr_enable">Enable automatic flattring</string>
@@ -403,11 +410,11 @@
<string name="opml_import_error_dir_empty">The import directory is empty.</string>
<string name="select_all_label">Select all</string>
<string name="deselect_all_label">Deselect all</string>
- <string name="select_options_label">Select ...</string>
+ <string name="select_options_label">Select&#8230;</string>
<string name="choose_file_from_filesystem">From local filesystem</string>
<string name="choose_file_from_external_application">Use external application</string>
<string name="opml_export_label">OPML export</string>
- <string name="exporting_label">Exporting...</string>
+ <string name="exporting_label">Exporting&#8230;</string>
<string name="export_error_label">Export error</string>
<string name="opml_export_success_title">OPML Export successful.</string>
<string name="opml_export_success_sum">The .opml file was written to:\u0020</string>
@@ -495,7 +502,7 @@
<!-- Online feed view -->
<string name="subscribe_label">Subscribe</string>
<string name="subscribed_label">Subscribed</string>
- <string name="downloading_label">Downloading...</string>
+ <string name="downloading_label">Downloading&#8230;</string>
<!-- Content descriptions for image buttons -->
<string name="show_chapters_label">Show chapters</string>
@@ -530,7 +537,7 @@
<string name="sp_apps_importing_feeds_msg">Importing subscriptions from single-purpose apps&#8230;</string>
<string name="search_itunes_label">Search iTunes</string>
- <string name="select_label"><b>Select ...</b></string>
+ <string name="select_label"><b>Select&#8230;</b></string>
<string name="all_label">All</string>
<string name="selected_all_label">Selected all Episodes</string>
<string name="none_label">None</string>
@@ -543,7 +550,7 @@
<string name="selected_downloaded_label">Selected downloaded Episodes</string>
<string name="not_downloaded_label">Not downloaded</string>
<string name="selected_not_downloaded_label">Selected not downloaded Episodes</string>
- <string name="sort_title"><b>Sort by ...</b></string>
+ <string name="sort_title"><b>Sort by&#8230;</b></string>
<string name="sort_title_a_z">Title (A \u2192 Z)</string>
<string name="sort_title_z_a">Title (Z \u2192 A)</string>
<string name="sort_date_new_old">Date (New \u2192 Old)</string>