summaryrefslogtreecommitdiff
path: root/src/de/danoeh
diff options
context:
space:
mode:
Diffstat (limited to 'src/de/danoeh')
-rw-r--r--src/de/danoeh/antennapod/AppConfig.java7
-rw-r--r--src/de/danoeh/antennapod/PodcastApp.java47
-rw-r--r--src/de/danoeh/antennapod/activity/AboutActivity.java32
-rw-r--r--src/de/danoeh/antennapod/activity/AudioplayerActivity.java746
-rw-r--r--src/de/danoeh/antennapod/activity/DefaultOnlineFeedViewActivity.java248
-rw-r--r--src/de/danoeh/antennapod/activity/DirectoryChooserActivity.java370
-rw-r--r--src/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java110
-rw-r--r--src/de/danoeh/antennapod/activity/FeedInfoActivity.java192
-rw-r--r--src/de/danoeh/antennapod/activity/FlattrAuthActivity.java125
-rw-r--r--src/de/danoeh/antennapod/activity/MainActivity.java432
-rw-r--r--src/de/danoeh/antennapod/activity/MediaplayerActivity.java525
-rw-r--r--src/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java428
-rw-r--r--src/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java134
-rw-r--r--src/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java90
-rw-r--r--src/de/danoeh/antennapod/activity/OpmlImportFromIntentActivity.java38
-rw-r--r--src/de/danoeh/antennapod/activity/OpmlImportFromPathActivity.java172
-rw-r--r--src/de/danoeh/antennapod/activity/OpmlImportHolder.java29
-rw-r--r--src/de/danoeh/antennapod/activity/PreferenceActivity.java513
-rw-r--r--src/de/danoeh/antennapod/activity/StorageErrorActivity.java75
-rw-r--r--src/de/danoeh/antennapod/activity/VideoplayerActivity.java359
-rw-r--r--src/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java372
-rw-r--r--src/de/danoeh/antennapod/adapter/ActionButtonCallback.java8
-rw-r--r--src/de/danoeh/antennapod/adapter/ActionButtonUtils.java78
-rw-r--r--src/de/danoeh/antennapod/adapter/AdapterUtils.java57
-rw-r--r--src/de/danoeh/antennapod/adapter/ChapterListAdapter.java180
-rw-r--r--src/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java57
-rw-r--r--src/de/danoeh/antennapod/adapter/DownloadLogAdapter.java112
-rw-r--r--src/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java122
-rw-r--r--src/de/danoeh/antennapod/adapter/DownloadlistAdapter.java142
-rw-r--r--src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java306
-rw-r--r--src/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java220
-rw-r--r--src/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java55
-rw-r--r--src/de/danoeh/antennapod/adapter/NavListAdapter.java229
-rw-r--r--src/de/danoeh/antennapod/adapter/NewEpisodesListAdapter.java170
-rw-r--r--src/de/danoeh/antennapod/adapter/QueueListAdapter.java127
-rw-r--r--src/de/danoeh/antennapod/adapter/SearchlistAdapter.java110
-rw-r--r--src/de/danoeh/antennapod/adapter/gpodnet/PodcastListAdapter.java64
-rw-r--r--src/de/danoeh/antennapod/asynctask/DownloadObserver.java177
-rw-r--r--src/de/danoeh/antennapod/asynctask/FeedRemover.java74
-rw-r--r--src/de/danoeh/antennapod/asynctask/FlattrClickWorker.java238
-rw-r--r--src/de/danoeh/antennapod/asynctask/FlattrStatusFetcher.java47
-rw-r--r--src/de/danoeh/antennapod/asynctask/FlattrTokenFetcher.java95
-rw-r--r--src/de/danoeh/antennapod/asynctask/OpmlExportWorker.java114
-rw-r--r--src/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java69
-rw-r--r--src/de/danoeh/antennapod/asynctask/OpmlImportWorker.java116
-rw-r--r--src/de/danoeh/antennapod/asynctask/PicassoImageResource.java37
-rw-r--r--src/de/danoeh/antennapod/asynctask/PicassoProvider.java152
-rw-r--r--src/de/danoeh/antennapod/backup/OpmlBackupAgent.java212
-rw-r--r--src/de/danoeh/antennapod/dialog/AuthenticationDialog.java89
-rw-r--r--src/de/danoeh/antennapod/dialog/AutoFlattrPreferenceDialog.java107
-rw-r--r--src/de/danoeh/antennapod/dialog/ConfirmationDialog.java64
-rw-r--r--src/de/danoeh/antennapod/dialog/DownloadRequestErrorDialogCreator.java30
-rw-r--r--src/de/danoeh/antennapod/dialog/FeedItemDialog.java428
-rw-r--r--src/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java67
-rw-r--r--src/de/danoeh/antennapod/dialog/TimeDialog.java138
-rw-r--r--src/de/danoeh/antennapod/dialog/VariableSpeedDialog.java100
-rw-r--r--src/de/danoeh/antennapod/feed/Chapter.java55
-rw-r--r--src/de/danoeh/antennapod/feed/EventDistributor.java140
-rw-r--r--src/de/danoeh/antennapod/feed/Feed.java445
-rw-r--r--src/de/danoeh/antennapod/feed/FeedComponent.java66
-rw-r--r--src/de/danoeh/antennapod/feed/FeedFile.java105
-rw-r--r--src/de/danoeh/antennapod/feed/FeedImage.java77
-rw-r--r--src/de/danoeh/antennapod/feed/FeedItem.java333
-rw-r--r--src/de/danoeh/antennapod/feed/FeedMedia.java411
-rw-r--r--src/de/danoeh/antennapod/feed/FeedPreferences.java89
-rw-r--r--src/de/danoeh/antennapod/feed/ID3Chapter.java36
-rw-r--r--src/de/danoeh/antennapod/feed/MediaType.java5
-rw-r--r--src/de/danoeh/antennapod/feed/SearchResult.java34
-rw-r--r--src/de/danoeh/antennapod/feed/SimpleChapter.java25
-rw-r--r--src/de/danoeh/antennapod/feed/VorbisCommentChapter.java109
-rw-r--r--src/de/danoeh/antennapod/fragment/AddFeedFragment.java76
-rw-r--r--src/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java196
-rw-r--r--src/de/danoeh/antennapod/fragment/CoverFragment.java105
-rw-r--r--src/de/danoeh/antennapod/fragment/DownloadLogFragment.java121
-rw-r--r--src/de/danoeh/antennapod/fragment/DownloadsFragment.java145
-rw-r--r--src/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java238
-rw-r--r--src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java476
-rw-r--r--src/de/danoeh/antennapod/fragment/ItemlistFragment.java456
-rw-r--r--src/de/danoeh/antennapod/fragment/NewEpisodesFragment.java425
-rw-r--r--src/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java288
-rw-r--r--src/de/danoeh/antennapod/fragment/QueueFragment.java383
-rw-r--r--src/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java69
-rw-r--r--src/de/danoeh/antennapod/fragment/SearchFragment.java258
-rw-r--r--src/de/danoeh/antennapod/fragment/gpodnet/GpodnetMainFragment.java131
-rw-r--r--src/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java169
-rw-r--r--src/de/danoeh/antennapod/fragment/gpodnet/PodcastTopListFragment.java20
-rw-r--r--src/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java80
-rw-r--r--src/de/danoeh/antennapod/fragment/gpodnet/SuggestionListFragment.java26
-rw-r--r--src/de/danoeh/antennapod/fragment/gpodnet/TagFragment.java50
-rw-r--r--src/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java146
-rw-r--r--src/de/danoeh/antennapod/gpoddernet/GpodnetService.java718
-rw-r--r--src/de/danoeh/antennapod/gpoddernet/GpodnetServiceAuthenticationException.java21
-rw-r--r--src/de/danoeh/antennapod/gpoddernet/GpodnetServiceBadStatusCodeException.java12
-rw-r--r--src/de/danoeh/antennapod/gpoddernet/GpodnetServiceException.java19
-rw-r--r--src/de/danoeh/antennapod/gpoddernet/model/GpodnetDevice.java72
-rw-r--r--src/de/danoeh/antennapod/gpoddernet/model/GpodnetPodcast.java65
-rw-r--r--src/de/danoeh/antennapod/gpoddernet/model/GpodnetSubscriptionChange.java41
-rw-r--r--src/de/danoeh/antennapod/gpoddernet/model/GpodnetTag.java46
-rw-r--r--src/de/danoeh/antennapod/gpoddernet/model/GpodnetUploadChangesResponse.java56
-rw-r--r--src/de/danoeh/antennapod/opml/OpmlElement.java46
-rw-r--r--src/de/danoeh/antennapod/opml/OpmlReader.java87
-rw-r--r--src/de/danoeh/antennapod/opml/OpmlSymbols.java21
-rw-r--r--src/de/danoeh/antennapod/opml/OpmlWriter.java65
-rw-r--r--src/de/danoeh/antennapod/preferences/GpodnetPreferences.java246
-rw-r--r--src/de/danoeh/antennapod/preferences/PlaybackPreferences.java146
-rw-r--r--src/de/danoeh/antennapod/preferences/UserPreferences.java577
-rw-r--r--src/de/danoeh/antennapod/receiver/AlarmUpdateReceiver.java33
-rw-r--r--src/de/danoeh/antennapod/receiver/ConnectivityActionReceiver.java46
-rw-r--r--src/de/danoeh/antennapod/receiver/FeedUpdateReceiver.java46
-rw-r--r--src/de/danoeh/antennapod/receiver/MediaButtonReceiver.java32
-rw-r--r--src/de/danoeh/antennapod/receiver/PlayerWidget.java50
-rw-r--r--src/de/danoeh/antennapod/receiver/SPAReceiver.java55
-rw-r--r--src/de/danoeh/antennapod/service/GpodnetSyncService.java245
-rw-r--r--src/de/danoeh/antennapod/service/download/APRedirectHandler.java54
-rw-r--r--src/de/danoeh/antennapod/service/download/AntennapodHttpClient.java96
-rw-r--r--src/de/danoeh/antennapod/service/download/DownloadRequest.java209
-rw-r--r--src/de/danoeh/antennapod/service/download/DownloadService.java1230
-rw-r--r--src/de/danoeh/antennapod/service/download/DownloadStatus.java181
-rw-r--r--src/de/danoeh/antennapod/service/download/Downloader.java69
-rw-r--r--src/de/danoeh/antennapod/service/download/DownloaderCallback.java10
-rw-r--r--src/de/danoeh/antennapod/service/download/HttpDownloader.java246
-rw-r--r--src/de/danoeh/antennapod/service/playback/PlaybackService.java1080
-rw-r--r--src/de/danoeh/antennapod/service/playback/PlaybackServiceMediaPlayer.java979
-rw-r--r--src/de/danoeh/antennapod/service/playback/PlaybackServiceTaskManager.java384
-rw-r--r--src/de/danoeh/antennapod/service/playback/PlayerStatus.java14
-rw-r--r--src/de/danoeh/antennapod/service/playback/PlayerWidgetService.java190
-rw-r--r--src/de/danoeh/antennapod/spa/SPAUtil.java69
-rw-r--r--src/de/danoeh/antennapod/storage/DBReader.java908
-rw-r--r--src/de/danoeh/antennapod/storage/DBTasks.java895
-rw-r--r--src/de/danoeh/antennapod/storage/DBWriter.java974
-rw-r--r--src/de/danoeh/antennapod/storage/DownloadRequestException.java25
-rw-r--r--src/de/danoeh/antennapod/storage/DownloadRequester.java367
-rw-r--r--src/de/danoeh/antennapod/storage/FeedItemStatistics.java70
-rw-r--r--src/de/danoeh/antennapod/storage/FeedSearcher.java57
-rw-r--r--src/de/danoeh/antennapod/storage/PodDBAdapter.java1391
-rw-r--r--src/de/danoeh/antennapod/syndication/handler/FeedHandler.java34
-rw-r--r--src/de/danoeh/antennapod/syndication/handler/FeedHandlerResult.java19
-rw-r--r--src/de/danoeh/antennapod/syndication/handler/HandlerState.java98
-rw-r--r--src/de/danoeh/antennapod/syndication/handler/SyndHandler.java126
-rw-r--r--src/de/danoeh/antennapod/syndication/handler/TypeGetter.java112
-rw-r--r--src/de/danoeh/antennapod/syndication/handler/UnsupportedFeedtypeException.java38
-rw-r--r--src/de/danoeh/antennapod/syndication/namespace/NSContent.java25
-rw-r--r--src/de/danoeh/antennapod/syndication/namespace/NSITunes.java51
-rw-r--r--src/de/danoeh/antennapod/syndication/namespace/NSMedia.java68
-rw-r--r--src/de/danoeh/antennapod/syndication/namespace/NSRSS20.java141
-rw-r--r--src/de/danoeh/antennapod/syndication/namespace/NSSimpleChapters.java42
-rw-r--r--src/de/danoeh/antennapod/syndication/namespace/Namespace.java21
-rw-r--r--src/de/danoeh/antennapod/syndication/namespace/SyndElement.java22
-rw-r--r--src/de/danoeh/antennapod/syndication/namespace/atom/AtomText.java46
-rw-r--r--src/de/danoeh/antennapod/syndication/namespace/atom/NSAtom.java194
-rw-r--r--src/de/danoeh/antennapod/syndication/util/SyndDateUtils.java153
-rw-r--r--src/de/danoeh/antennapod/syndication/util/SyndTypeUtils.java42
-rw-r--r--src/de/danoeh/antennapod/util/ChapterUtils.java261
-rw-r--r--src/de/danoeh/antennapod/util/Converter.java103
-rw-r--r--src/de/danoeh/antennapod/util/DownloadError.java52
-rw-r--r--src/de/danoeh/antennapod/util/DuckType.java117
-rw-r--r--src/de/danoeh/antennapod/util/EpisodeFilter.java49
-rw-r--r--src/de/danoeh/antennapod/util/FeedtitleComparator.java15
-rw-r--r--src/de/danoeh/antennapod/util/FileNameGenerator.java36
-rw-r--r--src/de/danoeh/antennapod/util/InvalidFeedException.java21
-rw-r--r--src/de/danoeh/antennapod/util/LangUtils.java120
-rw-r--r--src/de/danoeh/antennapod/util/NetworkUtils.java69
-rw-r--r--src/de/danoeh/antennapod/util/QueueAccess.java93
-rw-r--r--src/de/danoeh/antennapod/util/ShareUtils.java34
-rw-r--r--src/de/danoeh/antennapod/util/ShownotesProvider.java16
-rw-r--r--src/de/danoeh/antennapod/util/StorageUtils.java66
-rw-r--r--src/de/danoeh/antennapod/util/ThemeUtils.java22
-rw-r--r--src/de/danoeh/antennapod/util/URIUtil.java35
-rw-r--r--src/de/danoeh/antennapod/util/URLChecker.java51
-rw-r--r--src/de/danoeh/antennapod/util/UndoBarController.java137
-rw-r--r--src/de/danoeh/antennapod/util/comparator/ChapterStartTimeComparator.java20
-rw-r--r--src/de/danoeh/antennapod/util/comparator/DownloadStatusComparator.java15
-rw-r--r--src/de/danoeh/antennapod/util/comparator/FeedItemPubdateComparator.java19
-rw-r--r--src/de/danoeh/antennapod/util/comparator/PlaybackCompletionDateComparator.java19
-rw-r--r--src/de/danoeh/antennapod/util/comparator/SearchResultValueComparator.java14
-rw-r--r--src/de/danoeh/antennapod/util/exception/MediaFileNotFoundException.java23
-rw-r--r--src/de/danoeh/antennapod/util/flattr/FlattrServiceCreator.java25
-rw-r--r--src/de/danoeh/antennapod/util/flattr/FlattrStatus.java68
-rw-r--r--src/de/danoeh/antennapod/util/flattr/FlattrThing.java7
-rw-r--r--src/de/danoeh/antennapod/util/flattr/FlattrUtils.java305
-rw-r--r--src/de/danoeh/antennapod/util/flattr/SimpleFlattrThing.java30
-rw-r--r--src/de/danoeh/antennapod/util/gui/FeedItemUndoToken.java55
-rw-r--r--src/de/danoeh/antennapod/util/id3reader/ChapterReader.java118
-rw-r--r--src/de/danoeh/antennapod/util/id3reader/ID3Reader.java250
-rw-r--r--src/de/danoeh/antennapod/util/id3reader/ID3ReaderException.java20
-rw-r--r--src/de/danoeh/antennapod/util/id3reader/model/FrameHeader.java17
-rw-r--r--src/de/danoeh/antennapod/util/id3reader/model/Header.java29
-rw-r--r--src/de/danoeh/antennapod/util/id3reader/model/TagHeader.java26
-rw-r--r--src/de/danoeh/antennapod/util/menuhandler/FeedItemMenuHandler.java191
-rw-r--r--src/de/danoeh/antennapod/util/menuhandler/FeedMenuHandler.java87
-rw-r--r--src/de/danoeh/antennapod/util/menuhandler/MenuItemUtils.java31
-rw-r--r--src/de/danoeh/antennapod/util/menuhandler/NavDrawerActivity.java9
-rw-r--r--src/de/danoeh/antennapod/util/playback/AudioPlayer.java34
-rw-r--r--src/de/danoeh/antennapod/util/playback/ExternalMedia.java237
-rw-r--r--src/de/danoeh/antennapod/util/playback/IPlayer.java69
-rw-r--r--src/de/danoeh/antennapod/util/playback/MediaPlayerError.java23
-rw-r--r--src/de/danoeh/antennapod/util/playback/Playable.java207
-rw-r--r--src/de/danoeh/antennapod/util/playback/PlaybackController.java784
-rw-r--r--src/de/danoeh/antennapod/util/playback/Timeline.java161
-rw-r--r--src/de/danoeh/antennapod/util/playback/VideoPlayer.java67
-rw-r--r--src/de/danoeh/antennapod/util/syndication/FeedDiscoverer.java78
-rw-r--r--src/de/danoeh/antennapod/util/vorbiscommentreader/OggInputStream.java81
-rw-r--r--src/de/danoeh/antennapod/util/vorbiscommentreader/VorbisCommentChapterReader.java101
-rw-r--r--src/de/danoeh/antennapod/util/vorbiscommentreader/VorbisCommentHeader.java26
-rw-r--r--src/de/danoeh/antennapod/util/vorbiscommentreader/VorbisCommentReader.java194
-rw-r--r--src/de/danoeh/antennapod/util/vorbiscommentreader/VorbisCommentReaderException.java24
-rw-r--r--src/de/danoeh/antennapod/view/AspectRatioVideoView.java97
207 files changed, 0 insertions, 33556 deletions
diff --git a/src/de/danoeh/antennapod/AppConfig.java b/src/de/danoeh/antennapod/AppConfig.java
deleted file mode 100644
index 7a75e3a18..000000000
--- a/src/de/danoeh/antennapod/AppConfig.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package de.danoeh.antennapod;
-
-public final class AppConfig {
- /** Should be used when setting User-Agent header for HTTP-requests. */
- public final static String USER_AGENT = "AntennaPod/0.9.9.3";
-
-}
diff --git a/src/de/danoeh/antennapod/PodcastApp.java b/src/de/danoeh/antennapod/PodcastApp.java
deleted file mode 100644
index 74628f3d6..000000000
--- a/src/de/danoeh/antennapod/PodcastApp.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package de.danoeh.antennapod;
-
-import android.app.Application;
-import android.content.res.Configuration;
-import android.util.Log;
-import de.danoeh.antennapod.feed.EventDistributor;
-import de.danoeh.antennapod.preferences.PlaybackPreferences;
-import de.danoeh.antennapod.preferences.UserPreferences;
-import de.danoeh.antennapod.spa.SPAUtil;
-
-/** Main application class. */
-public class PodcastApp extends Application {
-
- private static final String TAG = "PodcastApp";
- public static final String EXPORT_DIR = "export/";
-
- private static float LOGICAL_DENSITY;
-
- private static PodcastApp singleton;
-
- public static PodcastApp getInstance() {
- return singleton;
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- singleton = this;
- LOGICAL_DENSITY = getResources().getDisplayMetrics().density;
-
- UserPreferences.createInstance(this);
- PlaybackPreferences.createInstance(this);
- EventDistributor.getInstance();
-
- SPAUtil.sendSPAppsQueryFeedsIntent(this);
- }
-
- public static float getLogicalDensity() {
- return LOGICAL_DENSITY;
- }
-
- public boolean isLargeScreen() {
- return (getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE
- || (getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE;
-
- }
-}
diff --git a/src/de/danoeh/antennapod/activity/AboutActivity.java b/src/de/danoeh/antennapod/activity/AboutActivity.java
deleted file mode 100644
index cf7de1709..000000000
--- a/src/de/danoeh/antennapod/activity/AboutActivity.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package de.danoeh.antennapod.activity;
-
-import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-import de.danoeh.antennapod.R;
-
-/** Displays the 'about' screen */
-public class AboutActivity extends ActionBarActivity {
-
- private WebView webview;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- getSupportActionBar().hide();
- setContentView(R.layout.about);
- webview = (WebView) findViewById(R.id.webvAbout);
- webview.setWebViewClient(new WebViewClient() {
-
- @Override
- public boolean shouldOverrideUrlLoading(WebView view, String url) {
- view.loadUrl(url);
- return false;
- }
-
- });
- webview.loadUrl("file:///android_asset/about.html");
- }
-
-}
diff --git a/src/de/danoeh/antennapod/activity/AudioplayerActivity.java b/src/de/danoeh/antennapod/activity/AudioplayerActivity.java
deleted file mode 100644
index 18d27ddda..000000000
--- a/src/de/danoeh/antennapod/activity/AudioplayerActivity.java
+++ /dev/null
@@ -1,746 +0,0 @@
-package de.danoeh.antennapod.activity;
-
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.res.Configuration;
-import android.content.res.TypedArray;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.support.v4.app.ActionBarDrawerToggle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentTransaction;
-import android.support.v4.app.ListFragment;
-import android.support.v4.widget.DrawerLayout;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.View.OnLongClickListener;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.Button;
-import android.widget.ImageButton;
-import android.widget.ImageView.ScaleType;
-import android.widget.ListView;
-import android.widget.TextView;
-
-import org.apache.commons.lang3.StringUtils;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.adapter.ChapterListAdapter;
-import de.danoeh.antennapod.adapter.NavListAdapter;
-import de.danoeh.antennapod.asynctask.PicassoProvider;
-import de.danoeh.antennapod.dialog.VariableSpeedDialog;
-import de.danoeh.antennapod.feed.Chapter;
-import de.danoeh.antennapod.feed.EventDistributor;
-import de.danoeh.antennapod.feed.Feed;
-import de.danoeh.antennapod.feed.MediaType;
-import de.danoeh.antennapod.feed.SimpleChapter;
-import de.danoeh.antennapod.fragment.CoverFragment;
-import de.danoeh.antennapod.fragment.ItemDescriptionFragment;
-import de.danoeh.antennapod.preferences.UserPreferences;
-import de.danoeh.antennapod.service.playback.PlaybackService;
-import de.danoeh.antennapod.storage.DBReader;
-import de.danoeh.antennapod.util.menuhandler.MenuItemUtils;
-import de.danoeh.antennapod.util.menuhandler.NavDrawerActivity;
-import de.danoeh.antennapod.util.playback.ExternalMedia;
-import de.danoeh.antennapod.util.playback.Playable;
-import de.danoeh.antennapod.util.playback.PlaybackController;
-
-/**
- * Activity for playing audio files.
- */
-public class AudioplayerActivity extends MediaplayerActivity implements ItemDescriptionFragment.ItemDescriptionFragmentCallback,
- NavDrawerActivity {
- private static final int POS_COVER = 0;
- private static final int POS_DESCR = 1;
- private static final int POS_CHAPTERS = 2;
- private static final int NUM_CONTENT_FRAGMENTS = 3;
-
- final String TAG = "AudioplayerActivity";
- private static final String PREFS = "AudioPlayerActivityPreferences";
- private static final String PREF_KEY_SELECTED_FRAGMENT_POSITION = "selectedFragmentPosition";
- private static final String PREF_PLAYABLE_ID = "playableId";
-
- private DrawerLayout drawerLayout;
- private NavListAdapter navAdapter;
- private ListView navList;
- private ActionBarDrawerToggle drawerToggle;
-
- private Fragment[] detachedFragments;
-
- private CoverFragment coverFragment;
- private ItemDescriptionFragment descriptionFragment;
- private ListFragment chapterFragment;
-
- private Fragment currentlyShownFragment;
- private int currentlyShownPosition = -1;
- /**
- * Used if onResume was called without loadMediaInfo.
- */
- private int savedPosition = -1;
-
- private TextView txtvTitle;
- private Button butPlaybackSpeed;
- private ImageButton butNavLeft;
- private ImageButton butNavRight;
-
- private void resetFragmentView() {
- FragmentTransaction fT = getSupportFragmentManager().beginTransaction();
-
- if (coverFragment != null) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Removing cover fragment");
- fT.remove(coverFragment);
- }
- if (descriptionFragment != null) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Removing description fragment");
- fT.remove(descriptionFragment);
- }
- if (chapterFragment != null) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Removing chapter fragment");
- fT.remove(chapterFragment);
- }
- if (currentlyShownFragment != null) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Removing currently shown fragment");
- fT.remove(currentlyShownFragment);
- }
- for (int i = 0; i < detachedFragments.length; i++) {
- Fragment f = detachedFragments[i];
- if (f != null) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Removing detached fragment");
- fT.remove(f);
- }
- }
- fT.commit();
- currentlyShownFragment = null;
- coverFragment = null;
- descriptionFragment = null;
- chapterFragment = null;
- currentlyShownPosition = -1;
- detachedFragments = new Fragment[NUM_CONTENT_FRAGMENTS];
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "onStop");
- cancelLoadTask();
- EventDistributor.getInstance().unregister(contentUpdate);
-
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- getSupportActionBar().setDisplayShowTitleEnabled(false);
- detachedFragments = new Fragment[NUM_CONTENT_FRAGMENTS];
- }
-
- private void savePreferences() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Saving preferences");
- SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
- SharedPreferences.Editor editor = prefs.edit();
- if (currentlyShownPosition >= 0 && controller != null
- && controller.getMedia() != null) {
- editor.putInt(PREF_KEY_SELECTED_FRAGMENT_POSITION,
- currentlyShownPosition);
- editor.putString(PREF_PLAYABLE_ID, controller.getMedia()
- .getIdentifier().toString());
- } else {
- editor.putInt(PREF_KEY_SELECTED_FRAGMENT_POSITION, -1);
- editor.putString(PREF_PLAYABLE_ID, "");
- }
- editor.commit();
-
- savedPosition = currentlyShownPosition;
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- drawerToggle.onConfigurationChanged(newConfig);
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- // super.onSaveInstanceState(outState); would cause crash
- if (BuildConfig.DEBUG)
- Log.d(TAG, "onSaveInstanceState");
-
- }
-
- @Override
- protected void onPause() {
- savePreferences();
- resetFragmentView();
- super.onPause();
- }
-
- @Override
- protected void onRestoreInstanceState(Bundle savedInstanceState) {
- super.onRestoreInstanceState(savedInstanceState);
- restoreFromPreferences();
- }
-
- /**
- * Tries to restore the selected fragment position from the Activity's
- * preferences.
- *
- * @return true if restoreFromPrefernces changed the activity's state
- */
- private boolean restoreFromPreferences() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Restoring instance state");
- SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
- int savedPosition = prefs.getInt(PREF_KEY_SELECTED_FRAGMENT_POSITION,
- -1);
- String playableId = prefs.getString(PREF_PLAYABLE_ID, "");
-
- if (savedPosition != -1
- && controller != null
- && controller.getMedia() != null
- && controller.getMedia().getIdentifier().toString()
- .equals(playableId)) {
- switchToFragment(savedPosition);
- return true;
- } else if (controller == null || controller.getMedia() == null) {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "Couldn't restore from preferences: controller or media was null");
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "Couldn't restore from preferences: savedPosition was -1 or saved identifier and playable identifier didn't match.\nsavedPosition: "
- + savedPosition + ", id: " + playableId
- );
-
- }
- return false;
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- if (StringUtils.equals(getIntent().getAction(), Intent.ACTION_VIEW)) {
- Intent intent = getIntent();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Received VIEW intent: "
- + intent.getData().getPath());
- ExternalMedia media = new ExternalMedia(intent.getData().getPath(),
- MediaType.AUDIO);
- Intent launchIntent = new Intent(this, PlaybackService.class);
- launchIntent.putExtra(PlaybackService.EXTRA_PLAYABLE, media);
- launchIntent.putExtra(PlaybackService.EXTRA_START_WHEN_PREPARED,
- true);
- launchIntent.putExtra(PlaybackService.EXTRA_SHOULD_STREAM, false);
- launchIntent.putExtra(PlaybackService.EXTRA_PREPARE_IMMEDIATELY,
- true);
- startService(launchIntent);
- }
- if (savedPosition != -1) {
- switchToFragment(savedPosition);
- }
-
- EventDistributor.getInstance().register(contentUpdate);
- loadData();
- }
-
- @Override
- protected void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
- setIntent(intent);
- }
-
- @Override
- protected void onAwaitingVideoSurface() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "onAwaitingVideoSurface was called in audio player -> switching to video player");
- startActivity(new Intent(this, VideoplayerActivity.class));
- }
-
- @Override
- protected void postStatusMsg(int resId) {
- setSupportProgressBarIndeterminateVisibility(resId == R.string.player_preparing_msg
- || resId == R.string.player_seeking_msg
- || resId == R.string.player_buffering_msg);
- }
-
- @Override
- protected void clearStatusMsg() {
- setSupportProgressBarIndeterminateVisibility(false);
- }
-
- /**
- * Changes the currently displayed fragment.
- *
- * @param pos Must be POS_COVER, POS_DESCR, or POS_CHAPTERS
- */
- private void switchToFragment(int pos) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Switching contentView to position " + pos);
- if (currentlyShownPosition != pos && controller != null) {
- Playable media = controller.getMedia();
- if (media != null) {
- FragmentTransaction ft = getSupportFragmentManager()
- .beginTransaction();
- if (currentlyShownFragment != null) {
- detachedFragments[currentlyShownPosition] = currentlyShownFragment;
- ft.detach(currentlyShownFragment);
- }
- switch (pos) {
- case POS_COVER:
- if (coverFragment == null) {
- Log.i(TAG, "Using new coverfragment");
- coverFragment = CoverFragment.newInstance(media);
- }
- currentlyShownFragment = coverFragment;
- break;
- case POS_DESCR:
- if (descriptionFragment == null) {
- descriptionFragment = ItemDescriptionFragment
- .newInstance(media, true, true);
- }
- currentlyShownFragment = descriptionFragment;
- break;
- case POS_CHAPTERS:
- if (chapterFragment == null) {
- chapterFragment = new ListFragment() {
-
- @Override
- public void onListItemClick(ListView l, View v,
- int position, long id) {
- super.onListItemClick(l, v, position, id);
- Chapter chapter = (Chapter) this
- .getListAdapter().getItem(position);
- controller.seekToChapter(chapter);
- }
-
- };
- chapterFragment.setListAdapter(new ChapterListAdapter(
- AudioplayerActivity.this, 0, media
- .getChapters(), media
- ));
- }
- currentlyShownFragment = chapterFragment;
- break;
- }
- if (currentlyShownFragment != null) {
- currentlyShownPosition = pos;
- if (detachedFragments[pos] != null) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Reattaching fragment at position "
- + pos);
- ft.attach(detachedFragments[pos]);
- } else {
- ft.add(R.id.contentView, currentlyShownFragment);
- }
- ft.disallowAddToBackStack();
- ft.commit();
- updateNavButtonDrawable();
- }
- }
- }
- }
-
- private void updateNavButtonDrawable() {
-
- final int[] buttonTexts = new int[]{R.string.show_shownotes_label,
- R.string.show_chapters_label, R.string.show_cover_label};
-
- final TypedArray drawables = obtainStyledAttributes(new int[]{
- R.attr.navigation_shownotes, R.attr.navigation_chapters});
- final Playable media = controller.getMedia();
- if (butNavLeft != null && butNavRight != null && media != null) {
-
- butNavRight.setTag(R.id.imageloader_key, null);
- butNavLeft.setTag(R.id.imageloader_key, null);
-
- switch (currentlyShownPosition) {
- case POS_COVER:
- butNavLeft.setScaleType(ScaleType.CENTER);
- butNavLeft.setImageDrawable(drawables.getDrawable(0));
- butNavLeft.setContentDescription(getString(buttonTexts[0]));
-
- butNavRight.setImageDrawable(drawables.getDrawable(1));
- butNavRight.setContentDescription(getString(buttonTexts[1]));
-
- break;
- case POS_DESCR:
- butNavLeft.setScaleType(ScaleType.CENTER_CROP);
- butNavLeft.post(new Runnable() {
-
- @Override
- public void run() {
- PicassoProvider.getMediaMetadataPicassoInstance(AudioplayerActivity.this)
- .load(media.getImageUri())
- .fit()
- .into(butNavLeft);
- }
- });
- butNavLeft.setContentDescription(getString(buttonTexts[2]));
-
- butNavRight.setImageDrawable(drawables.getDrawable(1));
- butNavRight.setContentDescription(getString(buttonTexts[1]));
- break;
- case POS_CHAPTERS:
- butNavLeft.setScaleType(ScaleType.CENTER_CROP);
- butNavLeft.post(new Runnable() {
-
- @Override
- public void run() {
- PicassoProvider.getMediaMetadataPicassoInstance(AudioplayerActivity.this)
- .load(media.getImageUri())
- .fit()
- .into(butNavLeft);
- }
-
- });
- butNavLeft.setContentDescription(getString(buttonTexts[2]));
-
- butNavRight.setImageDrawable(drawables.getDrawable(0));
- butNavRight.setContentDescription(getString(buttonTexts[0]));
- break;
- }
- }
- }
-
- @Override
- protected void setupGUI() {
- super.setupGUI();
- resetFragmentView();
- drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
- navList = (ListView) findViewById(R.id.nav_list);
- txtvTitle = (TextView) findViewById(R.id.txtvTitle);
- butNavLeft = (ImageButton) findViewById(R.id.butNavLeft);
- butNavRight = (ImageButton) findViewById(R.id.butNavRight);
- butPlaybackSpeed = (Button) findViewById(R.id.butPlaybackSpeed);
-
- TypedArray typedArray = obtainStyledAttributes(new int[]{R.attr.nav_drawer_toggle});
- drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, typedArray.getResourceId(0, 0), R.string.drawer_open, R.string.drawer_close) {
- String currentTitle = getSupportActionBar().getTitle().toString();
-
- @Override
- public void onDrawerOpened(View drawerView) {
- super.onDrawerOpened(drawerView);
- currentTitle = getSupportActionBar().getTitle().toString();
- getSupportActionBar().setTitle(R.string.app_name);
- supportInvalidateOptionsMenu();
- }
-
- @Override
- public void onDrawerClosed(View drawerView) {
- super.onDrawerClosed(drawerView);
- getSupportActionBar().setTitle(currentTitle);
- supportInvalidateOptionsMenu();
- }
- };
- typedArray.recycle();
- drawerToggle.setDrawerIndicatorEnabled(false);
- drawerLayout.setDrawerListener(drawerToggle);
-
- navAdapter = new NavListAdapter(itemAccess, this);
- navList.setAdapter(navAdapter);
- navList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- int viewType = parent.getAdapter().getItemViewType(position);
- if (viewType != NavListAdapter.VIEW_TYPE_SECTION_DIVIDER) {
- int relPos = (viewType == NavListAdapter.VIEW_TYPE_NAV) ? position : position - NavListAdapter.SUBSCRIPTION_OFFSET;
- Intent intent = new Intent(AudioplayerActivity.this, MainActivity.class);
- intent.putExtra(MainActivity.EXTRA_NAV_TYPE, viewType);
- intent.putExtra(MainActivity.EXTRA_NAV_INDEX, relPos);
- startActivity(intent);
- }
- drawerLayout.closeDrawer(navList);
- }
- });
- drawerToggle.syncState();
-
- butNavLeft.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- if (currentlyShownFragment == null
- || currentlyShownPosition == POS_DESCR) {
- switchToFragment(POS_COVER);
- } else if (currentlyShownPosition == POS_COVER) {
- switchToFragment(POS_DESCR);
- } else if (currentlyShownPosition == POS_CHAPTERS) {
- switchToFragment(POS_COVER);
- }
- }
- });
-
- butNavRight.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- if (currentlyShownPosition == POS_CHAPTERS) {
- switchToFragment(POS_DESCR);
- } else {
- switchToFragment(POS_CHAPTERS);
- }
- }
- });
-
- butPlaybackSpeed.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- if (controller != null && controller.canSetPlaybackSpeed()) {
- String[] availableSpeeds = UserPreferences
- .getPlaybackSpeedArray();
- String currentSpeed = UserPreferences.getPlaybackSpeed();
-
- // Provide initial value in case the speed list has changed
- // out from under us
- // and our current speed isn't in the new list
- String newSpeed;
- if (availableSpeeds.length > 0) {
- newSpeed = availableSpeeds[0];
- } else {
- newSpeed = "1.0";
- }
-
- for (int i = 0; i < availableSpeeds.length; i++) {
- if (availableSpeeds[i].equals(currentSpeed)) {
- if (i == availableSpeeds.length - 1) {
- newSpeed = availableSpeeds[0];
- } else {
- newSpeed = availableSpeeds[i + 1];
- }
- break;
- }
- }
- UserPreferences.setPlaybackSpeed(newSpeed);
- controller.setPlaybackSpeed(Float.parseFloat(newSpeed));
- }
- }
- });
-
- butPlaybackSpeed.setOnLongClickListener(new OnLongClickListener() {
- @Override
- public boolean onLongClick(View v) {
- VariableSpeedDialog.showDialog(AudioplayerActivity.this);
- return true;
- }
- });
- }
-
- @Override
- protected void onPlaybackSpeedChange() {
- super.onPlaybackSpeedChange();
- updateButPlaybackSpeed();
- }
-
- private void updateButPlaybackSpeed() {
- if (controller != null && controller.canSetPlaybackSpeed()) {
- butPlaybackSpeed.setText(UserPreferences.getPlaybackSpeed());
- }
- }
-
- @Override
- protected void onPositionObserverUpdate() {
- super.onPositionObserverUpdate();
- notifyMediaPositionChanged();
- }
-
- @Override
- protected boolean loadMediaInfo() {
- if (!super.loadMediaInfo()) {
- return false;
- }
- final Playable media = controller.getMedia();
- if (media == null) {
- return false;
- }
- txtvTitle.setText(media.getEpisodeTitle());
- if (media.getChapters() != null) {
- butNavRight.setVisibility(View.VISIBLE);
- } else {
- butNavRight.setVisibility(View.INVISIBLE);
- }
-
-
- if (currentlyShownPosition == -1) {
- if (!restoreFromPreferences()) {
- switchToFragment(POS_COVER);
- }
- }
- if (currentlyShownFragment instanceof AudioplayerContentFragment) {
- ((AudioplayerContentFragment) currentlyShownFragment)
- .onDataSetChanged(media);
- }
-
- if (controller == null
- || !controller.canSetPlaybackSpeed()) {
- butPlaybackSpeed.setVisibility(View.GONE);
- } else {
- butPlaybackSpeed.setVisibility(View.VISIBLE);
- }
-
- updateButPlaybackSpeed();
- return true;
- }
-
- public void notifyMediaPositionChanged() {
- if (chapterFragment != null) {
- ArrayAdapter<SimpleChapter> adapter = (ArrayAdapter<SimpleChapter>) chapterFragment
- .getListAdapter();
- adapter.notifyDataSetChanged();
- }
- }
-
- @Override
- protected void onReloadNotification(int notificationCode) {
- if (notificationCode == PlaybackService.EXTRA_CODE_VIDEO) {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "ReloadNotification received, switching to Videoplayer now");
- finish();
- startActivity(new Intent(this, VideoplayerActivity.class));
-
- }
- }
-
- @Override
- protected void onBufferStart() {
- postStatusMsg(R.string.player_buffering_msg);
- }
-
- @Override
- protected void onBufferEnd() {
- clearStatusMsg();
- }
-
- @Override
- public PlaybackController getPlaybackController() {
- return controller;
- }
-
- @Override
- public boolean isDrawerOpen() {
- return drawerLayout != null && navList != null && drawerLayout.isDrawerOpen(navList);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- if (!MenuItemUtils.isActivityDrawerOpen(this)) {
- return super.onCreateOptionsMenu(menu);
- } else {
- return false;
- }
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- if (!MenuItemUtils.isActivityDrawerOpen(this)) {
- return super.onPrepareOptionsMenu(menu);
- } else {
- return false;
- }
- }
-
- public interface AudioplayerContentFragment {
- public void onDataSetChanged(Playable media);
- }
-
- @Override
- protected int getContentViewResourceId() {
- return R.layout.audioplayer_activity;
- }
-
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (drawerToggle != null && drawerToggle.onOptionsItemSelected(item)) {
- return true;
- } else {
- return super.onOptionsItemSelected(item);
- }
- }
-
- private DBReader.NavDrawerData navDrawerData;
- private AsyncTask<Void, Void, DBReader.NavDrawerData> loadTask;
-
- private void loadData() {
- loadTask = new AsyncTask<Void, Void, DBReader.NavDrawerData>() {
- @Override
- protected DBReader.NavDrawerData doInBackground(Void... params) {
- return DBReader.getNavDrawerData(AudioplayerActivity.this);
- }
-
- @Override
- protected void onPostExecute(DBReader.NavDrawerData result) {
- super.onPostExecute(result);
- navDrawerData = result;
- if (navAdapter != null) {
- navAdapter.notifyDataSetChanged();
- }
- }
- };
- loadTask.execute();
- }
-
- private void cancelLoadTask() {
- if (loadTask != null) {
- loadTask.cancel(true);
- }
- }
-
- private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
-
- @Override
- public void update(EventDistributor eventDistributor, Integer arg) {
- if ((EventDistributor.FEED_LIST_UPDATE & arg) != 0) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Received contentUpdate Intent.");
- loadData();
- }
- }
- };
-
- private final NavListAdapter.ItemAccess itemAccess = new NavListAdapter.ItemAccess() {
- @Override
- public int getCount() {
- if (navDrawerData != null) {
- return navDrawerData.feeds.size();
- } else {
- return 0;
- }
- }
-
- @Override
- public Feed getItem(int position) {
- if (navDrawerData != null && position < navDrawerData.feeds.size()) {
- return navDrawerData.feeds.get(position);
- } else {
- return null;
- }
- }
-
- @Override
- public int getSelectedItemIndex() {
- return -1;
- }
-
- @Override
- public int getQueueSize() {
- return (navDrawerData != null) ? navDrawerData.queueSize : 0;
- }
-
- @Override
- public int getNumberOfUnreadItems() {
- return (navDrawerData != null) ? navDrawerData.numUnreadItems : 0;
- }
- };
-}
diff --git a/src/de/danoeh/antennapod/activity/DefaultOnlineFeedViewActivity.java b/src/de/danoeh/antennapod/activity/DefaultOnlineFeedViewActivity.java
deleted file mode 100644
index a03fa7949..000000000
--- a/src/de/danoeh/antennapod/activity/DefaultOnlineFeedViewActivity.java
+++ /dev/null
@@ -1,248 +0,0 @@
-package de.danoeh.antennapod.activity;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.support.v4.app.NavUtils;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.ListView;
-import android.widget.Spinner;
-import android.widget.TextView;
-
-import org.apache.commons.lang3.StringUtils;
-import org.jsoup.Jsoup;
-import org.jsoup.examples.HtmlToPlainText;
-import org.jsoup.nodes.Document;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.adapter.FeedItemlistDescriptionAdapter;
-import de.danoeh.antennapod.asynctask.PicassoProvider;
-import de.danoeh.antennapod.dialog.DownloadRequestErrorDialogCreator;
-import de.danoeh.antennapod.feed.EventDistributor;
-import de.danoeh.antennapod.feed.Feed;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.storage.DBReader;
-import de.danoeh.antennapod.storage.DownloadRequestException;
-import de.danoeh.antennapod.storage.DownloadRequester;
-
-/**
- * Default implementation of OnlineFeedViewActivity. Shows the downloaded feed's items with their descriptions,
- * a subscribe button and a spinner for choosing alternate feed URLs.
- */
-public class DefaultOnlineFeedViewActivity extends OnlineFeedViewActivity {
- private static final String TAG = "DefaultOnlineFeedViewActivity";
-
- private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED | EventDistributor.DOWNLOAD_QUEUED | EventDistributor.FEED_LIST_UPDATE;
- private volatile List<Feed> feeds;
- private Feed feed;
- private String selectedDownloadUrl;
-
- private Button subscribeButton;
-
- @Override
- protected void onCreate(Bundle arg0) {
- super.onCreate(arg0);
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- Intent destIntent = new Intent(this, MainActivity.class);
- if (NavUtils.shouldUpRecreateTask(this, destIntent)) {
- startActivity(destIntent);
- } else {
- NavUtils.navigateUpFromSameTask(this);
- }
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
-
- @Override
- protected void loadData() {
- super.loadData();
- feeds = DBReader.getFeedList(this);
- }
-
- @Override
- protected void beforeShowFeedInformation(Feed feed, Map<String, String> alternateFeedUrls) {
- super.beforeShowFeedInformation(feed, alternateFeedUrls);
-
- // remove HTML tags from descriptions
-
- if (BuildConfig.DEBUG) Log.d(TAG, "Removing HTML from shownotes");
- if (feed.getItems() != null) {
- HtmlToPlainText formatter = new HtmlToPlainText();
- for (FeedItem item : feed.getItems()) {
- if (item.getDescription() != null) {
- Document description = Jsoup.parse(item.getDescription());
- item.setDescription(StringUtils.trim(formatter.getPlainText(description)));
- }
- }
- }
- }
-
- @Override
- protected void showFeedInformation(final Feed feed, final Map<String, String> alternateFeedUrls) {
- super.showFeedInformation(feed, alternateFeedUrls);
- setContentView(R.layout.listview_activity);
-
- this.feed = feed;
- this.selectedDownloadUrl = feed.getDownload_url();
- EventDistributor.getInstance().register(listener);
- ListView listView = (ListView) findViewById(R.id.listview);
- LayoutInflater inflater = (LayoutInflater)
- getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View header = inflater.inflate(R.layout.onlinefeedview_header, listView, false);
- listView.addHeaderView(header);
-
- listView.setAdapter(new FeedItemlistDescriptionAdapter(this, 0, feed.getItems()));
-
- ImageView cover = (ImageView) header.findViewById(R.id.imgvCover);
- TextView title = (TextView) header.findViewById(R.id.txtvTitle);
- TextView author = (TextView) header.findViewById(R.id.txtvAuthor);
- TextView description = (TextView) header.findViewById(R.id.txtvDescription);
- Spinner spAlternateUrls = (Spinner) header.findViewById(R.id.spinnerAlternateUrls);
-
- subscribeButton = (Button) header.findViewById(R.id.butSubscribe);
-
- if (feed.getImage() != null) {
- PicassoProvider.getDefaultPicassoInstance(this)
- .load(feed.getImage().getDownload_url())
- .fit()
- .into(cover);
- }
-
- title.setText(feed.getTitle());
- author.setText(feed.getAuthor());
- description.setText(feed.getDescription());
-
- subscribeButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- try {
- Feed f = new Feed(selectedDownloadUrl, new Date(), feed.getTitle());
- f.setPreferences(feed.getPreferences());
- DefaultOnlineFeedViewActivity.this.feed = f;
-
- DownloadRequester.getInstance().downloadFeed(
- DefaultOnlineFeedViewActivity.this,
- f);
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- DownloadRequestErrorDialogCreator.newRequestErrorDialog(DefaultOnlineFeedViewActivity.this,
- e.getMessage());
- }
- setSubscribeButtonState(feed);
- }
- });
-
- if (alternateFeedUrls.isEmpty()) {
- spAlternateUrls.setVisibility(View.GONE);
- } else {
- spAlternateUrls.setVisibility(View.VISIBLE);
-
- final List<String> alternateUrlsList = new ArrayList<String>();
- final List<String> alternateUrlsTitleList = new ArrayList<String>();
-
- alternateUrlsList.add(feed.getDownload_url());
- alternateUrlsTitleList.add(feed.getTitle());
-
-
- alternateUrlsList.addAll(alternateFeedUrls.keySet());
- for (String url : alternateFeedUrls.keySet()) {
- alternateUrlsTitleList.add(alternateFeedUrls.get(url));
- }
- ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, alternateUrlsTitleList);
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- spAlternateUrls.setAdapter(adapter);
- spAlternateUrls.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
- @Override
- public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- selectedDownloadUrl = alternateUrlsList.get(position);
- }
-
- @Override
- public void onNothingSelected(AdapterView<?> parent) {
-
- }
- });
-
-
- }
- setSubscribeButtonState(feed);
-
- }
-
- private boolean feedInFeedlist(Feed feed) {
- if (feeds == null || feed == null)
- return false;
- for (Feed f : feeds) {
- if (f.getIdentifyingValue().equals(feed.getIdentifyingValue())) {
- return true;
- }
- }
- return false;
- }
-
- private void setSubscribeButtonState(Feed feed) {
- if (subscribeButton != null && feed != null) {
- if (DownloadRequester.getInstance().isDownloadingFile(feed.getDownload_url())) {
- subscribeButton.setEnabled(false);
- subscribeButton.setText(R.string.downloading_label);
- } else if (feedInFeedlist(feed)) {
- subscribeButton.setEnabled(false);
- subscribeButton.setText(R.string.subscribed_label);
- } else {
- subscribeButton.setEnabled(true);
- subscribeButton.setText(R.string.subscribe_label);
- }
- }
- }
-
- EventDistributor.EventListener listener = new EventDistributor.EventListener() {
- @Override
- public void update(EventDistributor eventDistributor, Integer arg) {
- if ((arg & EventDistributor.FEED_LIST_UPDATE) != 0) {
- new AsyncTask<Void, Void, List<Feed>>() {
- @Override
- protected List<Feed> doInBackground(Void... params) {
- return DBReader.getFeedList(DefaultOnlineFeedViewActivity.this);
- }
-
- @Override
- protected void onPostExecute(List<Feed> feeds) {
- super.onPostExecute(feeds);
- DefaultOnlineFeedViewActivity.this.feeds = feeds;
- setSubscribeButtonState(feed);
- }
- }.execute();
- } else if ((arg & EVENTS) != 0) {
- setSubscribeButtonState(feed);
- }
- }
- };
-
- @Override
- protected void onStop() {
- super.onStop();
- EventDistributor.getInstance().unregister(listener);
- }
-}
-
diff --git a/src/de/danoeh/antennapod/activity/DirectoryChooserActivity.java b/src/de/danoeh/antennapod/activity/DirectoryChooserActivity.java
deleted file mode 100644
index 06a11c775..000000000
--- a/src/de/danoeh/antennapod/activity/DirectoryChooserActivity.java
+++ /dev/null
@@ -1,370 +0,0 @@
-package de.danoeh.antennapod.activity;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Environment;
-import android.os.FileObserver;
-import android.support.v4.app.NavUtils;
-import android.support.v7.app.ActionBarActivity;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.*;
-import android.widget.AdapterView.OnItemClickListener;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.preferences.UserPreferences;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-
-/**
- * Let's the user choose a directory on the storage device. The selected folder
- * will be sent back to the starting activity as an activity result.
- */
-public class DirectoryChooserActivity extends ActionBarActivity {
- private static final String TAG = "DirectoryChooserActivity";
-
- private static final String CREATE_DIRECTORY_NAME = "AntennaPod";
-
- public static final String RESULT_SELECTED_DIR = "selected_dir";
- public static final int RESULT_CODE_DIR_SELECTED = 1;
-
- private Button butConfirm;
- private Button butCancel;
- private ImageButton butNavUp;
- private TextView txtvSelectedFolder;
- private ListView listDirectories;
-
- private ArrayAdapter<String> listDirectoriesAdapter;
- private ArrayList<String> filenames;
- /** The directory that is currently being shown. */
- private File selectedDir;
- private File[] filesInDir;
-
- private FileObserver fileObserver;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- setTheme(UserPreferences.getTheme());
- super.onCreate(savedInstanceState);
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
-
- setContentView(R.layout.directory_chooser);
- butConfirm = (Button) findViewById(R.id.butConfirm);
- butCancel = (Button) findViewById(R.id.butCancel);
- butNavUp = (ImageButton) findViewById(R.id.butNavUp);
- txtvSelectedFolder = (TextView) findViewById(R.id.txtvSelectedFolder);
- listDirectories = (ListView) findViewById(R.id.directory_list);
-
- butConfirm.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- if (isValidFile(selectedDir)) {
- if (selectedDir.list().length == 0) {
- returnSelectedFolder();
- } else {
- showNonEmptyDirectoryWarning();
- }
- }
- }
-
- private void showNonEmptyDirectoryWarning() {
- AlertDialog.Builder adb = new AlertDialog.Builder(
- DirectoryChooserActivity.this);
- adb.setTitle(R.string.folder_not_empty_dialog_title);
- adb.setMessage(R.string.folder_not_empty_dialog_msg);
- adb.setNegativeButton(R.string.cancel_label,
- new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog,
- int which) {
- dialog.dismiss();
- }
- });
- adb.setPositiveButton(R.string.confirm_label,
- new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog,
- int which) {
- dialog.dismiss();
- returnSelectedFolder();
- }
- });
- adb.create().show();
- }
- });
-
- butCancel.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- setResult(Activity.RESULT_CANCELED);
- finish();
- }
- });
-
- listDirectories.setOnItemClickListener(new OnItemClickListener() {
-
- @Override
- public void onItemClick(AdapterView<?> adapter, View view,
- int position, long id) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Selected index: " + position);
- if (filesInDir != null && position >= 0
- && position < filesInDir.length) {
- changeDirectory(filesInDir[position]);
- }
- }
- });
-
- butNavUp.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- File parent = null;
- if (selectedDir != null
- && (parent = selectedDir.getParentFile()) != null) {
- changeDirectory(parent);
- }
- }
- });
-
- filenames = new ArrayList<String>();
- listDirectoriesAdapter = new ArrayAdapter<String>(this,
- android.R.layout.simple_list_item_1, filenames);
- listDirectories.setAdapter(listDirectoriesAdapter);
- changeDirectory(Environment.getExternalStorageDirectory());
- }
-
- /**
- * Finishes the activity and returns the selected folder as a result. The
- * selected folder can also be null.
- */
- private void returnSelectedFolder() {
- if (selectedDir != null && BuildConfig.DEBUG)
- Log.d(TAG, "Returning " + selectedDir.getAbsolutePath()
- + " as result");
- Intent resultData = new Intent();
- if (selectedDir != null) {
- resultData.putExtra(RESULT_SELECTED_DIR,
- selectedDir.getAbsolutePath());
- }
- setResult(RESULT_CODE_DIR_SELECTED, resultData);
- finish();
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- if (fileObserver != null) {
- fileObserver.stopWatching();
- }
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- if (fileObserver != null) {
- fileObserver.startWatching();
- }
- }
-
- /**
- * Change the directory that is currently being displayed.
- *
- * @param dir
- * The file the activity should switch to. This File must be
- * non-null and a directory, otherwise the displayed directory
- * will not be changed
- */
- private void changeDirectory(File dir) {
- if (dir != null && dir.isDirectory()) {
- File[] contents = dir.listFiles();
- if (contents != null) {
- int numDirectories = 0;
- for (File f : contents) {
- if (f.isDirectory()) {
- numDirectories++;
- }
- }
- filesInDir = new File[numDirectories];
- filenames.clear();
- for (int i = 0, counter = 0; i < numDirectories; counter++) {
- if (contents[counter].isDirectory()) {
- filesInDir[i] = contents[counter];
- filenames.add(contents[counter].getName());
- i++;
- }
- }
- Arrays.sort(filesInDir);
- Collections.sort(filenames);
- selectedDir = dir;
- txtvSelectedFolder.setText(dir.getAbsolutePath());
- listDirectoriesAdapter.notifyDataSetChanged();
- fileObserver = createFileObserver(dir.getAbsolutePath());
- fileObserver.startWatching();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Changed directory to " + dir.getAbsolutePath());
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "Could not change folder: contents of dir were null");
- }
- } else {
- if (dir == null) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Could not change folder: dir was null");
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Could not change folder: dir is no directory");
- }
- }
- refreshButtonState();
- }
-
- /**
- * Changes the state of the buttons depending on the currently selected file
- * or folder.
- */
- private void refreshButtonState() {
- if (selectedDir != null) {
- butConfirm.setEnabled(isValidFile(selectedDir));
- supportInvalidateOptionsMenu();
- }
- }
-
- /** Refresh the contents of the directory that is currently shown. */
- private void refreshDirectory() {
- if (selectedDir != null) {
- changeDirectory(selectedDir);
- }
- }
-
- /** Sets up a FileObserver to watch the current directory. */
- private FileObserver createFileObserver(String path) {
- return new FileObserver(path, FileObserver.CREATE | FileObserver.DELETE
- | FileObserver.MOVED_FROM | FileObserver.MOVED_TO) {
-
- @Override
- public void onEvent(int event, String path) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "FileObserver received event " + event);
- runOnUiThread(new Runnable() {
-
- @Override
- public void run() {
- refreshDirectory();
- }
- });
- }
- };
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- super.onPrepareOptionsMenu(menu);
- menu.findItem(R.id.new_folder_item)
- .setVisible(isValidFile(selectedDir));
- return true;
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.directory_chooser, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- NavUtils.navigateUpFromSameTask(this);
- return true;
- case R.id.new_folder_item:
- openNewFolderDialog();
- return true;
- case R.id.set_to_default_folder_item:
- selectedDir = null;
- returnSelectedFolder();
- return true;
- default:
- return false;
- }
- }
-
- /**
- * Shows a confirmation dialog that asks the user if he wants to create a
- * new folder.
- */
- private void openNewFolderDialog() {
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setTitle(R.string.create_folder_label);
- builder.setMessage(String.format(getString(R.string.create_folder_msg),
- CREATE_DIRECTORY_NAME));
- builder.setNegativeButton(R.string.cancel_label,
- new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- }
- });
- builder.setPositiveButton(R.string.confirm_label,
- new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- int msg = createFolder();
- Toast t = Toast.makeText(DirectoryChooserActivity.this,
- msg, Toast.LENGTH_SHORT);
- t.show();
- }
- });
- builder.create().show();
- }
-
- /**
- * Creates a new folder in the current directory with the name
- * CREATE_DIRECTORY_NAME.
- */
- private int createFolder() {
- if (selectedDir == null) {
- return R.string.create_folder_error;
- } else if (selectedDir.canWrite()) {
- File newDir = new File(selectedDir, CREATE_DIRECTORY_NAME);
- if (!newDir.exists()) {
- boolean result = newDir.mkdir();
- if (result) {
- return R.string.create_folder_success;
- } else {
- return R.string.create_folder_error;
- }
- } else {
- return R.string.create_folder_error_already_exists;
- }
- } else {
- return R.string.create_folder_error_no_write_access;
- }
- }
-
- /** Returns true if the selected file or directory would be valid selection. */
- private boolean isValidFile(File file) {
- return (file != null && file.isDirectory() && file.canRead() && file
- .canWrite());
- }
-}
diff --git a/src/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java b/src/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java
deleted file mode 100644
index c5f25d813..000000000
--- a/src/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package de.danoeh.antennapod.activity;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
-import android.util.Log;
-import android.view.View;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.TextView;
-
-import org.apache.commons.lang3.Validate;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.preferences.UserPreferences;
-import de.danoeh.antennapod.service.download.DownloadRequest;
-import de.danoeh.antennapod.storage.DownloadRequester;
-
-/**
- * Shows a username and a password text field.
- * The activity MUST be started with the ARG_DOWNlOAD_REQUEST argument set to a non-null value.
- * Other arguments are optional.
- * The activity's result will be the same DownloadRequest with the entered username and password.
- */
-public class DownloadAuthenticationActivity extends ActionBarActivity {
- private static final String TAG = "DownloadAuthenticationActivity";
-
- /**
- * The download request object that contains information about the resource that requires a username and a password
- */
- public static final String ARG_DOWNLOAD_REQUEST = "request";
- /**
- * True if the request should be sent to the DownloadRequester when this activity is finished, false otherwise.
- * The default value is false.
- */
- public static final String ARG_SEND_TO_DOWNLOAD_REQUESTER_BOOL = "send_to_downloadrequester";
-
- public static final String RESULT_REQUEST = "request";
-
- private EditText etxtUsername;
- private EditText etxtPassword;
- private Button butConfirm;
- private Button butCancel;
- private TextView txtvDescription;
-
- private DownloadRequest request;
- private boolean sendToDownloadRequester;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- setTheme(UserPreferences.getTheme());
- super.onCreate(savedInstanceState);
- getSupportActionBar().hide();
- setContentView(R.layout.download_authentication_activity);
-
- etxtUsername = (EditText) findViewById(R.id.etxtUsername);
- etxtPassword = (EditText) findViewById(R.id.etxtPassword);
- butConfirm = (Button) findViewById(R.id.butConfirm);
- butCancel = (Button) findViewById(R.id.butCancel);
- txtvDescription = (TextView) findViewById(R.id.txtvDescription);
-
- Validate.isTrue(getIntent().hasExtra(ARG_DOWNLOAD_REQUEST), "Download request missing");
-
- request = getIntent().getParcelableExtra(ARG_DOWNLOAD_REQUEST);
- sendToDownloadRequester = getIntent().getBooleanExtra(ARG_SEND_TO_DOWNLOAD_REQUESTER_BOOL, false);
-
- if (savedInstanceState != null) {
- etxtUsername.setText(savedInstanceState.getString("username"));
- etxtPassword.setText(savedInstanceState.getString("password"));
- }
-
- txtvDescription.setText(txtvDescription.getText() + ":\n\n" + request.getTitle());
-
- butCancel.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- setResult(Activity.RESULT_CANCELED);
- finish();
- }
- });
-
- butConfirm.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- String username = etxtUsername.getText().toString();
- String password = etxtPassword.getText().toString();
- request.setUsername(username);
- request.setPassword(password);
- Intent result = new Intent();
- result.putExtra(RESULT_REQUEST, request);
- setResult(Activity.RESULT_OK, result);
-
- if (sendToDownloadRequester) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Sending request to DownloadRequester");
- DownloadRequester.getInstance().download(DownloadAuthenticationActivity.this, request);
- }
- finish();
- }
- });
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putString("username", etxtUsername.getText().toString());
- outState.putString("password", etxtPassword.getText().toString());
- }
-}
diff --git a/src/de/danoeh/antennapod/activity/FeedInfoActivity.java b/src/de/danoeh/antennapod/activity/FeedInfoActivity.java
deleted file mode 100644
index 5cf187eb6..000000000
--- a/src/de/danoeh/antennapod/activity/FeedInfoActivity.java
+++ /dev/null
@@ -1,192 +0,0 @@
-package de.danoeh.antennapod.activity;
-
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
-import android.text.Editable;
-import android.text.TextWatcher;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.widget.*;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.asynctask.PicassoProvider;
-import de.danoeh.antennapod.dialog.DownloadRequestErrorDialogCreator;
-import de.danoeh.antennapod.feed.Feed;
-import de.danoeh.antennapod.feed.FeedPreferences;
-import de.danoeh.antennapod.preferences.UserPreferences;
-import de.danoeh.antennapod.storage.DBReader;
-import de.danoeh.antennapod.storage.DBWriter;
-import de.danoeh.antennapod.storage.DownloadRequestException;
-import de.danoeh.antennapod.util.LangUtils;
-import de.danoeh.antennapod.util.menuhandler.FeedMenuHandler;
-
-/**
- * Displays information about a feed.
- */
-public class FeedInfoActivity extends ActionBarActivity {
- private static final String TAG = "FeedInfoActivity";
-
- public static final String EXTRA_FEED_ID = "de.danoeh.antennapod.extra.feedId";
-
- private Feed feed;
-
- private ImageView imgvCover;
- private TextView txtvTitle;
- private TextView txtvDescription;
- private TextView txtvLanguage;
- private TextView txtvAuthor;
- private EditText etxtUsername;
- private EditText etxtPassword;
- private CheckBox cbxAutoDownload;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- setTheme(UserPreferences.getTheme());
- super.onCreate(savedInstanceState);
- setContentView(R.layout.feedinfo);
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
- long feedId = getIntent().getLongExtra(EXTRA_FEED_ID, -1);
-
- imgvCover = (ImageView) findViewById(R.id.imgvCover);
- txtvTitle = (TextView) findViewById(R.id.txtvTitle);
- txtvDescription = (TextView) findViewById(R.id.txtvDescription);
- txtvLanguage = (TextView) findViewById(R.id.txtvLanguage);
- txtvAuthor = (TextView) findViewById(R.id.txtvAuthor);
- cbxAutoDownload = (CheckBox) findViewById(R.id.cbxAutoDownload);
- etxtUsername = (EditText) findViewById(R.id.etxtUsername);
- etxtPassword = (EditText) findViewById(R.id.etxtPassword);
-
- AsyncTask<Long, Void, Feed> loadTask = new AsyncTask<Long, Void, Feed>() {
-
- @Override
- protected Feed doInBackground(Long... params) {
- return DBReader.getFeed(FeedInfoActivity.this, params[0]);
- }
-
- @Override
- protected void onPostExecute(Feed result) {
- if (result != null) {
- feed = result;
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Language is " + feed.getLanguage());
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Author is " + feed.getAuthor());
- imgvCover.post(new Runnable() {
-
- @Override
- public void run() {
- PicassoProvider.getDefaultPicassoInstance(FeedInfoActivity.this)
- .load(feed.getImageUri())
- .fit()
- .into(imgvCover);
- }
- });
-
- txtvTitle.setText(feed.getTitle());
- txtvDescription.setText(feed.getDescription());
- if (feed.getAuthor() != null) {
- txtvAuthor.setText(feed.getAuthor());
- }
- if (feed.getLanguage() != null) {
- txtvLanguage.setText(LangUtils
- .getLanguageString(feed.getLanguage()));
- }
-
- cbxAutoDownload.setEnabled(UserPreferences.isEnableAutodownload());
- cbxAutoDownload.setChecked(feed.getPreferences().getAutoDownload());
- cbxAutoDownload.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
- feed.getPreferences().setAutoDownload(checked);
- feed.savePreferences(FeedInfoActivity.this);
- }
- });
-
- etxtUsername.setText(feed.getPreferences().getUsername());
- etxtPassword.setText(feed.getPreferences().getPassword());
-
- etxtUsername.addTextChangedListener(authTextWatcher);
- etxtPassword.addTextChangedListener(authTextWatcher);
-
- supportInvalidateOptionsMenu();
-
- } else {
- Log.e(TAG, "Activity was started with invalid arguments");
- }
- }
- };
- loadTask.execute(feedId);
- }
-
-
- private boolean authInfoChanged = false;
-
- private TextWatcher authTextWatcher = new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
-
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
-
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- authInfoChanged = true;
- }
- };
-
- @Override
- protected void onPause() {
- super.onPause();
- if (feed != null && authInfoChanged) {
- Log.d(TAG, "Auth info changed, saving credentials");
- FeedPreferences prefs = feed.getPreferences();
- prefs.setUsername(etxtUsername.getText().toString());
- prefs.setPassword(etxtPassword.getText().toString());
- DBWriter.setFeedPreferences(this, prefs);
- authInfoChanged = false;
- }
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.feedinfo, menu);
- return true;
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- super.onPrepareOptionsMenu(menu);
- menu.findItem(R.id.support_item).setVisible(
- feed != null && feed.getPaymentLink() != null);
- menu.findItem(R.id.share_link_item).setVisible(feed != null &&feed.getLink() != null);
- menu.findItem(R.id.visit_website_item).setVisible(feed != null && feed.getLink() != null);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- finish();
- return true;
- default:
- try {
- return FeedMenuHandler.onOptionsItemClicked(this, item, feed);
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- DownloadRequestErrorDialogCreator.newRequestErrorDialog(this,
- e.getMessage());
- }
- return super.onOptionsItemSelected(item);
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/activity/FlattrAuthActivity.java b/src/de/danoeh/antennapod/activity/FlattrAuthActivity.java
deleted file mode 100644
index 8dde14d3b..000000000
--- a/src/de/danoeh/antennapod/activity/FlattrAuthActivity.java
+++ /dev/null
@@ -1,125 +0,0 @@
-package de.danoeh.antennapod.activity;
-
-
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.TextView;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.preferences.UserPreferences;
-import de.danoeh.antennapod.util.flattr.FlattrUtils;
-import org.shredzone.flattr4j.exception.FlattrException;
-
-/** Guides the user through the authentication process */
-
-public class FlattrAuthActivity extends ActionBarActivity {
- private static final String TAG = "FlattrAuthActivity";
-
- private TextView txtvExplanation;
- private Button butAuthenticate;
- private Button butReturn;
-
- private boolean authSuccessful;
-
- private static FlattrAuthActivity singleton;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- setTheme(UserPreferences.getTheme());
- super.onCreate(savedInstanceState);
- singleton = this;
- authSuccessful = false;
- if (BuildConfig.DEBUG) Log.d(TAG, "Activity created");
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
- setContentView(R.layout.flattr_auth);
- txtvExplanation = (TextView) findViewById(R.id.txtvExplanation);
- butAuthenticate = (Button) findViewById(R.id.but_authenticate);
- butReturn = (Button) findViewById(R.id.but_return_home);
-
- butReturn.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(FlattrAuthActivity.this, MainActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivity(intent);
- }
- });
-
- butAuthenticate.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- try {
- FlattrUtils.startAuthProcess(FlattrAuthActivity.this);
- } catch (FlattrException e) {
- e.printStackTrace();
- }
- }
- });
- }
-
- public static FlattrAuthActivity getInstance() {
- return singleton;
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- if (BuildConfig.DEBUG) Log.d(TAG, "Activity resumed");
- Uri uri = getIntent().getData();
- if (uri != null) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Received uri");
- FlattrUtils.handleCallback(this, uri);
- }
- }
-
- public void handleAuthenticationSuccess() {
- authSuccessful = true;
- txtvExplanation.setText(R.string.flattr_auth_success);
- butAuthenticate.setEnabled(false);
- butReturn.setVisibility(View.VISIBLE);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- return true;
- }
-
-
-
- @Override
- protected void onPause() {
- super.onPause();
- if (authSuccessful) {
- finish();
- }
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- if (authSuccessful) {
- Intent intent = new Intent(this, PreferenceActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivity(intent);
- } else {
- finish();
- }
- break;
- default:
- return false;
- }
- return true;
- }
-
-
-}
diff --git a/src/de/danoeh/antennapod/activity/MainActivity.java b/src/de/danoeh/antennapod/activity/MainActivity.java
deleted file mode 100644
index b7014dab2..000000000
--- a/src/de/danoeh/antennapod/activity/MainActivity.java
+++ /dev/null
@@ -1,432 +0,0 @@
-package de.danoeh.antennapod.activity;
-
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.res.Configuration;
-import android.content.res.TypedArray;
-import android.media.AudioManager;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.os.Handler;
-import android.support.v4.app.ActionBarDrawerToggle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
-import android.support.v4.app.FragmentTransaction;
-import android.support.v4.widget.DrawerLayout;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.ActionBarActivity;
-import android.util.Log;
-import android.view.*;
-import android.widget.AdapterView;
-import android.widget.ListView;
-
-import org.apache.commons.lang3.Validate;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.adapter.NavListAdapter;
-import de.danoeh.antennapod.feed.EventDistributor;
-import de.danoeh.antennapod.feed.Feed;
-import de.danoeh.antennapod.fragment.*;
-import de.danoeh.antennapod.preferences.UserPreferences;
-import de.danoeh.antennapod.storage.DBReader;
-import de.danoeh.antennapod.util.StorageUtils;
-import de.danoeh.antennapod.util.menuhandler.NavDrawerActivity;
-
-import java.util.List;
-
-/**
- * The activity that is shown when the user launches the app.
- */
-public class MainActivity extends ActionBarActivity implements NavDrawerActivity{
- private static final String TAG = "MainActivity";
- private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED
- | EventDistributor.DOWNLOAD_QUEUED
- | EventDistributor.FEED_LIST_UPDATE
- | EventDistributor.UNREAD_ITEMS_UPDATE
- | EventDistributor.QUEUE_UPDATE;
-
- public static final String PREF_NAME = "MainActivityPrefs";
- public static final String PREF_IS_FIRST_LAUNCH = "prefMainActivityIsFirstLaunch";
-
- public static final String EXTRA_NAV_INDEX = "nav_index";
- public static final String EXTRA_NAV_TYPE = "nav_type";
- public static final String EXTRA_FRAGMENT_ARGS = "fragment_args";
-
- public static final int POS_NEW = 0,
- POS_QUEUE = 1,
- POS_DOWNLOADS = 2,
- POS_HISTORY = 3,
- POS_ADD = 4;
-
- private ExternalPlayerFragment externalPlayerFragment;
- private DrawerLayout drawerLayout;
-
- private ListView navList;
- private NavListAdapter navAdapter;
-
- private ActionBarDrawerToggle drawerToggle;
-
- private CharSequence drawerTitle;
- private CharSequence currentTitle;
-
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- setTheme(UserPreferences.getTheme());
- super.onCreate(savedInstanceState);
- supportRequestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
- StorageUtils.checkStorageAvailability(this);
- setContentView(R.layout.main);
- setVolumeControlStream(AudioManager.STREAM_MUSIC);
-
- drawerTitle = currentTitle = getTitle();
-
- drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
- navList = (ListView) findViewById(R.id.nav_list);
-
- TypedArray typedArray = obtainStyledAttributes(new int[]{R.attr.nav_drawer_toggle});
- drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, typedArray.getResourceId(0, 0), R.string.drawer_open, R.string.drawer_close) {
- @Override
- public void onDrawerOpened(View drawerView) {
- super.onDrawerOpened(drawerView);
- currentTitle = getSupportActionBar().getTitle();
- getSupportActionBar().setTitle(drawerTitle);
- supportInvalidateOptionsMenu();
- }
-
- @Override
- public void onDrawerClosed(View drawerView) {
- super.onDrawerClosed(drawerView);
- getSupportActionBar().setTitle(currentTitle);
- supportInvalidateOptionsMenu();
-
- }
- };
- typedArray.recycle();
-
- drawerLayout.setDrawerListener(drawerToggle);
- FragmentManager fm = getSupportFragmentManager();
-
- FragmentTransaction transaction = fm.beginTransaction();
-
- Fragment mainFragment = fm.findFragmentByTag("main");
- if (mainFragment != null) {
- transaction.replace(R.id.main_view, mainFragment);
- } else {
- loadFragment(NavListAdapter.VIEW_TYPE_NAV, POS_NEW, null);
- }
-
- externalPlayerFragment = new ExternalPlayerFragment();
- transaction.replace(R.id.playerFragment, externalPlayerFragment);
- transaction.commit();
-
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
- getSupportActionBar().setHomeButtonEnabled(true);
-
- navAdapter = new NavListAdapter(itemAccess, this);
- navList.setAdapter(navAdapter);
- navList.setOnItemClickListener(navListClickListener);
-
- checkFirstLaunch();
- }
-
- private void checkFirstLaunch() {
- SharedPreferences prefs = getSharedPreferences(PREF_NAME, MODE_PRIVATE);
- if (prefs.getBoolean(PREF_IS_FIRST_LAUNCH, true)) {
- new Handler().postDelayed(new Runnable() {
- @Override
- public void run() {
- drawerLayout.openDrawer(navList);
- }
- }, 1500);
-
- SharedPreferences.Editor edit = prefs.edit();
- edit.putBoolean(PREF_IS_FIRST_LAUNCH, false);
- edit.commit();
- }
- }
-
- public ActionBar getMainActivtyActionBar() {
- return getSupportActionBar();
- }
-
- public boolean isDrawerOpen() {
- return drawerLayout != null && navList != null && drawerLayout.isDrawerOpen(navList);
- }
-
- public List<Feed> getFeeds() {
- return (navDrawerData != null) ? navDrawerData.feeds : null;
- }
-
- private void loadFragment(int viewType, int relPos, Bundle args) {
- FragmentManager fragmentManager = getSupportFragmentManager();
- // clear back stack
- for (int i = 0; i < fragmentManager.getBackStackEntryCount(); i++) {
- fragmentManager.popBackStack();
- }
-
- FragmentTransaction fT = fragmentManager.beginTransaction();
- Fragment fragment = null;
- if (viewType == NavListAdapter.VIEW_TYPE_NAV) {
- switch (relPos) {
- case POS_NEW:
- fragment = new NewEpisodesFragment();
- break;
- case POS_QUEUE:
- fragment = new QueueFragment();
- break;
- case POS_DOWNLOADS:
- fragment = new DownloadsFragment();
- break;
- case POS_HISTORY:
- fragment = new PlaybackHistoryFragment();
- break;
- case POS_ADD:
- fragment = new AddFeedFragment();
- break;
-
- }
- currentTitle = getString(NavListAdapter.NAV_TITLES[relPos]);
- selectedNavListIndex = relPos;
-
- } else if (viewType == NavListAdapter.VIEW_TYPE_SUBSCRIPTION) {
- Feed feed = itemAccess.getItem(relPos);
- currentTitle = "";
- fragment = ItemlistFragment.newInstance(feed.getId());
- selectedNavListIndex = NavListAdapter.SUBSCRIPTION_OFFSET + relPos;
-
- }
- if (fragment != null) {
- if (args != null) {
- fragment.setArguments(args);
- }
- fT.replace(R.id.main_view, fragment, "main");
- fragmentManager.popBackStack();
- }
- fT.commit();
- getSupportActionBar().setTitle(currentTitle);
- if (navAdapter != null) {
- navAdapter.notifyDataSetChanged();
- }
- }
-
- public void loadNavFragment(int position, Bundle args) {
- loadFragment(NavListAdapter.VIEW_TYPE_NAV, position, args);
- }
-
- public void loadFeedFragment(long feedID) {
- if (navDrawerData != null) {
- for (int i = 0; i < navDrawerData.feeds.size(); i++) {
- if (navDrawerData.feeds.get(i).getId() == feedID) {
- loadFragment(NavListAdapter.VIEW_TYPE_SUBSCRIPTION, i, null);
- break;
- }
- }
- }
- }
-
- public void loadChildFragment(Fragment fragment) {
- Validate.notNull(fragment);
- FragmentManager fm = getSupportFragmentManager();
- fm.beginTransaction()
- .replace(R.id.main_view, fragment, "main")
- .addToBackStack(null)
- .commit();
- }
-
- private AdapterView.OnItemClickListener navListClickListener = new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- int viewType = parent.getAdapter().getItemViewType(position);
- if (viewType != NavListAdapter.VIEW_TYPE_SECTION_DIVIDER && position != selectedNavListIndex) {
- int relPos = (viewType == NavListAdapter.VIEW_TYPE_NAV) ? position : position - NavListAdapter.SUBSCRIPTION_OFFSET;
- loadFragment(viewType, relPos, null);
- selectedNavListIndex = position;
- navAdapter.notifyDataSetChanged();
- }
- drawerLayout.closeDrawer(navList);
- }
- };
-
- @Override
- protected void onPostCreate(Bundle savedInstanceState) {
- super.onPostCreate(savedInstanceState);
- drawerToggle.syncState();
- if (savedInstanceState != null) {
- currentTitle = savedInstanceState.getString("title");
- if (!drawerLayout.isDrawerOpen(navList)) {
- getSupportActionBar().setTitle(currentTitle);
- }
- selectedNavListIndex = savedInstanceState.getInt("selectedNavIndex");
- }
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- drawerToggle.onConfigurationChanged(newConfig);
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putString("title", getSupportActionBar().getTitle().toString());
- outState.putInt("selectedNavIndex", selectedNavListIndex);
-
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- StorageUtils.checkStorageAvailability(this);
- EventDistributor.getInstance().register(contentUpdate);
-
- Intent intent = getIntent();
- if (navDrawerData != null && intent.hasExtra(EXTRA_NAV_INDEX) && intent.hasExtra(EXTRA_NAV_TYPE)) {
- handleNavIntent();
- }
-
- loadData();
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- cancelLoadTask();
- EventDistributor.getInstance().unregister(contentUpdate);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (drawerToggle.onOptionsItemSelected(item)) {
- return true;
- }
- switch (item.getItemId()) {
- case R.id.show_preferences:
- startActivity(new Intent(this, PreferenceActivity.class));
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- super.onPrepareOptionsMenu(menu);
- return true;
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.main, menu);
- return true;
- }
-
- private DBReader.NavDrawerData navDrawerData;
- private AsyncTask<Void, Void, DBReader.NavDrawerData> loadTask;
- private int selectedNavListIndex = 0;
-
- private NavListAdapter.ItemAccess itemAccess = new NavListAdapter.ItemAccess() {
- @Override
- public int getCount() {
- if (navDrawerData != null) {
- return navDrawerData.feeds.size();
- } else {
- return 0;
- }
- }
-
- @Override
- public Feed getItem(int position) {
- if (navDrawerData != null && position < navDrawerData.feeds.size()) {
- return navDrawerData.feeds.get(position);
- } else {
- return null;
- }
- }
-
- @Override
- public int getSelectedItemIndex() {
- return selectedNavListIndex;
- }
-
- @Override
- public int getQueueSize() {
- return (navDrawerData != null) ? navDrawerData.queueSize : 0;
- }
-
- @Override
- public int getNumberOfUnreadItems() {
- return (navDrawerData != null) ? navDrawerData.numUnreadItems : 0;
- }
-
-
- };
-
- private void loadData() {
- cancelLoadTask();
- loadTask = new AsyncTask<Void, Void, DBReader.NavDrawerData>() {
- @Override
- protected DBReader.NavDrawerData doInBackground(Void... params) {
- return DBReader.getNavDrawerData(MainActivity.this);
- }
-
- @Override
- protected void onPostExecute(DBReader.NavDrawerData result) {
- super.onPostExecute(navDrawerData);
- boolean handleIntent = (navDrawerData == null);
-
- navDrawerData = result;
- navAdapter.notifyDataSetChanged();
-
- if (handleIntent) {
- handleNavIntent();
- }
- }
- };
- loadTask.execute();
- }
-
- private void cancelLoadTask() {
- if (loadTask != null) {
- loadTask.cancel(true);
- }
- }
-
- private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
-
- @Override
- public void update(EventDistributor eventDistributor, Integer arg) {
- if ((EVENTS & arg) != 0) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Received contentUpdate Intent.");
- loadData();
- }
- }
- };
-
- private void handleNavIntent() {
- Intent intent = getIntent();
- if (intent.hasExtra(EXTRA_NAV_INDEX) && intent.hasExtra(EXTRA_NAV_TYPE)) {
- int index = intent.getIntExtra(EXTRA_NAV_INDEX, 0);
- int type = intent.getIntExtra(EXTRA_NAV_TYPE, NavListAdapter.VIEW_TYPE_NAV);
- Bundle args = intent.getBundleExtra(EXTRA_FRAGMENT_ARGS);
- loadFragment(type, index, args);
- }
- setIntent(new Intent(MainActivity.this, MainActivity.class)); // to avoid handling the intent twice when the configuration changes
- }
-
- @Override
- protected void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
- setIntent(intent);
- }
-}
diff --git a/src/de/danoeh/antennapod/activity/MediaplayerActivity.java b/src/de/danoeh/antennapod/activity/MediaplayerActivity.java
deleted file mode 100644
index 2e5372b60..000000000
--- a/src/de/danoeh/antennapod/activity/MediaplayerActivity.java
+++ /dev/null
@@ -1,525 +0,0 @@
-package de.danoeh.antennapod.activity;
-
-import android.app.AlertDialog;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.res.TypedArray;
-import android.graphics.PixelFormat;
-import android.media.AudioManager;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.support.v4.app.DialogFragment;
-import android.support.v7.app.ActionBarActivity;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.Window;
-import android.widget.ImageButton;
-import android.widget.SeekBar;
-import android.widget.SeekBar.OnSeekBarChangeListener;
-import android.widget.TextView;
-import com.doomonafireball.betterpickers.hmspicker.HmsPickerBuilder;
-import com.doomonafireball.betterpickers.hmspicker.HmsPickerDialogFragment;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.dialog.TimeDialog;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.feed.FeedMedia;
-import de.danoeh.antennapod.preferences.UserPreferences;
-import de.danoeh.antennapod.service.playback.PlaybackService;
-import de.danoeh.antennapod.storage.DBTasks;
-import de.danoeh.antennapod.util.Converter;
-import de.danoeh.antennapod.util.ShareUtils;
-import de.danoeh.antennapod.util.StorageUtils;
-import de.danoeh.antennapod.util.playback.MediaPlayerError;
-import de.danoeh.antennapod.util.playback.Playable;
-import de.danoeh.antennapod.util.playback.PlaybackController;
-import org.shredzone.flattr4j.model.User;
-
-/**
- * Provides general features which are both needed for playing audio and video
- * files.
- */
-public abstract class MediaplayerActivity extends ActionBarActivity
- implements OnSeekBarChangeListener {
- private static final String TAG = "MediaplayerActivity";
-
- protected PlaybackController controller;
-
- protected TextView txtvPosition;
- protected TextView txtvLength;
- protected SeekBar sbPosition;
- protected ImageButton butPlay;
- protected ImageButton butRev;
- protected ImageButton butFF;
-
- private PlaybackController newPlaybackController() {
- return new PlaybackController(this, false) {
-
- @Override
- public void setupGUI() {
- MediaplayerActivity.this.setupGUI();
- }
-
- @Override
- public void onPositionObserverUpdate() {
- MediaplayerActivity.this.onPositionObserverUpdate();
- }
-
- @Override
- public void onBufferStart() {
- MediaplayerActivity.this.onBufferStart();
- }
-
- @Override
- public void onBufferEnd() {
- MediaplayerActivity.this.onBufferEnd();
- }
-
- @Override
- public void onBufferUpdate(float progress) {
- MediaplayerActivity.this.onBufferUpdate(progress);
- }
-
- @Override
- public void handleError(int code) {
- MediaplayerActivity.this.handleError(code);
- }
-
- @Override
- public void onReloadNotification(int code) {
- MediaplayerActivity.this.onReloadNotification(code);
- }
-
- @Override
- public void onSleepTimerUpdate() {
- supportInvalidateOptionsMenu();
- }
-
- @Override
- public ImageButton getPlayButton() {
- return butPlay;
- }
-
- @Override
- public void postStatusMsg(int msg) {
- MediaplayerActivity.this.postStatusMsg(msg);
- }
-
- @Override
- public void clearStatusMsg() {
- MediaplayerActivity.this.clearStatusMsg();
- }
-
- @Override
- public boolean loadMediaInfo() {
- return MediaplayerActivity.this.loadMediaInfo();
- }
-
- @Override
- public void onAwaitingVideoSurface() {
- MediaplayerActivity.this.onAwaitingVideoSurface();
- }
-
- @Override
- public void onServiceQueried() {
- MediaplayerActivity.this.onServiceQueried();
- }
-
- @Override
- public void onShutdownNotification() {
- finish();
- }
-
- @Override
- public void onPlaybackEnd() {
- finish();
- }
-
- @Override
- public void onPlaybackSpeedChange() {
- MediaplayerActivity.this.onPlaybackSpeedChange();
- }
-
- @Override
- protected void setScreenOn(boolean enable) {
- super.setScreenOn(enable);
- MediaplayerActivity.this.setScreenOn(enable);
- }
- };
-
- }
-
- protected void onPlaybackSpeedChange() {
-
- }
-
- protected void onServiceQueried() {
- supportInvalidateOptionsMenu();
- }
-
- protected void chooseTheme() {
- setTheme(UserPreferences.getTheme());
- }
-
- protected void setScreenOn(boolean enable) {
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- chooseTheme();
- super.onCreate(savedInstanceState);
-
- // subclasses might use this feature
- supportRequestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
-
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Creating Activity");
- StorageUtils.checkStorageAvailability(this);
- setVolumeControlStream(AudioManager.STREAM_MUSIC);
-
- orientation = getResources().getConfiguration().orientation;
- getWindow().setFormat(PixelFormat.TRANSPARENT);
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- controller.reinitServiceIfPaused();
- controller.pause();
- }
-
- /**
- * Should be used to switch to another player activity if the mime type is
- * not the correct one for the current activity.
- */
- protected abstract void onReloadNotification(int notificationCode);
-
- /**
- * Should be used to inform the user that the PlaybackService is currently
- * buffering.
- */
- protected abstract void onBufferStart();
-
- /**
- * Should be used to hide the view that was showing the 'buffering'-message.
- */
- protected abstract void onBufferEnd();
-
- protected void onBufferUpdate(float progress) {
- if (sbPosition != null) {
- sbPosition.setSecondaryProgress((int) progress
- * sbPosition.getMax());
- }
- }
-
- /**
- * Current screen orientation.
- */
- protected int orientation;
-
- @Override
- protected void onStart() {
- super.onStart();
- if (controller != null) {
- controller.release();
- }
- controller = newPlaybackController();
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Activity stopped");
- if (controller != null) {
- controller.release();
- }
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Activity destroyed");
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.mediaplayer, menu);
- return true;
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- super.onPrepareOptionsMenu(menu);
- Playable media = controller.getMedia();
-
- menu.findItem(R.id.support_item).setVisible(
- media != null && media.getPaymentLink() != null &&
- (media instanceof FeedMedia) &&
- ((FeedMedia) media).getItem().getFlattrStatus().flattrable()
- );
- menu.findItem(R.id.share_link_item).setVisible(
- media != null && media.getWebsiteLink() != null);
- menu.findItem(R.id.visit_website_item).setVisible(
- media != null && media.getWebsiteLink() != null);
- menu.findItem(R.id.skip_episode_item).setVisible(media != null);
- boolean sleepTimerSet = controller.sleepTimerActive();
- boolean sleepTimerNotSet = controller.sleepTimerNotActive();
- menu.findItem(R.id.set_sleeptimer_item).setVisible(sleepTimerNotSet);
- menu.findItem(R.id.disable_sleeptimer_item).setVisible(sleepTimerSet);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- Playable media = controller.getMedia();
- if (item.getItemId() == android.R.id.home) {
- Intent intent = new Intent(MediaplayerActivity.this,
- MainActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
- | Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(intent);
- return true;
- } else if (media != null) {
- switch (item.getItemId()) {
- case R.id.disable_sleeptimer_item:
- if (controller.serviceAvailable()) {
- AlertDialog.Builder stDialog = new AlertDialog.Builder(this);
- stDialog.setTitle(R.string.sleep_timer_label);
- stDialog.setMessage(getString(R.string.time_left_label)
- + Converter.getDurationStringLong((int) controller
- .getSleepTimerTimeLeft()));
- stDialog.setPositiveButton(
- R.string.disable_sleeptimer_label,
- new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog,
- int which) {
- dialog.dismiss();
- controller.disableSleepTimer();
- }
- }
- );
- stDialog.setNegativeButton(R.string.cancel_label,
- new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog,
- int which) {
- dialog.dismiss();
- }
- }
- );
- stDialog.create().show();
- }
- break;
- case R.id.set_sleeptimer_item:
- if (controller.serviceAvailable()) {
- int pickerStyle = (UserPreferences.getTheme() == R.style.Theme_AntennaPod_Light) ?
- R.style.AntennaPodBetterPickerThemeLight : R.style.AntennaPodBetterPickerThemeDark;
- if (Build.VERSION.SDK_INT > 10) { // TODO remove this as soon as dialog is shown correctly on 2.3
- HmsPickerBuilder hpb = new HmsPickerBuilder()
- .setStyleResId(pickerStyle)
- .setFragmentManager(getSupportFragmentManager());
-
- hpb.addHmsPickerDialogHandler(new HmsPickerDialogFragment.HmsPickerDialogHandler() {
- @Override
- public void onDialogHmsSet(int ref, int hours, int minutes, int seconds) {
- if (controller != null && controller.serviceAvailable()) {
- controller.setSleepTimer((hours * 3600 + minutes * 60 + seconds) * 1000);
- }
- }
- });
- hpb.show();
- } else {
- TimeDialog td = new TimeDialog(this,
- R.string.set_sleeptimer_label,
- R.string.set_sleeptimer_label) {
-
- @Override
- public void onTimeEntered(long millis) {
- controller.setSleepTimer(millis);
- }
- };
- td.show();
- }
- break;
-
- }
- case R.id.visit_website_item:
- Uri uri = Uri.parse(media.getWebsiteLink());
- startActivity(new Intent(Intent.ACTION_VIEW, uri));
- break;
- case R.id.support_item:
- if (media instanceof FeedMedia) {
- FeedItem feedItem = ((FeedMedia) media).getItem();
- DBTasks.flattrItemIfLoggedIn(this, feedItem);
- }
- break;
- case R.id.share_link_item:
- ShareUtils.shareLink(this, media.getWebsiteLink());
- break;
- case R.id.skip_episode_item:
- sendBroadcast(new Intent(
- PlaybackService.ACTION_SKIP_CURRENT_EPISODE));
- break;
- default:
- return false;
-
- }
- return true;
- } else {
- return false;
- }
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Resuming Activity");
- StorageUtils.checkStorageAvailability(this);
- controller.init();
- }
-
- /**
- * Called by 'handleStatus()' when the PlaybackService is waiting for
- * a video surface.
- */
- protected abstract void onAwaitingVideoSurface();
-
- protected abstract void postStatusMsg(int resId);
-
- protected abstract void clearStatusMsg();
-
- protected void onPositionObserverUpdate() {
- if (controller != null) {
- int currentPosition = controller.getPosition();
- int duration = controller.getDuration();
- if (currentPosition != PlaybackService.INVALID_TIME
- && duration != PlaybackService.INVALID_TIME
- && controller.getMedia() != null) {
- txtvPosition.setText(Converter
- .getDurationStringLong(currentPosition));
- txtvLength.setText(Converter.getDurationStringLong(duration));
- updateProgressbarPosition(currentPosition, duration);
- } else {
- Log.w(TAG,
- "Could not react to position observer update because of invalid time");
- }
- }
- }
-
- private void updateProgressbarPosition(int position, int duration) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Updating progressbar info");
- float progress = ((float) position) / duration;
- sbPosition.setProgress((int) (progress * sbPosition.getMax()));
- }
-
- /**
- * Load information about the media that is going to be played or currently
- * being played. This method will be called when the activity is connected
- * to the PlaybackService to ensure that the activity has the right
- * FeedMedia object.
- */
- protected boolean loadMediaInfo() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Loading media info");
- Playable media = controller.getMedia();
- if (media != null) {
- txtvPosition.setText(Converter.getDurationStringLong((media
- .getPosition())));
-
- if (media.getDuration() != 0) {
- txtvLength.setText(Converter.getDurationStringLong(media
- .getDuration()));
- float progress = ((float) media.getPosition())
- / media.getDuration();
- sbPosition.setProgress((int) (progress * sbPosition.getMax()));
- }
- return true;
- } else {
- return false;
- }
- }
-
- protected void setupGUI() {
- setContentView(getContentViewResourceId());
- sbPosition = (SeekBar) findViewById(R.id.sbPosition);
- txtvPosition = (TextView) findViewById(R.id.txtvPosition);
- txtvLength = (TextView) findViewById(R.id.txtvLength);
- butPlay = (ImageButton) findViewById(R.id.butPlay);
- butRev = (ImageButton) findViewById(R.id.butRev);
- butFF = (ImageButton) findViewById(R.id.butFF);
-
- // SEEKBAR SETUP
-
- sbPosition.setOnSeekBarChangeListener(this);
-
- // BUTTON SETUP
-
- butPlay.setOnClickListener(controller.newOnPlayButtonClickListener());
-
- if (butFF != null) {
- butFF.setOnClickListener(controller.newOnFFButtonClickListener());
- }
- if (butRev != null) {
- butRev.setOnClickListener(controller.newOnRevButtonClickListener());
- }
-
- }
-
- protected abstract int getContentViewResourceId();
-
- void handleError(int errorCode) {
- final AlertDialog.Builder errorDialog = new AlertDialog.Builder(this);
- errorDialog.setTitle(R.string.error_label);
- errorDialog
- .setMessage(MediaPlayerError.getErrorString(this, errorCode));
- errorDialog.setNeutralButton("OK",
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- finish();
- }
- }
- );
- errorDialog.create().show();
- }
-
- float prog;
-
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress,
- boolean fromUser) {
- if (controller != null) {
- prog = controller.onSeekBarProgressChanged(seekBar, progress, fromUser,
- txtvPosition);
- }
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- if (controller != null) {
- controller.onSeekBarStartTrackingTouch(seekBar);
- }
- }
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- if (controller != null) {
- controller.onSeekBarStopTrackingTouch(seekBar, prog);
- }
- }
-
-}
diff --git a/src/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java b/src/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
deleted file mode 100644
index 2c6d75cd8..000000000
--- a/src/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
+++ /dev/null
@@ -1,428 +0,0 @@
-package de.danoeh.antennapod.activity;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnCancelListener;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
-import android.util.Log;
-import android.widget.ArrayAdapter;
-import android.widget.LinearLayout;
-import android.widget.ProgressBar;
-import android.widget.RelativeLayout;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.dialog.AuthenticationDialog;
-import de.danoeh.antennapod.feed.Feed;
-import de.danoeh.antennapod.feed.FeedPreferences;
-import de.danoeh.antennapod.preferences.UserPreferences;
-import de.danoeh.antennapod.service.download.DownloadRequest;
-import de.danoeh.antennapod.service.download.DownloadStatus;
-import de.danoeh.antennapod.service.download.Downloader;
-import de.danoeh.antennapod.service.download.HttpDownloader;
-import de.danoeh.antennapod.syndication.handler.FeedHandler;
-import de.danoeh.antennapod.syndication.handler.FeedHandlerResult;
-import de.danoeh.antennapod.syndication.handler.UnsupportedFeedtypeException;
-import de.danoeh.antennapod.util.DownloadError;
-import de.danoeh.antennapod.util.FileNameGenerator;
-import de.danoeh.antennapod.util.StorageUtils;
-import de.danoeh.antennapod.util.URLChecker;
-import de.danoeh.antennapod.util.syndication.FeedDiscoverer;
-import org.apache.commons.lang3.StringUtils;
-import org.xml.sax.SAXException;
-
-import javax.xml.parsers.ParserConfigurationException;
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Downloads a feed from a feed URL and parses it. Subclasses can display the
- * feed object that was parsed. This activity MUST be started with a given URL
- * or an Exception will be thrown.
- * <p/>
- * If the feed cannot be downloaded or parsed, an error dialog will be displayed
- * and the activity will finish as soon as the error dialog is closed.
- */
-public abstract class OnlineFeedViewActivity extends ActionBarActivity {
- private static final String TAG = "OnlineFeedViewActivity";
- public static final String ARG_FEEDURL = "arg.feedurl";
-
- /**
- * Optional argument: specify a title for the actionbar.
- */
- public static final String ARG_TITLE = "title";
-
- public static final int RESULT_ERROR = 2;
-
- private Feed feed;
- private Map<String, String> alternateFeedUrls;
- private Downloader downloader;
-
- private boolean isPaused;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- setTheme(UserPreferences.getTheme());
- super.onCreate(savedInstanceState);
-
- if (getIntent() != null && getIntent().hasExtra(ARG_TITLE)) {
- getSupportActionBar().setTitle(getIntent().getStringExtra(ARG_TITLE));
- }
-
- StorageUtils.checkStorageAvailability(this);
-
- final String feedUrl;
- if (getIntent().hasExtra(ARG_FEEDURL)) {
- feedUrl = getIntent().getStringExtra(ARG_FEEDURL);
- } else if (StringUtils.equals(getIntent().getAction(), Intent.ACTION_SEND)
- || StringUtils.equals(getIntent().getAction(), Intent.ACTION_VIEW)) {
- feedUrl = (StringUtils.equals(getIntent().getAction(), Intent.ACTION_SEND))
- ? getIntent().getStringExtra(Intent.EXTRA_TEXT) : getIntent().getDataString();
-
- getSupportActionBar().setTitle(R.string.add_new_feed_label);
- } else {
- throw new IllegalArgumentException(
- "Activity must be started with feedurl argument!");
- }
-
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Activity was started with url " + feedUrl);
- setLoadingLayout();
- if (savedInstanceState == null) {
- startFeedDownload(feedUrl, null, null);
- } else {
- startFeedDownload(feedUrl, savedInstanceState.getString("username"), savedInstanceState.getString("password"));
- }
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- isPaused = false;
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- isPaused = true;
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- if (feed != null && feed.getPreferences() != null) {
- outState.putString("username", feed.getPreferences().getUsername());
- outState.putString("password", feed.getPreferences().getPassword());
- }
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- if (downloader != null && !downloader.isFinished()) {
- downloader.cancel();
- }
- }
-
- private void resetIntent(String url, String title) {
- Intent intent = new Intent();
- intent.putExtra(ARG_FEEDURL, url);
- intent.putExtra(ARG_TITLE, title);
- setIntent(intent);
- }
-
-
- private void onDownloadCompleted(final Downloader downloader) {
- runOnUiThread(new Runnable() {
-
- @Override
- public void run() {
- if (BuildConfig.DEBUG) Log.d(TAG, "Download was completed");
- DownloadStatus status = downloader.getResult();
- if (status != null) {
- if (!status.isCancelled()) {
- if (status.isSuccessful()) {
- parseFeed();
- } else if (status.getReason() == DownloadError.ERROR_UNAUTHORIZED) {
- if (!isFinishing() && !isPaused) {
- Dialog dialog = new FeedViewAuthenticationDialog(OnlineFeedViewActivity.this,
- R.string.authentication_notification_title, downloader.getDownloadRequest().getSource());
- dialog.show();
- }
- } else {
- String errorMsg = status.getReason().getErrorString(
- OnlineFeedViewActivity.this);
- if (errorMsg != null
- && status.getReasonDetailed() != null) {
- errorMsg += " ("
- + status.getReasonDetailed() + ")";
- }
- showErrorDialog(errorMsg);
- }
- }
- } else {
- Log.wtf(TAG,
- "DownloadStatus returned by Downloader was null");
- finish();
- }
- }
- });
-
- }
-
- private void startFeedDownload(String url, String username, String password) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Starting feed download");
- url = URLChecker.prepareURL(url);
- feed = new Feed(url, new Date());
- if (username != null && password != null) {
- feed.setPreferences(new FeedPreferences(0, true, username, password));
- }
- String fileUrl = new File(getExternalCacheDir(),
- FileNameGenerator.generateFileName(feed.getDownload_url()))
- .toString();
- feed.setFile_url(fileUrl);
- final DownloadRequest request = new DownloadRequest(feed.getFile_url(),
- feed.getDownload_url(), "OnlineFeed", 0, Feed.FEEDFILETYPE_FEED, username, password, true);
- downloader = new HttpDownloader(
- request);
- new Thread() {
- @Override
- public void run() {
- loadData();
- downloader.call();
- onDownloadCompleted(downloader);
- }
- }.start();
-
-
- }
-
- /**
- * Displays a progress indicator.
- */
- private void setLoadingLayout() {
- RelativeLayout rl = new RelativeLayout(this);
- RelativeLayout.LayoutParams rlLayoutParams = new RelativeLayout.LayoutParams(
- LinearLayout.LayoutParams.MATCH_PARENT,
- LinearLayout.LayoutParams.MATCH_PARENT);
-
- ProgressBar pb = new ProgressBar(this);
- pb.setIndeterminate(true);
- RelativeLayout.LayoutParams pbLayoutParams = new RelativeLayout.LayoutParams(
- LinearLayout.LayoutParams.WRAP_CONTENT,
- LinearLayout.LayoutParams.WRAP_CONTENT);
- pbLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
- rl.addView(pb, pbLayoutParams);
- addContentView(rl, rlLayoutParams);
- }
-
- private void parseFeed() {
- if (feed == null || feed.getFile_url() == null && feed.isDownloaded()) {
- throw new IllegalStateException(
- "feed must be non-null and downloaded when parseFeed is called");
- }
-
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Parsing feed");
-
- Thread thread = new Thread() {
-
- @Override
- public void run() {
- String reasonDetailed = "";
- boolean successful = false;
- FeedHandler handler = new FeedHandler();
- try {
- FeedHandlerResult result = handler.parseFeed(feed);
- feed = result.feed;
- alternateFeedUrls = result.alternateFeedUrls;
- successful = true;
- } catch (SAXException e) {
- e.printStackTrace();
- reasonDetailed = e.getMessage();
- } catch (IOException e) {
- e.printStackTrace();
- reasonDetailed = e.getMessage();
- } catch (ParserConfigurationException e) {
- e.printStackTrace();
- reasonDetailed = e.getMessage();
- } catch (UnsupportedFeedtypeException e) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Unsupported feed type detected");
- if (StringUtils.equalsIgnoreCase("html", e.getRootElement())) {
- if (showFeedDiscoveryDialog(new File(feed.getFile_url()), feed.getDownload_url())) {
- return;
- }
- } else {
- e.printStackTrace();
- reasonDetailed = e.getMessage();
- }
- } finally {
- boolean rc = new File(feed.getFile_url()).delete();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Deleted feed source file. Result: " + rc);
- }
-
- if (successful) {
- beforeShowFeedInformation(feed, alternateFeedUrls);
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- showFeedInformation(feed, alternateFeedUrls);
- }
- });
- } else {
- final String errorMsg =
- DownloadError.ERROR_PARSER_EXCEPTION.getErrorString(
- OnlineFeedViewActivity.this)
- + " (" + reasonDetailed + ")";
- runOnUiThread(new Runnable() {
-
- @Override
- public void run() {
- showErrorDialog(errorMsg);
- }
- });
- }
- }
- };
- thread.start();
- }
-
- /**
- * Can be used to load data asynchronously.
- */
- protected void loadData() {
-
- }
-
- /**
- * Called after the feed has been downloaded and parsed and before showFeedInformation is called.
- * This method is executed on a background thread
- */
- protected void beforeShowFeedInformation(Feed feed, Map<String, String> alternateFeedUrls) {
-
- }
-
- /**
- * Called when feed parsed successfully.
- * This method is executed on the GUI thread.
- */
- protected void showFeedInformation(Feed feed, Map<String, String> alternateFeedUrls) {
-
- }
-
- private void showErrorDialog(String errorMsg) {
- if (!isFinishing() && !isPaused) {
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setTitle(R.string.error_label);
- if (errorMsg != null) {
- builder.setMessage(getString(R.string.error_msg_prefix) + errorMsg);
- } else {
- builder.setMessage(R.string.error_msg_prefix);
- }
- builder.setNeutralButton(android.R.string.ok,
- new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.cancel();
- }
- }
- );
- builder.setOnCancelListener(new OnCancelListener() {
- @Override
- public void onCancel(DialogInterface dialog) {
- setResult(RESULT_ERROR);
- finish();
- }
- });
- builder.show();
- }
- }
-
- private boolean showFeedDiscoveryDialog(File feedFile, String baseUrl) {
- FeedDiscoverer fd = new FeedDiscoverer();
- final Map<String, String> urlsMap;
- try {
- urlsMap = fd.findLinks(feedFile, baseUrl);
- if (urlsMap == null || urlsMap.isEmpty()) {
- return false;
- }
- } catch (IOException e) {
- e.printStackTrace();
- return false;
- }
-
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- if (isPaused || isFinishing()) {
- return;
- }
-
- final List<String> titles = new ArrayList<String>();
- final List<String> urls = new ArrayList<String>();
-
- urls.addAll(urlsMap.keySet());
- for (String url : urls) {
- titles.add(urlsMap.get(url));
- }
-
- final ArrayAdapter<String> adapter = new ArrayAdapter<String>(OnlineFeedViewActivity.this, R.layout.ellipsize_start_listitem, R.id.txtvTitle, titles);
- DialogInterface.OnClickListener onClickListener = new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- String selectedUrl = urls.get(which);
- dialog.dismiss();
- resetIntent(selectedUrl, titles.get(which));
- startFeedDownload(selectedUrl, null, null);
- }
- };
-
- AlertDialog.Builder ab = new AlertDialog.Builder(OnlineFeedViewActivity.this)
- .setTitle(R.string.feeds_label)
- .setCancelable(true)
- .setOnCancelListener(new OnCancelListener() {
- @Override
- public void onCancel(DialogInterface dialog) {
- finish();
- }
- })
- .setAdapter(adapter, onClickListener);
- ab.show();
- }
- });
-
-
- return true;
- }
-
- private class FeedViewAuthenticationDialog extends AuthenticationDialog {
-
- private String feedUrl;
-
- public FeedViewAuthenticationDialog(Context context, int titleRes, String feedUrl) {
- super(context, titleRes, true, false, null, null);
- this.feedUrl = feedUrl;
- }
-
- @Override
- protected void onCancelled() {
- super.onCancelled();
- finish();
- }
-
- @Override
- protected void onConfirmed(String username, String password, boolean saveUsernamePassword) {
- startFeedDownload(feedUrl, username, password);
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java b/src/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java
deleted file mode 100644
index e09941abf..000000000
--- a/src/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java
+++ /dev/null
@@ -1,134 +0,0 @@
-package de.danoeh.antennapod.activity;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.v4.view.MenuItemCompat;
-import android.support.v7.app.ActionBarActivity;
-import android.util.SparseBooleanArray;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.ArrayAdapter;
-import android.widget.Button;
-import android.widget.ListView;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.opml.OpmlElement;
-import de.danoeh.antennapod.preferences.UserPreferences;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Displays the feeds that the OPML-Importer has read and lets the user choose
- * which feeds he wants to import.
- */
-public class OpmlFeedChooserActivity extends ActionBarActivity {
- private static final String TAG = "OpmlFeedChooserActivity";
-
- public static final String EXTRA_SELECTED_ITEMS = "de.danoeh.antennapod.selectedItems";
-
- private Button butConfirm;
- private Button butCancel;
- private ListView feedlist;
- private ArrayAdapter<String> listAdapter;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- setTheme(UserPreferences.getTheme());
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.opml_selection);
- butConfirm = (Button) findViewById(R.id.butConfirm);
- butCancel = (Button) findViewById(R.id.butCancel);
- feedlist = (ListView) findViewById(R.id.feedlist);
-
- feedlist.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
- listAdapter = new ArrayAdapter<String>(this,
- android.R.layout.simple_list_item_multiple_choice,
- getTitleList());
-
- feedlist.setAdapter(listAdapter);
-
- butCancel.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- setResult(RESULT_CANCELED);
- finish();
- }
- });
-
- butConfirm.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- Intent intent = new Intent();
- SparseBooleanArray checked = feedlist.getCheckedItemPositions();
-
- int checkedCount = 0;
- // Get number of checked items
- for (int i = 0; i < checked.size(); i++) {
- if (checked.valueAt(i)) {
- checkedCount++;
- }
- }
- int[] selection = new int[checkedCount];
- for (int i = 0, collected = 0; collected < checkedCount; i++) {
- if (checked.valueAt(i)) {
- selection[collected] = checked.keyAt(i);
- collected++;
- }
- }
- intent.putExtra(EXTRA_SELECTED_ITEMS, selection);
- setResult(RESULT_OK, intent);
- finish();
- }
- });
-
- }
-
- private List<String> getTitleList() {
- List<String> result = new ArrayList<String>();
- if (OpmlImportHolder.getReadElements() != null) {
- for (OpmlElement element : OpmlImportHolder.getReadElements()) {
- result.add(element.getText());
- }
-
- }
- return result;
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- MenuItemCompat.setShowAsAction(menu.add(Menu.NONE, R.id.select_all_item, Menu.NONE,
- R.string.select_all_label),
- MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
-
- MenuItemCompat.setShowAsAction(menu.add(Menu.NONE, R.id.deselect_all_item, Menu.NONE,
- R.string.deselect_all_label),
- MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.select_all_item:
- selectAllItems(true);
- return true;
- case R.id.deselect_all_item:
- selectAllItems(false);
- return true;
- default:
- return false;
- }
- }
-
- private void selectAllItems(boolean b) {
- for (int i = 0; i < feedlist.getCount(); i++) {
- feedlist.setItemChecked(i, b);
- }
- }
-
-}
diff --git a/src/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java b/src/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java
deleted file mode 100644
index d3fd3949c..000000000
--- a/src/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package de.danoeh.antennapod.activity;
-
-import android.content.Intent;
-import android.support.v7.app.ActionBarActivity;
-import android.util.Log;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.asynctask.OpmlFeedQueuer;
-import de.danoeh.antennapod.asynctask.OpmlImportWorker;
-import de.danoeh.antennapod.opml.OpmlElement;
-
-import java.io.Reader;
-import java.util.ArrayList;
-
-/**
- * Base activity for Opml Import - e.g. with code what to do afterwards
- * */
-public class OpmlImportBaseActivity extends ActionBarActivity {
-
- private static final String TAG = "OpmlImportBaseActivity";
- private OpmlImportWorker importWorker;
-
- /**
- * Handles the choices made by the user in the OpmlFeedChooserActivity and
- * starts the OpmlFeedQueuer if necessary.
- */
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Received result");
- if (resultCode == RESULT_CANCELED) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Activity was cancelled");
- if (finishWhenCanceled())
- finish();
- } else {
- int[] selected = data
- .getIntArrayExtra(OpmlFeedChooserActivity.EXTRA_SELECTED_ITEMS);
- if (selected != null && selected.length > 0) {
- OpmlFeedQueuer queuer = new OpmlFeedQueuer(this, selected) {
-
- @Override
- protected void onPostExecute(Void result) {
- super.onPostExecute(result);
- Intent intent = new Intent(OpmlImportBaseActivity.this, MainActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
- | Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(intent);
- }
-
- };
- queuer.executeAsync();
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "No items were selected");
- }
- }
- }
-
- /** Starts the import process. */
- protected void startImport(Reader reader) {
-
- if (reader != null) {
- importWorker = new OpmlImportWorker(this, reader) {
-
- @Override
- protected void onPostExecute(ArrayList<OpmlElement> result) {
- super.onPostExecute(result);
- if (result != null) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Parsing was successful");
- OpmlImportHolder.setReadElements(result);
- startActivityForResult(new Intent(
- OpmlImportBaseActivity.this,
- OpmlFeedChooserActivity.class), 0);
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Parser error occurred");
- }
- }
- };
- importWorker.executeAsync();
- }
- }
-
- protected boolean finishWhenCanceled() {
- return false;
- }
-
-
-}
diff --git a/src/de/danoeh/antennapod/activity/OpmlImportFromIntentActivity.java b/src/de/danoeh/antennapod/activity/OpmlImportFromIntentActivity.java
deleted file mode 100644
index 16e663fac..000000000
--- a/src/de/danoeh/antennapod/activity/OpmlImportFromIntentActivity.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package de.danoeh.antennapod.activity;
-
-import android.app.AlertDialog;
-import android.os.Bundle;
-import de.danoeh.antennapod.preferences.UserPreferences;
-import de.danoeh.antennapod.util.LangUtils;
-
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.net.URL;
-
-/** Lets the user start the OPML-import process. */
-public class OpmlImportFromIntentActivity extends OpmlImportBaseActivity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- setTheme(UserPreferences.getTheme());
- super.onCreate(savedInstanceState);
-
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
-
- try {
- URL mOpmlURL = new URL(getIntent().getData().toString());
- BufferedReader in = new BufferedReader(new InputStreamReader(mOpmlURL.openStream(),
- LangUtils.UTF_8));
- startImport(in);
- } catch (Exception e) {
- new AlertDialog.Builder(this).setMessage("Cannot open XML - Reason: " + e.getMessage()).show();
- }
-
- }
-
- @Override
- protected boolean finishWhenCanceled() {
- return true;
- }
-
-}
diff --git a/src/de/danoeh/antennapod/activity/OpmlImportFromPathActivity.java b/src/de/danoeh/antennapod/activity/OpmlImportFromPathActivity.java
deleted file mode 100644
index 94f100321..000000000
--- a/src/de/danoeh/antennapod/activity/OpmlImportFromPathActivity.java
+++ /dev/null
@@ -1,172 +0,0 @@
-package de.danoeh.antennapod.activity;
-
-import android.app.AlertDialog;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.TextView;
-import android.widget.Toast;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.preferences.UserPreferences;
-import de.danoeh.antennapod.util.LangUtils;
-import de.danoeh.antennapod.util.StorageUtils;
-
-import java.io.*;
-
-/**
- * Lets the user start the OPML-import process from a path
- */
-public class OpmlImportFromPathActivity extends OpmlImportBaseActivity {
- public static final String IMPORT_DIR = "import/";
- private static final String TAG = "OpmlImportFromPathActivity";
- private TextView txtvPath;
- private Button butStart;
- private String importPath;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- setTheme(UserPreferences.getTheme());
- super.onCreate(savedInstanceState);
-
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
- setContentView(R.layout.opml_import);
-
- txtvPath = (TextView) findViewById(R.id.txtvPath);
- butStart = (Button) findViewById(R.id.butStartImport);
-
- butStart.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- checkFolderForFiles();
- }
-
- });
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- StorageUtils.checkStorageAvailability(this);
- setImportPath();
- }
-
- /**
- * Sets the importPath variable and makes txtvPath display the import
- * directory.
- */
- private void setImportPath() {
- File importDir = UserPreferences.getDataFolder(this, IMPORT_DIR);
- boolean success = true;
- if (!importDir.exists()) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Import directory doesn't exist. Creating...");
- success = importDir.mkdir();
- if (!success) {
- Log.e(TAG, "Could not create directory");
- }
- }
- if (success) {
- txtvPath.setText(importDir.toString());
- importPath = importDir.toString();
- } else {
- txtvPath.setText(R.string.opml_directory_error);
- }
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- finish();
- return true;
- default:
- return false;
- }
- }
-
- /**
- * Looks at the contents of the import directory and decides what to do. If
- * more than one file is in the directory, a dialog will be created to let
- * the user choose which item to import
- */
- private void checkFolderForFiles() {
- File dir = new File(importPath);
- if (dir.isDirectory()) {
- File[] fileList = dir.listFiles();
- if (fileList.length == 1) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Found one file, choosing that one.");
- startImport(fileList[0]);
- } else if (fileList.length > 1) {
- Log.w(TAG, "Import directory contains more than one file.");
- askForFile(dir);
- } else {
- Log.e(TAG, "Import directory is empty");
- Toast toast = Toast
- .makeText(this, R.string.opml_import_error_dir_empty,
- Toast.LENGTH_LONG);
- toast.show();
- }
- }
- }
-
- private void startImport(File file) {
- Reader mReader = null;
- try {
- mReader = new InputStreamReader(new FileInputStream(file),
- LangUtils.UTF_8);
- if (BuildConfig.DEBUG) Log.d(TAG, "Parsing " + file.toString());
- startImport(mReader);
- } catch (FileNotFoundException e) {
- Log.d(TAG, "File not found which really should be there");
- // this should never happen as it is a file we have just chosen
- }
- }
-
- /**
- * Asks the user to choose from a list of files in a directory and returns
- * his choice.
- */
- private void askForFile(File dir) {
- final File[] fileList = dir.listFiles();
- String[] fileNames = dir.list();
-
- AlertDialog.Builder dialog = new AlertDialog.Builder(this);
- dialog.setTitle(R.string.choose_file_to_import_label);
- dialog.setNeutralButton(android.R.string.cancel,
- new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Dialog was cancelled");
- dialog.dismiss();
- }
- });
- dialog.setItems(fileNames, new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "File at index " + which + " was chosen");
- dialog.dismiss();
- startImport(fileList[which]);
- }
- });
- dialog.create().show();
- }
-
-
-}
diff --git a/src/de/danoeh/antennapod/activity/OpmlImportHolder.java b/src/de/danoeh/antennapod/activity/OpmlImportHolder.java
deleted file mode 100644
index ec53ed7b6..000000000
--- a/src/de/danoeh/antennapod/activity/OpmlImportHolder.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package de.danoeh.antennapod.activity;
-
-import de.danoeh.antennapod.opml.OpmlElement;
-
-import java.util.ArrayList;
-
-/**
- * Hold infos gathered by Ompl-Import
- * <p/>
- * Created with IntelliJ IDEA.
- * User: ligi
- * Date: 1/23/13
- * Time: 2:15 PM
- */
-public class OpmlImportHolder {
-
- private static ArrayList<OpmlElement> readElements;
-
- public static ArrayList<OpmlElement> getReadElements() {
- return readElements;
- }
-
- public static void setReadElements(ArrayList<OpmlElement> _readElements) {
- readElements = _readElements;
- }
-
-
-}
-
diff --git a/src/de/danoeh/antennapod/activity/PreferenceActivity.java b/src/de/danoeh/antennapod/activity/PreferenceActivity.java
deleted file mode 100644
index cd6731c02..000000000
--- a/src/de/danoeh/antennapod/activity/PreferenceActivity.java
+++ /dev/null
@@ -1,513 +0,0 @@
-package de.danoeh.antennapod.activity;
-
-import android.annotation.SuppressLint;
-import android.app.ActionBar;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.res.Resources.Theme;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiManager;
-import android.os.Bundle;
-import android.preference.CheckBoxPreference;
-import android.preference.ListPreference;
-import android.preference.Preference;
-import android.preference.Preference.OnPreferenceChangeListener;
-import android.preference.Preference.OnPreferenceClickListener;
-import android.preference.PreferenceScreen;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.widget.Toast;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.asynctask.FlattrClickWorker;
-import de.danoeh.antennapod.asynctask.OpmlExportWorker;
-import de.danoeh.antennapod.dialog.AuthenticationDialog;
-import de.danoeh.antennapod.dialog.AutoFlattrPreferenceDialog;
-import de.danoeh.antennapod.dialog.GpodnetSetHostnameDialog;
-import de.danoeh.antennapod.dialog.VariableSpeedDialog;
-import de.danoeh.antennapod.preferences.GpodnetPreferences;
-import de.danoeh.antennapod.preferences.UserPreferences;
-import de.danoeh.antennapod.util.flattr.FlattrStatus;
-import de.danoeh.antennapod.util.flattr.FlattrUtils;
-import de.danoeh.antennapod.util.flattr.SimpleFlattrThing;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * The main preference activity
- */
-public class PreferenceActivity extends android.preference.PreferenceActivity {
- private static final String TAG = "PreferenceActivity";
-
- private static final String PREF_FLATTR_THIS_APP = "prefFlattrThisApp";
- private static final String PREF_FLATTR_SETTINGS = "prefFlattrSettings";
- private static final String PREF_FLATTR_AUTH = "pref_flattr_authenticate";
- private static final String PREF_FLATTR_REVOKE = "prefRevokeAccess";
- private static final String PREF_AUTO_FLATTR_PREFS = "prefAutoFlattrPrefs";
- private static final String PREF_OPML_EXPORT = "prefOpmlExport";
- private static final String PREF_ABOUT = "prefAbout";
- private static final String PREF_CHOOSE_DATA_DIR = "prefChooseDataDir";
- private static final String AUTO_DL_PREF_SCREEN = "prefAutoDownloadSettings";
- private static final String PREF_PLAYBACK_SPEED_LAUNCHER = "prefPlaybackSpeedLauncher";
-
- private static final String PREF_GPODNET_LOGIN = "pref_gpodnet_authenticate";
- private static final String PREF_GPODNET_SETLOGIN_INFORMATION = "pref_gpodnet_setlogin_information";
- private static final String PREF_GPODNET_LOGOUT = "pref_gpodnet_logout";
- private static final String PREF_GPODNET_HOSTNAME = "pref_gpodnet_hostname";
-
- private CheckBoxPreference[] selectedNetworks;
-
- @SuppressLint("NewApi")
- @SuppressWarnings("deprecation")
- @Override
- public void onCreate(Bundle savedInstanceState) {
- setTheme(UserPreferences.getTheme());
- super.onCreate(savedInstanceState);
-
- if (android.os.Build.VERSION.SDK_INT >= 11) {
- @SuppressLint("AppCompatMethod") ActionBar ab = getActionBar();
- if (ab != null) {
- ab.setDisplayHomeAsUpEnabled(true);
- }
- }
-
- addPreferencesFromResource(R.xml.preferences);
- findPreference(PREF_FLATTR_THIS_APP).setOnPreferenceClickListener(
- new OnPreferenceClickListener() {
-
- @Override
- public boolean onPreferenceClick(Preference preference) {
- new FlattrClickWorker(PreferenceActivity.this,
- new SimpleFlattrThing(PreferenceActivity.this.getString(R.string.app_name),
- FlattrUtils.APP_URL,
- new FlattrStatus(FlattrStatus.STATUS_QUEUE)
- )
- ).executeAsync();
-
- return true;
- }
- }
- );
-
- findPreference(PREF_FLATTR_REVOKE).setOnPreferenceClickListener(
- new OnPreferenceClickListener() {
-
- @Override
- public boolean onPreferenceClick(Preference preference) {
- FlattrUtils.revokeAccessToken(PreferenceActivity.this);
- checkItemVisibility();
- return true;
- }
-
- }
- );
-
- findPreference(PREF_ABOUT).setOnPreferenceClickListener(
- new OnPreferenceClickListener() {
-
- @Override
- public boolean onPreferenceClick(Preference preference) {
- PreferenceActivity.this.startActivity(new Intent(
- PreferenceActivity.this, AboutActivity.class));
- return true;
- }
-
- }
- );
-
- findPreference(PREF_OPML_EXPORT).setOnPreferenceClickListener(
- new OnPreferenceClickListener() {
-
- @Override
- public boolean onPreferenceClick(Preference preference) {
- new OpmlExportWorker(PreferenceActivity.this)
- .executeAsync();
-
- return true;
- }
- }
- );
-
- findPreference(PREF_CHOOSE_DATA_DIR).setOnPreferenceClickListener(
- new OnPreferenceClickListener() {
-
- @Override
- public boolean onPreferenceClick(Preference preference) {
- startActivityForResult(
- new Intent(PreferenceActivity.this,
- DirectoryChooserActivity.class),
- DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED
- );
- return true;
- }
- }
- );
- findPreference(UserPreferences.PREF_THEME)
- .setOnPreferenceChangeListener(
- new OnPreferenceChangeListener() {
-
- @Override
- public boolean onPreferenceChange(
- Preference preference, Object newValue) {
- Intent i = getIntent();
- i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK
- | Intent.FLAG_ACTIVITY_NEW_TASK);
- finish();
- startActivity(i);
- return true;
- }
- }
- );
- findPreference(UserPreferences.PREF_ENABLE_AUTODL)
- .setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- if (newValue instanceof Boolean) {
- findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER).setEnabled((Boolean) newValue);
- setSelectedNetworksEnabled((Boolean) newValue && UserPreferences.isEnableAutodownloadWifiFilter());
- }
- return true;
- }
- });
- findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER)
- .setOnPreferenceChangeListener(
- new OnPreferenceChangeListener() {
-
- @Override
- public boolean onPreferenceChange(
- Preference preference, Object newValue) {
- if (newValue instanceof Boolean) {
- setSelectedNetworksEnabled((Boolean) newValue);
- return true;
- } else {
- return false;
- }
- }
- }
- );
- findPreference(UserPreferences.PREF_EPISODE_CACHE_SIZE)
- .setOnPreferenceChangeListener(
- new OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object o) {
- if (o instanceof String) {
- setEpisodeCacheSizeText(UserPreferences.readEpisodeCacheSize((String) o));
- }
- return true;
- }
- }
- );
- findPreference(PREF_PLAYBACK_SPEED_LAUNCHER)
- .setOnPreferenceClickListener(new OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference preference) {
- VariableSpeedDialog.showDialog(PreferenceActivity.this);
- return true;
- }
- });
- findPreference(PREF_GPODNET_SETLOGIN_INFORMATION).setOnPreferenceClickListener(new OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference preference) {
- AuthenticationDialog dialog = new AuthenticationDialog(PreferenceActivity.this,
- R.string.pref_gpodnet_setlogin_information_title, false, false, GpodnetPreferences.getUsername(),
- null) {
-
- @Override
- protected void onConfirmed(String username, String password, boolean saveUsernamePassword) {
- GpodnetPreferences.setPassword(password);
- }
- };
- dialog.show();
- return true;
- }
- });
- findPreference(PREF_GPODNET_LOGOUT).setOnPreferenceClickListener(new OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference preference) {
- GpodnetPreferences.logout();
- Toast toast = Toast.makeText(PreferenceActivity.this, R.string.pref_gpodnet_logout_toast, Toast.LENGTH_SHORT);
- toast.show();
- updateGpodnetPreferenceScreen();
- return true;
- }
- });
- findPreference(PREF_GPODNET_HOSTNAME).setOnPreferenceClickListener(new OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference preference) {
- GpodnetSetHostnameDialog.createDialog(PreferenceActivity.this).setOnDismissListener(new DialogInterface.OnDismissListener() {
- @Override
- public void onDismiss(DialogInterface dialog) {
- updateGpodnetPreferenceScreen();
- }
- });
- return true;
- }
- });
-
- findPreference(PREF_AUTO_FLATTR_PREFS).setOnPreferenceClickListener(new OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference preference) {
- AutoFlattrPreferenceDialog.newAutoFlattrPreferenceDialog(PreferenceActivity.this,
- new AutoFlattrPreferenceDialog.AutoFlattrPreferenceDialogInterface() {
- @Override
- public void onCancelled() {
-
- }
-
- @Override
- public void onConfirmed(boolean autoFlattrEnabled, float autoFlattrValue) {
- UserPreferences.setAutoFlattrSettings(PreferenceActivity.this, autoFlattrEnabled, autoFlattrValue);
- checkItemVisibility();
- }
- });
- return true;
- }
- });
- buildUpdateIntervalPreference();
- buildAutodownloadSelectedNetworsPreference();
- setSelectedNetworksEnabled(UserPreferences
- .isEnableAutodownloadWifiFilter());
-
-
- }
-
- private void updateGpodnetPreferenceScreen() {
- final boolean loggedIn = GpodnetPreferences.loggedIn();
- findPreference(PREF_GPODNET_LOGIN).setEnabled(!loggedIn);
- findPreference(PREF_GPODNET_SETLOGIN_INFORMATION).setEnabled(loggedIn);
- findPreference(PREF_GPODNET_LOGOUT).setEnabled(loggedIn);
- findPreference(PREF_GPODNET_HOSTNAME).setSummary(GpodnetPreferences.getHostname());
- }
-
- private void buildUpdateIntervalPreference() {
- ListPreference pref = (ListPreference) findPreference(UserPreferences.PREF_UPDATE_INTERVAL);
- String[] values = getResources().getStringArray(
- R.array.update_intervall_values);
- String[] entries = new String[values.length];
- for (int x = 0; x < values.length; x++) {
- Integer v = Integer.parseInt(values[x]);
- switch (v) {
- case 0:
- entries[x] = getString(R.string.pref_update_interval_hours_manual);
- break;
- case 1:
- entries[x] = v
- + " "
- + getString(R.string.pref_update_interval_hours_singular);
- break;
- default:
- entries[x] = v + " "
- + getString(R.string.pref_update_interval_hours_plural);
- break;
-
- }
- }
- pref.setEntries(entries);
-
- }
-
- private void setSelectedNetworksEnabled(boolean b) {
- if (selectedNetworks != null) {
- for (Preference p : selectedNetworks) {
- p.setEnabled(b);
- }
- }
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- checkItemVisibility();
- setEpisodeCacheSizeText(UserPreferences.getEpisodeCacheSize());
- setDataFolderText();
- updateGpodnetPreferenceScreen();
- }
-
- @SuppressWarnings("deprecation")
- private void checkItemVisibility() {
-
- boolean hasFlattrToken = FlattrUtils.hasToken();
-
- findPreference(PREF_FLATTR_SETTINGS).setEnabled(FlattrUtils.hasAPICredentials());
- findPreference(PREF_FLATTR_AUTH).setEnabled(!hasFlattrToken);
- findPreference(PREF_FLATTR_REVOKE).setEnabled(hasFlattrToken);
- findPreference(PREF_AUTO_FLATTR_PREFS).setEnabled(hasFlattrToken);
-
- findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER)
- .setEnabled(UserPreferences.isEnableAutodownload());
- setSelectedNetworksEnabled(UserPreferences.isEnableAutodownload()
- && UserPreferences.isEnableAutodownloadWifiFilter());
-
- }
-
- private void setEpisodeCacheSizeText(int cacheSize) {
- String s;
- if (cacheSize == getResources().getInteger(
- R.integer.episode_cache_size_unlimited)) {
- s = getString(R.string.pref_episode_cache_unlimited);
- } else {
- s = Integer.toString(cacheSize)
- + getString(R.string.episodes_suffix);
- }
- findPreference(UserPreferences.PREF_EPISODE_CACHE_SIZE).setSummary(s);
- }
-
- private void setDataFolderText() {
- File f = UserPreferences.getDataFolder(this, null);
- if (f != null) {
- findPreference(PREF_CHOOSE_DATA_DIR)
- .setSummary(f.getAbsolutePath());
- }
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- Intent destIntent = new Intent(this, MainActivity.class);
- destIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(destIntent);
- finish();
- return true;
- default:
- return false;
- }
- }
-
- @Override
- protected void onApplyThemeResource(Theme theme, int resid, boolean first) {
- theme.applyStyle(UserPreferences.getTheme(), true);
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- if (resultCode == DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED) {
- String dir = data
- .getStringExtra(DirectoryChooserActivity.RESULT_SELECTED_DIR);
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Setting data folder");
- UserPreferences.setDataFolder(dir);
- }
- }
-
- private void buildAutodownloadSelectedNetworsPreference() {
- if (selectedNetworks != null) {
- clearAutodownloadSelectedNetworsPreference();
- }
- // get configured networks
- WifiManager wifiservice = (WifiManager) getSystemService(Context.WIFI_SERVICE);
- List<WifiConfiguration> networks = wifiservice.getConfiguredNetworks();
-
- if (networks != null) {
- selectedNetworks = new CheckBoxPreference[networks.size()];
- List<String> 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<String> prefValuesList = new ArrayList<String>(
- Arrays.asList(UserPreferences
- .getAutodownloadSelectedNetworks())
- );
- boolean newValue = ((CheckBoxPreference) preference)
- .isChecked();
- if (BuildConfig.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]);
- }
- }
- }
- }
-
- @SuppressWarnings("deprecation")
- @Override
- public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
- Preference preference) {
- super.onPreferenceTreeClick(preferenceScreen, preference);
- if (preference != null)
- if (preference instanceof PreferenceScreen)
- if (((PreferenceScreen) preference).getDialog() != null)
- ((PreferenceScreen) preference)
- .getDialog()
- .getWindow()
- .getDecorView()
- .setBackgroundDrawable(
- this.getWindow().getDecorView()
- .getBackground().getConstantState()
- .newDrawable()
- );
- return false;
- }
-
- @Override
- public void onBackPressed() {
- // The default back button behavior has to be overwritten because changing the theme clears the back stack
- Intent destIntent = new Intent(this, MainActivity.class);
- destIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(destIntent);
- finish();
- }
-}
diff --git a/src/de/danoeh/antennapod/activity/StorageErrorActivity.java b/src/de/danoeh/antennapod/activity/StorageErrorActivity.java
deleted file mode 100644
index d8a137eb9..000000000
--- a/src/de/danoeh/antennapod/activity/StorageErrorActivity.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package de.danoeh.antennapod.activity;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
-import android.util.Log;
-
-import org.apache.commons.lang3.StringUtils;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.preferences.UserPreferences;
-import de.danoeh.antennapod.util.StorageUtils;
-
-/** Is show if there is now external storage available. */
-public class StorageErrorActivity extends ActionBarActivity {
- private static final String TAG = "StorageErrorActivity";
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- setTheme(UserPreferences.getTheme());
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.storage_error);
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- try {
- unregisterReceiver(mediaUpdate);
- } catch (IllegalArgumentException e) {
-
- }
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- if (StorageUtils.storageAvailable(this)) {
- leaveErrorState();
- } else {
- registerReceiver(mediaUpdate, new IntentFilter(
- Intent.ACTION_MEDIA_MOUNTED));
- }
- }
-
- private void leaveErrorState() {
- finish();
- startActivity(new Intent(this, MainActivity.class));
- }
-
- private BroadcastReceiver mediaUpdate = new BroadcastReceiver() {
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (StringUtils.equals(intent.getAction(), Intent.ACTION_MEDIA_MOUNTED)) {
- if (intent.getBooleanExtra("read-only", true)) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Media was mounted; Finishing activity");
- leaveErrorState();
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "Media seemed to have been mounted read only");
- }
- }
- }
-
- };
-
-}
diff --git a/src/de/danoeh/antennapod/activity/VideoplayerActivity.java b/src/de/danoeh/antennapod/activity/VideoplayerActivity.java
deleted file mode 100644
index 81661a288..000000000
--- a/src/de/danoeh/antennapod/activity/VideoplayerActivity.java
+++ /dev/null
@@ -1,359 +0,0 @@
-package de.danoeh.antennapod.activity;
-
-import android.annotation.SuppressLint;
-import android.content.Intent;
-import android.graphics.drawable.ColorDrawable;
-import android.os.AsyncTask;
-import android.os.Build;
-import android.os.Bundle;
-import android.util.Log;
-import android.util.Pair;
-import android.view.MotionEvent;
-import android.view.SurfaceHolder;
-import android.view.View;
-import android.view.Window;
-import android.view.WindowManager;
-import android.view.animation.Animation;
-import android.view.animation.AnimationUtils;
-import android.widget.LinearLayout;
-import android.widget.ProgressBar;
-import android.widget.SeekBar;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.feed.MediaType;
-import de.danoeh.antennapod.service.playback.PlaybackService;
-import de.danoeh.antennapod.service.playback.PlayerStatus;
-import de.danoeh.antennapod.util.playback.ExternalMedia;
-import de.danoeh.antennapod.util.playback.Playable;
-import de.danoeh.antennapod.view.AspectRatioVideoView;
-
-/**
- * Activity for playing video files.
- */
-public class VideoplayerActivity extends MediaplayerActivity {
- private static final String TAG = "VideoplayerActivity";
-
- /**
- * True if video controls are currently visible.
- */
- private boolean videoControlsShowing = true;
- private boolean videoSurfaceCreated = false;
- private VideoControlsHider videoControlsToggler;
-
- private LinearLayout videoOverlay;
- private AspectRatioVideoView videoview;
- private ProgressBar progressIndicator;
-
- @Override
- protected void chooseTheme() {
- setTheme(R.style.Theme_AntennaPod_Dark);
- }
-
- @SuppressLint("AppCompatMethod")
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- if (Build.VERSION.SDK_INT >= 11) {
- requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
- }
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- super.onCreate(savedInstanceState);
- getSupportActionBar().setBackgroundDrawable(new ColorDrawable(0x80000000));
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- if (videoControlsToggler != null) {
- videoControlsToggler.cancel(true);
- }
- if (controller != null && controller.getStatus() == PlayerStatus.PLAYING) {
- controller.pause();
- }
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- if (getIntent().getAction() != null
- && getIntent().getAction().equals(Intent.ACTION_VIEW)) {
- Intent intent = getIntent();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Received VIEW intent: "
- + intent.getData().getPath());
- ExternalMedia media = new ExternalMedia(intent.getData().getPath(),
- MediaType.VIDEO);
- Intent launchIntent = new Intent(this, PlaybackService.class);
- launchIntent.putExtra(PlaybackService.EXTRA_PLAYABLE, media);
- launchIntent.putExtra(PlaybackService.EXTRA_START_WHEN_PREPARED,
- true);
- launchIntent.putExtra(PlaybackService.EXTRA_SHOULD_STREAM, false);
- launchIntent.putExtra(PlaybackService.EXTRA_PREPARE_IMMEDIATELY,
- true);
- startService(launchIntent);
- }
- }
-
- @Override
- protected boolean loadMediaInfo() {
- if (!super.loadMediaInfo()) {
- return false;
- }
- Playable media = controller.getMedia();
- if (media != null) {
- getSupportActionBar().setSubtitle(media.getEpisodeTitle());
- getSupportActionBar().setTitle(media.getFeedTitle());
- return true;
- }
-
- return false;
- }
-
- @Override
- protected void setupGUI() {
- super.setupGUI();
- videoOverlay = (LinearLayout) findViewById(R.id.overlay);
- videoview = (AspectRatioVideoView) findViewById(R.id.videoview);
- progressIndicator = (ProgressBar) findViewById(R.id.progressIndicator);
- videoview.getHolder().addCallback(surfaceHolderCallback);
- videoview.setOnTouchListener(onVideoviewTouched);
-
- setupVideoControlsToggler();
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
- WindowManager.LayoutParams.FLAG_FULLSCREEN);
- }
-
- @Override
- protected void onAwaitingVideoSurface() {
- if (videoSurfaceCreated) {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "Videosurface already created, setting videosurface now");
-
- Pair<Integer, Integer> videoSize = controller.getVideoSize();
- if (videoSize != null && videoSize.first > 0 && videoSize.second > 0) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Width,height of video: " + videoSize.first + ", " + videoSize.second);
- videoview.setVideoSize(videoSize.first, videoSize.second);
- } else {
- Log.e(TAG, "Could not determine video size");
- }
- controller.setVideoSurface(videoview.getHolder());
- }
- }
-
- @Override
- protected void postStatusMsg(int resId) {
- if (resId == R.string.player_preparing_msg) {
- progressIndicator.setVisibility(View.VISIBLE);
- } else {
- progressIndicator.setVisibility(View.INVISIBLE);
- }
-
- }
-
- @Override
- protected void clearStatusMsg() {
- progressIndicator.setVisibility(View.INVISIBLE);
- }
-
- View.OnTouchListener onVideoviewTouched = new View.OnTouchListener() {
-
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_DOWN) {
- if (videoControlsToggler != null) {
- videoControlsToggler.cancel(true);
- }
- toggleVideoControlsVisibility();
- if (videoControlsShowing) {
- setupVideoControlsToggler();
- }
-
- return true;
- } else {
- return false;
- }
- }
- };
-
- @SuppressLint("NewApi")
- void setupVideoControlsToggler() {
- if (videoControlsToggler != null) {
- videoControlsToggler.cancel(true);
- }
- videoControlsToggler = new VideoControlsHider();
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- videoControlsToggler
- .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- } else {
- videoControlsToggler.execute();
- }
- }
-
- private void toggleVideoControlsVisibility() {
- if (videoControlsShowing) {
- getSupportActionBar().hide();
- hideVideoControls();
- } else {
- getSupportActionBar().show();
- showVideoControls();
- }
- videoControlsShowing = !videoControlsShowing;
- }
-
- /**
- * Hides the videocontrols after a certain period of time.
- */
- public class VideoControlsHider extends AsyncTask<Void, Void, Void> {
- @Override
- protected void onCancelled() {
- videoControlsToggler = null;
- }
-
- @Override
- protected void onPostExecute(Void result) {
- videoControlsToggler = null;
- }
-
- private static final int WAITING_INTERVALL = 5000;
- private static final String TAG = "VideoControlsToggler";
-
- @Override
- protected void onProgressUpdate(Void... values) {
- if (videoControlsShowing) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Hiding video controls");
- getSupportActionBar().hide();
- hideVideoControls();
- videoControlsShowing = false;
- }
- }
-
- @Override
- protected Void doInBackground(Void... params) {
- try {
- Thread.sleep(WAITING_INTERVALL);
- } catch (InterruptedException e) {
- return null;
- }
- publishProgress();
- return null;
- }
-
- }
-
- private final SurfaceHolder.Callback surfaceHolderCallback = new SurfaceHolder.Callback() {
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width,
- int height) {
- holder.setFixedSize(width, height);
- }
-
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Videoview holder created");
- videoSurfaceCreated = true;
- if (controller.getStatus() == PlayerStatus.PLAYING) {
- if (controller.serviceAvailable()) {
- controller.setVideoSurface(holder);
- } else {
- Log.e(TAG,
- "Could'nt attach surface to mediaplayer - reference to service was null");
- }
- }
-
- }
-
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Videosurface was destroyed");
- videoSurfaceCreated = false;
- controller.notifyVideoSurfaceAbandoned();
- }
- };
-
-
- @Override
- protected void onReloadNotification(int notificationCode) {
- if (notificationCode == PlaybackService.EXTRA_CODE_AUDIO) {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "ReloadNotification received, switching to Audioplayer now");
- finish();
- startActivity(new Intent(this, AudioplayerActivity.class));
- }
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- super.onStartTrackingTouch(seekBar);
- if (videoControlsToggler != null) {
- videoControlsToggler.cancel(true);
- }
- }
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- super.onStopTrackingTouch(seekBar);
- setupVideoControlsToggler();
- }
-
- @Override
- protected void onBufferStart() {
- progressIndicator.setVisibility(View.VISIBLE);
- }
-
- @Override
- protected void onBufferEnd() {
- progressIndicator.setVisibility(View.INVISIBLE);
- }
-
- @SuppressLint("NewApi")
- private void showVideoControls() {
- videoOverlay.setVisibility(View.VISIBLE);
- butPlay.setVisibility(View.VISIBLE);
- final Animation animation = AnimationUtils.loadAnimation(this,
- R.anim.fade_in);
- if (animation != null) {
- videoOverlay.startAnimation(animation);
- butPlay.startAnimation(animation);
- }
- if (Build.VERSION.SDK_INT >= 14) {
- videoview.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
- }
- }
-
- @SuppressLint("NewApi")
- private void hideVideoControls() {
- final Animation animation = AnimationUtils.loadAnimation(this,
- R.anim.fade_out);
- if (animation != null) {
- videoOverlay.startAnimation(animation);
- butPlay.startAnimation(animation);
- }
- if (Build.VERSION.SDK_INT >= 14) {
- videoview.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
- }
- videoOverlay.setVisibility(View.GONE);
- butPlay.setVisibility(View.GONE);
- }
-
- @Override
- protected int getContentViewResourceId() {
- return R.layout.videoplayer_activity;
- }
-
-
- @Override
- protected void setScreenOn(boolean enable) {
- super.setScreenOn(enable);
- if (enable) {
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- } else {
- getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java b/src/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java
deleted file mode 100644
index 6a60f65fe..000000000
--- a/src/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java
+++ /dev/null
@@ -1,372 +0,0 @@
-package de.danoeh.antennapod.activity.gpoddernet;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.support.v4.app.NavUtils;
-import android.support.v7.app.ActionBarActivity;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.*;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.MainActivity;
-import de.danoeh.antennapod.gpoddernet.GpodnetService;
-import de.danoeh.antennapod.gpoddernet.GpodnetServiceException;
-import de.danoeh.antennapod.gpoddernet.model.GpodnetDevice;
-import de.danoeh.antennapod.preferences.GpodnetPreferences;
-import de.danoeh.antennapod.preferences.UserPreferences;
-import de.danoeh.antennapod.service.GpodnetSyncService;
-
-import java.security.SecureRandom;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * Guides the user through the authentication process
- * Step 1: Request username and password from user
- * Step 2: Choose device from a list of available devices or create a new one
- * Step 3: Choose from a list of actions
- */
-public class GpodnetAuthenticationActivity extends ActionBarActivity {
- private static final String TAG = "GpodnetAuthenticationActivity";
-
- private static final String CURRENT_STEP = "current_step";
-
- private ViewFlipper viewFlipper;
-
- private static final int STEP_DEFAULT = -1;
- private static final int STEP_LOGIN = 0;
- private static final int STEP_DEVICE = 1;
- private static final int STEP_FINISH = 2;
-
- private int currentStep = -1;
-
- private GpodnetService service;
- private volatile String username;
- private volatile String password;
- private volatile GpodnetDevice selectedDevice;
-
- View[] views;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- setTheme(UserPreferences.getTheme());
- super.onCreate(savedInstanceState);
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
-
- setContentView(R.layout.gpodnetauth_activity);
- service = new GpodnetService();
-
- viewFlipper = (ViewFlipper) findViewById(R.id.viewflipper);
- LayoutInflater inflater = (LayoutInflater)
- getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- views = new View[]{
- inflater.inflate(R.layout.gpodnetauth_credentials, viewFlipper, false),
- inflater.inflate(R.layout.gpodnetauth_device, viewFlipper, false),
- inflater.inflate(R.layout.gpodnetauth_finish, viewFlipper, false)
- };
- for (View view : views) {
- viewFlipper.addView(view);
- }
- advance();
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- if (service != null) {
- service.shutdown();
- }
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- NavUtils.navigateUpFromSameTask(this);
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- }
-
- private void setupLoginView(View view) {
- final EditText username = (EditText) view.findViewById(R.id.etxtUsername);
- final EditText password = (EditText) view.findViewById(R.id.etxtPassword);
- final Button login = (Button) view.findViewById(R.id.butLogin);
- final TextView txtvError = (TextView) view.findViewById(R.id.txtvError);
- final ProgressBar progressBar = (ProgressBar) view.findViewById(R.id.progBarLogin);
-
- login.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
-
- final String usernameStr = username.getText().toString();
- final String passwordStr = password.getText().toString();
-
- if (BuildConfig.DEBUG) Log.d(TAG, "Checking login credentials");
- new AsyncTask<GpodnetService, Void, Void>() {
-
- volatile Exception exception;
-
- @Override
- protected void onPreExecute() {
- super.onPreExecute();
- login.setEnabled(false);
- progressBar.setVisibility(View.VISIBLE);
- txtvError.setVisibility(View.GONE);
-
- }
-
- @Override
- protected void onPostExecute(Void aVoid) {
- super.onPostExecute(aVoid);
- login.setEnabled(true);
- progressBar.setVisibility(View.GONE);
-
- if (exception == null) {
- advance();
- } else {
- txtvError.setText(exception.getMessage());
- txtvError.setVisibility(View.VISIBLE);
- }
- }
-
- @Override
- protected Void doInBackground(GpodnetService... params) {
- try {
- params[0].authenticate(usernameStr, passwordStr);
- GpodnetAuthenticationActivity.this.username = usernameStr;
- GpodnetAuthenticationActivity.this.password = passwordStr;
- } catch (GpodnetServiceException e) {
- e.printStackTrace();
- exception = e;
- }
- return null;
- }
- }.execute(service);
- }
- });
- }
-
- private void setupDeviceView(View view) {
- final EditText deviceID = (EditText) view.findViewById(R.id.etxtDeviceID);
- final EditText caption = (EditText) view.findViewById(R.id.etxtCaption);
- final Button createNewDevice = (Button) view.findViewById(R.id.butCreateNewDevice);
- final Button chooseDevice = (Button) view.findViewById(R.id.butChooseExistingDevice);
- final TextView txtvError = (TextView) view.findViewById(R.id.txtvError);
- final ProgressBar progBarCreateDevice = (ProgressBar) view.findViewById(R.id.progbarCreateDevice);
- final Spinner spinnerDevices = (Spinner) view.findViewById(R.id.spinnerChooseDevice);
-
-
- // load device list
- final AtomicReference<List<GpodnetDevice>> devices = new AtomicReference<List<GpodnetDevice>>();
- new AsyncTask<GpodnetService, Void, List<GpodnetDevice>>() {
-
- private volatile Exception exception;
-
- @Override
- protected void onPreExecute() {
- super.onPreExecute();
- chooseDevice.setEnabled(false);
- spinnerDevices.setEnabled(false);
- createNewDevice.setEnabled(false);
- }
-
- @Override
- protected void onPostExecute(List<GpodnetDevice> gpodnetDevices) {
- super.onPostExecute(gpodnetDevices);
- if (gpodnetDevices != null) {
- List<String> deviceNames = new ArrayList<String>();
- for (GpodnetDevice device : gpodnetDevices) {
- deviceNames.add(device.getCaption());
- }
- spinnerDevices.setAdapter(new ArrayAdapter<String>(GpodnetAuthenticationActivity.this,
- android.R.layout.simple_spinner_dropdown_item, deviceNames));
- spinnerDevices.setEnabled(true);
- if (!deviceNames.isEmpty()) {
- chooseDevice.setEnabled(true);
- }
- devices.set(gpodnetDevices);
- createNewDevice.setEnabled(true);
- }
- }
-
- @Override
- protected List<GpodnetDevice> doInBackground(GpodnetService... params) {
- try {
- return params[0].getDevices(username);
- } catch (GpodnetServiceException e) {
- e.printStackTrace();
- exception = e;
- return null;
- }
- }
- }.execute(service);
-
-
- createNewDevice.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (checkDeviceIDText(deviceID, txtvError, devices.get())) {
- final String deviceStr = deviceID.getText().toString();
- final String captionStr = caption.getText().toString();
-
- new AsyncTask<GpodnetService, Void, GpodnetDevice>() {
-
- private volatile Exception exception;
-
- @Override
- protected void onPreExecute() {
- super.onPreExecute();
- createNewDevice.setEnabled(false);
- chooseDevice.setEnabled(false);
- progBarCreateDevice.setVisibility(View.VISIBLE);
- txtvError.setVisibility(View.GONE);
- }
-
- @Override
- protected void onPostExecute(GpodnetDevice result) {
- super.onPostExecute(result);
- createNewDevice.setEnabled(true);
- chooseDevice.setEnabled(true);
- progBarCreateDevice.setVisibility(View.GONE);
- if (exception == null) {
- selectedDevice = result;
- advance();
- } else {
- txtvError.setText(exception.getMessage());
- txtvError.setVisibility(View.VISIBLE);
- }
- }
-
- @Override
- protected GpodnetDevice doInBackground(GpodnetService... params) {
- try {
- params[0].configureDevice(username, deviceStr, captionStr, GpodnetDevice.DeviceType.MOBILE);
- return new GpodnetDevice(deviceStr, captionStr, GpodnetDevice.DeviceType.MOBILE.toString(), 0);
- } catch (GpodnetServiceException e) {
- e.printStackTrace();
- exception = e;
- }
- return null;
- }
- }.execute(service);
- }
- }
- });
-
- deviceID.setText(generateDeviceID());
- chooseDevice.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- final int position = spinnerDevices.getSelectedItemPosition();
- if (position != AdapterView.INVALID_POSITION) {
- selectedDevice = devices.get().get(position);
- advance();
- }
- }
- });
- }
-
-
- private String generateDeviceID() {
- final int DEVICE_ID_LENGTH = 10;
- StringBuilder buffer = new StringBuilder(DEVICE_ID_LENGTH);
- SecureRandom random = new SecureRandom();
- for (int i = 0; i < DEVICE_ID_LENGTH; i++) {
- buffer.append(random.nextInt(10));
-
- }
- return buffer.toString();
- }
-
- private boolean checkDeviceIDText(EditText deviceID, TextView txtvError, List<GpodnetDevice> devices) {
- String text = deviceID.getText().toString();
- if (text.length() == 0) {
- txtvError.setText(R.string.gpodnetauth_device_errorEmpty);
- txtvError.setVisibility(View.VISIBLE);
- return false;
- } else {
- if (devices != null) {
- for (GpodnetDevice device : devices) {
- if (device.getId().equals(text)) {
- txtvError.setText(R.string.gpodnetauth_device_errorAlreadyUsed);
- txtvError.setVisibility(View.VISIBLE);
- return false;
- }
- }
- txtvError.setVisibility(View.GONE);
- return true;
- }
- return true;
- }
-
- }
-
- private void setupFinishView(View view) {
- final Button sync = (Button) view.findViewById(R.id.butSyncNow);
- final Button back = (Button) view.findViewById(R.id.butGoMainscreen);
-
- sync.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- GpodnetSyncService.sendSyncIntent(GpodnetAuthenticationActivity.this);
- finish();
- }
- });
- back.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(GpodnetAuthenticationActivity.this, MainActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivity(intent);
- }
- });
- }
-
- private void writeLoginCredentials() {
- if (BuildConfig.DEBUG) Log.d(TAG, "Writing login credentials");
- GpodnetPreferences.setUsername(username);
- GpodnetPreferences.setPassword(password);
- GpodnetPreferences.setDeviceID(selectedDevice.getId());
- }
-
- private void advance() {
- if (currentStep < STEP_FINISH) {
-
- View view = views[currentStep + 1];
- if (currentStep == STEP_DEFAULT) {
- setupLoginView(view);
- } else if (currentStep == STEP_LOGIN) {
- if (username == null || password == null) {
- throw new IllegalStateException("Username and password must not be null here");
- } else {
- setupDeviceView(view);
- }
- } else if (currentStep == STEP_DEVICE) {
- if (selectedDevice == null) {
- throw new IllegalStateException("Device must not be null here");
- } else {
- writeLoginCredentials();
- setupFinishView(view);
- }
- }
- if (currentStep != STEP_DEFAULT) {
- viewFlipper.showNext();
- }
- currentStep++;
- } else {
- finish();
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/adapter/ActionButtonCallback.java b/src/de/danoeh/antennapod/adapter/ActionButtonCallback.java
deleted file mode 100644
index 30ad2d03f..000000000
--- a/src/de/danoeh/antennapod/adapter/ActionButtonCallback.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package de.danoeh.antennapod.adapter;
-
-import de.danoeh.antennapod.feed.FeedItem;
-
-public interface ActionButtonCallback {
- /** Is called when the action button of a list item has been pressed. */
- abstract void onActionButtonPressed(FeedItem item);
-}
diff --git a/src/de/danoeh/antennapod/adapter/ActionButtonUtils.java b/src/de/danoeh/antennapod/adapter/ActionButtonUtils.java
deleted file mode 100644
index 1de071a73..000000000
--- a/src/de/danoeh/antennapod/adapter/ActionButtonUtils.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package de.danoeh.antennapod.adapter;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.view.View;
-import android.widget.ImageButton;
-
-import org.apache.commons.lang3.Validate;
-
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.feed.FeedMedia;
-import de.danoeh.antennapod.storage.DownloadRequester;
-
-/**
- * Utility methods for the action button that is displayed on the right hand side
- * of a listitem.
- */
-public class ActionButtonUtils {
-
- private final int[] labels;
- private final TypedArray drawables;
- private final Context context;
-
- public ActionButtonUtils(Context context) {
- Validate.notNull(context);
-
- this.context = context;
- drawables = context.obtainStyledAttributes(new int[]{
- R.attr.av_play, R.attr.navigation_cancel, R.attr.av_download, R.attr.navigation_chapters, R.attr.navigation_accept});
- labels = new int[]{R.string.play_label, R.string.cancel_download_label, R.string.download_label, R.string.mark_read_label};
- }
-
- /**
- * Sets the displayed bitmap and content description of the given
- * action button so that it matches the state of the FeedItem.
- */
- public void configureActionButton(ImageButton butSecondary, FeedItem item) {
- Validate.isTrue(butSecondary != null && item != null, "butSecondary or item was null");
-
- final FeedMedia media = item.getMedia();
- if (media != null) {
- final boolean isDownloadingMedia = DownloadRequester.getInstance().isDownloadingFile(media);
- if (!media.isDownloaded()) {
- if (isDownloadingMedia) {
- // item is being downloaded
- butSecondary.setVisibility(View.VISIBLE);
- butSecondary.setImageDrawable(drawables
- .getDrawable(1));
- butSecondary.setContentDescription(context.getString(labels[1]));
- } else {
- // item is not downloaded and not being downloaded
- butSecondary.setVisibility(View.VISIBLE);
- butSecondary.setImageDrawable(drawables.getDrawable(2));
- butSecondary.setContentDescription(context.getString(labels[2]));
- }
- } else {
- // item is not being downloaded
- butSecondary.setVisibility(View.VISIBLE);
- if (media.isPlaying()) {
- butSecondary.setImageDrawable(drawables.getDrawable(3));
- } else {
- butSecondary
- .setImageDrawable(drawables.getDrawable(0));
- }
- butSecondary.setContentDescription(context.getString(labels[0]));
- }
- } else {
- if (item.isRead()) {
- butSecondary.setVisibility(View.INVISIBLE);
- } else {
- butSecondary.setVisibility(View.VISIBLE);
- butSecondary.setImageDrawable(drawables.getDrawable(4));
- butSecondary.setContentDescription(context.getString(labels[3]));
- }
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/adapter/AdapterUtils.java b/src/de/danoeh/antennapod/adapter/AdapterUtils.java
deleted file mode 100644
index f393fb7d7..000000000
--- a/src/de/danoeh/antennapod/adapter/AdapterUtils.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package de.danoeh.antennapod.adapter;
-
-import android.content.res.Resources;
-import android.view.View;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.feed.FeedMedia;
-import de.danoeh.antennapod.util.Converter;
-
-/**
- * Utility methods for adapters
- */
-public class AdapterUtils {
-
- private AdapterUtils() {
-
- }
-
- /**
- * Updates the contents of the TextView that shows the current playback position and the ProgressBar.
- */
- public static void updateEpisodePlaybackProgress(FeedItem item, Resources res, TextView txtvPos, ProgressBar episodeProgress) {
- FeedMedia media = item.getMedia();
- episodeProgress.setVisibility(View.GONE);
- if (media == null) {
- txtvPos.setVisibility(View.GONE);
- return;
- } else {
- txtvPos.setVisibility(View.VISIBLE);
- }
-
- FeedItem.State state = item.getState();
- if (state == FeedItem.State.PLAYING
- || state == FeedItem.State.IN_PROGRESS) {
- if (media.getDuration() > 0) {
- episodeProgress.setVisibility(View.VISIBLE);
- episodeProgress
- .setProgress((int) (((double) media
- .getPosition()) / media.getDuration() * 100));
- txtvPos.setText(Converter
- .getDurationStringLong(media.getDuration()
- - media.getPosition()));
- }
- } else if (!media.isDownloaded()) {
- txtvPos.setText(res.getString(
- R.string.size_prefix)
- + Converter.byteToString(media.getSize()));
- } else {
- txtvPos.setText(res.getString(
- R.string.length_prefix)
- + Converter.getDurationStringLong(media
- .getDuration()));
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/adapter/ChapterListAdapter.java b/src/de/danoeh/antennapod/adapter/ChapterListAdapter.java
deleted file mode 100644
index c12de6ebd..000000000
--- a/src/de/danoeh/antennapod/adapter/ChapterListAdapter.java
+++ /dev/null
@@ -1,180 +0,0 @@
-package de.danoeh.antennapod.adapter;
-
-import android.content.Context;
-import android.text.Layout;
-import android.text.Selection;
-import android.text.Spannable;
-import android.text.Spanned;
-import android.text.style.ClickableSpan;
-import android.text.util.Linkify;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.View.OnTouchListener;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.TextView;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.feed.Chapter;
-import de.danoeh.antennapod.util.ChapterUtils;
-import de.danoeh.antennapod.util.Converter;
-import de.danoeh.antennapod.util.playback.Playable;
-
-import java.util.List;
-
-public class ChapterListAdapter extends ArrayAdapter<Chapter> {
-
- private static final String TAG = "ChapterListAdapter";
-
- private List<Chapter> chapters;
- private Playable media;
-
- private int defaultTextColor;
-
- public ChapterListAdapter(Context context, int textViewResourceId,
- List<Chapter> objects, Playable media) {
- super(context, textViewResourceId, objects);
- this.chapters = objects;
- this.media = media;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- Holder holder;
-
- Chapter sc = getItem(position);
-
- // Inflate Layout
- if (convertView == null) {
- holder = new Holder();
- LayoutInflater inflater = (LayoutInflater) getContext()
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
- convertView = inflater.inflate(R.layout.simplechapter_item, parent, false);
- holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
- defaultTextColor = holder.title.getTextColors().getDefaultColor();
- holder.start = (TextView) convertView.findViewById(R.id.txtvStart);
- holder.link = (TextView) convertView.findViewById(R.id.txtvLink);
- convertView.setTag(holder);
- } else {
- holder = (Holder) convertView.getTag();
-
- }
-
- holder.title.setText(sc.getTitle());
- holder.start.setText(Converter.getDurationStringLong((int) sc
- .getStart()));
- if (sc.getLink() != null) {
- holder.link.setVisibility(View.VISIBLE);
- holder.link.setText(sc.getLink());
- Linkify.addLinks(holder.link, Linkify.WEB_URLS);
- } else {
- holder.link.setVisibility(View.GONE);
- }
- holder.link.setMovementMethod(null);
- holder.link.setOnTouchListener(new OnTouchListener() {
-
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- // from
- // http://stackoverflow.com/questions/7236840/android-textview-linkify-intercepts-with-parent-view-gestures
- TextView widget = (TextView) v;
- Object text = widget.getText();
- if (text instanceof Spanned) {
- Spannable buffer = (Spannable) text;
-
- int action = event.getAction();
-
- if (action == MotionEvent.ACTION_UP
- || action == MotionEvent.ACTION_DOWN) {
- int x = (int) event.getX();
- int y = (int) event.getY();
-
- x -= widget.getTotalPaddingLeft();
- y -= widget.getTotalPaddingTop();
-
- x += widget.getScrollX();
- y += widget.getScrollY();
-
- Layout layout = widget.getLayout();
- int line = layout.getLineForVertical(y);
- int off = layout.getOffsetForHorizontal(line, x);
-
- ClickableSpan[] link = buffer.getSpans(off, off,
- ClickableSpan.class);
-
- if (link.length != 0) {
- if (action == MotionEvent.ACTION_UP) {
- link[0].onClick(widget);
- } else if (action == MotionEvent.ACTION_DOWN) {
- Selection.setSelection(buffer,
- buffer.getSpanStart(link[0]),
- buffer.getSpanEnd(link[0]));
- }
- return true;
- }
- }
-
- }
-
- return false;
-
- }
- });
- Chapter current = ChapterUtils.getCurrentChapter(media);
- if (current != null) {
- if (current == sc) {
- holder.title.setTextColor(convertView.getResources().getColor(
- R.color.bright_blue));
- holder.start.setTextColor(convertView.getResources().getColor(
- R.color.bright_blue));
- } else {
- holder.title.setTextColor(defaultTextColor);
- holder.start.setTextColor(defaultTextColor);
- }
- } else {
- Log.w(TAG, "Could not find out what the current chapter is.");
- }
-
- return convertView;
- }
-
- static class Holder {
- TextView title;
- TextView start;
- TextView link;
- }
-
- @Override
- public int getCount() {
- // ignore invalid chapters
- int counter = 0;
- for (Chapter chapter : chapters) {
- if (!ignoreChapter(chapter)) {
- counter++;
- }
- }
- return counter;
- }
-
- private boolean ignoreChapter(Chapter c) {
- return media.getDuration() > 0 && media.getDuration() < c.getStart();
- }
-
- @Override
- public Chapter getItem(int position) {
- int i = 0;
- for (Chapter chapter : chapters) {
- if (!ignoreChapter(chapter)) {
- if (i == position) {
- return chapter;
- } else {
- i++;
- }
- }
- }
- return super.getItem(position);
- }
-
-}
diff --git a/src/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java b/src/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java
deleted file mode 100644
index 0c4cbe685..000000000
--- a/src/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package de.danoeh.antennapod.adapter;
-
-import android.content.Context;
-import android.widget.Toast;
-
-import org.apache.commons.lang3.Validate;
-
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.dialog.DownloadRequestErrorDialogCreator;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.feed.FeedMedia;
-import de.danoeh.antennapod.storage.DBTasks;
-import de.danoeh.antennapod.storage.DBWriter;
-import de.danoeh.antennapod.storage.DownloadRequestException;
-import de.danoeh.antennapod.storage.DownloadRequester;
-
-/**
- * Default implementation of an ActionButtonCallback
- */
-public class DefaultActionButtonCallback implements ActionButtonCallback {
- private static final String TAG = "DefaultActionButtonCallback";
-
- private final Context context;
-
- public DefaultActionButtonCallback(Context context) {
- Validate.notNull(context);
- this.context = context;
- }
-
- @Override
- public void onActionButtonPressed(final FeedItem item) {
-
-
- if (item.hasMedia()) {
- final FeedMedia media = item.getMedia();
- boolean isDownloading = DownloadRequester.getInstance().isDownloadingFile(media);
- if (!isDownloading && !media.isDownloaded()) {
- try {
- DBTasks.downloadFeedItems(context, item);
- Toast.makeText(context, R.string.status_downloading_label, Toast.LENGTH_SHORT).show();
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- DownloadRequestErrorDialogCreator.newRequestErrorDialog(context, e.getMessage());
- }
- } else if (isDownloading) {
- DownloadRequester.getInstance().cancelDownload(context, media);
- Toast.makeText(context, R.string.download_cancelled_msg, Toast.LENGTH_SHORT).show();
- } else { // media is downloaded
- DBTasks.playMedia(context, media, true, true, false);
- }
- } else {
- if (!item.isRead()) {
- DBWriter.markItemRead(context, item, true, true);
- }
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/adapter/DownloadLogAdapter.java b/src/de/danoeh/antennapod/adapter/DownloadLogAdapter.java
deleted file mode 100644
index 2cc216227..000000000
--- a/src/de/danoeh/antennapod/adapter/DownloadLogAdapter.java
+++ /dev/null
@@ -1,112 +0,0 @@
-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;
-import android.widget.BaseAdapter;
-import android.widget.TextView;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.feed.Feed;
-import de.danoeh.antennapod.feed.FeedImage;
-import de.danoeh.antennapod.feed.FeedMedia;
-import de.danoeh.antennapod.service.download.DownloadStatus;
-
-/** Displays a list of DownloadStatus entries. */
-public class DownloadLogAdapter extends BaseAdapter {
-
- private Context context;
-
- private ItemAccess itemAccess;
-
- public DownloadLogAdapter(Context context, ItemAccess itemAccess) {
- super();
- this.itemAccess = itemAccess;
- this.context = context;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- Holder holder;
- DownloadStatus status = getItem(position);
- if (convertView == null) {
- holder = new Holder();
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- convertView = inflater.inflate(R.layout.downloadlog_item, parent, false);
- holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
- holder.type = (TextView) convertView.findViewById(R.id.txtvType);
- holder.date = (TextView) convertView.findViewById(R.id.txtvDate);
- holder.successful = (TextView) convertView
- .findViewById(R.id.txtvStatus);
- holder.reason = (TextView) convertView
- .findViewById(R.id.txtvReason);
- convertView.setTag(holder);
- } else {
- holder = (Holder) convertView.getTag();
- }
- if (status.getFeedfileType() == Feed.FEEDFILETYPE_FEED) {
- holder.type.setText(R.string.download_type_feed);
- } else if (status.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
- holder.type.setText(R.string.download_type_media);
- } else if (status.getFeedfileType() == FeedImage.FEEDFILETYPE_FEEDIMAGE) {
- holder.type.setText(R.string.download_type_image);
- }
- if (status.getTitle() != null) {
- holder.title.setText(status.getTitle());
- } else {
- holder.title.setText(R.string.download_log_title_unknown);
- }
- holder.date.setText(DateUtils.getRelativeTimeSpanString(
- status.getCompletionDate().getTime(),
- System.currentTimeMillis(), 0, 0));
- if (status.isSuccessful()) {
- holder.successful.setTextColor(convertView.getResources().getColor(
- R.color.download_success_green));
- holder.successful.setText(R.string.download_successful);
- holder.reason.setVisibility(View.GONE);
- } else {
- holder.successful.setTextColor(convertView.getResources().getColor(
- R.color.download_failed_red));
- holder.successful.setText(R.string.download_failed);
- String reasonText = status.getReason().getErrorString(context);
- if (status.getReasonDetailed() != null) {
- reasonText += ": " + status.getReasonDetailed();
- }
- holder.reason.setText(reasonText);
- holder.reason.setVisibility(View.VISIBLE);
- }
-
- return convertView;
- }
-
- static class Holder {
- TextView title;
- TextView type;
- TextView date;
- TextView successful;
- TextView reason;
- }
-
- @Override
- public int getCount() {
- return itemAccess.getCount();
- }
-
- @Override
- public DownloadStatus getItem(int position) {
- return itemAccess.getItem(position);
- }
-
- @Override
- public long getItemId(int position) {
- return position;
- }
-
- public static interface ItemAccess {
- public int getCount();
- public DownloadStatus getItem(int position);
- }
-
-}
diff --git a/src/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java b/src/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java
deleted file mode 100644
index ef5af67de..000000000
--- a/src/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java
+++ /dev/null
@@ -1,122 +0,0 @@
-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;
-import android.widget.BaseAdapter;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.asynctask.PicassoProvider;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.util.Converter;
-
-/**
- * Shows a list of downloaded episodes
- */
-public class DownloadedEpisodesListAdapter extends BaseAdapter {
-
- private final Context context;
- private final ItemAccess itemAccess;
-
- private final int imageSize;
-
- public DownloadedEpisodesListAdapter(Context context, ItemAccess itemAccess) {
- super();
- this.context = context;
- this.itemAccess = itemAccess;
- this.imageSize = (int) context.getResources().getDimension(R.dimen.thumbnail_length_downloaded_item);
- }
-
- @Override
- public int getCount() {
- return itemAccess.getCount();
- }
-
- @Override
- public FeedItem getItem(int position) {
- return itemAccess.getItem(position);
- }
-
- @Override
- public long getItemId(int position) {
- return position;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- Holder holder;
- final FeedItem item = (FeedItem) getItem(position);
- if (item == null) return null;
-
- if (convertView == null) {
- holder = new Holder();
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- convertView = inflater.inflate(R.layout.downloaded_episodeslist_item,
- parent, false);
- holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
- holder.pubDate = (TextView) convertView
- .findViewById(R.id.txtvPublished);
- holder.butSecondary = (ImageButton) convertView
- .findViewById(R.id.butSecondaryAction);
- holder.imageView = (ImageView) convertView.findViewById(R.id.imgvImage);
- holder.txtvSize = (TextView) convertView.findViewById(R.id.txtvSize);
- convertView.setTag(holder);
- } else {
- holder = (Holder) convertView.getTag();
- }
-
- holder.title.setText(item.getTitle());
- holder.pubDate.setText(DateUtils.formatDateTime(context, item.getPubDate().getTime(), DateUtils.FORMAT_SHOW_DATE));
- holder.txtvSize.setText(Converter.byteToString(item.getMedia().getSize()));
- FeedItem.State state = item.getState();
-
- if (state == FeedItem.State.PLAYING) {
- holder.butSecondary.setEnabled(false);
- } else {
- holder.butSecondary.setEnabled(true);
- }
-
- holder.butSecondary.setFocusable(false);
- holder.butSecondary.setTag(item);
- holder.butSecondary.setOnClickListener(secondaryActionListener);
-
-
- PicassoProvider.getMediaMetadataPicassoInstance(context)
- .load(item.getImageUri())
- .fit()
- .into(holder.imageView);
-
- return convertView;
- }
-
- private View.OnClickListener secondaryActionListener = new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- FeedItem item = (FeedItem) v.getTag();
- itemAccess.onFeedItemSecondaryAction(item);
- }
- };
-
-
- static class Holder {
- TextView title;
- TextView pubDate;
- ImageView imageView;
- TextView txtvSize;
- ImageButton butSecondary;
- }
-
- public interface ItemAccess {
- int getCount();
-
- FeedItem getItem(int position);
-
- void onFeedItemSecondaryAction(FeedItem item);
- }
-}
diff --git a/src/de/danoeh/antennapod/adapter/DownloadlistAdapter.java b/src/de/danoeh/antennapod/adapter/DownloadlistAdapter.java
deleted file mode 100644
index 658af9e4e..000000000
--- a/src/de/danoeh/antennapod/adapter/DownloadlistAdapter.java
+++ /dev/null
@@ -1,142 +0,0 @@
-package de.danoeh.antennapod.adapter;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.ImageButton;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.service.download.DownloadRequest;
-import de.danoeh.antennapod.service.download.DownloadStatus;
-import de.danoeh.antennapod.service.download.Downloader;
-import de.danoeh.antennapod.util.Converter;
-import de.danoeh.antennapod.util.ThemeUtils;
-
-public class DownloadlistAdapter extends BaseAdapter {
-
- public static final int SELECTION_NONE = -1;
-
- private int selectedItemIndex;
- private ItemAccess itemAccess;
- private Context context;
-
- public DownloadlistAdapter(Context context,
- ItemAccess itemAccess) {
- super();
- this.selectedItemIndex = SELECTION_NONE;
- this.context = context;
- this.itemAccess = itemAccess;
- }
-
- @Override
- public int getCount() {
- return itemAccess.getCount();
- }
-
- @Override
- public Downloader getItem(int position) {
- return itemAccess.getItem(position);
- }
-
- @Override
- public long getItemId(int position) {
- return position;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- Holder holder;
- Downloader downloader = getItem(position);
- DownloadRequest request = downloader.getDownloadRequest();
- // Inflate layout
- if (convertView == null) {
- holder = new Holder();
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- convertView = inflater.inflate(R.layout.downloadlist_item, parent, false);
- holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
- holder.message = (TextView) convertView
- .findViewById(R.id.txtvMessage);
- holder.downloaded = (TextView) convertView
- .findViewById(R.id.txtvDownloaded);
- holder.percent = (TextView) convertView
- .findViewById(R.id.txtvPercent);
- holder.progbar = (ProgressBar) convertView
- .findViewById(R.id.progProgress);
- holder.butSecondary = (ImageButton) convertView
- .findViewById(R.id.butSecondaryAction);
-
- convertView.setTag(holder);
- } else {
- holder = (Holder) convertView.getTag();
- }
-
- if (position == selectedItemIndex) {
- convertView.setBackgroundColor(convertView.getResources().getColor(
- ThemeUtils.getSelectionBackgroundColor()));
- } else {
- convertView.setBackgroundResource(0);
- }
-
- holder.title.setText(request.getTitle());
- if (request.getStatusMsg() != 0) {
- holder.message.setText(request.getStatusMsg());
- }
- String strDownloaded = Converter.byteToString(request.getSoFar());
- if (request.getSize() != DownloadStatus.SIZE_UNKNOWN) {
- strDownloaded += " / " + Converter.byteToString(request.getSize());
- holder.percent.setText(request.getProgressPercent() + "%");
- holder.progbar.setProgress(request.getProgressPercent());
- holder.percent.setVisibility(View.VISIBLE);
- } else {
- holder.progbar.setProgress(0);
- holder.percent.setVisibility(View.INVISIBLE);
- }
-
- holder.downloaded.setText(strDownloaded);
-
- holder.butSecondary.setFocusable(false);
- holder.butSecondary.setTag(downloader);
- holder.butSecondary.setOnClickListener(butSecondaryListener);
-
- return convertView;
- }
-
- private View.OnClickListener butSecondaryListener = new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Downloader downloader = (Downloader) v.getTag();
- itemAccess.onSecondaryActionClick(downloader);
- }
- };
-
- static class Holder {
- TextView title;
- TextView message;
- TextView downloaded;
- TextView percent;
- ProgressBar progbar;
- ImageButton butSecondary;
- }
-
- public int getSelectedItemIndex() {
- return selectedItemIndex;
- }
-
- public void setSelectedItemIndex(int selectedItemIndex) {
- this.selectedItemIndex = selectedItemIndex;
- notifyDataSetChanged();
- }
-
- public interface ItemAccess {
- public int getCount();
-
- public Downloader getItem(int position);
-
- public void onSecondaryActionClick(Downloader downloader);
- }
-
-}
diff --git a/src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java b/src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java
deleted file mode 100644
index 3f666eb8b..000000000
--- a/src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java
+++ /dev/null
@@ -1,306 +0,0 @@
-package de.danoeh.antennapod.adapter;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-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.PicassoProvider;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.feed.FeedMedia;
-import de.danoeh.antennapod.storage.DownloadRequester;
-import de.danoeh.antennapod.util.Converter;
-
-/**
- * Displays unread items and items in the queue in one combined list. The
- * structure of this list is: [header] [queueItems] [header] [unreadItems].
- */
-public class ExternalEpisodesListAdapter extends BaseExpandableListAdapter {
- private static final String TAG = "ExternalEpisodesListAdapter";
-
- public static final int GROUP_POS_QUEUE = 0;
- public static final int GROUP_POS_UNREAD = 1;
-
- private Context context;
- private ItemAccess itemAccess;
-
- private ActionButtonCallback feedItemActionCallback;
- private OnGroupActionClicked groupActionCallback;
-
- private final int imageSize;
-
- public ExternalEpisodesListAdapter(Context context,
- ActionButtonCallback callback,
- OnGroupActionClicked groupActionCallback,
- ItemAccess itemAccess) {
- super();
- this.context = context;
- this.itemAccess = itemAccess;
- this.feedItemActionCallback = callback;
- this.groupActionCallback = groupActionCallback;
- this.imageSize = (int) context.getResources().getDimension(R.dimen.thumbnail_length);
- }
-
- @Override
- public boolean areAllItemsEnabled() {
- return true;
- }
-
- @Override
- public FeedItem getChild(int groupPosition, int childPosition) {
- if (groupPosition == GROUP_POS_QUEUE) {
- return itemAccess.getQueueItemAt(childPosition);
- } else if (groupPosition == GROUP_POS_UNREAD) {
- return itemAccess.getUnreadItemAt(childPosition);
- }
- return null;
- }
-
- @Override
- public long getChildId(int groupPosition, int childPosition) {
- return childPosition;
- }
-
- @Override
- public View getChildView(int groupPosition, final int childPosition,
- boolean isLastChild, View convertView, ViewGroup parent) {
- Holder holder;
- final FeedItem item = getChild(groupPosition, childPosition);
-
- if (convertView == null) {
- holder = new Holder();
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- convertView = inflater.inflate(R.layout.external_itemlist_item,
- parent, false);
- holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
- holder.feedTitle = (TextView) convertView
- .findViewById(R.id.txtvFeedname);
- holder.lenSize = (TextView) convertView
- .findViewById(R.id.txtvLenSize);
- holder.downloadStatus = (ImageView) convertView
- .findViewById(R.id.imgvDownloadStatus);
- holder.feedImage = (ImageView) convertView
- .findViewById(R.id.imgvFeedimage);
- holder.butAction = (ImageButton) convertView
- .findViewById(R.id.butAction);
- holder.statusPlaying = (View) convertView
- .findViewById(R.id.statusPlaying);
- holder.episodeProgress = (ProgressBar) convertView
- .findViewById(R.id.pbar_episode_progress);
- convertView.setTag(holder);
- } else {
- holder = (Holder) convertView.getTag();
- }
-
- holder.title.setText(item.getTitle());
- holder.feedTitle.setText(item.getFeed().getTitle());
- FeedItem.State state = item.getState();
-
- if (groupPosition == GROUP_POS_QUEUE) {
- switch (state) {
- case PLAYING:
- holder.statusPlaying.setVisibility(View.VISIBLE);
- holder.episodeProgress.setVisibility(View.VISIBLE);
- break;
- case IN_PROGRESS:
- holder.statusPlaying.setVisibility(View.GONE);
- holder.episodeProgress.setVisibility(View.VISIBLE);
- break;
- case NEW:
- holder.statusPlaying.setVisibility(View.GONE);
- holder.episodeProgress.setVisibility(View.GONE);
- break;
- default:
- holder.statusPlaying.setVisibility(View.GONE);
- holder.episodeProgress.setVisibility(View.GONE);
- break;
- }
- } else {
- holder.statusPlaying.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});
- final int[] labels = new int[]{R.string.status_downloaded_label, R.string.downloading_label};
- holder.lenSize.setVisibility(View.VISIBLE);
- if (!media.isDownloaded()) {
- if (DownloadRequester.getInstance().isDownloadingFile(media)) {
- holder.downloadStatus.setVisibility(View.VISIBLE);
- holder.downloadStatus.setImageDrawable(drawables
- .getDrawable(1));
- holder.downloadStatus.setContentDescription(context.getString(labels[1]));
- } else {
- holder.downloadStatus.setVisibility(View.INVISIBLE);
- }
- } else {
- holder.downloadStatus.setVisibility(View.VISIBLE);
- holder.downloadStatus
- .setImageDrawable(drawables.getDrawable(0));
- holder.downloadStatus.setContentDescription(context.getString(labels[0]));
- }
- } else {
- holder.downloadStatus.setVisibility(View.INVISIBLE);
- holder.lenSize.setVisibility(View.INVISIBLE);
- }
-
- PicassoProvider.getMediaMetadataPicassoInstance(context)
- .load(item.getImageUri())
- .fit()
- .into(holder.feedImage);
-
- holder.butAction.setFocusable(false);
- holder.butAction.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- feedItemActionCallback.onActionButtonPressed(item);
- }
- });
-
- return convertView;
-
- }
-
- static class Holder {
- TextView title;
- TextView feedTitle;
- TextView lenSize;
- ImageView downloadStatus;
- ImageView feedImage;
- ImageButton butAction;
- View statusPlaying;
- ProgressBar episodeProgress;
- }
-
- @Override
- public int getChildrenCount(int groupPosition) {
- if (groupPosition == GROUP_POS_QUEUE) {
- return itemAccess.getQueueSize();
- } else if (groupPosition == GROUP_POS_UNREAD) {
- return itemAccess.getUnreadItemsSize();
- }
- return 0;
- }
-
- @Override
- public int getGroupCount() {
- // Hide 'unread items' group if empty
- if (itemAccess.getUnreadItemsSize() > 0) {
- return 2;
- } else {
- return 1;
- }
- }
-
- @Override
- public long getGroupId(int groupPosition) {
- return groupPosition;
- }
-
- @Override
- public View getGroupView(final int groupPosition, boolean isExpanded,
- View convertView, ViewGroup parent) {
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- convertView = inflater.inflate(R.layout.feeditemlist_header, parent, false);
- TextView headerTitle = (TextView) convertView
- .findViewById(0);
- ImageButton actionButton = (ImageButton) convertView
- .findViewById(R.id.butAction);
- TextView numItems = (TextView) convertView.findViewById(0);
-
- String headerString = null;
- int childrenCount = 0;
-
- if (groupPosition == 0) {
- headerString = context.getString(R.string.queue_label);
- childrenCount = getChildrenCount(GROUP_POS_QUEUE);
- } else {
- headerString = context.getString(R.string.waiting_list_label);
- childrenCount = getChildrenCount(GROUP_POS_UNREAD);
- }
- headerTitle.setText(headerString);
- if (childrenCount <= 0) {
- numItems.setVisibility(View.INVISIBLE);
- } else {
- numItems.setVisibility(View.VISIBLE);
- numItems.setText(Integer.toString(childrenCount));
- }
- actionButton.setFocusable(false);
- actionButton.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- groupActionCallback.onClick(getGroupId(groupPosition));
- }
- });
- return convertView;
- }
-
- @Override
- public boolean isEmpty() {
- return itemAccess.getUnreadItemsSize() == 0
- && itemAccess.getQueueSize() == 0;
- }
-
- @Override
- public Object getGroup(int groupPosition) {
- return null;
- }
-
- @Override
- public boolean hasStableIds() {
- return true;
- }
-
- @Override
- public boolean isChildSelectable(int groupPosition, int childPosition) {
- return true;
- }
-
- public interface OnGroupActionClicked {
- public void onClick(long groupId);
- }
-
- public static interface ItemAccess {
- public int getQueueSize();
-
- public int getUnreadItemsSize();
-
- public FeedItem getQueueItemAt(int position);
-
- public FeedItem getUnreadItemAt(int position);
- }
-
-}
diff --git a/src/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java b/src/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java
deleted file mode 100644
index 357b5f8b4..000000000
--- a/src/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java
+++ /dev/null
@@ -1,220 +0,0 @@
-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;
-import android.view.ViewGroup;
-import android.widget.*;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.feed.FeedMedia;
-import de.danoeh.antennapod.feed.MediaType;
-import de.danoeh.antennapod.storage.DownloadRequester;
-import de.danoeh.antennapod.util.Converter;
-import de.danoeh.antennapod.util.ThemeUtils;
-
-/**
- * List adapter for items of feeds that the user has already subscribed to.
- */
-public class FeedItemlistAdapter extends BaseAdapter {
-
- private ActionButtonCallback callback;
- private final ItemAccess itemAccess;
- private final Context context;
- private boolean showFeedtitle;
- private int selectedItemIndex;
- private final ActionButtonUtils actionButtonUtils;
-
- public static final int SELECTION_NONE = -1;
-
- public FeedItemlistAdapter(Context context,
- ItemAccess itemAccess,
- ActionButtonCallback callback, boolean showFeedtitle) {
- super();
- this.callback = callback;
- this.context = context;
- this.itemAccess = itemAccess;
- this.showFeedtitle = showFeedtitle;
- this.selectedItemIndex = SELECTION_NONE;
- this.actionButtonUtils = new ActionButtonUtils(context);
- }
-
- @Override
- public int getCount() {
- return itemAccess.getCount();
-
- }
-
- @Override
- public long getItemId(int position) {
- return position;
- }
-
- @Override
- public FeedItem getItem(int position) {
- return itemAccess.getItem(position);
- }
-
- @Override
- public View getView(final int position, View convertView, ViewGroup parent) {
- Holder holder;
- final FeedItem item = getItem(position);
-
- if (convertView == null) {
- holder = new Holder();
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- convertView = inflater.inflate(R.layout.feeditemlist_item, parent, false);
- holder.title = (TextView) convertView
- .findViewById(R.id.txtvItemname);
- holder.lenSize = (TextView) convertView
- .findViewById(R.id.txtvLenSize);
- holder.butAction = (ImageButton) convertView
- .findViewById(R.id.butSecondaryAction);
- holder.published = (TextView) convertView
- .findViewById(R.id.txtvPublished);
- holder.inPlaylist = (ImageView) convertView
- .findViewById(R.id.imgvInPlaylist);
- holder.type = (ImageView) convertView.findViewById(R.id.imgvType);
- holder.statusUnread = (View) convertView
- .findViewById(R.id.statusUnread);
- holder.episodeProgress = (ProgressBar) convertView
- .findViewById(R.id.pbar_episode_progress);
-
- convertView.setTag(holder);
- } else {
- holder = (Holder) convertView.getTag();
- }
- if (!(getItemViewType(position) == Adapter.IGNORE_ITEM_VIEW_TYPE)) {
- convertView.setVisibility(View.VISIBLE);
- if (position == selectedItemIndex) {
- convertView.setBackgroundColor(convertView.getResources()
- .getColor(ThemeUtils.getSelectionBackgroundColor()));
- } else {
- convertView.setBackgroundResource(0);
- }
-
- StringBuilder buffer = new StringBuilder(item.getTitle());
- if (showFeedtitle) {
- buffer.append("(");
- buffer.append(item.getFeed().getTitle());
- buffer.append(")");
- }
- holder.title.setText(buffer.toString());
-
- FeedItem.State state = item.getState();
- switch (state) {
- case PLAYING:
- holder.statusUnread.setVisibility(View.GONE);
- holder.episodeProgress.setVisibility(View.VISIBLE);
- break;
- case IN_PROGRESS:
- holder.statusUnread.setVisibility(View.GONE);
- holder.episodeProgress.setVisibility(View.VISIBLE);
- break;
- case NEW:
- holder.statusUnread.setVisibility(View.VISIBLE);
- break;
- default:
- holder.statusUnread.setVisibility(View.GONE);
- break;
- }
-
- holder.published.setText(DateUtils.formatDateTime(context, item.getPubDate().getTime(), DateUtils.FORMAT_SHOW_DATE));
-
-
- FeedMedia media = item.getMedia();
- if (media == null) {
- holder.episodeProgress.setVisibility(View.GONE);
- holder.inPlaylist.setVisibility(View.INVISIBLE);
- holder.type.setVisibility(View.INVISIBLE);
- holder.lenSize.setVisibility(View.INVISIBLE);
- } else {
-
- AdapterUtils.updateEpisodePlaybackProgress(item, context.getResources(), holder.lenSize, holder.episodeProgress);
-
- if (((ItemAccess) itemAccess).isInQueue(item)) {
- holder.inPlaylist.setVisibility(View.VISIBLE);
- } else {
- holder.inPlaylist.setVisibility(View.INVISIBLE);
- }
-
- if (DownloadRequester.getInstance().isDownloadingFile(
- item.getMedia())) {
- holder.episodeProgress.setVisibility(View.VISIBLE);
- holder.episodeProgress.setProgress(((ItemAccess) itemAccess).getItemDownloadProgressPercent(item));
- }
-
- TypedArray typeDrawables = context.obtainStyledAttributes(
- new int[]{R.attr.type_audio, R.attr.type_video});
- final int[] labels = new int[]{R.string.media_type_audio_label, R.string.media_type_video_label};
-
- MediaType mediaType = item.getMedia().getMediaType();
- if (mediaType == MediaType.AUDIO) {
- holder.type.setImageDrawable(typeDrawables.getDrawable(0));
- holder.type.setContentDescription(context.getString(labels[0]));
- holder.type.setVisibility(View.VISIBLE);
- } else if (mediaType == MediaType.VIDEO) {
- holder.type.setImageDrawable(typeDrawables.getDrawable(1));
- holder.type.setContentDescription(context.getString(labels[1]));
- holder.type.setVisibility(View.VISIBLE);
- } else {
- holder.type.setImageBitmap(null);
- holder.type.setVisibility(View.GONE);
- }
- }
-
- actionButtonUtils.configureActionButton(holder.butAction, item);
- holder.butAction.setFocusable(false);
- holder.butAction.setTag(item);
- holder.butAction.setOnClickListener(butActionListener);
-
- } else {
- convertView.setVisibility(View.GONE);
- }
- return convertView;
-
- }
-
- private final OnClickListener butActionListener = new OnClickListener() {
- @Override
- public void onClick(View v) {
- FeedItem item = (FeedItem) v.getTag();
- callback.onActionButtonPressed(item);
- }
- };
-
- static class Holder {
- TextView title;
- TextView published;
- TextView lenSize;
- ImageView type;
- ImageView inPlaylist;
- ImageButton butAction;
- View statusUnread;
- ProgressBar episodeProgress;
- }
-
- public int getSelectedItemIndex() {
- return selectedItemIndex;
- }
-
- public void setSelectedItemIndex(int selectedItemIndex) {
- this.selectedItemIndex = selectedItemIndex;
- notifyDataSetChanged();
- }
-
- public static interface ItemAccess {
- public boolean isInQueue(FeedItem item);
-
- int getItemDownloadProgressPercent(FeedItem item);
-
- int getCount();
-
- FeedItem getItem(int position);
- }
-
-}
diff --git a/src/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java b/src/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java
deleted file mode 100644
index c2c2285ac..000000000
--- a/src/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package de.danoeh.antennapod.adapter;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.TextView;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.feed.FeedItem;
-
-import java.util.List;
-
-/**
- * List adapter for showing a list of FeedItems with their title and description.
- */
-public class FeedItemlistDescriptionAdapter extends ArrayAdapter<FeedItem> {
-
- public FeedItemlistDescriptionAdapter(Context context, int resource, List<FeedItem> objects) {
- super(context, resource, objects);
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- Holder holder;
-
- FeedItem item = getItem(position);
-
- // Inflate layout
- if (convertView == null) {
- holder = new Holder();
- LayoutInflater inflater = (LayoutInflater) getContext()
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- convertView = inflater.inflate(R.layout.itemdescription_listitem, parent, false);
- holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
- holder.description = (TextView) convertView.findViewById(R.id.txtvDescription);
-
- convertView.setTag(holder);
- } else {
- holder = (Holder) convertView.getTag();
- }
-
- holder.title.setText(item.getTitle());
- if (item.getDescription() != null) {
- holder.description.setText(item.getDescription());
- }
-
- return convertView;
- }
-
- static class Holder {
- TextView title;
- TextView description;
- }
-}
diff --git a/src/de/danoeh/antennapod/adapter/NavListAdapter.java b/src/de/danoeh/antennapod/adapter/NavListAdapter.java
deleted file mode 100644
index ef8e8ce07..000000000
--- a/src/de/danoeh/antennapod/adapter/NavListAdapter.java
+++ /dev/null
@@ -1,229 +0,0 @@
-package de.danoeh.antennapod.adapter;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Typeface;
-import android.graphics.drawable.Drawable;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.ImageView;
-import android.widget.TextView;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.asynctask.PicassoProvider;
-import de.danoeh.antennapod.feed.Feed;
-
-/**
- * BaseAdapter for the navigation drawer
- */
-public class NavListAdapter extends BaseAdapter {
- public static final int VIEW_TYPE_COUNT = 3;
- public static final int VIEW_TYPE_NAV = 0;
- public static final int VIEW_TYPE_SECTION_DIVIDER = 1;
- public static final int VIEW_TYPE_SUBSCRIPTION = 2;
-
- public static final int[] NAV_TITLES = {R.string.all_episodes_label, R.string.queue_label, R.string.downloads_label, R.string.playback_history_label, R.string.add_feed_label};
-
- private final Drawable[] drawables;
-
- public static final int SUBSCRIPTION_OFFSET = 1 + NAV_TITLES.length;
-
- private ItemAccess itemAccess;
- private Context context;
-
- public NavListAdapter(ItemAccess itemAccess, Context context) {
- this.itemAccess = itemAccess;
- this.context = context;
-
- TypedArray ta = context.obtainStyledAttributes(new int[]{R.attr.ic_new, R.attr.stat_playlist,
- R.attr.av_download, R.attr.device_access_time, R.attr.content_new});
- drawables = new Drawable[]{ta.getDrawable(0), ta.getDrawable(1), ta.getDrawable(2),
- ta.getDrawable(3), ta.getDrawable(4)};
- ta.recycle();
- }
-
- @Override
- public int getCount() {
- return NAV_TITLES.length + 1 + itemAccess.getCount();
- }
-
- @Override
- public Object getItem(int position) {
- int viewType = getItemViewType(position);
- if (viewType == VIEW_TYPE_NAV) {
- return context.getString(NAV_TITLES[position]);
- } else if (viewType == VIEW_TYPE_SECTION_DIVIDER) {
- return context.getString(R.string.podcasts_label);
- } else {
- return itemAccess.getItem(position);
- }
- }
-
- @Override
- public long getItemId(int position) {
- return position;
- }
-
- @Override
- public int getItemViewType(int position) {
- if (0 <= position && position < NAV_TITLES.length) {
- return VIEW_TYPE_NAV;
- } else if (position < NAV_TITLES.length + 1) {
- return VIEW_TYPE_SECTION_DIVIDER;
- } else {
- return VIEW_TYPE_SUBSCRIPTION;
- }
- }
-
- @Override
- public int getViewTypeCount() {
- return VIEW_TYPE_COUNT;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- int viewType = getItemViewType(position);
- View v = null;
- if (viewType == VIEW_TYPE_NAV) {
- v = getNavView((String) getItem(position), position, convertView, parent);
- } else if (viewType == VIEW_TYPE_SECTION_DIVIDER) {
- v = getSectionDividerView((String) getItem(position), position, convertView, parent);
- } else {
- v = getFeedView(position - SUBSCRIPTION_OFFSET, convertView, parent);
- }
- if (v != null) {
- TextView txtvTitle = (TextView) v.findViewById(R.id.txtvTitle);
- if (position == itemAccess.getSelectedItemIndex()) {
- txtvTitle.setTypeface(null, Typeface.BOLD);
- } else {
- txtvTitle.setTypeface(null, Typeface.NORMAL);
- }
- }
- return v;
- }
-
- private View getNavView(String title, int position, View convertView, ViewGroup parent) {
- NavHolder holder;
- if (convertView == null) {
- holder = new NavHolder();
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
- convertView = inflater.inflate(R.layout.nav_listitem, parent, false);
-
- holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
- holder.count = (TextView) convertView.findViewById(R.id.txtvCount);
- holder.image = (ImageView) convertView.findViewById(R.id.imgvCover);
- convertView.setTag(holder);
- } else {
- holder = (NavHolder) convertView.getTag();
- }
-
- holder.title.setText(title);
-
- if (NAV_TITLES[position] == R.string.queue_label) {
- int queueSize = itemAccess.getQueueSize();
- if (queueSize > 0) {
- holder.count.setVisibility(View.VISIBLE);
- holder.count.setText(String.valueOf(queueSize));
- } else {
- holder.count.setVisibility(View.GONE);
- }
- } else if (NAV_TITLES[position] == R.string.all_episodes_label) {
- int unreadItems = itemAccess.getNumberOfUnreadItems();
- if (unreadItems > 0) {
- holder.count.setVisibility(View.VISIBLE);
- holder.count.setText(String.valueOf(unreadItems));
- } else {
- holder.count.setVisibility(View.GONE);
- }
- } else {
- holder.count.setVisibility(View.GONE);
- }
-
- holder.image.setImageDrawable(drawables[position]);
-
- return convertView;
- }
-
- private View getSectionDividerView(String title, int position, View convertView, ViewGroup parent) {
- SectionHolder holder;
- if (convertView == null) {
- holder = new SectionHolder();
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
- convertView = inflater.inflate(R.layout.nav_section_item, parent, false);
-
- holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
- convertView.setTag(holder);
- } else {
- holder = (SectionHolder) convertView.getTag();
- }
-
- holder.title.setText(title);
-
- convertView.setEnabled(false);
- convertView.setOnClickListener(null);
-
- return convertView;
- }
-
- private View getFeedView(int feedPos, View convertView, ViewGroup parent) {
- FeedHolder holder;
- Feed feed = itemAccess.getItem(feedPos);
-
- if (convertView == null) {
- holder = new FeedHolder();
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
- convertView = inflater.inflate(R.layout.nav_feedlistitem, parent, false);
-
- holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
- holder.image = (ImageView) convertView.findViewById(R.id.imgvCover);
- convertView.setTag(holder);
- } else {
- holder = (FeedHolder) convertView.getTag();
- }
-
- holder.title.setText(feed.getTitle());
-
- PicassoProvider.getDefaultPicassoInstance(context)
- .load(feed.getImageUri())
- .fit()
- .into(holder.image);
-
- return convertView;
- }
-
- static class NavHolder {
- TextView title;
- TextView count;
- ImageView image;
- }
-
- static class SectionHolder {
- TextView title;
- }
-
- static class FeedHolder {
- TextView title;
- ImageView image;
- }
-
-
- public interface ItemAccess {
- public int getCount();
-
- public Feed getItem(int position);
-
- public int getSelectedItemIndex();
-
- public int getQueueSize();
-
- public int getNumberOfUnreadItems();
- }
-
-}
diff --git a/src/de/danoeh/antennapod/adapter/NewEpisodesListAdapter.java b/src/de/danoeh/antennapod/adapter/NewEpisodesListAdapter.java
deleted file mode 100644
index 8abe49133..000000000
--- a/src/de/danoeh/antennapod/adapter/NewEpisodesListAdapter.java
+++ /dev/null
@@ -1,170 +0,0 @@
-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;
-import android.widget.BaseAdapter;
-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.PicassoProvider;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.feed.FeedMedia;
-import de.danoeh.antennapod.storage.DownloadRequester;
-import de.danoeh.antennapod.util.Converter;
-
-/**
- * List adapter for the list of new episodes
- */
-public class NewEpisodesListAdapter extends BaseAdapter {
-
- private final Context context;
- private final ItemAccess itemAccess;
- private final ActionButtonCallback actionButtonCallback;
- private final ActionButtonUtils actionButtonUtils;
-
- public NewEpisodesListAdapter(Context context, ItemAccess itemAccess, ActionButtonCallback actionButtonCallback) {
- super();
- this.context = context;
- this.itemAccess = itemAccess;
- this.actionButtonUtils = new ActionButtonUtils(context);
- this.actionButtonCallback = actionButtonCallback;
- }
-
- @Override
- public int getCount() {
- return itemAccess.getCount();
- }
-
- @Override
- public Object getItem(int position) {
- return itemAccess.getItem(position);
- }
-
- @Override
- public long getItemId(int position) {
- return position;
- }
-
- @Override
- public int getViewTypeCount() {
- return 1;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- Holder holder;
- final FeedItem item = (FeedItem) getItem(position);
- if (item == null) return null;
-
- if (convertView == null) {
- holder = new Holder();
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- convertView = inflater.inflate(R.layout.new_episodes_listitem,
- parent, false);
- holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
- holder.pubDate = (TextView) convertView
- .findViewById(R.id.txtvPublished);
- holder.statusUnread = convertView.findViewById(R.id.statusUnread);
- holder.butSecondary = (ImageButton) convertView
- .findViewById(R.id.butSecondaryAction);
- holder.queueStatus = (ImageView) convertView
- .findViewById(R.id.imgvInPlaylist);
- holder.downloadProgress = (ProgressBar) convertView
- .findViewById(R.id.pbar_download_progress);
- holder.imageView = (ImageView) convertView.findViewById(R.id.imgvImage);
- holder.txtvDuration = (TextView) convertView.findViewById(R.id.txtvDuration);
- convertView.setTag(holder);
- } else {
- holder = (Holder) convertView.getTag();
- }
-
- holder.title.setText(item.getTitle());
- holder.pubDate.setText(DateUtils.formatDateTime(context, item.getPubDate().getTime(), DateUtils.FORMAT_SHOW_DATE));
- if (item.isRead()) {
- holder.statusUnread.setVisibility(View.GONE);
- } else {
- holder.statusUnread.setVisibility(View.VISIBLE);
- }
-
- FeedMedia media = item.getMedia();
- if (media != null) {
- final boolean isDownloadingMedia = DownloadRequester.getInstance().isDownloadingFile(media);
-
- if (media.getDuration() > 0) {
- holder.txtvDuration.setText(Converter.getDurationStringLong(media.getDuration()));
- } else {
- holder.txtvDuration.setText("");
- }
-
- if (isDownloadingMedia) {
- holder.downloadProgress.setVisibility(View.VISIBLE);
- holder.txtvDuration.setVisibility(View.GONE);
- } else {
- holder.txtvDuration.setVisibility(View.VISIBLE);
- holder.downloadProgress.setVisibility(View.GONE);
- }
-
- if (!media.isDownloaded()) {
- if (isDownloadingMedia) {
- // item is being downloaded
- holder.downloadProgress.setProgress(itemAccess.getItemDownloadProgressPercent(item));
- }
- }
- }
- if (itemAccess.isInQueue(item)) {
- holder.queueStatus.setVisibility(View.VISIBLE);
- } else {
- holder.queueStatus.setVisibility(View.INVISIBLE);
- }
-
- actionButtonUtils.configureActionButton(holder.butSecondary, item);
- holder.butSecondary.setFocusable(false);
- holder.butSecondary.setTag(item);
- holder.butSecondary.setOnClickListener(secondaryActionListener);
-
- PicassoProvider.getMediaMetadataPicassoInstance(context)
- .load(item.getImageUri())
- .fit()
- .into(holder.imageView);
-
- return convertView;
- }
-
- private View.OnClickListener secondaryActionListener = new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- FeedItem item = (FeedItem) v.getTag();
- actionButtonCallback.onActionButtonPressed(item);
- }
- };
-
-
- static class Holder {
- TextView title;
- TextView pubDate;
- View statusUnread;
- ImageView queueStatus;
- ImageView imageView;
- ProgressBar downloadProgress;
- TextView txtvDuration;
- ImageButton butSecondary;
- }
-
- public interface ItemAccess {
-
- int getCount();
-
- FeedItem getItem(int position);
-
- int getItemDownloadProgressPercent(FeedItem item);
-
- boolean isInQueue(FeedItem item);
- }
-}
diff --git a/src/de/danoeh/antennapod/adapter/QueueListAdapter.java b/src/de/danoeh/antennapod/adapter/QueueListAdapter.java
deleted file mode 100644
index ebe519592..000000000
--- a/src/de/danoeh/antennapod/adapter/QueueListAdapter.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package de.danoeh.antennapod.adapter;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.*;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.asynctask.PicassoProvider;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.feed.FeedMedia;
-import de.danoeh.antennapod.storage.DownloadRequester;
-
-/**
- * List adapter for the queue.
- */
-public class QueueListAdapter extends BaseAdapter {
-
-
- private final Context context;
- private final ItemAccess itemAccess;
- private final ActionButtonCallback actionButtonCallback;
- private final ActionButtonUtils actionButtonUtils;
-
-
- public QueueListAdapter(Context context, ItemAccess itemAccess, ActionButtonCallback actionButtonCallback) {
- super();
- this.context = context;
- this.itemAccess = itemAccess;
- this.actionButtonUtils = new ActionButtonUtils(context);
- this.actionButtonCallback = actionButtonCallback;
- }
-
- @Override
- public int getCount() {
- return itemAccess.getCount();
- }
-
- @Override
- public Object getItem(int position) {
- return itemAccess.getItem(position);
- }
-
- @Override
- public long getItemId(int position) {
- return position;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- Holder holder;
- final FeedItem item = (FeedItem) getItem(position);
- if (item == null) return null;
-
- if (convertView == null) {
- holder = new Holder();
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- convertView = inflater.inflate(R.layout.queue_listitem,
- parent, false);
- holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
- holder.butSecondary = (ImageButton) convertView
- .findViewById(R.id.butSecondaryAction);
- holder.position = (TextView) convertView.findViewById(R.id.txtvPosition);
- holder.progress = (ProgressBar) convertView
- .findViewById(R.id.pbar_download_progress);
- holder.imageView = (ImageView) convertView.findViewById(R.id.imgvImage);
- convertView.setTag(holder);
- } else {
- holder = (Holder) convertView.getTag();
- }
-
- holder.title.setText(item.getTitle());
-
- AdapterUtils.updateEpisodePlaybackProgress(item, context.getResources(), holder.position, holder.progress);
-
- FeedMedia media = item.getMedia();
- if (media != null) {
- final boolean isDownloadingMedia = DownloadRequester.getInstance().isDownloadingFile(media);
-
- if (!media.isDownloaded()) {
- if (isDownloadingMedia) {
- // item is being downloaded
- holder.progress.setVisibility(View.VISIBLE);
- holder.progress.setProgress(itemAccess.getItemDownloadProgressPercent(item));
- }
- }
- }
-
- actionButtonUtils.configureActionButton(holder.butSecondary, item);
- holder.butSecondary.setFocusable(false);
- holder.butSecondary.setTag(item);
- holder.butSecondary.setOnClickListener(secondaryActionListener);
-
- PicassoProvider.getMediaMetadataPicassoInstance(context)
- .load(item.getImageUri())
- .fit()
- .into(holder.imageView);
-
- return convertView;
- }
-
- private View.OnClickListener secondaryActionListener = new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- FeedItem item = (FeedItem) v.getTag();
- actionButtonCallback.onActionButtonPressed(item);
- }
- };
-
-
- static class Holder {
- TextView title;
- ImageView imageView;
- TextView position;
- ProgressBar progress;
- ImageButton butSecondary;
- }
-
- public interface ItemAccess {
- int getCount();
-
- FeedItem getItem(int position);
-
- int getItemDownloadProgressPercent(FeedItem item);
- }
-}
diff --git a/src/de/danoeh/antennapod/adapter/SearchlistAdapter.java b/src/de/danoeh/antennapod/adapter/SearchlistAdapter.java
deleted file mode 100644
index 2314c2269..000000000
--- a/src/de/danoeh/antennapod/adapter/SearchlistAdapter.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package de.danoeh.antennapod.adapter;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.asynctask.PicassoProvider;
-import de.danoeh.antennapod.feed.Feed;
-import de.danoeh.antennapod.feed.FeedComponent;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.feed.SearchResult;
-
-/**
- * List adapter for search activity.
- */
-public class SearchlistAdapter extends BaseAdapter {
-
- private final Context context;
- private final ItemAccess itemAccess;
-
-
- public SearchlistAdapter(Context context, ItemAccess itemAccess) {
- this.context = context;
- this.itemAccess = itemAccess;
- }
-
- @Override
- public int getCount() {
- return itemAccess.getCount();
- }
-
- @Override
- public SearchResult getItem(int position) {
- return itemAccess.getItem(position);
- }
-
- @Override
- public long getItemId(int position) {
- return 0;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- final Holder holder;
- SearchResult result = getItem(position);
- FeedComponent component = result.getComponent();
-
- // Inflate Layout
- if (convertView == null) {
- holder = new Holder();
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
- convertView = inflater.inflate(R.layout.searchlist_item, parent, false);
- holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
- holder.cover = (ImageView) convertView
- .findViewById(R.id.imgvFeedimage);
- holder.subtitle = (TextView) convertView
- .findViewById(R.id.txtvSubtitle);
-
- convertView.setTag(holder);
- } else {
- holder = (Holder) convertView.getTag();
- }
- if (component.getClass() == Feed.class) {
- final Feed feed = (Feed) component;
- holder.title.setText(feed.getTitle());
- holder.subtitle.setVisibility(View.GONE);
-
- PicassoProvider.getDefaultPicassoInstance(context)
- .load(feed.getImageUri())
- .fit()
- .into(holder.cover);
-
- } else if (component.getClass() == FeedItem.class) {
- final FeedItem item = (FeedItem) component;
- holder.title.setText(item.getTitle());
- if (result.getSubtitle() != null) {
- holder.subtitle.setVisibility(View.VISIBLE);
- holder.subtitle.setText(result.getSubtitle());
- }
-
- PicassoProvider.getDefaultPicassoInstance(context)
- .load(item.getFeed().getImageUri())
- .fit()
- .into(holder.cover);
-
- }
-
- return convertView;
- }
-
- static class Holder {
- ImageView cover;
- TextView title;
- TextView subtitle;
- }
-
- public static interface ItemAccess {
- int getCount();
-
- SearchResult getItem(int position);
- }
-
-}
diff --git a/src/de/danoeh/antennapod/adapter/gpodnet/PodcastListAdapter.java b/src/de/danoeh/antennapod/adapter/gpodnet/PodcastListAdapter.java
deleted file mode 100644
index f2e78a57e..000000000
--- a/src/de/danoeh/antennapod/adapter/gpodnet/PodcastListAdapter.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package de.danoeh.antennapod.adapter.gpodnet;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import java.util.List;
-
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.asynctask.PicassoProvider;
-import de.danoeh.antennapod.gpoddernet.model.GpodnetPodcast;
-
-/**
- * Adapter for displaying a list of GPodnetPodcast-Objects.
- */
-public class PodcastListAdapter extends ArrayAdapter<GpodnetPodcast> {
-
- public PodcastListAdapter(Context context, int resource, List<GpodnetPodcast> objects) {
- super(context, resource, objects);
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- Holder holder;
-
- GpodnetPodcast podcast = getItem(position);
-
- // Inflate Layout
- if (convertView == null) {
- holder = new Holder();
- LayoutInflater inflater = (LayoutInflater) getContext()
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
- convertView = inflater.inflate(R.layout.gpodnet_podcast_listitem, parent, false);
- holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
- holder.description = (TextView) convertView.findViewById(R.id.txtvDescription);
- holder.image = (ImageView) convertView.findViewById(R.id.imgvCover);
-
- convertView.setTag(holder);
- } else {
- holder = (Holder) convertView.getTag();
- }
-
- holder.title.setText(podcast.getTitle());
- holder.description.setText(podcast.getDescription());
-
- PicassoProvider.getDefaultPicassoInstance(convertView.getContext())
- .load(podcast.getLogoUrl())
- .fit()
- .into(holder.image);
-
- return convertView;
- }
-
- static class Holder {
- TextView title;
- TextView description;
- ImageView image;
- }
-}
diff --git a/src/de/danoeh/antennapod/asynctask/DownloadObserver.java b/src/de/danoeh/antennapod/asynctask/DownloadObserver.java
deleted file mode 100644
index 21ae5291e..000000000
--- a/src/de/danoeh/antennapod/asynctask/DownloadObserver.java
+++ /dev/null
@@ -1,177 +0,0 @@
-package de.danoeh.antennapod.asynctask;
-
-import android.app.Activity;
-import android.content.*;
-import android.os.Handler;
-import android.os.IBinder;
-import android.util.Log;
-
-import org.apache.commons.lang3.Validate;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.service.download.DownloadService;
-import de.danoeh.antennapod.service.download.Downloader;
-
-import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * Provides access to the DownloadService's list of items that are currently being downloaded.
- * The DownloadObserver object should be created in the activity's onCreate() method. resume() and pause()
- * should be called in the activity's onResume() and onPause() methods
- */
-public class DownloadObserver {
- private static final String TAG = "DownloadObserver";
-
- /**
- * Time period between update notifications.
- */
- public static final int WAITING_INTERVAL_MS = 3000;
-
- private volatile Activity activity;
- private final Handler handler;
- private final Callback callback;
-
- private DownloadService downloadService = null;
- private AtomicBoolean mIsBound = new AtomicBoolean(false);
-
- private Thread refresherThread;
- private AtomicBoolean refresherThreadRunning = new AtomicBoolean(false);
-
-
- /**
- * Creates a new download observer.
- *
- * @param activity Used for registering receivers
- * @param handler All callback methods are executed on this handler. The handler MUST run on the GUI thread.
- * @param callback Callback methods for posting content updates
- * @throws java.lang.IllegalArgumentException if one of the arguments is null.
- */
- public DownloadObserver(Activity activity, Handler handler, Callback callback) {
- Validate.notNull(activity);
- Validate.notNull(handler);
- Validate.notNull(callback);
-
- this.activity = activity;
- this.handler = handler;
- this.callback = callback;
- }
-
- public void onResume() {
- if (BuildConfig.DEBUG) Log.d(TAG, "DownloadObserver resumed");
- activity.registerReceiver(contentChangedReceiver, new IntentFilter(DownloadService.ACTION_DOWNLOADS_CONTENT_CHANGED));
- connectToDownloadService();
- }
-
- public void onPause() {
- if (BuildConfig.DEBUG) Log.d(TAG, "DownloadObserver paused");
- try {
- activity.unregisterReceiver(contentChangedReceiver);
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- }
- try {
- activity.unbindService(mConnection);
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- }
- stopRefresher();
- }
-
- private BroadcastReceiver contentChangedReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- // reconnect to DownloadService if connection has been closed
- if (downloadService == null) {
- connectToDownloadService();
- }
- callback.onContentChanged();
- startRefresher();
- }
- };
-
- public interface Callback {
- void onContentChanged();
-
- void onDownloadDataAvailable(List<Downloader> downloaderList);
- }
-
- private void connectToDownloadService() {
- activity.bindService(new Intent(activity, DownloadService.class), mConnection, 0);
- }
-
- private ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceDisconnected(ComponentName className) {
- downloadService = null;
- mIsBound.set(false);
- stopRefresher();
- Log.i(TAG, "Closed connection with DownloadService.");
- }
-
- public void onServiceConnected(ComponentName name, IBinder service) {
- downloadService = ((DownloadService.LocalBinder) service)
- .getService();
- mIsBound.set(true);
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Connection to service established");
- List<Downloader> downloaderList = downloadService.getDownloads();
- if (downloaderList != null && !downloaderList.isEmpty()) {
- callback.onDownloadDataAvailable(downloaderList);
- startRefresher();
- }
- }
- };
-
- private void stopRefresher() {
- if (refresherThread != null) {
- refresherThread.interrupt();
- }
- }
-
- private void startRefresher() {
- if (refresherThread == null || refresherThread.isInterrupted()) {
- refresherThread = new Thread(new RefresherThread());
- refresherThread.start();
- }
- }
-
- private class RefresherThread implements Runnable {
-
- public void run() {
- refresherThreadRunning.set(true);
- while (!Thread.interrupted()) {
- try {
- Thread.sleep(WAITING_INTERVAL_MS);
- } catch (InterruptedException e) {
- Log.d(TAG, "Refresher thread was interrupted");
- }
- if (mIsBound.get()) {
- postUpdate();
- }
- }
- refresherThreadRunning.set(false);
- }
-
- private void postUpdate() {
- handler.post(new Runnable() {
- @Override
- public void run() {
- callback.onContentChanged();
- if (downloadService != null) {
- List<Downloader> downloaderList = downloadService.getDownloads();
- if (downloaderList == null || downloaderList.isEmpty()) {
- Thread.currentThread().interrupt();
- }
- }
- }
- });
- }
- }
-
- public void setActivity(Activity activity) {
- Validate.notNull(activity);
- this.activity = activity;
- }
-
-}
-
diff --git a/src/de/danoeh/antennapod/asynctask/FeedRemover.java b/src/de/danoeh/antennapod/asynctask/FeedRemover.java
deleted file mode 100644
index 0549a4255..000000000
--- a/src/de/danoeh/antennapod/asynctask/FeedRemover.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package de.danoeh.antennapod.asynctask;
-
-import android.annotation.SuppressLint;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnCancelListener;
-import android.os.AsyncTask;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.feed.Feed;
-import de.danoeh.antennapod.storage.DBWriter;
-
-import java.util.concurrent.ExecutionException;
-
-/** Removes a feed in the background. */
-public class FeedRemover extends AsyncTask<Void, Void, Void> {
- Context context;
- ProgressDialog dialog;
- Feed feed;
-
- public FeedRemover(Context context, Feed feed) {
- super();
- this.context = context;
- this.feed = feed;
- }
-
- @Override
- protected Void doInBackground(Void... params) {
- try {
- DBWriter.deleteFeed(context, feed.getId()).get();
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
- return null;
- }
-
- @Override
- protected void onCancelled() {
- dialog.dismiss();
- }
-
- @Override
- protected void onPostExecute(Void result) {
- dialog.dismiss();
- }
-
- @Override
- protected void onPreExecute() {
- dialog = new ProgressDialog(context);
- dialog.setMessage(context.getString(R.string.feed_remover_msg));
- dialog.setOnCancelListener(new OnCancelListener() {
-
- @Override
- public void onCancel(DialogInterface dialog) {
- cancel(true);
-
- }
-
- });
- dialog.show();
- }
-
- @SuppressLint("NewApi")
- public void executeAsync() {
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- } else {
- execute();
- }
- }
-
-}
diff --git a/src/de/danoeh/antennapod/asynctask/FlattrClickWorker.java b/src/de/danoeh/antennapod/asynctask/FlattrClickWorker.java
deleted file mode 100644
index 9210ac1d1..000000000
--- a/src/de/danoeh/antennapod/asynctask/FlattrClickWorker.java
+++ /dev/null
@@ -1,238 +0,0 @@
-package de.danoeh.antennapod.asynctask;
-
-import android.annotation.TargetApi;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.os.AsyncTask;
-import android.support.v4.app.NotificationCompat;
-import android.util.Log;
-import android.widget.Toast;
-
-import org.apache.commons.lang3.Validate;
-import org.shredzone.flattr4j.exception.FlattrException;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.FlattrAuthActivity;
-import de.danoeh.antennapod.activity.MainActivity;
-import de.danoeh.antennapod.storage.DBReader;
-import de.danoeh.antennapod.storage.DBWriter;
-import de.danoeh.antennapod.util.NetworkUtils;
-import de.danoeh.antennapod.util.flattr.FlattrThing;
-import de.danoeh.antennapod.util.flattr.FlattrUtils;
-
-/**
- * Performs a click action in a background thread.
- * <p/>
- * When started, the flattr click worker will try to flattr every item that is in the flattr queue. If no network
- * connection is available it will shut down immediately. The FlattrClickWorker can also be given one additional
- * FlattrThing which will be flattrd immediately.
- * <p/>
- * The FlattrClickWorker will display a toast notification for every item that has been flattrd. If the FlattrClickWorker failed
- * to flattr something, a notification will be displayed.
- */
-public class FlattrClickWorker extends AsyncTask<Void, Integer, FlattrClickWorker.ExitCode> {
- protected static final String TAG = "FlattrClickWorker";
-
- private static final int NOTIFICATION_ID = 4;
-
- private final Context context;
-
- public static enum ExitCode {EXIT_NORMAL, NO_TOKEN, NO_NETWORK, NO_THINGS}
-
- private volatile int countFailed = 0;
- private volatile int countSuccess = 0;
-
- private volatile FlattrThing extraFlattrThing;
-
- /**
- * Only relevant if just one thing is flattrd
- */
- private volatile FlattrException exception;
-
- /**
- * Creates a new FlattrClickWorker which will only flattr all things in the queue.
- * <p/>
- * The FlattrClickWorker has to be started by calling executeAsync().
- *
- * @param context A context for accessing the database and posting notifications. Must not be null.
- */
- public FlattrClickWorker(Context context) {
- Validate.notNull(context);
- this.context = context.getApplicationContext();
- }
-
- /**
- * Creates a new FlattrClickWorker which will flattr all things in the queue and one additional
- * FlattrThing.
- * <p/>
- * The FlattrClickWorker has to be started by calling executeAsync().
- *
- * @param context A context for accessing the database and posting notifications. Must not be null.
- * @param extraFlattrThing The additional thing to flattr
- */
- public FlattrClickWorker(Context context, FlattrThing extraFlattrThing) {
- this(context);
- this.extraFlattrThing = extraFlattrThing;
- }
-
-
- @Override
- protected ExitCode doInBackground(Void... params) {
-
- if (!FlattrUtils.hasToken()) {
- return ExitCode.NO_TOKEN;
- }
-
- if (!NetworkUtils.networkAvailable(context)) {
- return ExitCode.NO_NETWORK;
- }
-
- final List<FlattrThing> flattrQueue = DBReader.getFlattrQueue(context);
- if (extraFlattrThing != null) {
- flattrQueue.add(extraFlattrThing);
- } else if (flattrQueue.size() == 1) {
- // if only one item is flattrd, the report can specifically mentioned that this item has failed
- extraFlattrThing = flattrQueue.get(0);
- }
-
- if (flattrQueue.isEmpty()) {
- return ExitCode.NO_THINGS;
- }
-
- List<Future> dbFutures = new LinkedList<Future>();
- for (FlattrThing thing : flattrQueue) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Processing " + thing.getTitle());
-
- try {
- thing.getFlattrStatus().setUnflattred(); // pop from queue to prevent unflattrable things from getting stuck in flattr queue infinitely
- FlattrUtils.clickUrl(context, thing.getPaymentLink());
- thing.getFlattrStatus().setFlattred();
- publishProgress(R.string.flattr_click_success);
- countSuccess++;
-
- } catch (FlattrException e) {
- e.printStackTrace();
- countFailed++;
- if (countFailed == 1) {
- exception = e;
- }
- }
-
- Future<?> f = DBWriter.setFlattredStatus(context, thing, false);
- if (f != null) {
- dbFutures.add(f);
- }
- }
-
- for (Future f : dbFutures) {
- try {
- f.get();
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
- }
-
- return ExitCode.EXIT_NORMAL;
- }
-
- @Override
- protected void onPostExecute(ExitCode exitCode) {
- super.onPostExecute(exitCode);
- switch (exitCode) {
- case EXIT_NORMAL:
- if (countFailed > 0) {
- postFlattrFailedNotification();
- }
- break;
- case NO_NETWORK:
- postToastNotification(R.string.flattr_click_enqueued);
- break;
- case NO_TOKEN:
- postNoTokenNotification();
- break;
- case NO_THINGS: // nothing to notify here
- break;
- }
- }
-
- @Override
- protected void onProgressUpdate(Integer... values) {
- super.onProgressUpdate(values);
- postToastNotification(values[0]);
- }
-
- private void postToastNotification(int msg) {
- Toast.makeText(context, context.getString(msg), Toast.LENGTH_LONG).show();
- }
-
- private void postNoTokenNotification() {
- PendingIntent contentIntent = PendingIntent.getActivity(context, 0, new Intent(context, FlattrAuthActivity.class), 0);
-
- Notification notification = new NotificationCompat.Builder(context)
- .setStyle(new NotificationCompat.BigTextStyle().bigText(context.getString(R.string.no_flattr_token_notification_msg)))
- .setContentIntent(contentIntent)
- .setContentTitle(context.getString(R.string.no_flattr_token_title))
- .setTicker(context.getString(R.string.no_flattr_token_title))
- .setSmallIcon(R.drawable.stat_notify_sync_error)
- .setOngoing(false)
- .setAutoCancel(true)
- .build();
- ((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE)).notify(NOTIFICATION_ID, notification);
- }
-
- private void postFlattrFailedNotification() {
- if (countFailed == 0) {
- return;
- }
-
- PendingIntent contentIntent = PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class), 0);
- String title;
- String subtext;
-
- if (countFailed == 1) {
- title = context.getString(R.string.flattrd_failed_label);
- String exceptionMsg = (exception.getMessage() != null) ? exception.getMessage() : "";
- subtext = context.getString(R.string.flattr_click_failure, extraFlattrThing.getTitle())
- + "\n" + exceptionMsg;
- } else {
- title = context.getString(R.string.flattrd_label);
- subtext = context.getString(R.string.flattr_click_success_count, countSuccess) + "\n"
- + context.getString(R.string.flattr_click_failure_count, countFailed);
- }
-
- Notification notification = new NotificationCompat.Builder(context)
- .setStyle(new NotificationCompat.BigTextStyle().bigText(subtext))
- .setContentIntent(contentIntent)
- .setContentTitle(title)
- .setTicker(title)
- .setSmallIcon(R.drawable.stat_notify_sync_error)
- .setOngoing(false)
- .setAutoCancel(true)
- .build();
- ((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE)).notify(NOTIFICATION_ID, notification);
- }
-
-
- /**
- * Starts the FlattrClickWorker as an AsyncTask.
- */
- @TargetApi(11)
- public void executeAsync() {
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- } else {
- execute();
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/asynctask/FlattrStatusFetcher.java b/src/de/danoeh/antennapod/asynctask/FlattrStatusFetcher.java
deleted file mode 100644
index 04d349671..000000000
--- a/src/de/danoeh/antennapod/asynctask/FlattrStatusFetcher.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package de.danoeh.antennapod.asynctask;
-
-import android.content.Context;
-import android.util.Log;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.storage.DBWriter;
-import de.danoeh.antennapod.util.flattr.FlattrUtils;
-import org.shredzone.flattr4j.exception.FlattrException;
-import org.shredzone.flattr4j.model.Flattr;
-
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-
-/**
- * Fetch list of flattred things and flattr status in database in a background thread.
- */
-
-public class FlattrStatusFetcher extends Thread {
- protected static final String TAG = "FlattrStatusFetcher";
- protected Context context;
-
- public FlattrStatusFetcher(Context context) {
- super();
- this.context = context;
- }
-
- @Override
- public void run() {
- if (BuildConfig.DEBUG) Log.d(TAG, "Starting background work: Retrieving Flattr status");
-
- Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
-
- try {
- List<Flattr> flattredThings = FlattrUtils.retrieveFlattredThings();
- DBWriter.setFlattredStatus(context, flattredThings).get();
- } catch (FlattrException e) {
- e.printStackTrace();
- Log.d(TAG, "flattrQueue exception retrieving list with flattred items " + e.getMessage());
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
-
- if (BuildConfig.DEBUG) Log.d(TAG, "Finished background work: Retrieved Flattr status");
- }
-}
diff --git a/src/de/danoeh/antennapod/asynctask/FlattrTokenFetcher.java b/src/de/danoeh/antennapod/asynctask/FlattrTokenFetcher.java
deleted file mode 100644
index 0dcf832f7..000000000
--- a/src/de/danoeh/antennapod/asynctask/FlattrTokenFetcher.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package de.danoeh.antennapod.asynctask;
-
-
-import android.annotation.SuppressLint;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.util.Log;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.FlattrAuthActivity;
-import de.danoeh.antennapod.util.flattr.FlattrUtils;
-import org.shredzone.flattr4j.exception.FlattrException;
-import org.shredzone.flattr4j.oauth.AccessToken;
-import org.shredzone.flattr4j.oauth.AndroidAuthenticator;
-
-/** Fetches the access token in the background in order to avoid networkOnMainThread exception. */
-
-public class FlattrTokenFetcher extends AsyncTask<Void, Void, AccessToken> {
- private static final String TAG = "FlattrTokenFetcher";
- Context context;
- AndroidAuthenticator auth;
- AccessToken token;
- Uri uri;
- ProgressDialog dialog;
- FlattrException exception;
-
- public FlattrTokenFetcher(Context context, AndroidAuthenticator auth, Uri uri) {
- super();
- this.context = context;
- this.auth = auth;
- this.uri = uri;
- }
-
- @Override
- protected void onPostExecute(AccessToken result) {
- if (result != null) {
- FlattrUtils.storeToken(result);
- }
- dialog.dismiss();
- if (exception == null) {
- FlattrAuthActivity instance = FlattrAuthActivity.getInstance();
- if (instance != null) {
- instance.handleAuthenticationSuccess();
- } else {
- Log.e(TAG, "FlattrAuthActivity instance was null");
- }
- } else {
- FlattrUtils.showErrorDialog(context, exception.getMessage());
- }
- }
-
-
-
- @Override
- protected void onPreExecute() {
- super.onPreExecute();
- dialog = new ProgressDialog(context);
- dialog.setMessage(context.getString(R.string.processing_label));
- dialog.setIndeterminate(true);
- dialog.setCancelable(false);
- dialog.show();
- }
-
-
-
- @Override
- protected AccessToken doInBackground(Void... params) {
- try {
- token = auth.fetchAccessToken(uri);
- } catch (FlattrException e) {
- e.printStackTrace();
- exception = e;
- return null;
- }
- if (token != null) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Successfully got token");
- return token;
- } else {
- Log.w(TAG, "Flattr token was null");
- return null;
- }
- }
-
- @SuppressLint("NewApi")
- public void executeAsync() {
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- } else {
- execute();
- }
- }
-
-}
diff --git a/src/de/danoeh/antennapod/asynctask/OpmlExportWorker.java b/src/de/danoeh/antennapod/asynctask/OpmlExportWorker.java
deleted file mode 100644
index 4abb1a67d..000000000
--- a/src/de/danoeh/antennapod/asynctask/OpmlExportWorker.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package de.danoeh.antennapod.asynctask;
-
-import android.annotation.SuppressLint;
-import android.app.AlertDialog;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.os.AsyncTask;
-import android.util.Log;
-import de.danoeh.antennapod.PodcastApp;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.opml.OpmlWriter;
-import de.danoeh.antennapod.preferences.UserPreferences;
-import de.danoeh.antennapod.storage.DBReader;
-import de.danoeh.antennapod.util.LangUtils;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-
-/** Writes an OPML file into the export directory in the background. */
-public class OpmlExportWorker extends AsyncTask<Void, Void, Void> {
- private static final String TAG = "OpmlExportWorker";
- private static final String DEFAULT_OUTPUT_NAME = "antennapod-feeds.opml";
- private Context context;
- private File output;
-
- private ProgressDialog progDialog;
- private Exception exception;
-
- public OpmlExportWorker(Context context, File output) {
- this.context = context;
- this.output = output;
- }
-
- public OpmlExportWorker(Context context) {
- this.context = context;
- }
-
- @Override
- protected Void doInBackground(Void... params) {
- OpmlWriter opmlWriter = new OpmlWriter();
- if (output == null) {
- output = new File(
- UserPreferences.getDataFolder(context, PodcastApp.EXPORT_DIR),
- DEFAULT_OUTPUT_NAME);
- if (output.exists()) {
- Log.w(TAG, "Overwriting previously exported file.");
- output.delete();
- }
- }
- OutputStreamWriter writer = null;
- try {
- writer = new OutputStreamWriter(new FileOutputStream(output), LangUtils.UTF_8);
- opmlWriter.writeDocument(DBReader.getFeedList(context), writer);
- } catch (IOException e) {
- e.printStackTrace();
- exception = e;
- } finally {
- if (writer != null) {
- try {
- writer.close();
- } catch (IOException ioe) {
- exception = ioe;
- }
- }
- }
- return null;
- }
-
- @Override
- protected void onPostExecute(Void result) {
- progDialog.dismiss();
- AlertDialog.Builder alert = new AlertDialog.Builder(context)
- .setNeutralButton(android.R.string.ok,
- new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog,
- int which) {
- dialog.dismiss();
- }
- });
- if (exception != null) {
- alert.setTitle(R.string.export_error_label);
- alert.setMessage(exception.getMessage());
- } else {
- alert.setTitle(R.string.opml_export_success_title);
- alert.setMessage(context
- .getString(R.string.opml_export_success_sum)
- + output.toString());
- }
- alert.create().show();
- }
-
- @Override
- protected void onPreExecute() {
- progDialog = new ProgressDialog(context);
- progDialog.setMessage(context.getString(R.string.exporting_label));
- progDialog.setIndeterminate(true);
- progDialog.show();
- }
-
- @SuppressLint("NewApi")
- public void executeAsync() {
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- executeOnExecutor(THREAD_POOL_EXECUTOR);
- } else {
- execute();
- }
- }
-
-}
diff --git a/src/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java b/src/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java
deleted file mode 100644
index 038b8dcc5..000000000
--- a/src/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package de.danoeh.antennapod.asynctask;
-
-import android.annotation.SuppressLint;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.os.AsyncTask;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.OpmlImportHolder;
-import de.danoeh.antennapod.feed.Feed;
-import de.danoeh.antennapod.opml.OpmlElement;
-import de.danoeh.antennapod.storage.DownloadRequestException;
-import de.danoeh.antennapod.storage.DownloadRequester;
-
-import java.util.Arrays;
-import java.util.Date;
-
-/** Queues items for download in the background. */
-public class OpmlFeedQueuer extends AsyncTask<Void, Void, Void> {
- private Context context;
- private ProgressDialog progDialog;
- private int[] selection;
-
- public OpmlFeedQueuer(Context context, int[] selection) {
- super();
- this.context = context;
- this.selection = Arrays.copyOf(selection, selection.length);
- }
-
- @Override
- protected void onPostExecute(Void result) {
- progDialog.dismiss();
- }
-
- @Override
- protected void onPreExecute() {
- progDialog = new ProgressDialog(context);
- progDialog.setMessage(context.getString(R.string.processing_label));
- progDialog.setCancelable(false);
- progDialog.setIndeterminate(true);
- progDialog.show();
- }
-
- @Override
- protected Void doInBackground(Void... params) {
- DownloadRequester requester = DownloadRequester.getInstance();
- for (int idx = 0; idx < selection.length; idx++) {
- OpmlElement element = OpmlImportHolder.getReadElements().get(
- selection[idx]);
- Feed feed = new Feed(element.getXmlUrl(), new Date(),
- element.getText());
- try {
- requester.downloadFeed(context.getApplicationContext(), feed);
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- }
- }
- return null;
- }
-
- @SuppressLint("NewApi")
- public void executeAsync() {
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- executeOnExecutor(THREAD_POOL_EXECUTOR);
- } else {
- execute();
- }
- }
-
-}
diff --git a/src/de/danoeh/antennapod/asynctask/OpmlImportWorker.java b/src/de/danoeh/antennapod/asynctask/OpmlImportWorker.java
deleted file mode 100644
index 13534fa64..000000000
--- a/src/de/danoeh/antennapod/asynctask/OpmlImportWorker.java
+++ /dev/null
@@ -1,116 +0,0 @@
-package de.danoeh.antennapod.asynctask;
-
-import android.annotation.SuppressLint;
-import android.app.AlertDialog;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
-import android.os.AsyncTask;
-import android.util.Log;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.opml.OpmlElement;
-import de.danoeh.antennapod.opml.OpmlReader;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.io.Reader;
-import java.util.ArrayList;
-
-public class OpmlImportWorker extends
- AsyncTask<Void, Void, ArrayList<OpmlElement>> {
- private static final String TAG = "OpmlImportWorker";
-
- private Context context;
- private Exception exception;
-
- private ProgressDialog progDialog;
-
- private Reader mReader;
-
- public OpmlImportWorker(Context context, Reader reader) {
- super();
- this.context = context;
- this.mReader=reader;
- }
-
- @Override
- protected ArrayList<OpmlElement> doInBackground(Void... params) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Starting background work");
-
- if (mReader==null) {
- return null;
- }
-
- OpmlReader opmlReader = new OpmlReader();
- try {
- ArrayList<OpmlElement> result = opmlReader.readDocument(mReader);
- mReader.close();
- return result;
- } catch (XmlPullParserException e) {
- e.printStackTrace();
- exception = e;
- return null;
- } catch (IOException e) {
- e.printStackTrace();
- exception = e;
- return null;
- }
-
- }
-
- @Override
- protected void onPostExecute(ArrayList<OpmlElement> result) {
- if (mReader != null) {
- try {
- mReader.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- progDialog.dismiss();
- if (exception != null) {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "An error occured while trying to parse the opml document");
- AlertDialog.Builder alert = new AlertDialog.Builder(context);
- alert.setTitle(R.string.error_label);
- alert.setMessage(context.getString(R.string.opml_reader_error)
- + exception.getMessage());
- alert.setNeutralButton(android.R.string.ok, new OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- }
-
- });
- alert.create().show();
- }
- }
-
- @Override
- protected void onPreExecute() {
- progDialog = new ProgressDialog(context);
- progDialog.setMessage(context.getString(R.string.reading_opml_label));
- progDialog.setIndeterminate(true);
- progDialog.setCancelable(false);
- progDialog.show();
- }
-
- public boolean wasSuccessful() {
- return exception != null;
- }
-
- @SuppressLint("NewApi")
- public void executeAsync() {
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- executeOnExecutor(THREAD_POOL_EXECUTOR);
- } else {
- execute();
- }
- }
-
-}
diff --git a/src/de/danoeh/antennapod/asynctask/PicassoImageResource.java b/src/de/danoeh/antennapod/asynctask/PicassoImageResource.java
deleted file mode 100644
index 26f9d9278..000000000
--- a/src/de/danoeh/antennapod/asynctask/PicassoImageResource.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package de.danoeh.antennapod.asynctask;
-
-import android.net.Uri;
-
-/**
- * Classes that implement this interface provide access to an image resource that can
- * be loaded by the Picasso library.
- */
-public interface PicassoImageResource {
-
- /**
- * This scheme should be used by PicassoImageResources to
- * indicate that the image Uri points to a file that is not an image
- * (e.g. a media file). This workaround is needed so that the Picasso library
- * loads these Uri with a Downloader instead of trying to load it directly.
- * <p/>
- * For example implementations, see FeedMedia or ExternalMedia.
- */
- public static final String SCHEME_MEDIA = "media";
-
-
- /**
- * Parameter key for an encoded fallback Uri. This Uri MUST point to a local image file
- */
- public static final String PARAM_FALLBACK = "fallback";
-
- /**
- * Returns a Uri to the image or null if no image is available.
- * <p/>
- * The Uri can either be an HTTP-URL, a URL pointing to a local image file or
- * a non-image file (see SCHEME_MEDIA for more details).
- * <p/>
- * The Uri can also have an optional fallback-URL if loading the default URL
- * failed (see PARAM_FALLBACK).
- */
- public Uri getImageUri();
-}
diff --git a/src/de/danoeh/antennapod/asynctask/PicassoProvider.java b/src/de/danoeh/antennapod/asynctask/PicassoProvider.java
deleted file mode 100644
index 849725630..000000000
--- a/src/de/danoeh/antennapod/asynctask/PicassoProvider.java
+++ /dev/null
@@ -1,152 +0,0 @@
-package de.danoeh.antennapod.asynctask;
-
-import android.content.Context;
-import android.media.MediaMetadataRetriever;
-import android.net.Uri;
-import android.util.Log;
-import android.webkit.MimeTypeMap;
-
-import com.squareup.picasso.Cache;
-import com.squareup.picasso.Downloader;
-import com.squareup.picasso.LruCache;
-import com.squareup.picasso.OkHttpDownloader;
-import com.squareup.picasso.Picasso;
-
-import org.apache.commons.io.FilenameUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.Validate;
-
-import java.io.BufferedInputStream;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-/**
- * Provides access to Picasso instances.
- */
-public class PicassoProvider {
- private static final String TAG = "PicassoProvider";
-
- private static final boolean DEBUG = false;
-
- private static ExecutorService executorService;
- private static Cache memoryCache;
-
- private static Picasso defaultPicassoInstance;
- private static Picasso mediaMetadataPicassoInstance;
-
- private static synchronized ExecutorService getExecutorService() {
- if (executorService == null) {
- executorService = Executors.newFixedThreadPool(3);
- }
- return executorService;
- }
-
- private static synchronized Cache getMemoryCache(Context context) {
- if (memoryCache == null) {
- memoryCache = new LruCache(context);
- }
- return memoryCache;
- }
-
- /**
- * Returns a Picasso instance that uses an OkHttpDownloader. This instance can only load images
- * from image files.
- * <p/>
- * This instance should be used as long as no images from media files are loaded.
- */
- public static synchronized Picasso getDefaultPicassoInstance(Context context) {
- Validate.notNull(context);
- if (defaultPicassoInstance == null) {
- defaultPicassoInstance = new Picasso.Builder(context)
- .indicatorsEnabled(DEBUG)
- .loggingEnabled(DEBUG)
- .downloader(new OkHttpDownloader(context))
- .executor(getExecutorService())
- .memoryCache(getMemoryCache(context))
- .listener(new Picasso.Listener() {
- @Override
- public void onImageLoadFailed(Picasso picasso, Uri uri, Exception e) {
- Log.e(TAG, "Failed to load Uri:" + uri.toString());
- e.printStackTrace();
- }
- })
- .build();
- }
- return defaultPicassoInstance;
- }
-
- /**
- * Returns a Picasso instance that uses a MediaMetadataRetriever if the given Uri is a media file
- * and a default OkHttpDownloader otherwise.
- */
- public static synchronized Picasso getMediaMetadataPicassoInstance(Context context) {
- Validate.notNull(context);
- if (mediaMetadataPicassoInstance == null) {
- mediaMetadataPicassoInstance = new Picasso.Builder(context)
- .indicatorsEnabled(DEBUG)
- .loggingEnabled(DEBUG)
- .downloader(new MediaMetadataDownloader(context))
- .executor(getExecutorService())
- .memoryCache(getMemoryCache(context))
- .listener(new Picasso.Listener() {
- @Override
- public void onImageLoadFailed(Picasso picasso, Uri uri, Exception e) {
- Log.e(TAG, "Failed to load Uri:" + uri.toString());
- e.printStackTrace();
- }
- })
- .build();
- }
- return mediaMetadataPicassoInstance;
- }
-
- private static class MediaMetadataDownloader implements Downloader {
-
- private static final String TAG = "MediaMetadataDownloader";
-
- private final OkHttpDownloader okHttpDownloader;
-
- public MediaMetadataDownloader(Context context) {
- Validate.notNull(context);
- okHttpDownloader = new OkHttpDownloader(context);
- }
-
- @Override
- public Response load(Uri uri, boolean b) throws IOException {
- if (StringUtils.equals(uri.getScheme(), PicassoImageResource.SCHEME_MEDIA)) {
- String type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(FilenameUtils.getExtension(uri.getLastPathSegment()));
- if (StringUtils.startsWith(type, "image")) {
- File imageFile = new File(uri.toString());
- return new Response(new BufferedInputStream(new FileInputStream(imageFile)), true, imageFile.length());
- } else {
- MediaMetadataRetriever mmr = new MediaMetadataRetriever();
- mmr.setDataSource(uri.getPath());
- byte[] data = mmr.getEmbeddedPicture();
- mmr.release();
-
- if (data != null) {
- return new Response(new ByteArrayInputStream(data), true, data.length);
- } else {
-
- // check for fallback Uri
- String fallbackParam = uri.getQueryParameter(PicassoImageResource.PARAM_FALLBACK);
-
- if (fallbackParam != null) {
- String fallback = Uri.decode(Uri.parse(fallbackParam).getPath());
- if (fallback != null) {
- File imageFile = new File(fallback);
- return new Response(new BufferedInputStream(new FileInputStream(imageFile)), true, imageFile.length());
- }
- }
- return null;
- }
- }
- }
- return okHttpDownloader.load(uri, b);
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/backup/OpmlBackupAgent.java b/src/de/danoeh/antennapod/backup/OpmlBackupAgent.java
deleted file mode 100644
index 56d1ca092..000000000
--- a/src/de/danoeh/antennapod/backup/OpmlBackupAgent.java
+++ /dev/null
@@ -1,212 +0,0 @@
-package de.danoeh.antennapod.backup;
-
-import android.app.backup.BackupAgentHelper;
-import android.app.backup.BackupDataInputStream;
-import android.app.backup.BackupDataOutput;
-import android.app.backup.BackupHelper;
-import android.content.Context;
-import android.os.ParcelFileDescriptor;
-import android.util.Log;
-
-import de.danoeh.antennapod.BuildConfig;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.ByteArrayOutputStream;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.Reader;
-import java.io.Writer;
-import java.math.BigInteger;
-import java.security.DigestInputStream;
-import java.security.DigestOutputStream;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-
-import de.danoeh.antennapod.AppConfig;
-import de.danoeh.antennapod.feed.Feed;
-import de.danoeh.antennapod.opml.OpmlElement;
-import de.danoeh.antennapod.opml.OpmlReader;
-import de.danoeh.antennapod.opml.OpmlWriter;
-import de.danoeh.antennapod.storage.DBReader;
-import de.danoeh.antennapod.storage.DownloadRequestException;
-import de.danoeh.antennapod.storage.DownloadRequester;
-import de.danoeh.antennapod.util.LangUtils;
-
-public class OpmlBackupAgent extends BackupAgentHelper {
- private static final String OPML_BACKUP_KEY = "opml";
-
- @Override
- public void onCreate() {
- addHelper(OPML_BACKUP_KEY, new OpmlBackupHelper(this));
- }
-
- private static final void LOGD(String tag, String msg) {
- if (BuildConfig.DEBUG && Log.isLoggable(tag, Log.DEBUG)) {
- Log.d(tag, msg);
- }
- }
-
- private static final void LOGD(String tag, String msg, Throwable tr) {
- if (BuildConfig.DEBUG && Log.isLoggable(tag, Log.DEBUG)) {
- Log.d(tag, msg, tr);
- }
- }
-
- /** Class for backing up and restoring the OPML file. */
- private static class OpmlBackupHelper implements BackupHelper {
- private static final String TAG = "OpmlBackupHelper";
-
- private static final String OPML_ENTITY_KEY = "antennapod-feeds.opml";
-
- private final Context mContext;
-
- /** Checksum of restored OPML file */
- private byte[] mChecksum;
-
- public OpmlBackupHelper(Context context) {
- mContext = context;
- }
-
- @Override
- public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) {
- Log.d(TAG, "Performing backup");
- ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
- MessageDigest digester = null;
- Writer writer;
-
- try {
- digester = MessageDigest.getInstance("MD5");
- writer = new OutputStreamWriter(new DigestOutputStream(byteStream, digester),
- LangUtils.UTF_8);
- } catch (NoSuchAlgorithmException e) {
- writer = new OutputStreamWriter(byteStream, LangUtils.UTF_8);
- }
-
- try {
- // Write OPML
- new OpmlWriter().writeDocument(DBReader.getFeedList(mContext), writer);
-
- // Compare checksum of new and old file to see if we need to perform a backup at all
- if (digester != null) {
- byte[] newChecksum = digester.digest();
- LOGD(TAG, "New checksum: " + new BigInteger(1, newChecksum).toString(16));
-
- // Get the old checksum
- if (oldState != null) {
- FileInputStream inState = new FileInputStream(oldState.getFileDescriptor());
- int len = inState.read();
-
- if (len != -1) {
- byte[] oldChecksum = new byte[len];
- inState.read(oldChecksum);
- LOGD(TAG, "Old checksum: " + new BigInteger(1, oldChecksum).toString(16));
-
- if (Arrays.equals(oldChecksum, newChecksum)) {
- LOGD(TAG, "Checksums are the same; won't backup");
- return;
- }
- }
- }
-
- writeNewStateDescription(newState, newChecksum);
- }
-
- LOGD(TAG, "Backing up OPML");
- byte[] bytes = byteStream.toByteArray();
- data.writeEntityHeader(OPML_ENTITY_KEY, bytes.length);
- data.writeEntityData(bytes, bytes.length);
- } catch (IOException e) {
- Log.e(TAG, "Error during backup", e);
- } finally {
- if (writer != null) {
- try {
- writer.close();
- } catch (IOException e) {
- }
- }
- }
- }
-
- @Override
- public void restoreEntity(BackupDataInputStream data) {
- LOGD(TAG, "Backup restore");
-
- if (!OPML_ENTITY_KEY.equals(data.getKey())) {
- LOGD(TAG, "Unknown entity key: " + data.getKey());
- return;
- }
-
- MessageDigest digester = null;
- Reader reader;
-
- try {
- digester = MessageDigest.getInstance("MD5");
- reader = new InputStreamReader(new DigestInputStream(data, digester),
- LangUtils.UTF_8);
- } catch (NoSuchAlgorithmException e) {
- reader = new InputStreamReader(data, LangUtils.UTF_8);
- }
-
- try {
- ArrayList<OpmlElement> opmlElements = new OpmlReader().readDocument(reader);
- mChecksum = digester == null ? null : digester.digest();
- DownloadRequester downloader = DownloadRequester.getInstance();
- Date lastUpdated = new Date();
-
- for (OpmlElement opmlElem : opmlElements) {
- Feed feed = new Feed(opmlElem.getXmlUrl(), lastUpdated, opmlElem.getText());
-
- try {
- downloader.downloadFeed(mContext, feed);
- } catch (DownloadRequestException e) {
- LOGD(TAG, "Error while restoring/downloading feed", e);
- }
- }
- } catch (XmlPullParserException e) {
- Log.e(TAG, "Error while parsing the OPML file", e);
- } catch (IOException e) {
- Log.e(TAG, "Failed to restore OPML backup", e);
- } finally {
- if (reader != null) {
- try {
- reader.close();
- } catch (IOException e) {
- }
- }
- }
- }
-
- @Override
- public void writeNewStateDescription(ParcelFileDescriptor newState) {
- writeNewStateDescription(newState, mChecksum);
- }
-
- /**
- * Writes the new state description, which is the checksum of the OPML file.
- *
- * @param newState
- * @param checksum
- */
- private void writeNewStateDescription(ParcelFileDescriptor newState, byte[] checksum) {
- if (checksum == null) {
- return;
- }
-
- try {
- FileOutputStream outState = new FileOutputStream(newState.getFileDescriptor());
- outState.write(checksum.length);
- outState.write(checksum);
- outState.flush();
- outState.close();
- } catch (IOException e) {
- Log.e(TAG, "Failed to write new state description", e);
- }
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/dialog/AuthenticationDialog.java b/src/de/danoeh/antennapod/dialog/AuthenticationDialog.java
deleted file mode 100644
index bdb2d68ba..000000000
--- a/src/de/danoeh/antennapod/dialog/AuthenticationDialog.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package de.danoeh.antennapod.dialog;
-
-import android.app.Dialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import android.view.View;
-import android.view.Window;
-import android.widget.Button;
-import android.widget.CheckBox;
-import android.widget.EditText;
-import de.danoeh.antennapod.R;
-
-/**
- * Displays a dialog with a username and password text field and an optional checkbox to save username and preferences.
- */
-public abstract class AuthenticationDialog extends Dialog {
-
- private final int titleRes;
- private final boolean enableUsernameField;
- private final boolean showSaveCredentialsCheckbox;
- private final String usernameInitialValue;
- private final String passwordInitialValue;
-
- public AuthenticationDialog(Context context, int titleRes, boolean enableUsernameField, boolean showSaveCredentialsCheckbox, String usernameInitialValue, String passwordInitialValue) {
- super(context);
- this.titleRes = titleRes;
- this.enableUsernameField = enableUsernameField;
- this.showSaveCredentialsCheckbox = showSaveCredentialsCheckbox;
- this.usernameInitialValue = usernameInitialValue;
- this.passwordInitialValue = passwordInitialValue;
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.authentication_dialog);
- final EditText etxtUsername = (EditText) findViewById(R.id.etxtUsername);
- final EditText etxtPassword = (EditText) findViewById(R.id.etxtPassword);
- final CheckBox saveUsernamePassword = (CheckBox) findViewById(R.id.chkSaveUsernamePassword);
- final Button butConfirm = (Button) findViewById(R.id.butConfirm);
- final Button butCancel = (Button) findViewById(R.id.butCancel);
-
- if (titleRes != 0) {
- setTitle(titleRes);
- } else {
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- }
- etxtUsername.setEnabled(enableUsernameField);
- if (showSaveCredentialsCheckbox) {
- saveUsernamePassword.setVisibility(View.VISIBLE);
- } else {
- saveUsernamePassword.setVisibility(View.GONE);
- }
- if (usernameInitialValue != null) {
- etxtUsername.setText(usernameInitialValue);
- }
- if (passwordInitialValue != null) {
- etxtPassword.setText(passwordInitialValue);
- }
- setOnCancelListener(new OnCancelListener() {
- @Override
- public void onCancel(DialogInterface dialog) {
- onCancelled();
- }
- });
- butCancel.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- cancel();
- }
- });
- butConfirm.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- onConfirmed(etxtUsername.getText().toString(),
- etxtPassword.getText().toString(),
- showSaveCredentialsCheckbox && saveUsernamePassword.isChecked());
- dismiss();
- }
- });
- }
-
- protected void onCancelled() {
-
- }
-
- protected abstract void onConfirmed(String username, String password, boolean saveUsernamePassword);
-}
diff --git a/src/de/danoeh/antennapod/dialog/AutoFlattrPreferenceDialog.java b/src/de/danoeh/antennapod/dialog/AutoFlattrPreferenceDialog.java
deleted file mode 100644
index d1ed795dc..000000000
--- a/src/de/danoeh/antennapod/dialog/AutoFlattrPreferenceDialog.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package de.danoeh.antennapod.dialog;
-
-import android.annotation.SuppressLint;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.view.View;
-import android.widget.CheckBox;
-import android.widget.SeekBar;
-import android.widget.TextView;
-
-import org.apache.commons.lang3.Validate;
-
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.preferences.UserPreferences;
-
-/**
- * Creates a new AlertDialog that displays preferences for auto-flattring to the user.
- */
-public class AutoFlattrPreferenceDialog {
-
- private AutoFlattrPreferenceDialog() {
- }
-
- public static void newAutoFlattrPreferenceDialog(final Activity activity, final AutoFlattrPreferenceDialogInterface callback) {
- Validate.notNull(activity);
- Validate.notNull(callback);
-
- AlertDialog.Builder builder = new AlertDialog.Builder(activity);
-
- @SuppressLint("InflateParams") View view = activity.getLayoutInflater().inflate(R.layout.autoflattr_preference_dialog, null);
- final CheckBox chkAutoFlattr = (CheckBox) view.findViewById(R.id.chkAutoFlattr);
- final SeekBar skbPercent = (SeekBar) view.findViewById(R.id.skbPercent);
- final TextView txtvStatus = (TextView) view.findViewById(R.id.txtvStatus);
-
- chkAutoFlattr.setChecked(UserPreferences.isAutoFlattr());
- skbPercent.setEnabled(chkAutoFlattr.isChecked());
- txtvStatus.setEnabled(chkAutoFlattr.isChecked());
-
- final int initialValue = (int) (UserPreferences.getAutoFlattrPlayedDurationThreshold() * 100.0f);
- setStatusMsgText(activity, txtvStatus, initialValue);
- skbPercent.setProgress(initialValue);
-
- chkAutoFlattr.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- skbPercent.setEnabled(chkAutoFlattr.isChecked());
- txtvStatus.setEnabled(chkAutoFlattr.isChecked());
- }
- });
-
- skbPercent.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- setStatusMsgText(activity, txtvStatus, progress);
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
-
- }
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
-
- }
- });
-
- builder.setTitle(R.string.pref_auto_flattr_title)
- .setView(view)
- .setPositiveButton(R.string.confirm_label, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- float progDouble = ((float) skbPercent.getProgress()) / 100.0f;
- callback.onConfirmed(chkAutoFlattr.isChecked(), progDouble);
- dialog.dismiss();
- }
- })
- .setNegativeButton(R.string.cancel_label, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- callback.onCancelled();
- dialog.dismiss();
- }
- })
- .setCancelable(false).show();
- }
-
- private static void setStatusMsgText(Context context, TextView txtvStatus, int progress) {
- if (progress == 0) {
- txtvStatus.setText(R.string.auto_flattr_ater_beginning);
- } else if (progress == 100) {
- txtvStatus.setText(R.string.auto_flattr_ater_end);
- } else {
- txtvStatus.setText(context.getString(R.string.auto_flattr_after_percent, progress));
- }
- }
-
- public static interface AutoFlattrPreferenceDialogInterface {
- public void onCancelled();
-
- public void onConfirmed(boolean autoFlattrEnabled, float autoFlattrValue);
- }
-
-
-}
diff --git a/src/de/danoeh/antennapod/dialog/ConfirmationDialog.java b/src/de/danoeh/antennapod/dialog/ConfirmationDialog.java
deleted file mode 100644
index df71fff77..000000000
--- a/src/de/danoeh/antennapod/dialog/ConfirmationDialog.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package de.danoeh.antennapod.dialog;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.util.Log;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-
-/**
- * Creates an AlertDialog which asks the user to confirm something. Other
- * classes can handle events like confirmation or cancellation.
- */
-public abstract class ConfirmationDialog {
- private static final String TAG = "ConfirmationDialog";
-
- Context context;
- int titleId;
- int messageId;
-
- public ConfirmationDialog(Context context, int titleId, int messageId) {
- this.context = context;
- this.titleId = titleId;
- this.messageId = messageId;
- }
-
- public void onCancelButtonPressed(DialogInterface dialog) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Dialog was cancelled");
- dialog.dismiss();
- }
-
- public abstract void onConfirmButtonPressed(DialogInterface dialog);
-
- public final AlertDialog createNewDialog() {
- AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle(titleId);
- builder.setMessage(messageId);
- builder.setPositiveButton(R.string.confirm_label,
- new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- onConfirmButtonPressed(dialog);
- }
- });
- builder.setNegativeButton(R.string.cancel_label,
- new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- onCancelButtonPressed(dialog);
- }
- });
- builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
-
- @Override
- public void onCancel(DialogInterface dialog) {
- onCancelButtonPressed(dialog);
- }
- });
- return builder.create();
- }
-}
diff --git a/src/de/danoeh/antennapod/dialog/DownloadRequestErrorDialogCreator.java b/src/de/danoeh/antennapod/dialog/DownloadRequestErrorDialogCreator.java
deleted file mode 100644
index e363a6911..000000000
--- a/src/de/danoeh/antennapod/dialog/DownloadRequestErrorDialogCreator.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package de.danoeh.antennapod.dialog;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import de.danoeh.antennapod.R;
-
-/** Creates Alert Dialogs if a DownloadRequestException has happened. */
-public class DownloadRequestErrorDialogCreator {
- private DownloadRequestErrorDialogCreator() {
- }
-
- public static void newRequestErrorDialog(Context context,
- String errorMessage) {
- AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setNeutralButton(android.R.string.ok,
- new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- }
- })
- .setTitle(R.string.download_error_request_error)
- .setMessage(
- context.getString(R.string.download_request_error_dialog_message_prefix)
- + errorMessage);
- builder.create().show();
- }
-}
diff --git a/src/de/danoeh/antennapod/dialog/FeedItemDialog.java b/src/de/danoeh/antennapod/dialog/FeedItemDialog.java
deleted file mode 100644
index 7384463de..000000000
--- a/src/de/danoeh/antennapod/dialog/FeedItemDialog.java
+++ /dev/null
@@ -1,428 +0,0 @@
-package de.danoeh.antennapod.dialog;
-
-import android.annotation.TargetApi;
-import android.app.Dialog;
-import android.content.ActivityNotFoundException;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.TypedArray;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Build;
-import android.os.Bundle;
-import android.support.v7.widget.PopupMenu;
-import android.util.Log;
-import android.util.TypedValue;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.Window;
-import android.webkit.WebSettings;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-import android.widget.ImageButton;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import org.apache.commons.lang3.StringEscapeUtils;
-import org.apache.commons.lang3.Validate;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.Callable;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.feed.FeedMedia;
-import de.danoeh.antennapod.preferences.UserPreferences;
-import de.danoeh.antennapod.storage.DBTasks;
-import de.danoeh.antennapod.storage.DBWriter;
-import de.danoeh.antennapod.storage.DownloadRequestException;
-import de.danoeh.antennapod.storage.DownloadRequester;
-import de.danoeh.antennapod.util.QueueAccess;
-import de.danoeh.antennapod.util.ShownotesProvider;
-import de.danoeh.antennapod.util.menuhandler.FeedItemMenuHandler;
-
-/**
- * Shows information about a specific FeedItem and provides actions like playing, downloading, etc.
- */
-public class FeedItemDialog extends Dialog {
- private static final String TAG = "FeedItemDialog";
-
- private FeedItem item;
- private QueueAccess queue;
-
- private View header;
- private TextView txtvTitle;
- private WebView webvDescription;
- private ImageButton butAction1;
- private ImageButton butAction2;
- private ImageButton butMore;
- private PopupMenu popupMenu;
-
- public static FeedItemDialog newInstance(Context context, FeedItemDialogSavedInstance savedInstance) {
- Validate.notNull(savedInstance);
- FeedItemDialog dialog = newInstance(context, savedInstance.item, savedInstance.queueAccess);
- if (savedInstance.isShowing) {
- dialog.show();
- }
- return dialog;
- }
-
- public static FeedItemDialog newInstance(Context context, FeedItem item, QueueAccess queue) {
- if (useDarkThemeWorkAround()) {
- return new FeedItemDialog(context, R.style.Theme_AntennaPod_Dark, item, queue);
- } else {
- return new FeedItemDialog(context, item, queue);
- }
- }
-
- public FeedItemDialog(Context context, int theme, FeedItem item, QueueAccess queue) {
- super(context, theme);
- Validate.notNull(item);
- Validate.notNull(queue);
- this.item = item;
- this.queue = queue;
- }
-
- private FeedItemDialog(Context context, FeedItem item, QueueAccess queue) {
- this(context, 0, item, queue);
- }
-
- /**
- * Returns true if the dialog should use a dark theme. This has to be done on Gingerbread devices
- * because dialogs are only available in a dark theme.
- */
- private static boolean useDarkThemeWorkAround() {
- return Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1
- && UserPreferences.getTheme() != R.style.Theme_AntennaPod_Dark;
- }
-
- @TargetApi(Build.VERSION_CODES.HONEYCOMB)
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.feeditem_dialog);
-
- txtvTitle = (TextView) findViewById(R.id.txtvTitle);
- header = findViewById(R.id.header);
- webvDescription = (WebView) findViewById(R.id.webview);
- butAction1 = (ImageButton) findViewById(R.id.butAction1);
- butAction2 = (ImageButton) findViewById(R.id.butAction2);
- butMore = (ImageButton) findViewById(R.id.butMoreActions);
- popupMenu = new PopupMenu(getContext(), butMore);
-
- webvDescription.setWebViewClient(new WebViewClient());
- txtvTitle.setText(item.getTitle());
-
- if (UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) {
- if (Build.VERSION.SDK_INT >= 11
- && Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
- webvDescription.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
- }
- webvDescription.setBackgroundColor(getContext().getResources().getColor(
- R.color.black));
- }
- webvDescription.getSettings().setUseWideViewPort(false);
- webvDescription.getSettings().setLayoutAlgorithm(
- WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
- webvDescription.getSettings().setLoadWithOverviewMode(true);
- webvDescription.setWebViewClient(new WebViewClient() {
-
- @Override
- public boolean shouldOverrideUrlLoading(WebView view, String url) {
- Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
- try {
- getContext().startActivity(intent);
- } catch (ActivityNotFoundException e) {
- e.printStackTrace();
- return false;
- }
- return true;
- }
- });
-
- loadDescriptionWebview(item);
-
- butAction1.setOnClickListener(new View.OnClickListener() {
- DefaultActionButtonCallback actionButtonCallback = new DefaultActionButtonCallback(getContext());
-
- @Override
-
- public void onClick(View v) {
- actionButtonCallback.onActionButtonPressed(item);
- FeedMedia media = item.getMedia();
- if (media != null && media.isDownloaded()) {
- // playback was started, dialog should close itself
- dismiss();
- }
-
- }
- }
- );
-
- butAction2.setOnClickListener(new View.OnClickListener()
-
- {
- @Override
- public void onClick(View v) {
- if (item.hasMedia()) {
- FeedMedia media = item.getMedia();
- if (!media.isDownloaded()) {
- DBTasks.playMedia(getContext(), media, true, true, true);
- dismiss();
- } else {
- DBWriter.deleteFeedMediaOfItem(getContext(), media.getId());
- }
- } else if (item.getLink() != null) {
- Uri uri = Uri.parse(item.getLink());
- getContext().startActivity(new Intent(Intent.ACTION_VIEW, uri));
- }
- }
- }
- );
-
- butMore.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- popupMenu.getMenu().clear();
- popupMenu.inflate(R.menu.feeditem_dialog);
- if (item.hasMedia()) {
- FeedItemMenuHandler.onPrepareMenu(popupMenuInterface, item, true, queue);
- } else {
- // these are already available via button1 and button2
- FeedItemMenuHandler.onPrepareMenu(popupMenuInterface, item, true, queue,
- R.id.mark_read_item, R.id.visit_website_item);
- }
- popupMenu.show();
- }
- }
- );
-
- popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
- @Override
- public boolean onMenuItemClick(MenuItem menuItem) {
-
- try {
- return FeedItemMenuHandler.onMenuItemClicked(getContext(), menuItem.getItemId(), item);
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_LONG).show();
- return true;
- }
- }
- }
- );
-
- updateMenuAppearance();
- }
-
-
- private final FeedItemMenuHandler.MenuInterface popupMenuInterface = new FeedItemMenuHandler.MenuInterface() {
- @Override
- public void setItemVisibility(int id, boolean visible) {
- MenuItem item = popupMenu.getMenu().findItem(id);
- if (item != null) {
- item.setVisible(visible);
- }
- }
- };
-
- public void updateMenuAppearance() {
- if (item == null || queue == null) {
- Log.w(TAG, "UpdateMenuAppearance called while item or queue was null");
- return;
- }
- FeedMedia media = item.getMedia();
- if (media == null) {
- TypedArray drawables = getContext().obtainStyledAttributes(new int[]{R.attr.navigation_accept,
- R.attr.location_web_site});
-
- if (!item.isRead()) {
- butAction1.setImageDrawable(drawables.getDrawable(0));
- butAction1.setContentDescription(getContext().getString(R.string.mark_read_label));
- butAction1.setVisibility(View.VISIBLE);
- } else {
- butAction1.setVisibility(View.INVISIBLE);
- }
-
- if (item.getLink() != null) {
- butAction2.setImageDrawable(drawables.getDrawable(1));
- butAction2.setContentDescription(getContext().getString(R.string.visit_website_label));
- } else {
- butAction2.setEnabled(false);
- }
-
- drawables.recycle();
- } else {
- boolean isDownloading = DownloadRequester.getInstance().isDownloadingFile(media);
- TypedArray drawables = getContext().obtainStyledAttributes(new int[]{R.attr.av_play,
- R.attr.av_download, R.attr.action_stream, R.attr.content_discard, R.attr.navigation_cancel});
-
- if (!media.isDownloaded()) {
- butAction2.setImageDrawable(drawables.getDrawable(2));
- butAction2.setContentDescription(getContext().getString(R.string.stream_label));
- } else {
- butAction2.setImageDrawable(drawables.getDrawable(3));
- butAction2.setContentDescription(getContext().getString(R.string.remove_episode_lable));
- }
-
- if (isDownloading) {
- butAction1.setImageDrawable(drawables.getDrawable(4));
- butAction1.setContentDescription(getContext().getString(R.string.cancel_download_label));
- } else if (media.isDownloaded()) {
- butAction1.setImageDrawable(drawables.getDrawable(0));
- butAction1.setContentDescription(getContext().getString(R.string.play_label));
- } else {
- butAction1.setImageDrawable(drawables.getDrawable(1));
- butAction1.setContentDescription(getContext().getString(R.string.download_label));
- }
-
- drawables.recycle();
- }
- }
-
-
- private void loadDescriptionWebview(final ShownotesProvider shownotesProvider) {
- AsyncTask<Void, Void, Void> loadTask = new AsyncTask<Void, Void, Void>() {
- String data;
-
-
- private String applyWebviewStyle(String textColor, String data) {
- final String WEBVIEW_STYLE = "<html><head><style type=\"text/css\"> @font-face { font-family: 'Roboto-Light'; src: url('file:///android_asset/Roboto-Light.ttf'); } * { color: %s; font-family: roboto-Light; font-size: 11pt; } a { font-style: normal; text-decoration: none; font-weight: normal; color: #00A8DF; } img { display: block; margin: 10 auto; max-width: %s; height: auto; } body { margin: %dpx %dpx %dpx %dpx; }</style></head><body>%s</body></html>";
- final int pageMargin = (int) TypedValue.applyDimension(
- TypedValue.COMPLEX_UNIT_DIP, 8, getContext().getResources()
- .getDisplayMetrics()
- );
- return String.format(WEBVIEW_STYLE, textColor, "100%", pageMargin,
- pageMargin, pageMargin, pageMargin, data);
- }
-
-
- @Override
- protected void onPostExecute(Void result) {
- super.onPostExecute(result);
- // /webvDescription.loadData(url, "text/html", "utf-8");
- if (FeedItemDialog.this.isShowing() && webvDescription != null) {
- webvDescription.loadDataWithBaseURL(null, data, "text/html",
- "utf-8", "about:blank");
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Webview loaded");
- }
- }
-
-
- @Override
- protected Void doInBackground(Void... params) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Loading Webview");
- try {
- Callable<String> shownotesLoadTask = shownotesProvider.loadShownotes();
- final String shownotes = shownotesLoadTask.call();
-
- data = StringEscapeUtils.unescapeHtml4(shownotes);
- TypedArray res = getContext()
- .getTheme()
- .obtainStyledAttributes(
- new int[]{android.R.attr.textColorPrimary});
- int colorResource;
- if (useDarkThemeWorkAround()) {
- colorResource = getContext().getResources().getColor(R.color.black);
- } else {
- colorResource = res.getColor(0, 0);
- }
- String colorString = String.format("#%06X",
- 0xFFFFFF & colorResource);
- Log.i(TAG, "text color: " + colorString);
- res.recycle();
- data = applyWebviewStyle(colorString, data);
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
-
- };
- loadTask.execute();
- }
-
- /**
- * Convenience method that calls setQueue() and setItemFromCollection() with
- * the given arguments.
- *
- * @return true if one of the calls to setItemFromCollection returned true,
- * false otherwise.
- */
- public boolean updateContent(QueueAccess queue, List<FeedItem>... collections) {
- setQueue(queue);
-
- boolean setItemFromCollectionResult = false;
- if (collections != null) {
- for (List<FeedItem> list : collections) {
- setItemFromCollectionResult |= setItemFromCollection(list);
- }
- }
- if (isShowing()) {
- updateMenuAppearance();
- }
-
- return setItemFromCollectionResult;
- }
-
-
- public void setItem(FeedItem item) {
- Validate.notNull(item);
- this.item = item;
- }
-
- /**
- * Finds the FeedItem of this dialog in a collection and updates its state from that
- * collection.
- *
- * @return true if the FeedItem was found, false otherwise.
- */
- public boolean setItemFromCollection(Collection<FeedItem> items) {
- for (FeedItem item : items) {
- if (item.getId() == this.item.getId()) {
- setItem(item);
- return true;
- }
- }
- return false;
- }
-
- public void setQueue(QueueAccess queue) {
- Validate.notNull(queue);
- this.queue = queue;
- }
-
- public FeedItem getItem() {
- return item;
- }
-
- public QueueAccess getQueue() {
- return queue;
- }
-
- public FeedItemDialogSavedInstance save() {
- return new FeedItemDialogSavedInstance(item, queue, isShowing());
- }
-
- /**
- * Used to save the FeedItemDialog's state across configuration changes
- */
- public static class FeedItemDialogSavedInstance {
- final FeedItem item;
- final QueueAccess queueAccess;
- final boolean isShowing;
-
- private FeedItemDialogSavedInstance(FeedItem item, QueueAccess queueAccess, boolean isShowing) {
- this.item = item;
- this.queueAccess = queueAccess;
- this.isShowing = isShowing;
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java b/src/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java
deleted file mode 100644
index a9c596d2e..000000000
--- a/src/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package de.danoeh.antennapod.dialog;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.text.Editable;
-import android.text.InputType;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.EditText;
-import android.widget.LinearLayout;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.gpoddernet.GpodnetService;
-import de.danoeh.antennapod.preferences.GpodnetPreferences;
-
-/**
- * Creates a dialog that lets the user change the hostname for the gpodder.net service.
- */
-public class GpodnetSetHostnameDialog {
- private static final String TAG = "GpodnetSetHostnameDialog";
-
- public static AlertDialog createDialog(final Context context) {
- AlertDialog.Builder dialog = new AlertDialog.Builder(context);
- final EditText et = new EditText(context);
- et.setText(GpodnetPreferences.getHostname());
- et.setInputType(InputType.TYPE_TEXT_VARIATION_URI);
- dialog.setTitle(R.string.pref_gpodnet_sethostname_title)
- .setView(setupContentView(context, et))
- .setPositiveButton(R.string.confirm_label, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- final Editable e = et.getText();
- if (e != null) {
- GpodnetPreferences.setHostname(e.toString());
- }
- dialog.dismiss();
- }
- })
- .setNegativeButton(R.string.cancel_label, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.cancel();
- }
- })
- .setNeutralButton(R.string.pref_gpodnet_sethostname_use_default_host, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- GpodnetPreferences.setHostname(GpodnetService.DEFAULT_BASE_HOST);
- dialog.dismiss();
- }
- })
- .setCancelable(true);
- return dialog.show();
- }
-
- private static View setupContentView(Context context, EditText et) {
- LinearLayout ll = new LinearLayout(context);
- ll.addView(et);
- LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) et.getLayoutParams();
- if (params != null) {
- params.setMargins(8, 8, 8, 8);
- params.width = ViewGroup.LayoutParams.MATCH_PARENT;
- params.height = ViewGroup.LayoutParams.MATCH_PARENT;
- }
- return ll;
- }
-}
diff --git a/src/de/danoeh/antennapod/dialog/TimeDialog.java b/src/de/danoeh/antennapod/dialog/TimeDialog.java
deleted file mode 100644
index bbd514640..000000000
--- a/src/de/danoeh/antennapod/dialog/TimeDialog.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package de.danoeh.antennapod.dialog;
-
-import android.app.Dialog;
-import android.content.Context;
-import android.os.Bundle;
-import android.text.Editable;
-import android.text.TextWatcher;
-import android.util.Log;
-import android.view.View;
-import android.view.Window;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.*;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-
-import java.util.concurrent.TimeUnit;
-
-public abstract class TimeDialog extends Dialog {
- private static final String TAG = "TimeDialog";
-
- private static final int DEFAULT_SPINNER_POSITION = 1;
-
- private Context context;
-
- private EditText etxtTime;
- private Spinner spTimeUnit;
- private Button butConfirm;
- private Button butCancel;
-
- private TimeUnit[] units = {TimeUnit.SECONDS, TimeUnit.MINUTES,
- TimeUnit.HOURS};
-
- public TimeDialog(Context context, int titleTextId, int leftButtonTextId) {
- super(context);
- this.context = context;
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- String[] spinnerContent = new String[]{context.getString(R.string.time_unit_seconds),
- context.getString(R.string.time_unit_minutes),
- context.getString(R.string.time_unit_hours)};
-
- setContentView(R.layout.time_dialog);
- etxtTime = (EditText) findViewById(R.id.etxtTime);
- spTimeUnit = (Spinner) findViewById(R.id.spTimeUnit);
- butConfirm = (Button) findViewById(R.id.butConfirm);
- butCancel = (Button) findViewById(R.id.butCancel);
-
- butConfirm.setText(R.string.set_sleeptimer_label);
- butCancel.setText(R.string.cancel_label);
- setTitle(R.string.set_sleeptimer_label);
- ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<String>(
- this.getContext(), android.R.layout.simple_spinner_item,
- spinnerContent);
- spinnerAdapter
- .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- spTimeUnit.setAdapter(spinnerAdapter);
- spTimeUnit.setSelection(DEFAULT_SPINNER_POSITION);
- butCancel.setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View v) {
- dismiss();
- }
- });
- butConfirm.setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View v) {
- try {
- long input = readTimeMillis();
- onTimeEntered(input);
- dismiss();
- } catch (NumberFormatException e) {
- e.printStackTrace();
- Toast toast = Toast.makeText(context,
- R.string.time_dialog_invalid_input,
- Toast.LENGTH_LONG);
- toast.show();
- }
- }
- });
- etxtTime.addTextChangedListener(new TextWatcher() {
-
- @Override
- public void afterTextChanged(Editable s) {
- checkInputLength(s.length());
- }
-
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count,
- int after) {
-
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before,
- int count) {
-
- }
- });
- checkInputLength(etxtTime.getText().length());
- etxtTime.postDelayed(new Runnable() {
- @Override
- public void run() {
- InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.showSoftInput(etxtTime, InputMethodManager.SHOW_IMPLICIT);
- }
- }, 100);
-
-
-
- }
-
- private void checkInputLength(int length) {
- if (length > 0) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Length is larger than 0, enabling confirm button");
- butConfirm.setEnabled(true);
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Length is smaller than 0, disabling confirm button");
- butConfirm.setEnabled(false);
- }
- }
-
- public abstract void onTimeEntered(long millis);
-
- private long readTimeMillis() {
- TimeUnit selectedUnit = units[spTimeUnit.getSelectedItemPosition()];
- long value = Long.valueOf(etxtTime.getText().toString());
- return selectedUnit.toMillis(value);
- }
-
-}
diff --git a/src/de/danoeh/antennapod/dialog/VariableSpeedDialog.java b/src/de/danoeh/antennapod/dialog/VariableSpeedDialog.java
deleted file mode 100644
index b009e76a7..000000000
--- a/src/de/danoeh/antennapod/dialog/VariableSpeedDialog.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package de.danoeh.antennapod.dialog;
-
-import android.app.AlertDialog;
-import android.content.ActivityNotFoundException;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.net.Uri;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.preferences.UserPreferences;
-
-import java.util.Arrays;
-import java.util.List;
-
-public class VariableSpeedDialog {
- private VariableSpeedDialog() {
- }
-
- public static void showDialog(final Context context) {
- if (com.aocate.media.MediaPlayer.isPrestoLibraryInstalled(context)) {
- showSpeedSelectorDialog(context);
- } else {
- showGetPluginDialog(context);
- }
- }
-
- private static void showGetPluginDialog(final Context context) {
- AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle(R.string.no_playback_plugin_title);
- builder.setMessage(R.string.no_playback_plugin_msg);
- builder.setNegativeButton(R.string.close_label, null);
- builder.setPositiveButton(R.string.download_plugin_label,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- try {
- Intent playStoreIntent = new Intent(
- Intent.ACTION_VIEW,
- Uri.parse("market://details?id=com.falconware.prestissimo"));
- context.startActivity(playStoreIntent);
- } catch (ActivityNotFoundException e) {
- // this is usually thrown on an emulator if the Android market is not installed
- e.printStackTrace();
- }
- }
- });
- builder.create().show();
- }
-
- private static void showSpeedSelectorDialog(final Context context) {
- final String[] speedValues = context.getResources().getStringArray(
- R.array.playback_speed_values);
- // According to Java spec these get initialized to false on creation
- final boolean[] speedChecked = new boolean[speedValues.length];
-
- // Build the "isChecked" array so that multiChoice dialog is
- // populated correctly
- List<String> selectedSpeedList = Arrays.asList(UserPreferences
- .getPlaybackSpeedArray());
- for (int i = 0; i < speedValues.length; i++) {
- speedChecked[i] = selectedSpeedList.contains(speedValues[i]);
- }
-
- AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle(R.string.set_playback_speed_label);
- builder.setMultiChoiceItems(R.array.playback_speed_values,
- speedChecked, new DialogInterface.OnMultiChoiceClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which,
- boolean isChecked) {
- speedChecked[which] = isChecked;
- }
-
- });
- builder.setNegativeButton(android.R.string.cancel, null);
- builder.setPositiveButton(android.R.string.ok,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- int choiceCount = 0;
- for (int i = 0; i < speedChecked.length; i++) {
- if (speedChecked[i]) {
- choiceCount++;
- }
- }
- String[] newSpeedValues = new String[choiceCount];
- int newSpeedIndex = 0;
- for (int i = 0; i < speedChecked.length; i++) {
- if (speedChecked[i]) {
- newSpeedValues[newSpeedIndex++] = speedValues[i];
- }
- }
-
- UserPreferences.setPlaybackSpeedArray(newSpeedValues);
-
- }
- });
- builder.create().show();
- }
-}
diff --git a/src/de/danoeh/antennapod/feed/Chapter.java b/src/de/danoeh/antennapod/feed/Chapter.java
deleted file mode 100644
index d6151ee9f..000000000
--- a/src/de/danoeh/antennapod/feed/Chapter.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package de.danoeh.antennapod.feed;
-
-public abstract class Chapter extends FeedComponent {
-
- /** Defines starting point in milliseconds. */
- protected long start;
- protected String title;
- protected String link;
-
- public Chapter() {
- }
-
- public Chapter(long start) {
- super();
- this.start = start;
- }
-
- public Chapter(long start, String title, FeedItem item, String link) {
- super();
- this.start = start;
- this.title = title;
- this.link = link;
- }
-
- public abstract int getChapterType();
-
- public long getStart() {
- return start;
- }
-
- public String getTitle() {
- return title;
- }
-
- public String getLink() {
- return link;
- }
-
- public void setStart(long start) {
- this.start = start;
- }
-
- public void setTitle(String title) {
- this.title = title;
- }
-
- public void setLink(String link) {
- this.link = link;
- }
-
- @Override
- public String getHumanReadableIdentifier() {
- return title;
- }
-}
diff --git a/src/de/danoeh/antennapod/feed/EventDistributor.java b/src/de/danoeh/antennapod/feed/EventDistributor.java
deleted file mode 100644
index 5fb72048e..000000000
--- a/src/de/danoeh/antennapod/feed/EventDistributor.java
+++ /dev/null
@@ -1,140 +0,0 @@
-package de.danoeh.antennapod.feed;
-
-import android.os.Handler;
-import android.util.Log;
-
-import org.apache.commons.lang3.Validate;
-
-import de.danoeh.antennapod.BuildConfig;
-
-import java.util.AbstractQueue;
-import java.util.Observable;
-import java.util.Observer;
-import java.util.concurrent.ConcurrentLinkedQueue;
-
-/**
- * Notifies its observers about changes in the feed database. Observers can
- * register by retrieving an instance of this class and registering an
- * EventListener. When new events arrive, the EventDistributor will process the
- * event queue in a handler that runs on the main thread. The observers will only
- * be notified once if the event queue contains multiple elements.
- *
- * Events can be sent with the send* methods.
- */
-public class EventDistributor extends Observable {
- private static final String TAG = "EventDistributor";
-
- public static final int FEED_LIST_UPDATE = 1;
- public static final int UNREAD_ITEMS_UPDATE = 2;
- public static final int QUEUE_UPDATE = 4;
- public static final int DOWNLOADLOG_UPDATE = 8;
- public static final int PLAYBACK_HISTORY_UPDATE = 16;
- public static final int DOWNLOAD_QUEUED = 32;
- public static final int DOWNLOAD_HANDLED = 64;
-
- private Handler handler;
- private AbstractQueue<Integer> events;
-
- private static EventDistributor instance;
-
- private EventDistributor() {
- this.handler = new Handler();
- events = new ConcurrentLinkedQueue<Integer>();
- }
-
- public static synchronized EventDistributor getInstance() {
- if (instance == null) {
- instance = new EventDistributor();
- }
- return instance;
- }
-
- public void register(EventListener el) {
- addObserver(el);
- }
-
- public void unregister(EventListener el) {
- deleteObserver(el);
- }
-
- public void addEvent(Integer i) {
- events.offer(i);
- handler.post(new Runnable() {
-
- @Override
- public void run() {
- processEventQueue();
- }
- });
- }
-
- private void processEventQueue() {
- Integer result = 0;
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "Processing event queue. Number of events: "
- + events.size());
- for (Integer current = events.poll(); current != null; current = events
- .poll()) {
- result |= current;
- }
- if (result != 0) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Notifying observers. Data: " + result);
- setChanged();
- notifyObservers(result);
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "Event queue didn't contain any new events. Observers will not be notified.");
- }
- }
-
- @Override
- public void addObserver(Observer observer) {
- super.addObserver(observer);
- Validate.isInstanceOf(EventListener.class, observer);
- }
-
- public void sendDownloadQueuedBroadcast() {
- addEvent(DOWNLOAD_QUEUED);
- }
-
- public void sendUnreadItemsUpdateBroadcast() {
- addEvent(UNREAD_ITEMS_UPDATE);
- }
-
- public void sendQueueUpdateBroadcast() {
- addEvent(QUEUE_UPDATE);
- }
-
- public void sendFeedUpdateBroadcast() {
- addEvent(FEED_LIST_UPDATE);
- }
-
- public void sendPlaybackHistoryUpdateBroadcast() {
- addEvent(PLAYBACK_HISTORY_UPDATE);
- }
-
- public void sendDownloadLogUpdateBroadcast() {
- addEvent(DOWNLOADLOG_UPDATE);
- }
-
- public void sendDownloadHandledBroadcast() {
- addEvent(DOWNLOAD_HANDLED);
- }
-
- public static abstract class EventListener implements Observer {
-
- @Override
- public void update(Observable observable, Object data) {
- if (observable instanceof EventDistributor
- && data instanceof Integer) {
- update((EventDistributor) observable, (Integer) data);
- }
- }
-
- public abstract void update(EventDistributor eventDistributor,
- Integer arg);
- }
-}
diff --git a/src/de/danoeh/antennapod/feed/Feed.java b/src/de/danoeh/antennapod/feed/Feed.java
deleted file mode 100644
index b5415c69c..000000000
--- a/src/de/danoeh/antennapod/feed/Feed.java
+++ /dev/null
@@ -1,445 +0,0 @@
-package de.danoeh.antennapod.feed;
-
-import android.content.Context;
-import android.net.Uri;
-
-import de.danoeh.antennapod.asynctask.PicassoImageResource;
-import de.danoeh.antennapod.preferences.UserPreferences;
-import de.danoeh.antennapod.storage.DBWriter;
-import de.danoeh.antennapod.util.EpisodeFilter;
-import de.danoeh.antennapod.util.flattr.FlattrStatus;
-import de.danoeh.antennapod.util.flattr.FlattrThing;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-/**
- * Data Object for a whole feed
- *
- * @author daniel
- */
-public class Feed extends FeedFile implements FlattrThing, PicassoImageResource {
- public static final int FEEDFILETYPE_FEED = 0;
- public static final String TYPE_RSS2 = "rss";
- public static final String TYPE_RSS091 = "rss";
- public static final String TYPE_ATOM1 = "atom";
-
- private String title;
- /**
- * Contains 'id'-element in Atom feed.
- */
- private String feedIdentifier;
- /**
- * Link to the website.
- */
- private String link;
- private String description;
- private String language;
- /**
- * Name of the author
- */
- private String author;
- private FeedImage image;
- private List<FeedItem> items;
- /**
- * Date of last refresh.
- */
- private Date lastUpdate;
- private FlattrStatus flattrStatus;
- private String paymentLink;
- /**
- * Feed type, for example RSS 2 or Atom
- */
- private String type;
-
- /**
- * Feed preferences
- */
- private FeedPreferences preferences;
-
- /**
- * This constructor is used for restoring a feed from the database.
- */
- public Feed(long id, Date lastUpdate, String title, String link, String description, String paymentLink,
- String author, String language, String type, String feedIdentifier, FeedImage image, String fileUrl,
- String downloadUrl, boolean downloaded, FlattrStatus status) {
- super(fileUrl, downloadUrl, downloaded);
- this.id = id;
- this.title = title;
- if (lastUpdate != null) {
- this.lastUpdate = (Date) lastUpdate.clone();
- } else {
- this.lastUpdate = null;
- }
- this.link = link;
- this.description = description;
- this.paymentLink = paymentLink;
- this.author = author;
- this.language = language;
- this.type = type;
- this.feedIdentifier = feedIdentifier;
- this.image = image;
- this.flattrStatus = status;
-
- items = new ArrayList<FeedItem>();
- }
-
- /**
- * This constructor is used for test purposes and uses a default flattr status object.
- */
- public Feed(long id, Date lastUpdate, String title, String link, String description, String paymentLink,
- String author, String language, String type, String feedIdentifier, FeedImage image, String fileUrl,
- String downloadUrl, boolean downloaded) {
- this(id, lastUpdate, title, link, description, paymentLink, author, language, type, feedIdentifier, image,
- fileUrl, downloadUrl, downloaded, new FlattrStatus());
- }
-
- /**
- * This constructor can be used when parsing feed data. Only the 'lastUpdate' and 'items' field are initialized.
- */
- public Feed() {
- super();
- items = new ArrayList<FeedItem>();
- lastUpdate = new Date();
- this.flattrStatus = new FlattrStatus();
- }
-
- /**
- * This constructor is used for requesting a feed download (it must not be used for anything else!). It should NOT be
- * used if the title of the feed is already known.
- */
- public Feed(String url, Date lastUpdate) {
- super(null, url, false);
- this.lastUpdate = (lastUpdate != null) ? (Date) lastUpdate.clone() : null;
- this.flattrStatus = new FlattrStatus();
- }
-
- /**
- * This constructor is used for requesting a feed download (it must not be used for anything else!). It should be
- * used if the title of the feed is already known.
- */
- public Feed(String url, Date lastUpdate, String title) {
- this(url, lastUpdate);
- this.title = title;
- this.flattrStatus = new FlattrStatus();
- }
-
- /**
- * This constructor is used for requesting a feed download (it must not be used for anything else!). It should be
- * used if the title of the feed is already known.
- */
- public Feed(String url, Date lastUpdate, String title, String username, String password) {
- this(url, lastUpdate, title);
- preferences = new FeedPreferences(0, true, username, password);
- }
-
- /**
- * Returns the number of FeedItems where 'read' is false. If the 'display
- * only episodes' - preference is set to true, this method will only count
- * items with episodes.
- */
- public int getNumOfNewItems() {
- int count = 0;
- for (FeedItem item : items) {
- if (item.getState() == FeedItem.State.NEW) {
- if (!UserPreferences.isDisplayOnlyEpisodes()
- || item.getMedia() != null) {
- count++;
- }
- }
- }
- return count;
- }
-
- /**
- * Returns the number of FeedItems where the media started to play but
- * wasn't finished yet.
- */
- public int getNumOfStartedItems() {
- int count = 0;
-
- for (FeedItem item : items) {
- FeedItem.State state = item.getState();
- if (state == FeedItem.State.IN_PROGRESS
- || state == FeedItem.State.PLAYING) {
- count++;
- }
- }
- return count;
- }
-
- /**
- * Returns true if at least one item in the itemlist is unread.
- *
- * @param enableEpisodeFilter true if this method should only count items with episodes if
- * the 'display only episodes' - preference is set to true by the
- * user.
- */
- public boolean hasNewItems(boolean enableEpisodeFilter) {
- for (FeedItem item : items) {
- if (item.getState() == FeedItem.State.NEW) {
- if (!(enableEpisodeFilter && UserPreferences
- .isDisplayOnlyEpisodes()) || item.getMedia() != null) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Returns the number of FeedItems.
- *
- * @param enableEpisodeFilter true if this method should only count items with episodes if
- * the 'display only episodes' - preference is set to true by the
- * user.
- */
- public int getNumOfItems(boolean enableEpisodeFilter) {
- if (enableEpisodeFilter && UserPreferences.isDisplayOnlyEpisodes()) {
- return EpisodeFilter.countItemsWithEpisodes(items);
- } else {
- return items.size();
- }
- }
-
- /**
- * Returns the item at the specified index.
- *
- * @param enableEpisodeFilter true if this method should ignore items without episdodes if
- * the episodes filter has been enabled by the user.
- */
- public FeedItem getItemAtIndex(boolean enableEpisodeFilter, int position) {
- if (enableEpisodeFilter && UserPreferences.isDisplayOnlyEpisodes()) {
- return EpisodeFilter.accessEpisodeByIndex(items, position);
- } else {
- return items.get(position);
- }
- }
-
- /**
- * Returns the value that uniquely identifies this Feed. If the
- * feedIdentifier attribute is not null, it will be returned. Else it will
- * try to return the title. If the title is not given, it will use the link
- * of the feed.
- */
- public String getIdentifyingValue() {
- if (feedIdentifier != null && !feedIdentifier.isEmpty()) {
- return feedIdentifier;
- } else if (download_url != null && !download_url.isEmpty()) {
- return download_url;
- } else if (title != null && !title.isEmpty()) {
- return title;
- } else {
- return link;
- }
- }
-
- @Override
- public String getHumanReadableIdentifier() {
- if (title != null) {
- return title;
- } else {
- return download_url;
- }
- }
-
- public void updateFromOther(Feed other) {
- super.updateFromOther(other);
- if (other.title != null) {
- title = other.title;
- }
- if (other.feedIdentifier != null) {
- feedIdentifier = other.feedIdentifier;
- }
- if (other.link != null) {
- link = other.link;
- }
- if (other.description != null) {
- description = other.description;
- }
- if (other.language != null) {
- language = other.language;
- }
- if (other.author != null) {
- author = other.author;
- }
- if (other.paymentLink != null) {
- paymentLink = other.paymentLink;
- }
- if (other.flattrStatus != null) {
- flattrStatus = other.flattrStatus;
- }
- }
-
- public boolean compareWithOther(Feed other) {
- if (super.compareWithOther(other)) {
- return true;
- }
- if (!title.equals(other.title)) {
- return true;
- }
- if (other.feedIdentifier != null) {
- if (feedIdentifier == null
- || !feedIdentifier.equals(other.feedIdentifier)) {
- return true;
- }
- }
- if (other.link != null) {
- if (link == null || !link.equals(other.link)) {
- return true;
- }
- }
- if (other.description != null) {
- if (description == null || !description.equals(other.description)) {
- return true;
- }
- }
- if (other.language != null) {
- if (language == null || !language.equals(other.language)) {
- return true;
- }
- }
- if (other.author != null) {
- if (author == null || !author.equals(other.author)) {
- return true;
- }
- }
- if (other.paymentLink != null) {
- if (paymentLink == null || !paymentLink.equals(other.paymentLink)) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public int getTypeAsInt() {
- return FEEDFILETYPE_FEED;
- }
-
- public String getTitle() {
- return title;
- }
-
- public void setTitle(String title) {
- this.title = title;
- }
-
- public String getLink() {
- return link;
- }
-
- public void setLink(String link) {
- this.link = link;
- }
-
- public String getDescription() {
- return description;
- }
-
- public void setDescription(String description) {
- this.description = description;
- }
-
- public FeedImage getImage() {
- return image;
- }
-
- public void setImage(FeedImage image) {
- this.image = image;
- }
-
- public List<FeedItem> getItems() {
- return items;
- }
-
- public void setItems(List<FeedItem> list) {
- this.items = list;
- }
-
- public Date getLastUpdate() {
- return (lastUpdate != null) ? (Date) lastUpdate.clone() : null;
- }
-
- public void setLastUpdate(Date lastUpdate) {
- this.lastUpdate = (lastUpdate != null) ? (Date) lastUpdate.clone() : null;
- }
-
- public String getFeedIdentifier() {
- return feedIdentifier;
- }
-
- public void setFeedIdentifier(String feedIdentifier) {
- this.feedIdentifier = feedIdentifier;
- }
-
- public void setFlattrStatus(FlattrStatus status) {
- this.flattrStatus = status;
- }
-
- public FlattrStatus getFlattrStatus() {
- return flattrStatus;
- }
-
- public String getPaymentLink() {
- return paymentLink;
- }
-
- public void setPaymentLink(String paymentLink) {
- this.paymentLink = paymentLink;
- }
-
- public String getLanguage() {
- return language;
- }
-
- public void setLanguage(String language) {
- this.language = language;
- }
-
- public String getAuthor() {
- return author;
- }
-
- public void setAuthor(String author) {
- this.author = author;
- }
-
- public String getType() {
- return type;
- }
-
- public void setType(String type) {
- this.type = type;
- }
-
- public void setPreferences(FeedPreferences preferences) {
- this.preferences = preferences;
- }
-
- public FeedPreferences getPreferences() {
- return preferences;
- }
-
- public void savePreferences(Context context) {
- DBWriter.setFeedPreferences(context, preferences);
- }
-
- @Override
- public void setId(long id) {
- super.setId(id);
- if (preferences != null) {
- preferences.setFeedID(id);
- }
- }
-
- @Override
- public Uri getImageUri() {
- if (image != null) {
- return image.getImageUri();
- } else {
- return null;
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/feed/FeedComponent.java b/src/de/danoeh/antennapod/feed/FeedComponent.java
deleted file mode 100644
index 48b243770..000000000
--- a/src/de/danoeh/antennapod/feed/FeedComponent.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package de.danoeh.antennapod.feed;
-
-/**
- * Represents every possible component of a feed
- *
- * @author daniel
- */
-public abstract class FeedComponent {
-
- protected long id;
-
- public FeedComponent() {
- super();
- }
-
- public long getId() {
- return id;
- }
-
- public void setId(long id) {
- this.id = id;
- }
-
- /**
- * Update this FeedComponent's attributes with the attributes from another
- * FeedComponent. This method should only update attributes which where read from
- * the feed.
- */
- public void updateFromOther(FeedComponent other) {
- }
-
- /**
- * Compare's this FeedComponent's attribute values with another FeedComponent's
- * attribute values. This method will only compare attributes which were
- * read from the feed.
- *
- * @return true if attribute values are different, false otherwise
- */
- public boolean compareWithOther(FeedComponent other) {
- return false;
- }
-
-
- /**
- * Should return a non-null, human-readable String so that the item can be
- * identified by the user. Can be title, download-url, etc.
- */
- public abstract String getHumanReadableIdentifier();
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- FeedComponent that = (FeedComponent) o;
-
- if (id != that.id) return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- return (int) (id ^ (id >>> 32));
- }
-} \ No newline at end of file
diff --git a/src/de/danoeh/antennapod/feed/FeedFile.java b/src/de/danoeh/antennapod/feed/FeedFile.java
deleted file mode 100644
index a05533ebc..000000000
--- a/src/de/danoeh/antennapod/feed/FeedFile.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package de.danoeh.antennapod.feed;
-
-import java.io.File;
-
-/**
- * Represents a component of a Feed that has to be downloaded
- */
-public abstract class FeedFile extends FeedComponent {
-
- protected String file_url;
- protected String download_url;
- protected boolean downloaded;
-
- /**
- * Creates a new FeedFile object.
- *
- * @param file_url The location of the FeedFile. If this is null, the downloaded-attribute
- * will automatically be set to false.
- * @param download_url The location where the FeedFile can be downloaded.
- * @param downloaded true if the FeedFile has been downloaded, false otherwise. This parameter
- * will automatically be interpreted as false if the file_url is null.
- */
- public FeedFile(String file_url, String download_url, boolean downloaded) {
- super();
- this.file_url = file_url;
- this.download_url = download_url;
- this.downloaded = (file_url != null) && downloaded;
- }
-
- public FeedFile() {
- this(null, null, false);
- }
-
- public abstract int getTypeAsInt();
-
- /**
- * Update this FeedFile's attributes with the attributes from another
- * FeedFile. This method should only update attributes which where read from
- * the feed.
- */
- public void updateFromOther(FeedFile other) {
- super.updateFromOther(other);
- this.download_url = other.download_url;
- }
-
- /**
- * Compare's this FeedFile's attribute values with another FeedFile's
- * attribute values. This method will only compare attributes which were
- * read from the feed.
- *
- * @return true if attribute values are different, false otherwise
- */
- public boolean compareWithOther(FeedFile other) {
- if (super.compareWithOther(other)) {
- return true;
- }
- if (!download_url.equals(other.download_url)) {
- return true;
- }
- return false;
- }
-
- /**
- * Returns true if the file exists at file_url.
- */
- public boolean fileExists() {
- if (file_url == null) {
- return false;
- } else {
- File f = new File(file_url);
- return f.exists();
- }
- }
-
- public String getFile_url() {
- return file_url;
- }
-
- /**
- * Changes the file_url of this FeedFile. Setting this value to
- * null will also set the downloaded-attribute to false.
- */
- public void setFile_url(String file_url) {
- this.file_url = file_url;
- if (file_url == null) {
- downloaded = false;
- }
- }
-
- public String getDownload_url() {
- return download_url;
- }
-
- public void setDownload_url(String download_url) {
- this.download_url = download_url;
- }
-
- public boolean isDownloaded() {
- return downloaded;
- }
-
- public void setDownloaded(boolean downloaded) {
- this.downloaded = downloaded;
- }
-}
diff --git a/src/de/danoeh/antennapod/feed/FeedImage.java b/src/de/danoeh/antennapod/feed/FeedImage.java
deleted file mode 100644
index c588f5e71..000000000
--- a/src/de/danoeh/antennapod/feed/FeedImage.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package de.danoeh.antennapod.feed;
-
-import android.net.Uri;
-
-import de.danoeh.antennapod.asynctask.PicassoImageResource;
-
-import org.apache.commons.io.IOUtils;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-
-
-
-public class FeedImage extends FeedFile implements PicassoImageResource {
- public static final int FEEDFILETYPE_FEEDIMAGE = 1;
-
- protected String title;
- protected FeedComponent owner;
-
- public FeedImage(String download_url, String title) {
- super(null, download_url, false);
- this.download_url = download_url;
- this.title = title;
- }
-
- public FeedImage(long id, String title, String file_url,
- String download_url, boolean downloaded) {
- super(file_url, download_url, downloaded);
- this.id = id;
- this.title = title;
- }
-
- @Override
- public String getHumanReadableIdentifier() {
- if (owner != null && owner.getHumanReadableIdentifier() != null) {
- return owner.getHumanReadableIdentifier();
- } else {
- return download_url;
- }
- }
-
- @Override
- public int getTypeAsInt() {
- return FEEDFILETYPE_FEEDIMAGE;
- }
-
- public FeedImage() {
- super();
- }
-
- public String getTitle() {
- return title;
- }
-
- public void setTitle(String title) {
- this.title = title;
- }
-
- public FeedComponent getOwner() {
- return owner;
- }
-
- public void setOwner(FeedComponent owner) {
- this.owner = owner;
- }
-
- @Override
- public Uri getImageUri() {
- if (file_url != null && downloaded) {
- return Uri.fromFile(new File(file_url));
- } else {
- return null;
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/feed/FeedItem.java b/src/de/danoeh/antennapod/feed/FeedItem.java
deleted file mode 100644
index 78091ea33..000000000
--- a/src/de/danoeh/antennapod/feed/FeedItem.java
+++ /dev/null
@@ -1,333 +0,0 @@
-package de.danoeh.antennapod.feed;
-
-import android.net.Uri;
-
-import de.danoeh.antennapod.PodcastApp;
-import de.danoeh.antennapod.asynctask.PicassoImageResource;
-import de.danoeh.antennapod.storage.DBReader;
-import de.danoeh.antennapod.util.ShownotesProvider;
-import de.danoeh.antennapod.util.flattr.FlattrStatus;
-import de.danoeh.antennapod.util.flattr.FlattrThing;
-
-import java.io.InputStream;
-import java.util.Date;
-import java.util.List;
-import java.util.concurrent.Callable;
-
-/**
- * Data Object for a XML message
- *
- * @author daniel
- */
-public class FeedItem extends FeedComponent implements ShownotesProvider, FlattrThing, PicassoImageResource {
-
- /**
- * The id/guid that can be found in the rss/atom feed. Might not be set.
- */
- private String itemIdentifier;
- private String title;
- /**
- * The description of a feeditem.
- */
- private String description;
- /**
- * The content of the content-encoded tag of a feeditem.
- */
- private String contentEncoded;
-
- private String link;
- private Date pubDate;
- private FeedMedia media;
-
- private Feed feed;
- private long feedId;
-
- private boolean read;
- private String paymentLink;
- private FlattrStatus flattrStatus;
- private List<Chapter> chapters;
- private FeedImage image;
-
- public FeedItem() {
- this.read = true;
- this.flattrStatus = new FlattrStatus();
- }
-
- /**
- * This constructor should be used for creating test objects.
- */
- public FeedItem(long id, String title, String itemIdentifier, String link, Date pubDate, boolean read, Feed feed) {
- this.id = id;
- this.title = title;
- this.itemIdentifier = itemIdentifier;
- this.link = link;
- this.pubDate = (pubDate != null) ? (Date) pubDate.clone() : null;
- this.read = read;
- this.feed = feed;
- this.flattrStatus = new FlattrStatus();
- }
-
- public void updateFromOther(FeedItem other) {
- super.updateFromOther(other);
- if (other.title != null) {
- title = other.title;
- }
- if (other.getDescription() != null) {
- description = other.getDescription();
- }
- if (other.getContentEncoded() != null) {
- contentEncoded = other.contentEncoded;
- }
- if (other.link != null) {
- link = other.link;
- }
- if (other.pubDate != null && other.pubDate != pubDate) {
- pubDate = other.pubDate;
- }
- if (other.media != null) {
- if (media == null) {
- setMedia(other.media);
- } else if (media.compareWithOther(other)) {
- media.updateFromOther(other);
- }
- }
- if (other.paymentLink != null) {
- paymentLink = other.paymentLink;
- }
- if (other.chapters != null) {
- if (chapters == null) {
- chapters = other.chapters;
- }
- }
- if (image == null) {
- image = other.image;
- }
- }
-
- /**
- * Returns the value that uniquely identifies this FeedItem. If the
- * itemIdentifier attribute is not null, it will be returned. Else it will
- * try to return the title. If the title is not given, it will use the link
- * of the entry.
- */
- public String getIdentifyingValue() {
- if (itemIdentifier != null && !itemIdentifier.isEmpty()) {
- return itemIdentifier;
- } else if (title != null && !title.isEmpty()) {
- return title;
- } else {
- return link;
- }
- }
-
- public String getTitle() {
- return title;
- }
-
- public void setTitle(String title) {
- this.title = title;
- }
-
- public String getDescription() {
- return description;
- }
-
- public void setDescription(String description) {
- this.description = description;
- }
-
- public String getLink() {
- return link;
- }
-
- public void setLink(String link) {
- this.link = link;
- }
-
- public Date getPubDate() {
- if (pubDate != null) {
- return (Date) pubDate.clone();
- } else {
- return null;
- }
- }
-
- public void setPubDate(Date pubDate) {
- if (pubDate != null) {
- this.pubDate = (Date) pubDate.clone();
- } else {
- this.pubDate = null;
- }
- }
-
- public FeedMedia getMedia() {
- return media;
- }
-
- /**
- * Sets the media object of this FeedItem. If the given
- * FeedMedia object is not null, it's 'item'-attribute value
- * will also be set to this item.
- */
- public void setMedia(FeedMedia media) {
- this.media = media;
- if (media != null && media.getItem() != this) {
- media.setItem(this);
- }
- }
-
- public Feed getFeed() {
- return feed;
- }
-
- public void setFeed(Feed feed) {
- this.feed = feed;
- }
-
- public boolean isRead() {
- return read || isInProgress();
- }
-
- public void setRead(boolean read) {
- this.read = read;
- }
-
- private boolean isInProgress() {
- return (media != null && media.isInProgress());
- }
-
- public String getContentEncoded() {
- return contentEncoded;
- }
-
- public void setContentEncoded(String contentEncoded) {
- this.contentEncoded = contentEncoded;
- }
-
- public void setFlattrStatus(FlattrStatus status) {
- this.flattrStatus = status;
- }
-
- public FlattrStatus getFlattrStatus() {
- return flattrStatus;
- }
-
- public String getPaymentLink() {
- return paymentLink;
- }
-
- public void setPaymentLink(String paymentLink) {
- this.paymentLink = paymentLink;
- }
-
- public List<Chapter> getChapters() {
- return chapters;
- }
-
- public void setChapters(List<Chapter> chapters) {
- this.chapters = chapters;
- }
-
- public String getItemIdentifier() {
- return itemIdentifier;
- }
-
- public void setItemIdentifier(String itemIdentifier) {
- this.itemIdentifier = itemIdentifier;
- }
-
- public boolean hasMedia() {
- return media != null;
- }
-
- private boolean isPlaying() {
- if (media != null) {
- return media.isPlaying();
- }
- return false;
- }
-
- @Override
- public Callable<String> loadShownotes() {
- return new Callable<String>() {
- @Override
- public String call() throws Exception {
-
- if (contentEncoded == null || description == null) {
- DBReader.loadExtraInformationOfFeedItem(PodcastApp.getInstance(), FeedItem.this);
-
- }
- return (contentEncoded != null) ? contentEncoded : description;
- }
- };
- }
-
- @Override
- public Uri getImageUri() {
- if (hasMedia()) {
- return media.getImageUri();
- } else if (feed != null) {
- return feed.getImageUri();
- } else {
- return null;
- }
- }
-
- public enum State {
- NEW, IN_PROGRESS, READ, PLAYING
- }
-
- public State getState() {
- if (hasMedia()) {
- if (isPlaying()) {
- return State.PLAYING;
- }
- if (isInProgress()) {
- return State.IN_PROGRESS;
- }
- }
- return (isRead() ? State.READ : State.NEW);
- }
-
- public long getFeedId() {
- return feedId;
- }
-
- public void setFeedId(long feedId) {
- this.feedId = feedId;
- }
-
- /**
- * Returns the image of this item or the image of the feed if this item does
- * not have its own image.
- */
- public FeedImage getImage() {
- return (hasItemImage()) ? image : feed.getImage();
- }
-
- public void setImage(FeedImage image) {
- this.image = image;
- if (image != null) {
- image.setOwner(this);
- }
- }
-
- /**
- * Returns true if this FeedItem has its own image, false otherwise.
- */
- public boolean hasItemImage() {
- return image != null;
- }
-
- /**
- * Returns true if this FeedItem has its own image and the image has been downloaded.
- */
- public boolean hasItemImageDownloaded() {
- return image != null && image.isDownloaded();
- }
-
- @Override
- public String getHumanReadableIdentifier() {
- return title;
- }
-}
diff --git a/src/de/danoeh/antennapod/feed/FeedMedia.java b/src/de/danoeh/antennapod/feed/FeedMedia.java
deleted file mode 100644
index 9298ebe8a..000000000
--- a/src/de/danoeh/antennapod/feed/FeedMedia.java
+++ /dev/null
@@ -1,411 +0,0 @@
-package de.danoeh.antennapod.feed;
-
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
-import android.net.Uri;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
-import java.util.Date;
-import java.util.List;
-import java.util.concurrent.Callable;
-
-import de.danoeh.antennapod.PodcastApp;
-import de.danoeh.antennapod.preferences.PlaybackPreferences;
-import de.danoeh.antennapod.storage.DBReader;
-import de.danoeh.antennapod.storage.DBWriter;
-import de.danoeh.antennapod.util.ChapterUtils;
-import de.danoeh.antennapod.util.playback.Playable;
-
-public class FeedMedia extends FeedFile implements Playable {
- private static final String TAG = "FeedMedia";
-
- public static final int FEEDFILETYPE_FEEDMEDIA = 2;
- public static final int PLAYABLE_TYPE_FEEDMEDIA = 1;
-
- public static final String PREF_MEDIA_ID = "FeedMedia.PrefMediaId";
- public static final String PREF_FEED_ID = "FeedMedia.PrefFeedId";
-
- private int duration;
- private int position; // Current position in file
- private int played_duration; // How many ms of this file have been played (for autoflattring)
- private long size; // File size in Byte
- private String mime_type;
- private volatile FeedItem item;
- private Date playbackCompletionDate;
-
- /* Used for loading item when restoring from parcel. */
- private long itemID;
-
- public FeedMedia(FeedItem i, String download_url, long size,
- String mime_type) {
- super(null, download_url, false);
- this.item = i;
- this.size = size;
- this.mime_type = mime_type;
- }
-
- public FeedMedia(long id, FeedItem item, int duration, int position,
- long size, String mime_type, String file_url, String download_url,
- boolean downloaded, Date playbackCompletionDate, int played_duration) {
- super(file_url, download_url, downloaded);
- this.id = id;
- this.item = item;
- this.duration = duration;
- this.position = position;
- this.played_duration = played_duration;
- this.size = size;
- this.mime_type = mime_type;
- this.playbackCompletionDate = playbackCompletionDate == null
- ? null : (Date) playbackCompletionDate.clone();
- }
-
- public FeedMedia(long id, FeedItem item) {
- super();
- this.id = id;
- this.item = item;
- }
-
- @Override
- public String getHumanReadableIdentifier() {
- if (item != null && item.getTitle() != null) {
- return item.getTitle();
- } else {
- return download_url;
- }
- }
-
- /**
- * Uses mimetype to determine the type of media.
- */
- public MediaType getMediaType() {
- if (mime_type == null || mime_type.isEmpty()) {
- return MediaType.UNKNOWN;
- } else {
- if (mime_type.startsWith("audio")) {
- return MediaType.AUDIO;
- } else if (mime_type.startsWith("video")) {
- return MediaType.VIDEO;
- } else if (mime_type.equals("application/ogg")) {
- return MediaType.AUDIO;
- }
- }
- return MediaType.UNKNOWN;
- }
-
- public void updateFromOther(FeedMedia other) {
- super.updateFromOther(other);
- if (other.size > 0) {
- size = other.size;
- }
- if (other.mime_type != null) {
- mime_type = other.mime_type;
- }
- }
-
- public boolean compareWithOther(FeedMedia other) {
- if (super.compareWithOther(other)) {
- return true;
- }
- if (other.mime_type != null) {
- if (mime_type == null || !mime_type.equals(other.mime_type)) {
- return true;
- }
- }
- if (other.size > 0 && other.size != size) {
- return true;
- }
- 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;
- }
-
- public int getDuration() {
- return duration;
- }
-
- public void setDuration(int duration) {
- this.duration = duration;
- }
-
- public int getPlayedDuration() {
- return played_duration;
- }
-
- public void setPlayedDuration(int played_duration) {
- this.played_duration = played_duration;
- }
-
- public int getPosition() {
- return position;
- }
-
- public void setPosition(int position) {
- this.position = position;
- }
-
- public long getSize() {
- return size;
- }
-
- public void setSize(long size) {
- this.size = size;
- }
-
- public String getMime_type() {
- return mime_type;
- }
-
- public void setMime_type(String mime_type) {
- this.mime_type = mime_type;
- }
-
- public FeedItem getItem() {
- return item;
- }
-
- /**
- * Sets the item object of this FeedMedia. If the given
- * FeedItem object is not null, it's 'media'-attribute value
- * will also be set to this media object.
- */
- public void setItem(FeedItem item) {
- this.item = item;
- if (item != null && item.getMedia() != this) {
- item.setMedia(this);
- }
- }
-
- public Date getPlaybackCompletionDate() {
- return playbackCompletionDate == null
- ? null : (Date) playbackCompletionDate.clone();
- }
-
- public void setPlaybackCompletionDate(Date playbackCompletionDate) {
- this.playbackCompletionDate = playbackCompletionDate == null
- ? null : (Date) playbackCompletionDate.clone();
- }
-
- public boolean isInProgress() {
- return (this.position > 0);
- }
-
- public FeedImage getImage() {
- if (item != null) {
- return (item.hasItemImageDownloaded()) ? item.getImage() : item.getFeed().getImage();
- }
- return null;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeLong(id);
- dest.writeLong(item.getId());
-
- dest.writeInt(duration);
- dest.writeInt(position);
- dest.writeLong(size);
- dest.writeString(mime_type);
- dest.writeString(file_url);
- dest.writeString(download_url);
- dest.writeByte((byte) ((downloaded) ? 1 : 0));
- dest.writeLong((playbackCompletionDate != null) ? playbackCompletionDate.getTime() : 0);
- dest.writeInt(played_duration);
- }
-
- @Override
- public void writeToPreferences(Editor prefEditor) {
- prefEditor.putLong(PREF_FEED_ID, item.getFeed().getId());
- prefEditor.putLong(PREF_MEDIA_ID, id);
- }
-
- @Override
- public void loadMetadata() throws PlayableException {
- if (item == null && itemID != 0) {
- item = DBReader.getFeedItem(PodcastApp.getInstance(), itemID);
- }
- }
-
- @Override
- public void loadChapterMarks() {
- if (getChapters() == null && !localFileAvailable()) {
- ChapterUtils.loadChaptersFromStreamUrl(this);
- if (getChapters() != null && item != null) {
- DBWriter.setFeedItem(PodcastApp.getInstance(),
- item);
- }
- }
-
- }
-
- @Override
- public String getEpisodeTitle() {
- if (item == null) {
- return null;
- }
- if (getItem().getTitle() != null) {
- return getItem().getTitle();
- } else {
- return getItem().getIdentifyingValue();
- }
- }
-
- @Override
- public List<Chapter> getChapters() {
- if (item == null) {
- return null;
- }
- return getItem().getChapters();
- }
-
- @Override
- public String getWebsiteLink() {
- if (item == null) {
- return null;
- }
- return getItem().getLink();
- }
-
- @Override
- public String getFeedTitle() {
- if (item == null) {
- return null;
- }
- return getItem().getFeed().getTitle();
- }
-
- @Override
- public Object getIdentifier() {
- return id;
- }
-
- @Override
- public String getLocalMediaUrl() {
- return file_url;
- }
-
- @Override
- public String getStreamUrl() {
- return download_url;
- }
-
- @Override
- public String getPaymentLink() {
- if (item == null) {
- return null;
- }
- return getItem().getPaymentLink();
- }
-
- @Override
- public boolean localFileAvailable() {
- return isDownloaded() && file_url != null;
- }
-
- @Override
- public boolean streamAvailable() {
- return download_url != null;
- }
-
- @Override
- public void saveCurrentPosition(SharedPreferences pref, int newPosition) {
- setPosition(newPosition);
- DBWriter.setFeedMediaPlaybackInformation(PodcastApp.getInstance(), this);
- }
-
- @Override
- public void onPlaybackStart() {
- }
-
- @Override
- public void onPlaybackCompleted() {
-
- }
-
- @Override
- public int getPlayableType() {
- return PLAYABLE_TYPE_FEEDMEDIA;
- }
-
- @Override
- public void setChapters(List<Chapter> chapters) {
- getItem().setChapters(chapters);
- }
-
- @Override
- public Callable<String> loadShownotes() {
- return new Callable<String>() {
- @Override
- public String call() throws Exception {
- if (item == null) {
- item = DBReader.getFeedItem(PodcastApp.getInstance(), itemID);
- }
- if (item.getContentEncoded() == null || item.getDescription() == null) {
- DBReader.loadExtraInformationOfFeedItem(PodcastApp.getInstance(), item);
-
- }
- return (item.getContentEncoded() != null) ? item.getContentEncoded() : item.getDescription();
- }
- };
- }
-
- public static final Parcelable.Creator<FeedMedia> CREATOR = new Parcelable.Creator<FeedMedia>() {
- public FeedMedia createFromParcel(Parcel in) {
- final long id = in.readLong();
- final long itemID = in.readLong();
- FeedMedia result = new FeedMedia(id, null, in.readInt(), in.readInt(), in.readLong(), in.readString(), in.readString(),
- in.readString(), in.readByte() != 0, new Date(in.readLong()), in.readInt());
- result.itemID = itemID;
- return result;
- }
-
- public FeedMedia[] newArray(int size) {
- return new FeedMedia[size];
- }
- };
-
- @Override
- public Uri getImageUri() {
- final Uri feedImgUri = getFeedImageUri();
-
- if (localFileAvailable()) {
- Uri.Builder builder = new Uri.Builder();
- builder.scheme(SCHEME_MEDIA)
- .encodedPath(getLocalMediaUrl());
- if (feedImgUri != null) {
- builder.appendQueryParameter(PARAM_FALLBACK, feedImgUri.toString());
- }
- return builder.build();
- } else {
- return feedImgUri;
- }
- }
-
- private Uri getFeedImageUri() {
- if (item != null && item.getFeed() != null) {
- return item.getFeed().getImageUri();
- } else {
- return null;
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/feed/FeedPreferences.java b/src/de/danoeh/antennapod/feed/FeedPreferences.java
deleted file mode 100644
index 29bc5ef0c..000000000
--- a/src/de/danoeh/antennapod/feed/FeedPreferences.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package de.danoeh.antennapod.feed;
-
-import android.content.Context;
-import de.danoeh.antennapod.storage.DBWriter;
-import org.apache.commons.lang3.StringUtils;
-
-/**
- * Contains preferences for a single feed.
- */
-public class FeedPreferences {
-
- private long feedID;
- private boolean autoDownload;
- private String username;
- private String password;
-
- public FeedPreferences(long feedID, boolean autoDownload, String username, String password) {
- this.feedID = feedID;
- this.autoDownload = autoDownload;
- this.username = username;
- this.password = password;
- }
-
-
- /**
- * Compare another FeedPreferences with this one. The feedID and autoDownload attribute are excluded from the
- * comparison.
- *
- * @return True if the two objects are different.
- */
- public boolean compareWithOther(FeedPreferences other) {
- if (other == null)
- return true;
- if (!StringUtils.equals(username, other.username)) {
- return true;
- }
- if (!StringUtils.equals(password, other.password)) {
- return true;
- }
- return false;
- }
-
- /**
- * Update this FeedPreferences object from another one. The feedID and autoDownload attributes are excluded
- * from the update.
- */
- public void updateFromOther(FeedPreferences other) {
- if (other == null)
- return;
- this.username = other.username;
- this.password = other.password;
- }
-
- public long getFeedID() {
- return feedID;
- }
-
- public void setFeedID(long feedID) {
- this.feedID = feedID;
- }
-
- public boolean getAutoDownload() {
- return autoDownload;
- }
-
- public void setAutoDownload(boolean autoDownload) {
- this.autoDownload = autoDownload;
- }
-
- public void save(Context context) {
- DBWriter.setFeedPreferences(context, this);
- }
-
- public String getUsername() {
- return username;
- }
-
- public void setUsername(String username) {
- this.username = username;
- }
-
- public String getPassword() {
- return password;
- }
-
- public void setPassword(String password) {
- this.password = password;
- }
-}
diff --git a/src/de/danoeh/antennapod/feed/ID3Chapter.java b/src/de/danoeh/antennapod/feed/ID3Chapter.java
deleted file mode 100644
index 6dde7854e..000000000
--- a/src/de/danoeh/antennapod/feed/ID3Chapter.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package de.danoeh.antennapod.feed;
-
-public class ID3Chapter extends Chapter {
- public static final int CHAPTERTYPE_ID3CHAPTER = 2;
-
- /**
- * Identifies the chapter in its ID3 tag. This attribute does not have to be
- * store in the DB and is only used for parsing.
- */
- private String id3ID;
-
- public ID3Chapter(String id3ID, long start) {
- super(start);
- this.id3ID = id3ID;
- }
-
- public ID3Chapter(long start, String title, FeedItem item, String link) {
- super(start, title, item, link);
- }
-
- @Override
- public String toString() {
- return "ID3Chapter [id3ID=" + id3ID + ", title=" + title + ", start="
- + start + ", url=" + link + "]";
- }
-
- @Override
- public int getChapterType() {
- return CHAPTERTYPE_ID3CHAPTER;
- }
-
- public String getId3ID() {
- return id3ID;
- }
-
-}
diff --git a/src/de/danoeh/antennapod/feed/MediaType.java b/src/de/danoeh/antennapod/feed/MediaType.java
deleted file mode 100644
index 324d0a221..000000000
--- a/src/de/danoeh/antennapod/feed/MediaType.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package de.danoeh.antennapod.feed;
-
-public enum MediaType {
- AUDIO, VIDEO, UNKNOWN
-}
diff --git a/src/de/danoeh/antennapod/feed/SearchResult.java b/src/de/danoeh/antennapod/feed/SearchResult.java
deleted file mode 100644
index 1cba389ec..000000000
--- a/src/de/danoeh/antennapod/feed/SearchResult.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package de.danoeh.antennapod.feed;
-
-public class SearchResult {
- private FeedComponent component;
- /** Additional information (e.g. where it was found) */
- private String subtitle;
- /** Higher value means more importance */
- private int value;
-
- public SearchResult(FeedComponent component, int value, String subtitle) {
- super();
- this.component = component;
- this.value = value;
- this.subtitle = subtitle;
- }
-
- public FeedComponent getComponent() {
- return component;
- }
-
- public String getSubtitle() {
- return subtitle;
- }
-
- public void setSubtitle(String subtitle) {
- this.subtitle = subtitle;
- }
-
- public int getValue() {
- return value;
- }
-
-
-}
diff --git a/src/de/danoeh/antennapod/feed/SimpleChapter.java b/src/de/danoeh/antennapod/feed/SimpleChapter.java
deleted file mode 100644
index 3dab1b74d..000000000
--- a/src/de/danoeh/antennapod/feed/SimpleChapter.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package de.danoeh.antennapod.feed;
-
-public class SimpleChapter extends Chapter {
- public static final int CHAPTERTYPE_SIMPLECHAPTER = 0;
-
- public SimpleChapter(long start, String title, FeedItem item, String link) {
- super(start, title, item, link);
- }
-
- @Override
- public int getChapterType() {
- return CHAPTERTYPE_SIMPLECHAPTER;
- }
-
- public void updateFromOther(SimpleChapter other) {
- super.updateFromOther(other);
- start = other.start;
- if (other.title != null) {
- title = other.title;
- }
- if (other.link != null) {
- link = other.link;
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/feed/VorbisCommentChapter.java b/src/de/danoeh/antennapod/feed/VorbisCommentChapter.java
deleted file mode 100644
index 59844ae1f..000000000
--- a/src/de/danoeh/antennapod/feed/VorbisCommentChapter.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package de.danoeh.antennapod.feed;
-
-import de.danoeh.antennapod.util.vorbiscommentreader.VorbisCommentReaderException;
-
-import java.util.concurrent.TimeUnit;
-
-public class VorbisCommentChapter extends Chapter {
- public static final int CHAPTERTYPE_VORBISCOMMENT_CHAPTER = 3;
-
- private static final int CHAPTERXXX_LENGTH = "chapterxxx".length();
-
- private int vorbisCommentId;
-
- public VorbisCommentChapter(int vorbisCommentId) {
- this.vorbisCommentId = vorbisCommentId;
- }
-
- public VorbisCommentChapter(long start, String title, FeedItem item,
- String link) {
- super(start, title, item, link);
- }
-
- @Override
- public String toString() {
- return "VorbisCommentChapter [id=" + id + ", title=" + title
- + ", link=" + link + ", start=" + start + "]";
- }
-
- public static long getStartTimeFromValue(String value)
- throws VorbisCommentReaderException {
- String[] parts = value.split(":");
- if (parts.length >= 3) {
- try {
- long hours = TimeUnit.MILLISECONDS.convert(
- Long.parseLong(parts[0]), TimeUnit.HOURS);
- long minutes = TimeUnit.MILLISECONDS.convert(
- Long.parseLong(parts[1]), TimeUnit.MINUTES);
- if (parts[2].contains("-->")) {
- parts[2] = parts[2].substring(0, parts[2].indexOf("-->"));
- }
- long seconds = TimeUnit.MILLISECONDS.convert(
- ((long) Float.parseFloat(parts[2])), TimeUnit.SECONDS);
- return hours + minutes + seconds;
- } catch (NumberFormatException e) {
- throw new VorbisCommentReaderException(e);
- }
- } else {
- throw new VorbisCommentReaderException("Invalid time string");
- }
- }
-
- /**
- * Return the id of a vorbiscomment chapter from a string like CHAPTERxxx*
- *
- * @return the id of the chapter key or -1 if the id couldn't be read.
- * @throws VorbisCommentReaderException
- * */
- public static int getIDFromKey(String key)
- throws VorbisCommentReaderException {
- if (key.length() >= CHAPTERXXX_LENGTH) { // >= CHAPTERxxx
- try {
- String strId = key.substring(8, 10);
- return Integer.parseInt(strId);
- } catch (NumberFormatException e) {
- throw new VorbisCommentReaderException(e);
- }
- }
- throw new VorbisCommentReaderException("key is too short (" + key + ")");
- }
-
- /**
- * Get the string that comes after 'CHAPTERxxx', for example 'name' or
- * 'url'.
- */
- public static String getAttributeTypeFromKey(String key) {
- if (key.length() > CHAPTERXXX_LENGTH) {
- return key.substring(CHAPTERXXX_LENGTH, key.length());
- }
- return null;
- }
-
- @Override
- public int getChapterType() {
- return CHAPTERTYPE_VORBISCOMMENT_CHAPTER;
- }
-
- public void setTitle(String title) {
- this.title = title;
- }
-
- public void setLink(String link) {
- this.link = link;
- }
-
- public void setStart(long start) {
- this.start = start;
- }
-
- public int getVorbisCommentId() {
- return vorbisCommentId;
- }
-
- public void setVorbisCommentId(int vorbisCommentId) {
- this.vorbisCommentId = vorbisCommentId;
- }
-
-
-
-}
diff --git a/src/de/danoeh/antennapod/fragment/AddFeedFragment.java b/src/de/danoeh/antennapod/fragment/AddFeedFragment.java
deleted file mode 100644
index f5ae5a777..000000000
--- a/src/de/danoeh/antennapod/fragment/AddFeedFragment.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package de.danoeh.antennapod.fragment;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.EditText;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.DefaultOnlineFeedViewActivity;
-import de.danoeh.antennapod.activity.MainActivity;
-import de.danoeh.antennapod.activity.OnlineFeedViewActivity;
-import de.danoeh.antennapod.activity.OpmlImportFromPathActivity;
-import de.danoeh.antennapod.fragment.gpodnet.GpodnetMainFragment;
-
-/**
- * Provides actions for adding new podcast subscriptions
- */
-public class AddFeedFragment extends Fragment {
- private static final String TAG = "AddFeedFragment";
-
- /**
- * Preset value for url text field.
- */
- public static final String ARG_FEED_URL = "feedurl";
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- super.onCreateView(inflater, container, savedInstanceState);
- View root = inflater.inflate(R.layout.addfeed, container, false);
-
- final EditText etxtFeedurl = (EditText) root.findViewById(R.id.etxtFeedurl);
-
- Bundle args = getArguments();
- if (args != null && args.getString(ARG_FEED_URL) != null) {
- etxtFeedurl.setText(args.getString(ARG_FEED_URL));
- }
-
- Button butBrowserGpoddernet = (Button) root.findViewById(R.id.butBrowseGpoddernet);
- Button butOpmlImport = (Button) root.findViewById(R.id.butOpmlImport);
- Button butConfirm = (Button) root.findViewById(R.id.butConfirm);
-
- final MainActivity activity = (MainActivity) getActivity();
- activity.getMainActivtyActionBar().setTitle(R.string.add_feed_label);
-
- butBrowserGpoddernet.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- activity.loadChildFragment(new GpodnetMainFragment());
- }
- });
-
- butOpmlImport.setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View v) {
- startActivity(new Intent(getActivity(),
- OpmlImportFromPathActivity.class));
- }
- });
-
- butConfirm.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(getActivity(), DefaultOnlineFeedViewActivity.class);
- intent.putExtra(OnlineFeedViewActivity.ARG_FEEDURL, etxtFeedurl.getText().toString());
- intent.putExtra(OnlineFeedViewActivity.ARG_TITLE, getString(R.string.add_feed_label));
- startActivity(intent);
- }
- });
-
- return root;
- }
-}
diff --git a/src/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java b/src/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
deleted file mode 100644
index 082fe93fc..000000000
--- a/src/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
+++ /dev/null
@@ -1,196 +0,0 @@
-package de.danoeh.antennapod.fragment;
-
-import android.app.Activity;
-import android.content.Context;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.support.v4.app.ListFragment;
-import android.view.View;
-import android.widget.ListView;
-import de.danoeh.antennapod.adapter.DownloadedEpisodesListAdapter;
-import de.danoeh.antennapod.dialog.FeedItemDialog;
-import de.danoeh.antennapod.feed.EventDistributor;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.storage.DBReader;
-import de.danoeh.antennapod.storage.DBWriter;
-import de.danoeh.antennapod.util.QueueAccess;
-
-import java.util.List;
-
-/**
- * Displays all running downloads and provides a button to delete them
- */
-public class CompletedDownloadsFragment extends ListFragment {
- private static final int EVENTS =
- EventDistributor.DOWNLOAD_HANDLED |
- EventDistributor.DOWNLOADLOG_UPDATE |
- EventDistributor.QUEUE_UPDATE |
- EventDistributor.UNREAD_ITEMS_UPDATE;
-
- private List<FeedItem> items;
- private QueueAccess queue;
- private DownloadedEpisodesListAdapter listAdapter;
-
- private boolean viewCreated = false;
- private boolean itemsLoaded = false;
-
- private FeedItemDialog feedItemDialog;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- startItemLoader();
- }
-
- @Override
- public void onStart() {
- super.onStart();
- EventDistributor.getInstance().register(contentUpdate);
- }
-
- @Override
- public void onStop() {
- super.onStop();
- EventDistributor.getInstance().unregister(contentUpdate);
- stopItemLoader();
- }
-
- @Override
- public void onDetach() {
- super.onDetach();
- stopItemLoader();
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- listAdapter = null;
- viewCreated = false;
- feedItemDialog = null;
- stopItemLoader();
- }
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- if (viewCreated && itemsLoaded) {
- onFragmentLoaded();
- }
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- viewCreated = true;
- if (itemsLoaded && getActivity() != null) {
- onFragmentLoaded();
- }
- }
-
- @Override
- public void onListItemClick(ListView l, View v, int position, long id) {
- super.onListItemClick(l, v, position, id);
- FeedItem item = listAdapter.getItem(position - l.getHeaderViewsCount());
- if (item != null) {
- feedItemDialog = FeedItemDialog.newInstance(getActivity(), item, queue);
- feedItemDialog.show();
- }
-
- }
-
- private void onFragmentLoaded() {
- if (listAdapter == null) {
- listAdapter = new DownloadedEpisodesListAdapter(getActivity(), itemAccess);
- setListAdapter(listAdapter);
- }
- setListShown(true);
- listAdapter.notifyDataSetChanged();
- if (feedItemDialog != null) {
- boolean res = feedItemDialog.updateContent(queue, items);
- if (!res && feedItemDialog.isShowing()) {
- feedItemDialog.dismiss();
- }
- }
- }
-
- private DownloadedEpisodesListAdapter.ItemAccess itemAccess = new DownloadedEpisodesListAdapter.ItemAccess() {
- @Override
- public int getCount() {
- return (items != null) ? items.size() : 0;
- }
-
- @Override
- public FeedItem getItem(int position) {
- return (items != null) ? items.get(position) : null;
- }
-
- @Override
- public void onFeedItemSecondaryAction(FeedItem item) {
- DBWriter.deleteFeedMediaOfItem(getActivity(), item.getMedia().getId());
- }
- };
-
- private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
- @Override
- public void update(EventDistributor eventDistributor, Integer arg) {
- if ((arg & EventDistributor.DOWNLOAD_QUEUED) != 0) {
- if (feedItemDialog != null && feedItemDialog.isShowing()) {
- feedItemDialog.updateMenuAppearance();
- }
- } else if ((arg & EVENTS) != 0) {
- startItemLoader();
- }
- }
- };
-
- private ItemLoader itemLoader;
-
- private void startItemLoader() {
- if (itemLoader != null) {
- itemLoader.cancel(true);
- }
- itemLoader = new ItemLoader();
- itemLoader.execute();
- }
-
- private void stopItemLoader() {
- if (itemLoader != null) {
- itemLoader.cancel(true);
- }
- }
-
- private class ItemLoader extends AsyncTask<Void, Void, Object[]> {
-
- @Override
- protected void onPreExecute() {
- super.onPreExecute();
- if (!itemsLoaded && viewCreated) {
- setListShown(false);
- }
- }
-
- @Override
- protected void onPostExecute(Object[] results) {
- super.onPostExecute(results);
- if (results != null) {
- items = (List<FeedItem>) results[0];
- queue = (QueueAccess) results[1];
- itemsLoaded = true;
- if (viewCreated && getActivity() != null) {
- onFragmentLoaded();
- }
- }
- }
-
- @Override
- protected Object[] doInBackground(Void... params) {
- Context context = getActivity();
- if (context != null) {
- return new Object[]{DBReader.getDownloadedItems(context),
- QueueAccess.IDListAccess(DBReader.getQueueIDList(context))};
- }
- return null;
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/fragment/CoverFragment.java b/src/de/danoeh/antennapod/fragment/CoverFragment.java
deleted file mode 100644
index ffce518bf..000000000
--- a/src/de/danoeh/antennapod/fragment/CoverFragment.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package de.danoeh.antennapod.fragment;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.AudioplayerActivity.AudioplayerContentFragment;
-import de.danoeh.antennapod.asynctask.PicassoProvider;
-import de.danoeh.antennapod.util.playback.Playable;
-
-/**
- * Displays the cover and the title of a FeedItem.
- */
-public class CoverFragment extends Fragment implements
- AudioplayerContentFragment {
- private static final String TAG = "CoverFragment";
- private static final String ARG_PLAYABLE = "arg.playable";
-
- private Playable media;
-
- private ImageView imgvCover;
-
- private boolean viewCreated = false;
-
- public static CoverFragment newInstance(Playable item) {
- CoverFragment f = new CoverFragment();
- if (item != null) {
- Bundle args = new Bundle();
- args.putParcelable(ARG_PLAYABLE, item);
- f.setArguments(args);
- }
- return f;
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setRetainInstance(true);
- Bundle args = getArguments();
- if (args != null) {
- media = args.getParcelable(ARG_PLAYABLE);
- } else {
- Log.e(TAG, TAG + " was called with invalid arguments");
- }
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- View root = inflater.inflate(R.layout.cover_fragment, container, false);
- imgvCover = (ImageView) root.findViewById(R.id.imgvCover);
- viewCreated = true;
- return root;
- }
-
- private void loadMediaInfo() {
- if (media != null) {
- imgvCover.post(new Runnable() {
-
- @Override
- public void run() {
- Context c = getActivity();
- if (c != null) {
- PicassoProvider.getMediaMetadataPicassoInstance(c)
- .load(media.getImageUri())
- .into(imgvCover);
- }
- }
- });
- } else {
- Log.w(TAG, "loadMediaInfo was called while media was null");
- }
- }
-
- @Override
- public void onStart() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "On Start");
- super.onStart();
- if (media != null) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Loading media info");
- loadMediaInfo();
- } else {
- Log.w(TAG, "Unable to load media info: media was null");
- }
- }
-
- @Override
- public void onDataSetChanged(Playable media) {
- this.media = media;
- if (viewCreated) {
- loadMediaInfo();
- }
-
- }
-
-}
diff --git a/src/de/danoeh/antennapod/fragment/DownloadLogFragment.java b/src/de/danoeh/antennapod/fragment/DownloadLogFragment.java
deleted file mode 100644
index d81ba4b86..000000000
--- a/src/de/danoeh/antennapod/fragment/DownloadLogFragment.java
+++ /dev/null
@@ -1,121 +0,0 @@
-package de.danoeh.antennapod.fragment;
-
-import android.content.Context;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.support.v4.app.ListFragment;
-import android.view.View;
-import de.danoeh.antennapod.adapter.DownloadLogAdapter;
-import de.danoeh.antennapod.feed.EventDistributor;
-import de.danoeh.antennapod.service.download.DownloadStatus;
-import de.danoeh.antennapod.storage.DBReader;
-
-import java.util.List;
-
-/**
- * Shows the download log
- */
-public class DownloadLogFragment extends ListFragment {
-
- private List<DownloadStatus> downloadLog;
- private DownloadLogAdapter adapter;
-
- private boolean viewsCreated = false;
- private boolean itemsLoaded = false;
-
- @Override
- public void onStart() {
- super.onStart();
- EventDistributor.getInstance().register(contentUpdate);
- startItemLoader();
- }
-
- @Override
- public void onStop() {
- super.onStop();
- EventDistributor.getInstance().unregister(contentUpdate);
- stopItemLoader();
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- viewsCreated = true;
- if (itemsLoaded) {
- onFragmentLoaded();
- }
- }
-
- private void onFragmentLoaded() {
- if (adapter == null) {
- adapter = new DownloadLogAdapter(getActivity(), itemAccess);
- setListAdapter(adapter);
- }
- setListShown(true);
- adapter.notifyDataSetChanged();
-
- }
-
- private DownloadLogAdapter.ItemAccess itemAccess = new DownloadLogAdapter.ItemAccess() {
-
- @Override
- public int getCount() {
- return (downloadLog != null) ? downloadLog.size() : 0;
- }
-
- @Override
- public DownloadStatus getItem(int position) {
- return (downloadLog != null) ? downloadLog.get(position) : null;
- }
- };
-
- private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
-
- @Override
- public void update(EventDistributor eventDistributor, Integer arg) {
- if ((arg & EventDistributor.DOWNLOADLOG_UPDATE) != 0) {
- startItemLoader();
- }
- }
- };
-
- private ItemLoader itemLoader;
-
- private void startItemLoader() {
- if (itemLoader != null) {
- itemLoader.cancel(true);
- }
- itemLoader = new ItemLoader();
- itemLoader.execute();
- }
-
- private void stopItemLoader() {
- if (itemLoader != null) {
- itemLoader.cancel(true);
- }
- }
-
- private class ItemLoader extends AsyncTask<Void, Void, List<DownloadStatus>> {
-
- @Override
- protected void onPostExecute(List<DownloadStatus> downloadStatuses) {
- super.onPostExecute(downloadStatuses);
- if (downloadStatuses != null) {
- downloadLog = downloadStatuses;
- itemsLoaded = true;
- if (viewsCreated) {
- onFragmentLoaded();
- }
- }
- }
-
- @Override
- protected List<DownloadStatus> doInBackground(Void... params) {
- Context context = getActivity();
- if (context != null) {
- return DBReader.getDownloadLog(context);
- }
- return null;
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/fragment/DownloadsFragment.java b/src/de/danoeh/antennapod/fragment/DownloadsFragment.java
deleted file mode 100644
index 5a71cb36b..000000000
--- a/src/de/danoeh/antennapod/fragment/DownloadsFragment.java
+++ /dev/null
@@ -1,145 +0,0 @@
-package de.danoeh.antennapod.fragment;
-
-import android.app.Activity;
-import android.content.res.Resources;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
-import android.support.v4.app.FragmentPagerAdapter;
-import android.support.v4.app.FragmentTransaction;
-import android.support.v4.view.ViewPager;
-import android.support.v7.app.ActionBar;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.MainActivity;
-
-/**
- * Shows the CompletedDownloadsFragment and the RunningDownloadsFragment
- */
-public class DownloadsFragment extends Fragment {
-
- public static final String ARG_SELECTED_TAB = "selected_tab";
-
- public static final int POS_RUNNING = 0;
- public static final int POS_COMPLETED = 1;
- public static final int POS_LOG = 2;
-
- private ViewPager pager;
- private MainActivity activity;
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- super.onCreateView(inflater, container, savedInstanceState);
- View root = inflater.inflate(R.layout.pager_fragment, container, false);
- pager = (ViewPager) root.findViewById(R.id.pager);
- DownloadsPagerAdapter pagerAdapter = new DownloadsPagerAdapter(getChildFragmentManager(), getResources());
- pager.setAdapter(pagerAdapter);
- final ActionBar actionBar = activity.getMainActivtyActionBar();
- actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
- ActionBar.TabListener tabListener = new ActionBar.TabListener() {
- @Override
- public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
- pager.setCurrentItem(tab.getPosition());
- }
-
- @Override
- public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
-
- }
-
- @Override
- public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
-
- }
- };
- actionBar.removeAllTabs();
- actionBar.addTab(actionBar.newTab()
- .setText(R.string.downloads_running_label)
- .setTabListener(tabListener));
- actionBar.addTab(actionBar.newTab()
- .setText(R.string.downloads_completed_label)
- .setTabListener(tabListener));
- actionBar.addTab(actionBar.newTab()
- .setText(R.string.downloads_log_label)
- .setTabListener(tabListener));
-
- pager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
- @Override
- public void onPageSelected(int position) {
- super.onPageSelected(position);
- actionBar.setSelectedNavigationItem(position);
- }
- });
- return root;
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- if (getArguments() != null) {
- int tab = getArguments().getInt(ARG_SELECTED_TAB);
- pager.setCurrentItem(tab, false);
- }
- }
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- this.activity = (MainActivity) activity;
- }
-
- @Override
- public void onDetach() {
- super.onDetach();
- activity.getMainActivtyActionBar().removeAllTabs();
- activity.getMainActivtyActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
- }
-
- public class DownloadsPagerAdapter extends FragmentPagerAdapter {
-
-
-
-
- Resources resources;
-
- public DownloadsPagerAdapter(FragmentManager fm, Resources resources) {
- super(fm);
- this.resources = resources;
- }
-
- @Override
- public Fragment getItem(int position) {
- switch (position) {
- case POS_RUNNING:
- return new RunningDownloadsFragment();
- case POS_COMPLETED:
- return new CompletedDownloadsFragment();
- case POS_LOG:
- return new DownloadLogFragment();
- default:
- return null;
- }
- }
-
- @Override
- public int getCount() {
- return 3;
- }
-
- @Override
- public CharSequence getPageTitle(int position) {
- switch (position) {
- case POS_RUNNING:
- return resources.getString(R.string.downloads_running_label);
- case POS_COMPLETED:
- return resources.getString(R.string.downloads_completed_label);
- case POS_LOG:
- return resources.getString(R.string.downloads_log_label);
- default:
- return super.getPageTitle(position);
- }
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java b/src/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java
deleted file mode 100644
index 985673dd3..000000000
--- a/src/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java
+++ /dev/null
@@ -1,238 +0,0 @@
-package de.danoeh.antennapod.fragment;
-
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.asynctask.PicassoProvider;
-import de.danoeh.antennapod.service.playback.PlaybackService;
-import de.danoeh.antennapod.util.Converter;
-import de.danoeh.antennapod.util.playback.Playable;
-import de.danoeh.antennapod.util.playback.PlaybackController;
-
-/**
- * Fragment which is supposed to be displayed outside of the MediaplayerActivity
- * if the PlaybackService is running
- */
-public class ExternalPlayerFragment extends Fragment {
- private static final String TAG = "ExternalPlayerFragment";
-
- private ViewGroup fragmentLayout;
- private ImageView imgvCover;
- private ViewGroup layoutInfo;
- private TextView txtvTitle;
- private ImageButton butPlay;
-
- private PlaybackController controller;
-
- public ExternalPlayerFragment() {
- super();
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- View root = inflater.inflate(R.layout.external_player_fragment,
- container, false);
- fragmentLayout = (ViewGroup) root.findViewById(R.id.fragmentLayout);
- imgvCover = (ImageView) root.findViewById(R.id.imgvCover);
- layoutInfo = (ViewGroup) root.findViewById(R.id.layoutInfo);
- txtvTitle = (TextView) root.findViewById(R.id.txtvTitle);
- butPlay = (ImageButton) root.findViewById(R.id.butPlay);
-
- layoutInfo.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "layoutInfo was clicked");
-
- if (controller.getMedia() != null) {
- startActivity(PlaybackService.getPlayerActivityIntent(
- getActivity(), controller.getMedia()));
- }
- }
- });
- return root;
- }
-
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- controller = setupPlaybackController();
- butPlay.setOnClickListener(controller.newOnPlayButtonClickListener());
- }
-
- private PlaybackController setupPlaybackController() {
- return new PlaybackController(getActivity(), true) {
-
- @Override
- public void setupGUI() {
- }
-
- @Override
- public void onPositionObserverUpdate() {
- }
-
- @Override
- public void onReloadNotification(int code) {
- }
-
- @Override
- public void onBufferStart() {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void onBufferEnd() {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void onBufferUpdate(float progress) {
- }
-
- @Override
- public void onSleepTimerUpdate() {
- }
-
- @Override
- public void handleError(int code) {
- }
-
- @Override
- public ImageButton getPlayButton() {
- return butPlay;
- }
-
- @Override
- public void postStatusMsg(int msg) {
- }
-
- @Override
- public void clearStatusMsg() {
- }
-
- @Override
- public boolean loadMediaInfo() {
- ExternalPlayerFragment fragment = ExternalPlayerFragment.this;
- if (fragment != null) {
- return fragment.loadMediaInfo();
- } else {
- return false;
- }
- }
-
- @Override
- public void onAwaitingVideoSurface() {
- }
-
- @Override
- public void onServiceQueried() {
- }
-
- @Override
- public void onShutdownNotification() {
- if (fragmentLayout != null) {
- fragmentLayout.setVisibility(View.GONE);
- }
- controller = setupPlaybackController();
- if (butPlay != null) {
- butPlay.setOnClickListener(controller
- .newOnPlayButtonClickListener());
- }
-
- }
-
- @Override
- public void onPlaybackEnd() {
- if (fragmentLayout != null) {
- fragmentLayout.setVisibility(View.GONE);
- }
- controller = setupPlaybackController();
- if (butPlay != null) {
- butPlay.setOnClickListener(controller
- .newOnPlayButtonClickListener());
- }
- }
-
- @Override
- public void onPlaybackSpeedChange() {
- // TODO Auto-generated method stub
-
- }
- };
- }
-
- @Override
- public void onResume() {
- super.onResume();
- controller.init();
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Fragment is about to be destroyed");
- if (controller != null) {
- controller.release();
- }
- }
-
- @Override
- public void onPause() {
- super.onPause();
- if (controller != null) {
- controller.pause();
- }
- }
-
- private boolean loadMediaInfo() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Loading media info");
- if (controller.serviceAvailable()) {
- Playable media = controller.getMedia();
- if (media != null) {
- txtvTitle.setText(media.getEpisodeTitle());
-
- PicassoProvider.getMediaMetadataPicassoInstance(getActivity())
- .load(media.getImageUri())
- .fit()
- .into(imgvCover);
-
- fragmentLayout.setVisibility(View.VISIBLE);
- if (controller.isPlayingVideo()) {
- butPlay.setVisibility(View.GONE);
- } else {
- butPlay.setVisibility(View.VISIBLE);
- }
- return true;
- } else {
- Log.w(TAG,
- "loadMediaInfo was called while the media object of playbackService was null!");
- return false;
- }
- } else {
- Log.w(TAG,
- "loadMediaInfo was called while playbackService was null!");
- return false;
- }
- }
-
- private String getPositionString(int position, int duration) {
- return Converter.getDurationStringLong(position) + " / "
- + Converter.getDurationStringLong(duration);
- }
-}
diff --git a/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java b/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java
deleted file mode 100644
index 04c7fbf8e..000000000
--- a/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java
+++ /dev/null
@@ -1,476 +0,0 @@
-package de.danoeh.antennapod.fragment;
-
-import android.annotation.SuppressLint;
-import android.app.Activity;
-import android.content.ActivityNotFoundException;
-import android.content.ClipData;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Build;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v7.app.ActionBarActivity;
-import android.util.Log;
-import android.view.ContextMenu;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.webkit.WebSettings.LayoutAlgorithm;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-import android.widget.Toast;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.preferences.UserPreferences;
-import de.danoeh.antennapod.storage.DBReader;
-import de.danoeh.antennapod.util.Converter;
-import de.danoeh.antennapod.util.ShareUtils;
-import de.danoeh.antennapod.util.ShownotesProvider;
-import de.danoeh.antennapod.util.playback.Playable;
-import de.danoeh.antennapod.util.playback.PlaybackController;
-import de.danoeh.antennapod.util.playback.Timeline;
-
-/**
- * Displays the description of a Playable object in a Webview.
- */
-public class ItemDescriptionFragment extends Fragment {
-
- private static final String TAG = "ItemDescriptionFragment";
-
- private static final String PREF = "ItemDescriptionFragmentPrefs";
- private static final String PREF_SCROLL_Y = "prefScrollY";
- private static final String PREF_PLAYABLE_ID = "prefPlayableId";
-
- private static final String ARG_PLAYABLE = "arg.playable";
- private static final String ARG_FEEDITEM_ID = "arg.feeditem";
-
- private static final String ARG_SAVE_STATE = "arg.saveState";
- private static final String ARG_HIGHLIGHT_TIMECODES = "arg.highlightTimecodes";
-
- private WebView webvDescription;
-
- private ShownotesProvider shownotesProvider;
- private Playable media;
-
-
- private AsyncTask<Void, Void, Void> webViewLoader;
-
- /**
- * URL that was selected via long-press.
- */
- private String selectedURL;
-
- /**
- * True if Fragment should save its state (e.g. scrolling position) in a
- * shared preference.
- */
- private boolean saveState;
-
- /**
- * True if Fragment should highlight timecodes (e.g. time codes in the HH:MM:SS format).
- */
- private boolean highlightTimecodes;
-
- public static ItemDescriptionFragment newInstance(Playable media,
- boolean saveState,
- boolean highlightTimecodes) {
- ItemDescriptionFragment f = new ItemDescriptionFragment();
- Bundle args = new Bundle();
- args.putParcelable(ARG_PLAYABLE, media);
- args.putBoolean(ARG_SAVE_STATE, saveState);
- args.putBoolean(ARG_HIGHLIGHT_TIMECODES, highlightTimecodes);
- f.setArguments(args);
- return f;
- }
-
- public static ItemDescriptionFragment newInstance(FeedItem item, boolean saveState, boolean highlightTimecodes) {
- ItemDescriptionFragment f = new ItemDescriptionFragment();
- Bundle args = new Bundle();
- args.putLong(ARG_FEEDITEM_ID, item.getId());
- args.putBoolean(ARG_SAVE_STATE, saveState);
- args.putBoolean(ARG_HIGHLIGHT_TIMECODES, highlightTimecodes);
- f.setArguments(args);
- return f;
- }
-
- @SuppressLint("NewApi")
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Creating view");
- webvDescription = new WebView(getActivity());
- if (UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) {
- if (Build.VERSION.SDK_INT >= 11
- && Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
- webvDescription.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
- }
- webvDescription.setBackgroundColor(getResources().getColor(
- R.color.black));
- }
- webvDescription.getSettings().setUseWideViewPort(false);
- webvDescription.getSettings().setLayoutAlgorithm(
- LayoutAlgorithm.NARROW_COLUMNS);
- webvDescription.getSettings().setLoadWithOverviewMode(true);
- webvDescription.setOnLongClickListener(webViewLongClickListener);
- webvDescription.setWebViewClient(new WebViewClient() {
-
- @Override
- public boolean shouldOverrideUrlLoading(WebView view, String url) {
- if (Timeline.isTimecodeLink(url)) {
- onTimecodeLinkSelected(url);
- } else {
- Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
- try {
- startActivity(intent);
- } catch (ActivityNotFoundException e) {
- e.printStackTrace();
- return true;
- }
- }
- return true;
- }
-
- @Override
- public void onPageFinished(WebView view, String url) {
- super.onPageFinished(view, url);
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Page finished");
- // Restoring the scroll position might not always work
- view.postDelayed(new Runnable() {
-
- @Override
- public void run() {
- restoreFromPreference();
- }
-
- }, 50);
- }
-
- });
-
- registerForContextMenu(webvDescription);
- return webvDescription;
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- }
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Fragment attached");
- }
-
- @Override
- public void onDetach() {
- super.onDetach();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Fragment detached");
- if (webViewLoader != null) {
- webViewLoader.cancel(true);
- }
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Fragment destroyed");
- if (webViewLoader != null) {
- webViewLoader.cancel(true);
- }
- }
-
- @SuppressLint("NewApi")
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Creating fragment");
- Bundle args = getArguments();
- saveState = args.getBoolean(ARG_SAVE_STATE, false);
- highlightTimecodes = args.getBoolean(ARG_HIGHLIGHT_TIMECODES, false);
-
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- Bundle args = getArguments();
- if (args.containsKey(ARG_PLAYABLE)) {
- media = args.getParcelable(ARG_PLAYABLE);
- shownotesProvider = media;
- startLoader();
- } else if (args.containsKey(ARG_FEEDITEM_ID)) {
- AsyncTask<Void, Void, FeedItem> itemLoadTask = new AsyncTask<Void, Void, FeedItem>() {
-
- @Override
- protected FeedItem doInBackground(Void... voids) {
- return DBReader.getFeedItem(getActivity(), getArguments().getLong(ARG_FEEDITEM_ID));
- }
-
- @Override
- protected void onPostExecute(FeedItem feedItem) {
- super.onPostExecute(feedItem);
- shownotesProvider = feedItem;
- startLoader();
- }
- };
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- itemLoadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- } else {
- itemLoadTask.execute();
- }
- }
-
-
- }
-
- @Override
- public void onResume() {
- super.onResume();
- }
-
- @SuppressLint("NewApi")
- private void startLoader() {
- webViewLoader = createLoader();
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- webViewLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- } else {
- webViewLoader.execute();
- }
- }
-
- private View.OnLongClickListener webViewLongClickListener = new View.OnLongClickListener() {
-
- @Override
- public boolean onLongClick(View v) {
- WebView.HitTestResult r = webvDescription.getHitTestResult();
- if (r != null
- && r.getType() == WebView.HitTestResult.SRC_ANCHOR_TYPE) {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "Link of webview was long-pressed. Extra: "
- + r.getExtra()
- );
- selectedURL = r.getExtra();
- webvDescription.showContextMenu();
- return true;
- }
- selectedURL = null;
- return false;
- }
- };
-
- @SuppressWarnings("deprecation")
- @SuppressLint("NewApi")
- @Override
- public boolean onContextItemSelected(MenuItem item) {
- boolean handled = selectedURL != null;
- if (selectedURL != null) {
- switch (item.getItemId()) {
- case R.id.open_in_browser_item:
- Uri uri = Uri.parse(selectedURL);
- getActivity()
- .startActivity(new Intent(Intent.ACTION_VIEW, uri));
- break;
- case R.id.share_url_item:
- ShareUtils.shareLink(getActivity(), selectedURL);
- break;
- case R.id.copy_url_item:
- if (android.os.Build.VERSION.SDK_INT >= 11) {
- ClipData clipData = ClipData.newPlainText(selectedURL,
- selectedURL);
- android.content.ClipboardManager cm = (android.content.ClipboardManager) getActivity()
- .getSystemService(Context.CLIPBOARD_SERVICE);
- cm.setPrimaryClip(clipData);
- } else {
- android.text.ClipboardManager cm = (android.text.ClipboardManager) getActivity()
- .getSystemService(Context.CLIPBOARD_SERVICE);
- cm.setText(selectedURL);
- }
- Toast t = Toast.makeText(getActivity(),
- R.string.copied_url_msg, Toast.LENGTH_SHORT);
- t.show();
- break;
- case R.id.go_to_position_item:
- if (Timeline.isTimecodeLink(selectedURL)) {
- onTimecodeLinkSelected(selectedURL);
- } else {
- Log.e(TAG, "Selected go_to_position_item, but URL was no timecode link: " + selectedURL);
- }
- break;
- default:
- handled = false;
- break;
-
- }
- selectedURL = null;
- }
- return handled;
-
- }
-
- @Override
- public void onCreateContextMenu(ContextMenu menu, View v,
- ContextMenuInfo menuInfo) {
- if (selectedURL != null) {
- super.onCreateContextMenu(menu, v, menuInfo);
- if (Timeline.isTimecodeLink(selectedURL)) {
- menu.add(Menu.NONE, R.id.go_to_position_item, Menu.NONE,
- R.string.go_to_position_label);
- menu.setHeaderTitle(Converter.getDurationStringLong(Timeline.getTimecodeLinkTime(selectedURL)));
- } else {
- menu.add(Menu.NONE, R.id.open_in_browser_item, Menu.NONE,
- R.string.open_in_browser_label);
- menu.add(Menu.NONE, R.id.copy_url_item, Menu.NONE,
- R.string.copy_url_label);
- menu.add(Menu.NONE, R.id.share_url_item, Menu.NONE,
- R.string.share_url_label);
- menu.setHeaderTitle(selectedURL);
- }
- }
- }
-
- private AsyncTask<Void, Void, Void> createLoader() {
- return new AsyncTask<Void, Void, Void>() {
- @Override
- protected void onCancelled() {
- super.onCancelled();
- if (getActivity() != null) {
- ((ActionBarActivity) getActivity())
- .setSupportProgressBarIndeterminateVisibility(false);
- }
- webViewLoader = null;
- }
-
- String data;
-
- @Override
- protected void onPostExecute(Void result) {
- super.onPostExecute(result);
- // /webvDescription.loadData(url, "text/html", "utf-8");
- webvDescription.loadDataWithBaseURL(null, data, "text/html",
- "utf-8", "about:blank");
- if (getActivity() != null) {
- ((ActionBarActivity) getActivity())
- .setSupportProgressBarIndeterminateVisibility(false);
- }
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Webview loaded");
- webViewLoader = null;
- }
-
- @Override
- protected void onPreExecute() {
- super.onPreExecute();
- if (getActivity() != null) {
- ((ActionBarActivity) getActivity())
- .setSupportProgressBarIndeterminateVisibility(false);
- }
- }
-
- @Override
- protected Void doInBackground(Void... params) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Loading Webview");
- try {
- Activity activity = getActivity();
- if (activity != null) {
- Timeline timeline = new Timeline(activity, shownotesProvider);
- data = timeline.processShownotes(highlightTimecodes);
- } else {
- cancel(true);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
-
- };
- }
-
- @Override
- public void onPause() {
- super.onPause();
- savePreference();
- }
-
- private void savePreference() {
- if (saveState) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Saving preferences");
- SharedPreferences prefs = getActivity().getSharedPreferences(PREF,
- Activity.MODE_PRIVATE);
- SharedPreferences.Editor editor = prefs.edit();
- if (media != null && webvDescription != null) {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "Saving scroll position: "
- + webvDescription.getScrollY()
- );
- editor.putInt(PREF_SCROLL_Y, webvDescription.getScrollY());
- editor.putString(PREF_PLAYABLE_ID, media.getIdentifier()
- .toString());
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "savePreferences was called while media or webview was null");
- editor.putInt(PREF_SCROLL_Y, -1);
- editor.putString(PREF_PLAYABLE_ID, "");
- }
- editor.commit();
- }
- }
-
- private boolean restoreFromPreference() {
- if (saveState) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Restoring from preferences");
- Activity activity = getActivity();
- if (activity != null) {
- SharedPreferences prefs = activity.getSharedPreferences(
- PREF, Activity.MODE_PRIVATE);
- String id = prefs.getString(PREF_PLAYABLE_ID, "");
- int scrollY = prefs.getInt(PREF_SCROLL_Y, -1);
- if (scrollY != -1 && media != null
- && id.equals(media.getIdentifier().toString())
- && webvDescription != null) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Restored scroll Position: " + scrollY);
- webvDescription.scrollTo(webvDescription.getScrollX(),
- scrollY);
- return true;
- }
- }
- }
- return false;
- }
-
- private void onTimecodeLinkSelected(String link) {
- int time = Timeline.getTimecodeLinkTime(link);
- if (getActivity() != null && getActivity() instanceof ItemDescriptionFragmentCallback) {
- PlaybackController pc = ((ItemDescriptionFragmentCallback) getActivity()).getPlaybackController();
- if (pc != null) {
- pc.seekTo(time);
- }
- }
- }
-
- public interface ItemDescriptionFragmentCallback {
- public PlaybackController getPlaybackController();
- }
-}
diff --git a/src/de/danoeh/antennapod/fragment/ItemlistFragment.java b/src/de/danoeh/antennapod/fragment/ItemlistFragment.java
deleted file mode 100644
index 909774467..000000000
--- a/src/de/danoeh/antennapod/fragment/ItemlistFragment.java
+++ /dev/null
@@ -1,456 +0,0 @@
-package de.danoeh.antennapod.fragment;
-
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.os.Handler;
-import android.support.v4.app.ListFragment;
-import android.support.v7.app.ActionBarActivity;
-import android.support.v7.widget.SearchView;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.ListView;
-import android.widget.TextView;
-
-import org.apache.commons.lang3.Validate;
-
-import java.util.List;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.FeedInfoActivity;
-import de.danoeh.antennapod.activity.MainActivity;
-import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
-import de.danoeh.antennapod.adapter.FeedItemlistAdapter;
-import de.danoeh.antennapod.asynctask.DownloadObserver;
-import de.danoeh.antennapod.asynctask.FeedRemover;
-import de.danoeh.antennapod.asynctask.PicassoProvider;
-import de.danoeh.antennapod.dialog.ConfirmationDialog;
-import de.danoeh.antennapod.dialog.DownloadRequestErrorDialogCreator;
-import de.danoeh.antennapod.dialog.FeedItemDialog;
-import de.danoeh.antennapod.feed.EventDistributor;
-import de.danoeh.antennapod.feed.Feed;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.feed.FeedMedia;
-import de.danoeh.antennapod.service.download.DownloadService;
-import de.danoeh.antennapod.service.download.Downloader;
-import de.danoeh.antennapod.storage.DBReader;
-import de.danoeh.antennapod.storage.DownloadRequestException;
-import de.danoeh.antennapod.storage.DownloadRequester;
-import de.danoeh.antennapod.util.QueueAccess;
-import de.danoeh.antennapod.util.menuhandler.FeedMenuHandler;
-import de.danoeh.antennapod.util.menuhandler.MenuItemUtils;
-import de.danoeh.antennapod.util.menuhandler.NavDrawerActivity;
-
-/**
- * Displays a list of FeedItems.
- */
-@SuppressLint("ValidFragment")
-public class ItemlistFragment extends ListFragment {
- private static final String TAG = "ItemlistFragment";
-
- private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED
- | EventDistributor.DOWNLOAD_QUEUED
- | EventDistributor.QUEUE_UPDATE
- | EventDistributor.UNREAD_ITEMS_UPDATE;
-
- public static final String EXTRA_SELECTED_FEEDITEM = "extra.de.danoeh.antennapod.activity.selected_feeditem";
- public static final String ARGUMENT_FEED_ID = "argument.de.danoeh.antennapod.feed_id";
-
- protected FeedItemlistAdapter adapter;
-
- private long feedID;
- private Feed feed;
- protected QueueAccess queue;
-
- private boolean itemsLoaded = false;
- private boolean viewsCreated = false;
-
- private DownloadObserver downloadObserver;
- private List<Downloader> downloaderList;
-
- private FeedItemDialog feedItemDialog;
- private FeedItemDialog.FeedItemDialogSavedInstance feedItemDialogSavedInstance;
-
-
- /**
- * Creates new ItemlistFragment which shows the Feeditems of a specific
- * feed. Sets 'showFeedtitle' to false
- *
- * @param feedId The id of the feed to show
- * @return the newly created instance of an ItemlistFragment
- */
- public static ItemlistFragment newInstance(long feedId) {
- ItemlistFragment i = new ItemlistFragment();
- Bundle b = new Bundle();
- b.putLong(ARGUMENT_FEED_ID, feedId);
- i.setArguments(b);
- return i;
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setRetainInstance(true);
- setHasOptionsMenu(true);
-
- Bundle args = getArguments();
- Validate.notNull(args);
- feedID = args.getLong(ARGUMENT_FEED_ID);
- }
-
- @Override
- public void onStart() {
- super.onStart();
- EventDistributor.getInstance().register(contentUpdate);
- if (downloadObserver != null) {
- downloadObserver.setActivity(getActivity());
- downloadObserver.onResume();
- }
- if (viewsCreated && itemsLoaded) {
- onFragmentLoaded();
- }
- }
-
- @Override
- public void onStop() {
- super.onStop();
- EventDistributor.getInstance().unregister(contentUpdate);
- stopItemLoader();
- }
-
- @Override
- public void onResume() {
- super.onResume();
- updateProgressBarVisibility();
- startItemLoader();
- }
-
- @Override
- public void onDetach() {
- super.onDetach();
- stopItemLoader();
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- resetViewState();
- }
-
- private void resetViewState() {
- adapter = null;
- viewsCreated = false;
- if (downloadObserver != null) {
- downloadObserver.onPause();
- }
- if (feedItemDialog != null) {
- feedItemDialogSavedInstance = feedItemDialog.save();
- }
- feedItemDialog = null;
- }
-
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- super.onCreateOptionsMenu(menu, inflater);
-
- if (itemsLoaded && !MenuItemUtils.isActivityDrawerOpen((NavDrawerActivity) getActivity())) {
- FeedMenuHandler.onCreateOptionsMenu(inflater, menu);
-
- final SearchView sv = new SearchView(getActivity());
- MenuItemUtils.addSearchItem(menu, sv);
- sv.setQueryHint(getString(R.string.search_hint));
- sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
- @Override
- public boolean onQueryTextSubmit(String s) {
- sv.clearFocus();
- if (itemsLoaded) {
- ((MainActivity) getActivity()).loadChildFragment(SearchFragment.newInstance(s, feed.getId()));
- }
- return true;
- }
-
- @Override
- public boolean onQueryTextChange(String s) {
- return false;
- }
- });
- }
- }
-
- @Override
- public void onPrepareOptionsMenu(Menu menu) {
- if (itemsLoaded && !MenuItemUtils.isActivityDrawerOpen((NavDrawerActivity) getActivity())) {
- FeedMenuHandler.onPrepareOptionsMenu(menu, feed);
- }
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (!super.onOptionsItemSelected(item)) {
- try {
- if (!FeedMenuHandler.onOptionsItemClicked(getActivity(), item, feed)) {
- switch (item.getItemId()) {
- case R.id.remove_item:
- final FeedRemover remover = new FeedRemover(
- getActivity(), feed) {
- @Override
- protected void onPostExecute(Void result) {
- super.onPostExecute(result);
- ((MainActivity) getActivity()).loadNavFragment(MainActivity.POS_NEW, null);
- }
- };
- ConfirmationDialog conDialog = new ConfirmationDialog(getActivity(),
- R.string.remove_feed_label,
- R.string.feed_delete_confirmation_msg) {
-
- @Override
- public void onConfirmButtonPressed(
- DialogInterface dialog) {
- dialog.dismiss();
- remover.executeAsync();
- }
- };
- conDialog.createNewDialog().show();
- return true;
- default:
- return false;
-
- }
- } else {
- return true;
- }
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- DownloadRequestErrorDialogCreator.newRequestErrorDialog(getActivity(), e.getMessage());
- return true;
- }
- } else {
- return true;
- }
-
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- ((ActionBarActivity) getActivity()).getSupportActionBar().setTitle("");
-
- viewsCreated = true;
- if (itemsLoaded) {
- onFragmentLoaded();
- }
- }
-
- @Override
- public void onListItemClick(ListView l, View v, int position, long id) {
- FeedItem selection = adapter.getItem(position - l.getHeaderViewsCount());
- feedItemDialog = FeedItemDialog.newInstance(getActivity(), selection, queue);
- feedItemDialog.show();
- }
-
- private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
-
- @Override
- public void update(EventDistributor eventDistributor, Integer arg) {
- if ((EVENTS & arg) != 0) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Received contentUpdate Intent.");
- if ((EventDistributor.DOWNLOAD_QUEUED & arg) != 0) {
- updateProgressBarVisibility();
- } else {
- startItemLoader();
- updateProgressBarVisibility();
- }
- }
- }
- };
-
- private void updateProgressBarVisibility() {
- if (feed != null) {
- if (DownloadService.isRunning
- && DownloadRequester.getInstance().isDownloadingFile(feed)) {
- ((ActionBarActivity) getActivity())
- .setSupportProgressBarIndeterminateVisibility(true);
- } else {
- ((ActionBarActivity) getActivity())
- .setSupportProgressBarIndeterminateVisibility(false);
- }
- getActivity().supportInvalidateOptionsMenu();
- }
- }
-
- private void onFragmentLoaded() {
- if (adapter == null) {
- getListView().setAdapter(null);
- setupHeaderView();
- adapter = new FeedItemlistAdapter(getActivity(), itemAccess, new DefaultActionButtonCallback(getActivity()), false);
- setListAdapter(adapter);
- downloadObserver = new DownloadObserver(getActivity(), new Handler(), downloadObserverCallback);
- downloadObserver.onResume();
- }
- setListShown(true);
- adapter.notifyDataSetChanged();
-
- if (feedItemDialog != null) {
- feedItemDialog.updateContent(queue, feed.getItems());
- } else if (feedItemDialogSavedInstance != null) {
- feedItemDialog = FeedItemDialog.newInstance(getActivity(), feedItemDialogSavedInstance);
- }
- getActivity().supportInvalidateOptionsMenu();
- }
-
- private DownloadObserver.Callback downloadObserverCallback = new DownloadObserver.Callback() {
- @Override
- public void onContentChanged() {
- if (adapter != null) {
- adapter.notifyDataSetChanged();
- }
- if (feedItemDialog != null && feedItemDialog.isShowing()) {
- feedItemDialog.updateMenuAppearance();
- }
- }
-
- @Override
- public void onDownloadDataAvailable(List<Downloader> downloaderList) {
- ItemlistFragment.this.downloaderList = downloaderList;
- if (adapter != null) {
- adapter.notifyDataSetChanged();
- }
- }
- };
-
- private void setupHeaderView() {
- if (getListView() == null || feed == null) {
- Log.e(TAG, "Unable to setup listview: listView = null or feed = null");
- return;
- }
- ListView lv = getListView();
- LayoutInflater inflater = (LayoutInflater)
- getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View header = inflater.inflate(R.layout.feeditemlist_header, lv, false);
- lv.addHeaderView(header);
-
- TextView txtvTitle = (TextView) header.findViewById(R.id.txtvTitle);
- TextView txtvAuthor = (TextView) header.findViewById(R.id.txtvAuthor);
- ImageView imgvCover = (ImageView) header.findViewById(R.id.imgvCover);
- ImageButton butShowInfo = (ImageButton) header.findViewById(R.id.butShowInfo);
- ImageButton butVisitWebsite = (ImageButton) header.findViewById(R.id.butVisitWebsite);
-
- txtvTitle.setText(feed.getTitle());
- txtvAuthor.setText(feed.getAuthor());
-
- PicassoProvider.getDefaultPicassoInstance(getActivity())
- .load(feed.getImageUri())
- .fit()
- .into(imgvCover);
-
- if (feed.getLink() == null) {
- butVisitWebsite.setVisibility(View.INVISIBLE);
- } else {
- butVisitWebsite.setVisibility(View.VISIBLE);
- butVisitWebsite.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Uri uri = Uri.parse(feed.getLink());
- startActivity(new Intent(Intent.ACTION_VIEW, uri));
- }
- });
- }
- butShowInfo.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (viewsCreated && itemsLoaded) {
- Intent startIntent = new Intent(getActivity(), FeedInfoActivity.class);
- startIntent.putExtra(FeedInfoActivity.EXTRA_FEED_ID,
- feed.getId());
- startActivity(startIntent);
- }
- }
- });
- }
-
- private FeedItemlistAdapter.ItemAccess itemAccess = new FeedItemlistAdapter.ItemAccess() {
-
- @Override
- public FeedItem getItem(int position) {
- return (feed != null) ? feed.getItemAtIndex(true, position) : null;
- }
-
- @Override
- public int getCount() {
- return (feed != null) ? feed.getNumOfItems(true) : 0;
- }
-
- @Override
- public boolean isInQueue(FeedItem item) {
- return (queue != null) && queue.contains(item.getId());
- }
-
- @Override
- public int getItemDownloadProgressPercent(FeedItem item) {
- if (downloaderList != null) {
- for (Downloader downloader : downloaderList) {
- if (downloader.getDownloadRequest().getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA
- && downloader.getDownloadRequest().getFeedfileId() == item.getMedia().getId()) {
- return downloader.getDownloadRequest().getProgressPercent();
- }
- }
- }
- return 0;
- }
- };
-
- private ItemLoader itemLoader;
-
- private void startItemLoader() {
- if (itemLoader != null) {
- itemLoader.cancel(true);
- }
- itemLoader = new ItemLoader();
- itemLoader.execute(feedID);
- }
-
- private void stopItemLoader() {
- if (itemLoader != null) {
- itemLoader.cancel(true);
- }
- }
-
- private class ItemLoader extends AsyncTask<Long, Void, Object[]> {
- @Override
- protected Object[] doInBackground(Long... params) {
- long feedID = params[0];
- Context context = getActivity();
- if (context != null) {
- return new Object[]{DBReader.getFeed(context, feedID),
- QueueAccess.IDListAccess(DBReader.getQueueIDList(context))};
- } else {
- return null;
- }
- }
-
- @Override
- protected void onPostExecute(Object[] res) {
- super.onPostExecute(res);
- if (res != null) {
- feed = (Feed) res[0];
- queue = (QueueAccess) res[1];
- itemsLoaded = true;
- if (viewsCreated) {
- onFragmentLoaded();
- }
- }
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/fragment/NewEpisodesFragment.java b/src/de/danoeh/antennapod/fragment/NewEpisodesFragment.java
deleted file mode 100644
index fe995256b..000000000
--- a/src/de/danoeh/antennapod/fragment/NewEpisodesFragment.java
+++ /dev/null
@@ -1,425 +0,0 @@
-package de.danoeh.antennapod.fragment;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.os.Handler;
-import android.support.v4.app.Fragment;
-import android.support.v7.app.ActionBarActivity;
-import android.support.v7.widget.SearchView;
-import android.view.*;
-import android.widget.AdapterView;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-import android.widget.Toast;
-import com.mobeta.android.dslv.DragSortListView;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.MainActivity;
-import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
-import de.danoeh.antennapod.adapter.NewEpisodesListAdapter;
-import de.danoeh.antennapod.asynctask.DownloadObserver;
-import de.danoeh.antennapod.dialog.FeedItemDialog;
-import de.danoeh.antennapod.feed.EventDistributor;
-import de.danoeh.antennapod.feed.Feed;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.feed.FeedMedia;
-import de.danoeh.antennapod.preferences.UserPreferences;
-import de.danoeh.antennapod.service.download.DownloadService;
-import de.danoeh.antennapod.service.download.Downloader;
-import de.danoeh.antennapod.storage.DBReader;
-import de.danoeh.antennapod.storage.DBTasks;
-import de.danoeh.antennapod.storage.DBWriter;
-import de.danoeh.antennapod.storage.DownloadRequester;
-import de.danoeh.antennapod.util.QueueAccess;
-import de.danoeh.antennapod.util.menuhandler.MenuItemUtils;
-import de.danoeh.antennapod.util.menuhandler.NavDrawerActivity;
-
-import java.util.List;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * Shows unread or recently published episodes
- */
-public class NewEpisodesFragment extends Fragment {
- private static final String TAG = "NewEpisodesFragment";
- private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED |
- EventDistributor.DOWNLOAD_QUEUED |
- EventDistributor.QUEUE_UPDATE |
- EventDistributor.UNREAD_ITEMS_UPDATE;
-
- private static final int RECENT_EPISODES_LIMIT = 150;
- private static final String PREF_NAME = "PrefNewEpisodesFragment";
- private static final String PREF_EPISODE_FILTER_BOOL = "newEpisodeFilterEnabled";
-
-
- private DragSortListView listView;
- private NewEpisodesListAdapter listAdapter;
- private TextView txtvEmpty;
- private ProgressBar progLoading;
-
- private List<FeedItem> unreadItems;
- private List<FeedItem> recentItems;
- private QueueAccess queueAccess;
- private List<Downloader> downloaderList;
-
- private boolean itemsLoaded = false;
- private boolean viewsCreated = false;
- private boolean showOnlyNewEpisodes = false;
-
- private AtomicReference<MainActivity> activity = new AtomicReference<MainActivity>();
-
- private DownloadObserver downloadObserver = null;
-
- private FeedItemDialog feedItemDialog;
- private FeedItemDialog.FeedItemDialogSavedInstance feedItemDialogSavedInstance;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setRetainInstance(true);
- setHasOptionsMenu(true);
-
- updateShowOnlyEpisodes();
- }
-
- @Override
- public void onResume() {
- super.onResume();
- startItemLoader();
- }
-
- @Override
- public void onStart() {
- super.onStart();
- EventDistributor.getInstance().register(contentUpdate);
- this.activity.set((MainActivity) getActivity());
- if (downloadObserver != null) {
- downloadObserver.setActivity(getActivity());
- downloadObserver.onResume();
- }
- if (viewsCreated && itemsLoaded) {
- onFragmentLoaded();
- }
- }
-
- @Override
- public void onStop() {
- super.onStop();
- EventDistributor.getInstance().unregister(contentUpdate);
- stopItemLoader();
- }
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- this.activity.set((MainActivity) getActivity());
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- resetViewState();
- }
-
- private void resetViewState() {
- listAdapter = null;
- activity.set(null);
- viewsCreated = false;
- if (downloadObserver != null) {
- downloadObserver.onPause();
- }
- if (feedItemDialog != null) {
- feedItemDialogSavedInstance = feedItemDialog.save();
- }
- feedItemDialog = null;
- }
-
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- super.onCreateOptionsMenu(menu, inflater);
- if (itemsLoaded && !MenuItemUtils.isActivityDrawerOpen((NavDrawerActivity) getActivity())) {
- inflater.inflate(R.menu.new_episodes, menu);
-
- final SearchView sv = new SearchView(getActivity());
- MenuItemUtils.addSearchItem(menu, sv);
- sv.setQueryHint(getString(R.string.search_hint));
- sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
- @Override
- public boolean onQueryTextSubmit(String s) {
- sv.clearFocus();
- ((MainActivity) getActivity()).loadChildFragment(SearchFragment.newInstance(s));
- return true;
- }
-
- @Override
- public boolean onQueryTextChange(String s) {
- return false;
- }
- });
- }
- }
-
- @Override
- public void onPrepareOptionsMenu(Menu menu) {
- super.onPrepareOptionsMenu(menu);
- if (itemsLoaded && !MenuItemUtils.isActivityDrawerOpen((NavDrawerActivity) getActivity())) {
- menu.findItem(R.id.mark_all_read_item).setVisible(unreadItems != null && !unreadItems.isEmpty());
- menu.findItem(R.id.episode_filter_item).setChecked(showOnlyNewEpisodes);
- }
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (!super.onOptionsItemSelected(item)) {
- switch (item.getItemId()) {
- case R.id.refresh_item:
- List<Feed> feeds = ((MainActivity) getActivity()).getFeeds();
- if (feeds != null) {
- DBTasks.refreshAllFeeds(getActivity(), feeds);
- }
- return true;
- case R.id.mark_all_read_item:
- DBWriter.markAllItemsRead(getActivity());
- Toast.makeText(getActivity(), R.string.mark_all_read_msg, Toast.LENGTH_SHORT).show();
- return true;
- case R.id.episode_filter_item:
- boolean newVal = !item.isChecked();
- setShowOnlyNewEpisodes(newVal);
- item.setChecked(newVal);
- return true;
- default:
- return false;
- }
- } else {
- return true;
- }
-
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- super.onCreateView(inflater, container, savedInstanceState);
- ((MainActivity) getActivity()).getSupportActionBar().setTitle(R.string.all_episodes_label);
-
- View root = inflater.inflate(R.layout.new_episodes_fragment, container, false);
-
- listView = (DragSortListView) root.findViewById(android.R.id.list);
- txtvEmpty = (TextView) root.findViewById(android.R.id.empty);
- progLoading = (ProgressBar) root.findViewById(R.id.progLoading);
-
- listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- FeedItem item = (FeedItem) listAdapter.getItem(position - listView.getHeaderViewsCount());
- if (item != null) {
- feedItemDialog = FeedItemDialog.newInstance(activity.get(), item, queueAccess);
- feedItemDialog.show();
- }
-
- }
- });
-
- final int secondColor = (UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) ? R.color.swipe_refresh_secondary_color_dark : R.color.swipe_refresh_secondary_color_light;
-
- if (!itemsLoaded) {
- progLoading.setVisibility(View.VISIBLE);
- txtvEmpty.setVisibility(View.GONE);
- }
-
- viewsCreated = true;
-
- if (itemsLoaded && activity.get() != null) {
- onFragmentLoaded();
- }
-
- return root;
- }
-
- private void onFragmentLoaded() {
- if (listAdapter == null) {
- listAdapter = new NewEpisodesListAdapter(activity.get(), itemAccess, new DefaultActionButtonCallback(activity.get()));
- listView.setAdapter(listAdapter);
- listView.setEmptyView(txtvEmpty);
- downloadObserver = new DownloadObserver(activity.get(), new Handler(), downloadObserverCallback);
- downloadObserver.onResume();
- }
- if (feedItemDialog != null) {
- feedItemDialog.updateContent(queueAccess, unreadItems, recentItems);
- } else if (feedItemDialogSavedInstance != null) {
- feedItemDialog = FeedItemDialog.newInstance(activity.get(), feedItemDialogSavedInstance);
- }
- listAdapter.notifyDataSetChanged();
- getActivity().supportInvalidateOptionsMenu();
- updateProgressBarVisibility();
- updateShowOnlyEpisodesListViewState();
- }
-
- private DownloadObserver.Callback downloadObserverCallback = new DownloadObserver.Callback() {
- @Override
- public void onContentChanged() {
- if (listAdapter != null) {
- listAdapter.notifyDataSetChanged();
- }
- if (feedItemDialog != null && feedItemDialog.isShowing()) {
- feedItemDialog.updateMenuAppearance();
- }
- }
-
- @Override
- public void onDownloadDataAvailable(List<Downloader> downloaderList) {
- NewEpisodesFragment.this.downloaderList = downloaderList;
- if (listAdapter != null) {
- listAdapter.notifyDataSetChanged();
- }
- }
- };
-
- private NewEpisodesListAdapter.ItemAccess itemAccess = new NewEpisodesListAdapter.ItemAccess() {
-
- @Override
- public int getCount() {
- if (itemsLoaded) {
- return (showOnlyNewEpisodes) ? unreadItems.size() : recentItems.size();
- }
- return 0;
- }
-
- @Override
- public FeedItem getItem(int position) {
- if (itemsLoaded) {
- return (showOnlyNewEpisodes) ? unreadItems.get(position) : recentItems.get(position);
- }
- return null;
- }
-
- @Override
- public int getItemDownloadProgressPercent(FeedItem item) {
- if (downloaderList != null) {
- for (Downloader downloader : downloaderList) {
- if (downloader.getDownloadRequest().getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA
- && downloader.getDownloadRequest().getFeedfileId() == item.getMedia().getId()) {
- return downloader.getDownloadRequest().getProgressPercent();
- }
- }
- }
- return 0;
- }
-
- @Override
- public boolean isInQueue(FeedItem item) {
- if (itemsLoaded) {
- return queueAccess.contains(item.getId());
- } else {
- return false;
- }
- }
-
-
- };
-
- private void updateProgressBarVisibility() {
- if (!viewsCreated) {
- return;
- }
- ((ActionBarActivity) getActivity())
- .setSupportProgressBarIndeterminateVisibility(DownloadService.isRunning
- && DownloadRequester.getInstance().isDownloadingFeeds());
- }
-
- private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
- @Override
- public void update(EventDistributor eventDistributor, Integer arg) {
- if ((arg & EVENTS) != 0) {
- startItemLoader();
- updateProgressBarVisibility();
- }
- }
- };
-
- private void updateShowOnlyEpisodes() {
- SharedPreferences prefs = getActivity().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
- showOnlyNewEpisodes = prefs.getBoolean(PREF_EPISODE_FILTER_BOOL, false);
- }
-
- private void setShowOnlyNewEpisodes(boolean newVal) {
- showOnlyNewEpisodes = newVal;
- SharedPreferences prefs = getActivity().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = prefs.edit();
- editor.putBoolean(PREF_EPISODE_FILTER_BOOL, showOnlyNewEpisodes);
- editor.commit();
- if (itemsLoaded && viewsCreated) {
- listAdapter.notifyDataSetChanged();
- activity.get().supportInvalidateOptionsMenu();
- updateShowOnlyEpisodesListViewState();
- }
- }
-
- private void updateShowOnlyEpisodesListViewState() {
- if (showOnlyNewEpisodes) {
- listView.setEmptyView(null);
- txtvEmpty.setVisibility(View.GONE);
- } else {
- listView.setEmptyView(txtvEmpty);
- }
- }
-
- private ItemLoader itemLoader;
-
- private void startItemLoader() {
- if (itemLoader != null) {
- itemLoader.cancel(true);
- }
- itemLoader = new ItemLoader();
- itemLoader.execute();
- }
-
- private void stopItemLoader() {
- if (itemLoader != null) {
- itemLoader.cancel(true);
- }
- }
-
- private class ItemLoader extends AsyncTask<Void, Void, Object[]> {
-
- @Override
- protected void onPreExecute() {
- super.onPreExecute();
- if (viewsCreated && !itemsLoaded) {
- listView.setVisibility(View.GONE);
- txtvEmpty.setVisibility(View.GONE);
- progLoading.setVisibility(View.VISIBLE);
- }
- }
-
- @Override
- protected Object[] doInBackground(Void... params) {
- Context context = activity.get();
- if (context != null) {
- return new Object[]{DBReader.getUnreadItemsList(context),
- DBReader.getRecentlyPublishedEpisodes(context, RECENT_EPISODES_LIMIT),
- QueueAccess.IDListAccess(DBReader.getQueueIDList(context))};
- } else {
- return null;
- }
- }
-
- @Override
- protected void onPostExecute(Object[] lists) {
- super.onPostExecute(lists);
- listView.setVisibility(View.VISIBLE);
- progLoading.setVisibility(View.GONE);
-
- if (lists != null) {
- unreadItems = (List<FeedItem>) lists[0];
- recentItems = (List<FeedItem>) lists[1];
- queueAccess = (QueueAccess) lists[2];
- itemsLoaded = true;
- if (viewsCreated && activity.get() != null) {
- onFragmentLoaded();
- }
- }
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java b/src/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java
deleted file mode 100644
index 470186180..000000000
--- a/src/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java
+++ /dev/null
@@ -1,288 +0,0 @@
-package de.danoeh.antennapod.fragment;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.os.Handler;
-import android.support.v4.app.ListFragment;
-import android.support.v4.view.MenuItemCompat;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.ListView;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
-import de.danoeh.antennapod.adapter.FeedItemlistAdapter;
-import de.danoeh.antennapod.asynctask.DownloadObserver;
-import de.danoeh.antennapod.dialog.FeedItemDialog;
-import de.danoeh.antennapod.feed.EventDistributor;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.feed.FeedMedia;
-import de.danoeh.antennapod.service.download.Downloader;
-import de.danoeh.antennapod.storage.DBReader;
-import de.danoeh.antennapod.storage.DBWriter;
-import de.danoeh.antennapod.util.QueueAccess;
-import de.danoeh.antennapod.util.menuhandler.MenuItemUtils;
-import de.danoeh.antennapod.util.menuhandler.NavDrawerActivity;
-
-import java.util.List;
-import java.util.concurrent.atomic.AtomicReference;
-
-public class PlaybackHistoryFragment extends ListFragment {
- private static final String TAG = "PlaybackHistoryFragment";
-
- private List<FeedItem> playbackHistory;
- private QueueAccess queue;
- private FeedItemlistAdapter adapter;
-
- private boolean itemsLoaded = false;
- private boolean viewsCreated = false;
-
- private AtomicReference<Activity> activity = new AtomicReference<Activity>();
-
- private DownloadObserver downloadObserver;
- private List<Downloader> downloaderList;
-
- private FeedItemDialog feedItemDialog;
- private FeedItemDialog.FeedItemDialogSavedInstance feedItemDialogSavedInstance;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setRetainInstance(true);
- setHasOptionsMenu(true);
- }
-
- @Override
- public void onResume() {
- super.onResume();
- startItemLoader();
- }
-
- @Override
- public void onStart() {
- super.onStart();
- EventDistributor.getInstance().register(contentUpdate);
- }
-
- @Override
- public void onStop() {
- super.onStop();
- EventDistributor.getInstance().unregister(contentUpdate);
- stopItemLoader();
- }
-
- @Override
- public void onDetach() {
- super.onDetach();
- stopItemLoader();
- activity.set(null);
- }
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- this.activity.set(activity);
- if (downloadObserver != null) {
- downloadObserver.setActivity(activity);
- downloadObserver.onResume();
- }
- if (viewsCreated && itemsLoaded) {
- onFragmentLoaded();
- }
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- adapter = null;
- viewsCreated = false;
- if (downloadObserver != null) {
- downloadObserver.onPause();
- }
- if (feedItemDialog != null) {
- feedItemDialogSavedInstance = feedItemDialog.save();
- }
- feedItemDialog = null;
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- viewsCreated = true;
- if (itemsLoaded) {
- onFragmentLoaded();
- }
- }
-
- @Override
- public void onListItemClick(ListView l, View v, int position, long id) {
- super.onListItemClick(l, v, position, id);
- FeedItem item = adapter.getItem(position - l.getHeaderViewsCount());
- if (item != null) {
- feedItemDialog = FeedItemDialog.newInstance(activity.get(), item, queue);
- feedItemDialog.show();
- }
- }
-
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- super.onCreateOptionsMenu(menu, inflater);
- if (itemsLoaded && !MenuItemUtils.isActivityDrawerOpen((NavDrawerActivity) getActivity())) {
- MenuItem clearHistory = menu.add(Menu.NONE, R.id.clear_history_item, Menu.CATEGORY_CONTAINER, R.string.clear_history_label);
- MenuItemCompat.setShowAsAction(clearHistory, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
- TypedArray drawables = getActivity().obtainStyledAttributes(new int[]{R.attr.content_discard});
- clearHistory.setIcon(drawables.getDrawable(0));
- drawables.recycle();
- }
- }
-
- @Override
- public void onPrepareOptionsMenu(Menu menu) {
- super.onPrepareOptionsMenu(menu);
- if (itemsLoaded && !MenuItemUtils.isActivityDrawerOpen((NavDrawerActivity) getActivity())) {
- menu.findItem(R.id.clear_history_item).setVisible(playbackHistory != null && !playbackHistory.isEmpty());
- }
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (!super.onOptionsItemSelected(item)) {
- switch(item.getItemId()) {
- case R.id.clear_history_item:
- DBWriter.clearPlaybackHistory(getActivity());
- return true;
- default:
- return false;
- }
- } else {
- return true;
- }
- }
-
- private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
-
- @Override
- public void update(EventDistributor eventDistributor, Integer arg) {
- if ((arg & EventDistributor.PLAYBACK_HISTORY_UPDATE) != 0) {
- startItemLoader();
- getActivity().supportInvalidateOptionsMenu();
- }
- }
- };
-
- private void onFragmentLoaded() {
- if (adapter == null) {
- adapter = new FeedItemlistAdapter(getActivity(), itemAccess, new DefaultActionButtonCallback(activity.get()), true);
- setListAdapter(adapter);
- downloadObserver = new DownloadObserver(activity.get(), new Handler(), downloadObserverCallback);
- downloadObserver.onResume();
- }
- setListShown(true);
- adapter.notifyDataSetChanged();
- if (feedItemDialog != null && feedItemDialog.isShowing()) {
- feedItemDialog.updateContent(queue, playbackHistory);
- } else if (feedItemDialogSavedInstance != null) {
- feedItemDialog = FeedItemDialog.newInstance(activity.get(), feedItemDialogSavedInstance);
- }
- getActivity().supportInvalidateOptionsMenu();
- }
-
- private DownloadObserver.Callback downloadObserverCallback = new DownloadObserver.Callback() {
- @Override
- public void onContentChanged() {
- if (adapter != null) {
- adapter.notifyDataSetChanged();
- }
- if (feedItemDialog != null && feedItemDialog.isShowing()) {
- feedItemDialog.updateMenuAppearance();
- }
- }
-
- @Override
- public void onDownloadDataAvailable(List<Downloader> downloaderList) {
- PlaybackHistoryFragment.this.downloaderList = downloaderList;
- if (adapter != null) {
- adapter.notifyDataSetChanged();
- }
- }
- };
-
- private FeedItemlistAdapter.ItemAccess itemAccess = new FeedItemlistAdapter.ItemAccess() {
- @Override
- public boolean isInQueue(FeedItem item) {
- return (queue != null) ? queue.contains(item.getId()) : false;
- }
-
- @Override
- public int getItemDownloadProgressPercent(FeedItem item) {
- if (downloaderList != null) {
- for (Downloader downloader : downloaderList) {
- if (downloader.getDownloadRequest().getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA
- && downloader.getDownloadRequest().getFeedfileId() == item.getMedia().getId()) {
- return downloader.getDownloadRequest().getProgressPercent();
- }
- }
- }
- return 0;
- }
-
- @Override
- public int getCount() {
- return (playbackHistory != null) ? playbackHistory.size() : 0;
- }
-
- @Override
- public FeedItem getItem(int position) {
- return (playbackHistory != null) ? playbackHistory.get(position) : null;
- }
- };
-
- private ItemLoader itemLoader;
-
- private void startItemLoader() {
- if (itemLoader != null) {
- itemLoader.cancel(true);
- }
- itemLoader = new ItemLoader();
- itemLoader.execute();
- }
-
- private void stopItemLoader() {
- if (itemLoader != null) {
- itemLoader.cancel(true);
- }
- }
-
- private class ItemLoader extends AsyncTask<Void, Void, Object[]> {
-
- @Override
- protected Object[] doInBackground(Void... params) {
- Context context = activity.get();
- if (context != null) {
- List<FeedItem> ph = DBReader.getPlaybackHistory(context);
- DBReader.loadFeedDataOfFeedItemlist(context, ph);
- return new Object[]{ph,
- QueueAccess.IDListAccess(DBReader.getQueueIDList(context))};
- } else {
- return null;
- }
- }
-
- @Override
- protected void onPostExecute(Object[] res) {
- super.onPostExecute(res);
- if (res != null) {
- playbackHistory = (List<FeedItem>) res[0];
- queue = (QueueAccess) res[1];
- itemsLoaded = true;
- if (viewsCreated) {
- onFragmentLoaded();
- }
- }
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/fragment/QueueFragment.java b/src/de/danoeh/antennapod/fragment/QueueFragment.java
deleted file mode 100644
index 2f322f75b..000000000
--- a/src/de/danoeh/antennapod/fragment/QueueFragment.java
+++ /dev/null
@@ -1,383 +0,0 @@
-package de.danoeh.antennapod.fragment;
-
-import android.app.Activity;
-import android.content.Context;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.os.Handler;
-import android.support.v4.app.Fragment;
-import android.support.v7.widget.SearchView;
-import android.util.Log;
-import android.view.ContextMenu;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-
-import com.mobeta.android.dslv.DragSortListView;
-
-import java.util.List;
-import java.util.concurrent.atomic.AtomicReference;
-
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.MainActivity;
-import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
-import de.danoeh.antennapod.adapter.QueueListAdapter;
-import de.danoeh.antennapod.asynctask.DownloadObserver;
-import de.danoeh.antennapod.dialog.FeedItemDialog;
-import de.danoeh.antennapod.feed.EventDistributor;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.feed.FeedMedia;
-import de.danoeh.antennapod.service.download.Downloader;
-import de.danoeh.antennapod.storage.DBReader;
-import de.danoeh.antennapod.storage.DBWriter;
-import de.danoeh.antennapod.util.QueueAccess;
-import de.danoeh.antennapod.util.menuhandler.MenuItemUtils;
-import de.danoeh.antennapod.util.menuhandler.NavDrawerActivity;
-
-/**
- * Shows all items in the queue
- */
-public class QueueFragment extends Fragment {
- private static final String TAG = "QueueFragment";
- private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED |
- EventDistributor.DOWNLOAD_QUEUED |
- EventDistributor.QUEUE_UPDATE;
-
- private DragSortListView listView;
- private QueueListAdapter listAdapter;
- private TextView txtvEmpty;
- private ProgressBar progLoading;
-
- private List<FeedItem> queue;
- private List<Downloader> downloaderList;
-
- private boolean itemsLoaded = false;
- private boolean viewsCreated = false;
-
- private AtomicReference<Activity> activity = new AtomicReference<Activity>();
-
- private DownloadObserver downloadObserver = null;
-
- private FeedItemDialog feedItemDialog;
- private FeedItemDialog.FeedItemDialogSavedInstance feedItemDialogSavedInstance;
-
- /**
- * Download observer updates won't result in an upate of the list adapter if this is true.
- */
- private boolean blockDownloadObserverUpdate = false;
-
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setRetainInstance(true);
- setHasOptionsMenu(true);
- }
-
- @Override
- public void onResume() {
- super.onResume();
- startItemLoader();
- }
-
- @Override
- public void onStart() {
- super.onStart();
- EventDistributor.getInstance().register(contentUpdate);
- this.activity.set((MainActivity) getActivity());
- if (downloadObserver != null) {
- downloadObserver.setActivity(getActivity());
- downloadObserver.onResume();
- }
- if (viewsCreated && itemsLoaded) {
- onFragmentLoaded();
- }
- }
-
- @Override
- public void onStop() {
- super.onStop();
- EventDistributor.getInstance().unregister(contentUpdate);
- stopItemLoader();
- }
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- this.activity.set((MainActivity) activity);
- }
-
- private void resetViewState() {
- unregisterForContextMenu(listView);
- listAdapter = null;
- activity.set(null);
- viewsCreated = false;
- blockDownloadObserverUpdate = false;
- if (downloadObserver != null) {
- downloadObserver.onPause();
- }
- if (feedItemDialog != null) {
- feedItemDialogSavedInstance = feedItemDialog.save();
- }
- feedItemDialog = null;
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- resetViewState();
- }
-
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- super.onCreateOptionsMenu(menu, inflater);
- if (itemsLoaded && !MenuItemUtils.isActivityDrawerOpen((NavDrawerActivity) getActivity())) {
- final SearchView sv = new SearchView(getActivity());
- MenuItemUtils.addSearchItem(menu, sv);
- sv.setQueryHint(getString(R.string.search_hint));
- sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
- @Override
- public boolean onQueryTextSubmit(String s) {
- sv.clearFocus();
- ((MainActivity) getActivity()).loadChildFragment(SearchFragment.newInstance(s));
- return true;
- }
-
- @Override
- public boolean onQueryTextChange(String s) {
- return false;
- }
- });
- }
- }
-
- @Override
- public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, v, menuInfo);
- AdapterView.AdapterContextMenuInfo adapterInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
- FeedItem item = itemAccess.getItem(adapterInfo.position);
-
- MenuInflater inflater = getActivity().getMenuInflater();
- inflater.inflate(R.menu.queue_context, menu);
-
- if (item != null) {
- menu.setHeaderTitle(item.getTitle());
- }
-
- menu.findItem(R.id.move_to_top_item).setEnabled(!queue.isEmpty() && queue.get(0) != item);
- menu.findItem(R.id.move_to_bottom_item).setEnabled(!queue.isEmpty() && queue.get(queue.size() - 1) != item);
- }
-
- @Override
- public boolean onContextItemSelected(MenuItem item) {
- AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
- FeedItem selectedItem = itemAccess.getItem(menuInfo.position);
-
- if (selectedItem == null) {
- Log.i(TAG, "Selected item at position " + menuInfo.position + " was null, ignoring selection");
- return super.onContextItemSelected(item);
- }
-
- switch (item.getItemId()) {
- case R.id.move_to_top_item:
- DBWriter.moveQueueItemToTop(getActivity(), selectedItem.getId(), true);
- return true;
- case R.id.move_to_bottom_item:
- DBWriter.moveQueueItemToBottom(getActivity(), selectedItem.getId(), true);
- return true;
- case R.id.remove_from_queue_item:
- DBWriter.removeQueueItem(getActivity(), selectedItem.getId(), false);
- return true;
- default:
- return super.onContextItemSelected(item);
- }
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- super.onCreateView(inflater, container, savedInstanceState);
- ((MainActivity) getActivity()).getSupportActionBar().setTitle(R.string.queue_label);
-
- View root = inflater.inflate(R.layout.queue_fragment, container, false);
- listView = (DragSortListView) root.findViewById(android.R.id.list);
- txtvEmpty = (TextView) root.findViewById(android.R.id.empty);
- progLoading = (ProgressBar) root.findViewById(R.id.progLoading);
- listView.setEmptyView(txtvEmpty);
-
- listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- FeedItem item = (FeedItem) listAdapter.getItem(position - listView.getHeaderViewsCount());
- if (item != null) {
- feedItemDialog = FeedItemDialog.newInstance(activity.get(), item, QueueAccess.ItemListAccess(queue));
- feedItemDialog.show();
- }
- }
- });
-
- listView.setDragSortListener(new DragSortListView.DragSortListener() {
- @Override
- public void drag(int from, int to) {
- Log.d(TAG, "drag");
- blockDownloadObserverUpdate = true;
- }
-
- @Override
- public void drop(int from, int to) {
- Log.d(TAG, "drop");
- blockDownloadObserverUpdate = false;
- stopItemLoader();
- final FeedItem item = queue.remove(from);
- queue.add(to, item);
- listAdapter.notifyDataSetChanged();
- DBWriter.moveQueueItem(getActivity(), from, to, true);
- }
-
- @Override
- public void remove(int which) {
- }
- });
-
- registerForContextMenu(listView);
-
- if (!itemsLoaded) {
- progLoading.setVisibility(View.VISIBLE);
- txtvEmpty.setVisibility(View.GONE);
- }
-
- viewsCreated = true;
-
- if (itemsLoaded && activity.get() != null) {
- onFragmentLoaded();
- }
-
- return root;
- }
-
- private void onFragmentLoaded() {
- if (listAdapter == null) {
- listAdapter = new QueueListAdapter(activity.get(), itemAccess, new DefaultActionButtonCallback(activity.get()));
- listView.setAdapter(listAdapter);
- downloadObserver = new DownloadObserver(activity.get(), new Handler(), downloadObserverCallback);
- downloadObserver.onResume();
- }
- listAdapter.notifyDataSetChanged();
- if (feedItemDialog != null) {
- feedItemDialog.updateContent(QueueAccess.ItemListAccess(queue), queue);
- } else if (feedItemDialogSavedInstance != null) {
- feedItemDialog = FeedItemDialog.newInstance(activity.get(), feedItemDialogSavedInstance);
- }
- }
-
- private DownloadObserver.Callback downloadObserverCallback = new DownloadObserver.Callback() {
- @Override
- public void onContentChanged() {
- if (listAdapter != null && !blockDownloadObserverUpdate) {
- listAdapter.notifyDataSetChanged();
- }
- if (feedItemDialog != null && feedItemDialog.isShowing()) {
- feedItemDialog.updateMenuAppearance();
- }
- }
-
- @Override
- public void onDownloadDataAvailable(List<Downloader> downloaderList) {
- QueueFragment.this.downloaderList = downloaderList;
- if (listAdapter != null && !blockDownloadObserverUpdate) {
- listAdapter.notifyDataSetChanged();
- }
- }
- };
-
- private QueueListAdapter.ItemAccess itemAccess = new QueueListAdapter.ItemAccess() {
- @Override
- public int getCount() {
- return (itemsLoaded) ? queue.size() : 0;
- }
-
- @Override
- public FeedItem getItem(int position) {
- return (itemsLoaded) ? queue.get(position) : null;
- }
-
- @Override
- public int getItemDownloadProgressPercent(FeedItem item) {
- if (downloaderList != null) {
- for (Downloader downloader : downloaderList) {
- if (downloader.getDownloadRequest().getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA
- && downloader.getDownloadRequest().getFeedfileId() == item.getMedia().getId()) {
- return downloader.getDownloadRequest().getProgressPercent();
- }
- }
- }
- return 0;
- }
- };
-
- private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
- @Override
- public void update(EventDistributor eventDistributor, Integer arg) {
- if ((arg & EVENTS) != 0) {
- startItemLoader();
- }
- }
- };
-
- private ItemLoader itemLoader;
-
- private void startItemLoader() {
- if (itemLoader != null) {
- itemLoader.cancel(true);
- }
- itemLoader = new ItemLoader();
- itemLoader.execute();
- }
-
- private void stopItemLoader() {
- if (itemLoader != null) {
- itemLoader.cancel(true);
- }
- }
-
- private class ItemLoader extends AsyncTask<Void, Void, List<FeedItem>> {
- @Override
- protected void onPreExecute() {
- super.onPreExecute();
- if (viewsCreated && !itemsLoaded) {
- listView.setVisibility(View.GONE);
- txtvEmpty.setVisibility(View.GONE);
- progLoading.setVisibility(View.VISIBLE);
- }
- }
-
- @Override
- protected void onPostExecute(List<FeedItem> feedItems) {
- super.onPostExecute(feedItems);
- listView.setVisibility(View.VISIBLE);
- progLoading.setVisibility(View.GONE);
-
- if (feedItems != null) {
- queue = feedItems;
- itemsLoaded = true;
- if (viewsCreated && activity.get() != null) {
- onFragmentLoaded();
- }
- }
- }
-
- @Override
- protected List<FeedItem> doInBackground(Void... params) {
- Context context = activity.get();
- if (context != null) {
- return DBReader.getQueue(context);
- }
- return null;
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java b/src/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java
deleted file mode 100644
index 89c30e34b..000000000
--- a/src/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package de.danoeh.antennapod.fragment;
-
-import android.os.Bundle;
-import android.os.Handler;
-import android.support.v4.app.ListFragment;
-import android.view.View;
-import de.danoeh.antennapod.adapter.DownloadlistAdapter;
-import de.danoeh.antennapod.asynctask.DownloadObserver;
-import de.danoeh.antennapod.service.download.Downloader;
-import de.danoeh.antennapod.storage.DownloadRequester;
-
-import java.util.List;
-
-/**
- * Displays all running downloads and provides actions to cancel them
- */
-public class RunningDownloadsFragment extends ListFragment {
- private static final String TAG = "RunningDownloadsFragment";
-
- private DownloadObserver downloadObserver;
- private List<Downloader> downloaderList;
-
-
- @Override
- public void onDetach() {
- super.onDetach();
- if (downloadObserver != null) {
- downloadObserver.onPause();
- }
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- final DownloadlistAdapter downloadlistAdapter = new DownloadlistAdapter(getActivity(), itemAccess);
- setListAdapter(downloadlistAdapter);
-
- downloadObserver = new DownloadObserver(getActivity(), new Handler(), new DownloadObserver.Callback() {
- @Override
- public void onContentChanged() {
- downloadlistAdapter.notifyDataSetChanged();
- }
-
- @Override
- public void onDownloadDataAvailable(List<Downloader> downloaderList) {
- RunningDownloadsFragment.this.downloaderList = downloaderList;
- downloadlistAdapter.notifyDataSetChanged();
- }
- });
- downloadObserver.onResume();
- }
-
- private DownloadlistAdapter.ItemAccess itemAccess = new DownloadlistAdapter.ItemAccess() {
- @Override
- public int getCount() {
- return (downloaderList != null) ? downloaderList.size() : 0;
- }
-
- @Override
- public Downloader getItem(int position) {
- return (downloaderList != null) ? downloaderList.get(position) : null;
- }
-
- @Override
- public void onSecondaryActionClick(Downloader downloader) {
- DownloadRequester.getInstance().cancelDownload(getActivity(), downloader.getDownloadRequest().getSource());
- }
- };
-}
diff --git a/src/de/danoeh/antennapod/fragment/SearchFragment.java b/src/de/danoeh/antennapod/fragment/SearchFragment.java
deleted file mode 100644
index b3ade4d70..000000000
--- a/src/de/danoeh/antennapod/fragment/SearchFragment.java
+++ /dev/null
@@ -1,258 +0,0 @@
-package de.danoeh.antennapod.fragment;
-
-import android.content.Context;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.support.v4.app.ListFragment;
-import android.support.v4.view.MenuItemCompat;
-import android.support.v7.app.ActionBarActivity;
-import android.support.v7.widget.SearchView;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.ListView;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.MainActivity;
-import de.danoeh.antennapod.adapter.SearchlistAdapter;
-import de.danoeh.antennapod.dialog.FeedItemDialog;
-import de.danoeh.antennapod.feed.*;
-import de.danoeh.antennapod.storage.DBReader;
-import de.danoeh.antennapod.storage.FeedSearcher;
-import de.danoeh.antennapod.util.QueueAccess;
-import de.danoeh.antennapod.util.menuhandler.MenuItemUtils;
-import de.danoeh.antennapod.util.menuhandler.NavDrawerActivity;
-
-import java.util.List;
-
-/**
- * Performs a search operation on all feeds or one specific feed and displays the search result.
- */
-public class SearchFragment extends ListFragment {
- private static final String TAG = "SearchFragment";
-
- private static final String ARG_QUERY = "query";
- private static final String ARG_FEED = "feed";
-
- private SearchlistAdapter searchAdapter;
- private List<SearchResult> searchResults;
-
- private boolean viewCreated = false;
- private boolean itemsLoaded = false;
-
- private QueueAccess queue;
-
- private FeedItemDialog feedItemDialog;
- private FeedItemDialog.FeedItemDialogSavedInstance feedItemDialogSavedInstance;
-
- /**
- * Create a new SearchFragment that searches all feeds.
- */
- public static SearchFragment newInstance(String query) {
- if (query == null) query = "";
- SearchFragment fragment = new SearchFragment();
- Bundle args = new Bundle();
- args.putString(ARG_QUERY, query);
- args.putLong(ARG_FEED, 0);
- fragment.setArguments(args);
- return fragment;
- }
-
- /**
- * Create a new SearchFragment that searches one specific feed.
- */
- public static SearchFragment newInstance(String query, long feed) {
- SearchFragment fragment = newInstance(query);
- fragment.getArguments().putLong(ARG_FEED, feed);
- return fragment;
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setRetainInstance(true);
- setHasOptionsMenu(true);
- startSearchTask();
- }
-
- @Override
- public void onStart() {
- super.onStart();
- EventDistributor.getInstance().register(contentUpdate);
- }
-
- @Override
- public void onStop() {
- super.onStop();
- stopSearchTask();
- EventDistributor.getInstance().unregister(contentUpdate);
- }
-
- @Override
- public void onDetach() {
- super.onDetach();
- stopSearchTask();
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- searchAdapter = null;
- viewCreated = false;
- if (feedItemDialog != null) {
- feedItemDialogSavedInstance = feedItemDialog.save();
- }
- feedItemDialog = null;
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- ((ActionBarActivity) getActivity()).getSupportActionBar().setTitle(R.string.search_label);
- viewCreated = true;
- if (itemsLoaded) {
- onFragmentLoaded();
- }
- }
-
- @Override
- public void onListItemClick(ListView l, View v, int position, long id) {
- super.onListItemClick(l, v, position, id);
- SearchResult result = (SearchResult) l.getAdapter().getItem(position);
- FeedComponent comp = result.getComponent();
- if (comp.getClass() == Feed.class) {
- ((MainActivity)getActivity()).loadFeedFragment(comp.getId());
- } else {
- if (comp.getClass() == FeedItem.class) {
- feedItemDialog = FeedItemDialog.newInstance(getActivity(), (FeedItem) comp, queue);
- feedItemDialog.show();
- }
- }
- }
-
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- super.onCreateOptionsMenu(menu, inflater);
- if (itemsLoaded && !MenuItemUtils.isActivityDrawerOpen((NavDrawerActivity) getActivity())) {
- MenuItem item = menu.add(Menu.NONE, R.id.search_item, Menu.NONE, R.string.search_label);
- MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
- final SearchView sv = new SearchView(getActivity());
- sv.setQueryHint(getString(R.string.search_hint));
- sv.setQuery(getArguments().getString(ARG_QUERY), false);
- sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
- @Override
- public boolean onQueryTextSubmit(String s) {
- getArguments().putString(ARG_QUERY, s);
- itemsLoaded = false;
- startSearchTask();
- return true;
- }
-
- @Override
- public boolean onQueryTextChange(String s) {
- return false;
- }
- });
- MenuItemCompat.setActionView(item, sv);
- }
- }
-
- private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
- @Override
- public void update(EventDistributor eventDistributor, Integer arg) {
- if ((arg & (EventDistributor.DOWNLOAD_QUEUED)) != 0) {
- feedItemDialog.updateMenuAppearance();
- }
- if ((arg & (EventDistributor.UNREAD_ITEMS_UPDATE
- | EventDistributor.DOWNLOAD_HANDLED
- | EventDistributor.QUEUE_UPDATE)) != 0) {
- startSearchTask();
- }
- }
- };
-
- private void onFragmentLoaded() {
- if (searchAdapter == null) {
- searchAdapter = new SearchlistAdapter(getActivity(), itemAccess);
- setListAdapter(searchAdapter);
- }
- searchAdapter.notifyDataSetChanged();
- setListShown(true);
- if (feedItemDialog != null && feedItemDialog.isShowing()) {
- feedItemDialog.setQueue(queue);
- for (SearchResult result : searchResults) {
- FeedComponent comp = result.getComponent();
- if (comp.getClass() == FeedItem.class && ((FeedItem) comp).getId() == feedItemDialog.getItem().getId()) {
- feedItemDialog.setItem((FeedItem) comp);
- }
- }
- feedItemDialog.updateMenuAppearance();
- } else if (feedItemDialogSavedInstance != null) {
- feedItemDialog = FeedItemDialog.newInstance(getActivity(), feedItemDialogSavedInstance);
- }
- }
-
- private final SearchlistAdapter.ItemAccess itemAccess = new SearchlistAdapter.ItemAccess() {
- @Override
- public int getCount() {
- return (searchResults != null) ? searchResults.size() : 0;
- }
-
- @Override
- public SearchResult getItem(int position) {
- return (searchResults != null) ? searchResults.get(position) : null;
- }
- };
-
- private SearchTask searchTask;
-
- private void startSearchTask() {
- if (searchTask != null) {
- searchTask.cancel(true);
- }
- searchTask = new SearchTask();
- searchTask.execute(getArguments());
- }
-
- private void stopSearchTask() {
- if (searchTask != null) {
- searchTask.cancel(true);
- }
- }
-
- private class SearchTask extends AsyncTask<Bundle, Void, Object[]> {
- @Override
- protected Object[] doInBackground(Bundle... params) {
- String query = params[0].getString(ARG_QUERY);
- long feed = params[0].getLong(ARG_FEED);
- Context context = getActivity();
- if (context != null) {
- return new Object[]{FeedSearcher.performSearch(context, query, feed),
- QueueAccess.IDListAccess(DBReader.getQueueIDList(context))};
- } else {
- return null;
- }
- }
-
- @Override
- protected void onPreExecute() {
- super.onPreExecute();
- if (viewCreated && !itemsLoaded) {
- setListShown(false);
- }
- }
-
- @Override
- protected void onPostExecute(Object[] results) {
- super.onPostExecute(results);
- if (results != null) {
- itemsLoaded = true;
- searchResults = (List<SearchResult>) results[0];
- queue = (QueueAccess) results[1];
- if (viewCreated) {
- onFragmentLoaded();
- }
- }
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/fragment/gpodnet/GpodnetMainFragment.java b/src/de/danoeh/antennapod/fragment/gpodnet/GpodnetMainFragment.java
deleted file mode 100644
index ec8f69368..000000000
--- a/src/de/danoeh/antennapod/fragment/gpodnet/GpodnetMainFragment.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package de.danoeh.antennapod.fragment.gpodnet;
-
-import android.app.Activity;
-import android.content.res.Resources;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
-import android.support.v4.app.FragmentPagerAdapter;
-import android.support.v4.app.FragmentTransaction;
-import android.support.v4.view.ViewPager;
-import android.support.v7.app.ActionBar;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.MainActivity;
-
-/**
- * Main navigation hub for gpodder.net podcast directory
- */
-public class GpodnetMainFragment extends Fragment {
-
- private ViewPager pager;
- private MainActivity activity;
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- super.onCreateView(inflater, container, savedInstanceState);
- View root = inflater.inflate(R.layout.pager_fragment, container, false);
- pager = (ViewPager) root.findViewById(R.id.pager);
- GpodnetPagerAdapter pagerAdapter = new GpodnetPagerAdapter(getChildFragmentManager(), getResources());
- pager.setAdapter(pagerAdapter);
- final ActionBar actionBar = activity.getMainActivtyActionBar();
- actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
- ActionBar.TabListener tabListener = new ActionBar.TabListener() {
- @Override
- public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
- pager.setCurrentItem(tab.getPosition());
- }
-
- @Override
- public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
-
- }
-
- @Override
- public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
-
- }
- };
- actionBar.removeAllTabs();
- actionBar.addTab(actionBar.newTab()
- .setText(R.string.gpodnet_taglist_header)
- .setTabListener(tabListener));
- actionBar.addTab(actionBar.newTab()
- .setText(R.string.gpodnet_toplist_header)
- .setTabListener(tabListener));
- actionBar.setTitle(R.string.gpodnet_main_label);
-
- pager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
- @Override
- public void onPageSelected(int position) {
- super.onPageSelected(position);
- actionBar.setSelectedNavigationItem(position);
- }
- });
- return root;
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- activity.getMainActivtyActionBar().removeAllTabs();
- activity.getMainActivtyActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
- }
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- this.activity = (MainActivity) activity;
- }
-
- public class GpodnetPagerAdapter extends FragmentPagerAdapter {
-
-
- private static final int NUM_PAGES = 2;
- private static final int POS_TAGS = 0;
- private static final int POS_TOPLIST = 1;
- private static final int POS_SUGGESTIONS = 2;
-
- Resources resources;
-
- public GpodnetPagerAdapter(FragmentManager fm, Resources resources) {
- super(fm);
- this.resources = resources;
- }
-
- @Override
- public Fragment getItem(int i) {
- switch (i) {
- case POS_TAGS:
- return new TagListFragment();
- case POS_TOPLIST:
- return new PodcastTopListFragment();
- case POS_SUGGESTIONS:
- return new SuggestionListFragment();
- default:
- return null;
- }
- }
-
- @Override
- public CharSequence getPageTitle(int position) {
- switch (position) {
- case POS_TAGS:
- return getString(R.string.gpodnet_taglist_header);
- case POS_TOPLIST:
- return getString(R.string.gpodnet_toplist_header);
- case POS_SUGGESTIONS:
- return getString(R.string.gpodnet_suggestions_header);
- default:
- return super.getPageTitle(position);
- }
- }
-
- @Override
- public int getCount() {
- return NUM_PAGES;
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java b/src/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java
deleted file mode 100644
index 1b4616207..000000000
--- a/src/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java
+++ /dev/null
@@ -1,169 +0,0 @@
-package de.danoeh.antennapod.fragment.gpodnet;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v7.widget.*;
-import android.util.Log;
-import android.view.*;
-import android.widget.*;
-import android.widget.SearchView;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.DefaultOnlineFeedViewActivity;
-import de.danoeh.antennapod.activity.MainActivity;
-import de.danoeh.antennapod.activity.OnlineFeedViewActivity;
-import de.danoeh.antennapod.adapter.gpodnet.PodcastListAdapter;
-import de.danoeh.antennapod.fragment.SearchFragment;
-import de.danoeh.antennapod.gpoddernet.GpodnetService;
-import de.danoeh.antennapod.gpoddernet.GpodnetServiceException;
-import de.danoeh.antennapod.gpoddernet.model.GpodnetPodcast;
-import de.danoeh.antennapod.util.menuhandler.MenuItemUtils;
-import de.danoeh.antennapod.util.menuhandler.NavDrawerActivity;
-
-import java.util.List;
-
-/**
- * Displays a list of GPodnetPodcast-Objects in a GridView
- */
-public abstract class PodcastListFragment extends Fragment {
- private static final String TAG = "PodcastListFragment";
-
- private GridView gridView;
- private ProgressBar progressBar;
- private TextView txtvError;
- private Button butRetry;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setHasOptionsMenu(true);
- }
-
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- super.onCreateOptionsMenu(menu, inflater);
- if (!MenuItemUtils.isActivityDrawerOpen((NavDrawerActivity) getActivity())) {
- final android.support.v7.widget.SearchView sv = new android.support.v7.widget.SearchView(getActivity());
- MenuItemUtils.addSearchItem(menu, sv);
- sv.setQueryHint(getString(R.string.gpodnet_search_hint));
- sv.setOnQueryTextListener(new android.support.v7.widget.SearchView.OnQueryTextListener() {
- @Override
- public boolean onQueryTextSubmit(String s) {
- sv.clearFocus();
- ((MainActivity) getActivity()).loadChildFragment(SearchListFragment.newInstance(s));
- return true;
- }
-
- @Override
- public boolean onQueryTextChange(String s) {
- return false;
- }
- });
- }
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View root = inflater.inflate(R.layout.gpodnet_podcast_list, container, false);
-
- gridView = (GridView) root.findViewById(R.id.gridView);
- progressBar = (ProgressBar) root.findViewById(R.id.progressBar);
- txtvError = (TextView) root.findViewById(R.id.txtvError);
- butRetry = (Button) root.findViewById(R.id.butRetry);
-
- gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- onPodcastSelected((GpodnetPodcast) gridView.getAdapter().getItem(position));
- }
- });
- butRetry.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- loadData();
- }
- });
-
- loadData();
- return root;
- }
-
- protected void onPodcastSelected(GpodnetPodcast selection) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Selected podcast: " + selection.toString());
- Intent intent = new Intent(getActivity(), DefaultOnlineFeedViewActivity.class);
- intent.putExtra(OnlineFeedViewActivity.ARG_FEEDURL, selection.getUrl());
- intent.putExtra(DefaultOnlineFeedViewActivity.ARG_TITLE, getString(R.string.gpodnet_main_label));
- startActivity(intent);
- }
-
- protected abstract List<GpodnetPodcast> loadPodcastData(GpodnetService service) throws GpodnetServiceException;
-
- protected final void loadData() {
- AsyncTask<Void, Void, List<GpodnetPodcast>> loaderTask = new AsyncTask<Void, Void, List<GpodnetPodcast>>() {
- volatile Exception exception = null;
-
- @Override
- protected List<GpodnetPodcast> doInBackground(Void... params) {
- GpodnetService service = null;
- try {
- service = new GpodnetService();
- return loadPodcastData(service);
- } catch (GpodnetServiceException e) {
- exception = e;
- e.printStackTrace();
- return null;
- } finally {
- if (service != null) {
- service.shutdown();
- }
- }
- }
-
- @Override
- protected void onPostExecute(List<GpodnetPodcast> gpodnetPodcasts) {
- super.onPostExecute(gpodnetPodcasts);
- final Context context = getActivity();
- if (context != null && gpodnetPodcasts != null && gpodnetPodcasts.size() > 0) {
- PodcastListAdapter listAdapter = new PodcastListAdapter(context, 0, gpodnetPodcasts);
- gridView.setAdapter(listAdapter);
- listAdapter.notifyDataSetChanged();
-
- progressBar.setVisibility(View.GONE);
- gridView.setVisibility(View.VISIBLE);
- txtvError.setVisibility(View.GONE);
- butRetry.setVisibility(View.GONE);
- } else if (context != null && gpodnetPodcasts != null) {
- gridView.setVisibility(View.GONE);
- progressBar.setVisibility(View.GONE);
- txtvError.setText(getString(R.string.search_status_no_results));
- txtvError.setVisibility(View.VISIBLE);
- butRetry.setVisibility(View.GONE);
- } else if (context != null) {
- gridView.setVisibility(View.GONE);
- progressBar.setVisibility(View.GONE);
- txtvError.setText(getString(R.string.error_msg_prefix) + exception.getMessage());
- txtvError.setVisibility(View.VISIBLE);
- butRetry.setVisibility(View.VISIBLE);
- }
- }
-
- @Override
- protected void onPreExecute() {
- super.onPreExecute();
- gridView.setVisibility(View.GONE);
- progressBar.setVisibility(View.VISIBLE);
- txtvError.setVisibility(View.GONE);
- butRetry.setVisibility(View.GONE);
- }
- };
-
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- loaderTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- } else {
- loaderTask.execute();
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/fragment/gpodnet/PodcastTopListFragment.java b/src/de/danoeh/antennapod/fragment/gpodnet/PodcastTopListFragment.java
deleted file mode 100644
index 5717a74e7..000000000
--- a/src/de/danoeh/antennapod/fragment/gpodnet/PodcastTopListFragment.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package de.danoeh.antennapod.fragment.gpodnet;
-
-import de.danoeh.antennapod.gpoddernet.GpodnetService;
-import de.danoeh.antennapod.gpoddernet.GpodnetServiceException;
-import de.danoeh.antennapod.gpoddernet.model.GpodnetPodcast;
-
-import java.util.List;
-
-/**
- *
- */
-public class PodcastTopListFragment extends PodcastListFragment {
- private static final String TAG = "PodcastTopListFragment";
- private static final int PODCAST_COUNT = 50;
-
- @Override
- protected List<GpodnetPodcast> loadPodcastData(GpodnetService service) throws GpodnetServiceException {
- return service.getPodcastToplist(PODCAST_COUNT);
- }
-}
diff --git a/src/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java b/src/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java
deleted file mode 100644
index 801024787..000000000
--- a/src/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package de.danoeh.antennapod.fragment.gpodnet;
-
-import android.os.Bundle;
-import android.support.v7.widget.SearchView;
-import android.view.Menu;
-import android.view.MenuInflater;
-
-import org.apache.commons.lang3.Validate;
-
-import java.util.List;
-
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.gpoddernet.GpodnetService;
-import de.danoeh.antennapod.gpoddernet.GpodnetServiceException;
-import de.danoeh.antennapod.gpoddernet.model.GpodnetPodcast;
-import de.danoeh.antennapod.util.menuhandler.MenuItemUtils;
-import de.danoeh.antennapod.util.menuhandler.NavDrawerActivity;
-
-/**
- * Performs a search on the gpodder.net directory and displays the results.
- */
-public class SearchListFragment extends PodcastListFragment {
- private static final String ARG_QUERY = "query";
-
- private String query;
-
- public static SearchListFragment newInstance(String query) {
- SearchListFragment fragment = new SearchListFragment();
- Bundle args = new Bundle();
- args.putString(ARG_QUERY, query);
- fragment.setArguments(args);
- return fragment;
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- if (getArguments() != null && getArguments().containsKey(ARG_QUERY)) {
- this.query = getArguments().getString(ARG_QUERY);
- } else {
- this.query = "";
- }
- }
-
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- final SearchView sv = new SearchView(getActivity());
- if (!MenuItemUtils.isActivityDrawerOpen((NavDrawerActivity) getActivity())) {
- MenuItemUtils.addSearchItem(menu, sv);
- sv.setQueryHint(getString(R.string.gpodnet_search_hint));
- sv.setQuery(query, false);
- sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
- @Override
- public boolean onQueryTextSubmit(String s) {
- sv.clearFocus();
- changeQuery(s);
- return true;
- }
-
- @Override
- public boolean onQueryTextChange(String s) {
- return false;
- }
- });
- }
- }
-
- @Override
- protected List<GpodnetPodcast> loadPodcastData(GpodnetService service) throws GpodnetServiceException {
- return service.searchPodcasts(query, 0);
- }
-
- public void changeQuery(String query) {
- Validate.notNull(query);
-
- this.query = query;
- loadData();
- }
-}
diff --git a/src/de/danoeh/antennapod/fragment/gpodnet/SuggestionListFragment.java b/src/de/danoeh/antennapod/fragment/gpodnet/SuggestionListFragment.java
deleted file mode 100644
index 45fe25580..000000000
--- a/src/de/danoeh/antennapod/fragment/gpodnet/SuggestionListFragment.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package de.danoeh.antennapod.fragment.gpodnet;
-
-import de.danoeh.antennapod.gpoddernet.GpodnetService;
-import de.danoeh.antennapod.gpoddernet.GpodnetServiceException;
-import de.danoeh.antennapod.gpoddernet.model.GpodnetPodcast;
-import de.danoeh.antennapod.preferences.GpodnetPreferences;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Displays suggestions from gpodder.net
- */
-public class SuggestionListFragment extends PodcastListFragment {
- private static final int SUGGESTIONS_COUNT = 50;
-
- @Override
- protected List<GpodnetPodcast> loadPodcastData(GpodnetService service) throws GpodnetServiceException {
- if (GpodnetPreferences.loggedIn()) {
- service.authenticate(GpodnetPreferences.getUsername(), GpodnetPreferences.getPassword());
- return service.getSuggestions(SUGGESTIONS_COUNT);
- } else {
- return new ArrayList<GpodnetPodcast>();
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/fragment/gpodnet/TagFragment.java b/src/de/danoeh/antennapod/fragment/gpodnet/TagFragment.java
deleted file mode 100644
index 204dda992..000000000
--- a/src/de/danoeh/antennapod/fragment/gpodnet/TagFragment.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package de.danoeh.antennapod.fragment.gpodnet;
-
-import android.os.Bundle;
-
-import org.apache.commons.lang3.Validate;
-
-import de.danoeh.antennapod.activity.MainActivity;
-import de.danoeh.antennapod.gpoddernet.GpodnetService;
-import de.danoeh.antennapod.gpoddernet.GpodnetServiceException;
-import de.danoeh.antennapod.gpoddernet.model.GpodnetPodcast;
-import de.danoeh.antennapod.gpoddernet.model.GpodnetTag;
-
-import java.util.List;
-
-/**
- * Shows all podcasts from gpodder.net that belong to a specific tag.
- * Use the newInstance method of this class to create a new TagFragment.
- */
-public class TagFragment extends PodcastListFragment {
-
- private static final String TAG = "TagFragment";
- private static final int PODCAST_COUNT = 50;
-
- private GpodnetTag tag;
-
- public static TagFragment newInstance(String tagName) {
- Validate.notNull(tagName);
- TagFragment fragment = new TagFragment();
- Bundle args = new Bundle();
- args.putString("tag", tagName);
- fragment.setArguments(args);
- return fragment;
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- Bundle args = getArguments();
- Validate.isTrue(args != null && args.getString("tag") != null, "args invalid");
-
- tag = new GpodnetTag(args.getString("tag"));
- ((MainActivity) getActivity()).getMainActivtyActionBar().setTitle(tag.getName());
- }
-
- @Override
- protected List<GpodnetPodcast> loadPodcastData(GpodnetService service) throws GpodnetServiceException {
- return service.getPodcastsForTag(tag, PODCAST_COUNT);
- }
-}
diff --git a/src/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java b/src/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java
deleted file mode 100644
index a7e1033df..000000000
--- a/src/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java
+++ /dev/null
@@ -1,146 +0,0 @@
-package de.danoeh.antennapod.fragment.gpodnet;
-
-import android.app.Activity;
-import android.content.Context;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.support.v4.app.ListFragment;
-import android.support.v7.widget.SearchView;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.MainActivity;
-import de.danoeh.antennapod.gpoddernet.GpodnetService;
-import de.danoeh.antennapod.gpoddernet.GpodnetServiceException;
-import de.danoeh.antennapod.gpoddernet.model.GpodnetTag;
-import de.danoeh.antennapod.util.menuhandler.MenuItemUtils;
-import de.danoeh.antennapod.util.menuhandler.NavDrawerActivity;
-
-public class TagListFragment extends ListFragment {
- private static final String TAG = "TagListFragment";
- private static final int COUNT = 50;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setHasOptionsMenu(true);
- }
-
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- super.onCreateOptionsMenu(menu, inflater);
- if (!MenuItemUtils.isActivityDrawerOpen((NavDrawerActivity) getActivity())) {
- final SearchView sv = new SearchView(getActivity());
- MenuItemUtils.addSearchItem(menu, sv);
- sv.setQueryHint(getString(R.string.gpodnet_search_hint));
- sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
- @Override
- public boolean onQueryTextSubmit(String s) {
- Activity activity = getActivity();
- if (activity != null) {
- sv.clearFocus();
- ((MainActivity) activity).loadChildFragment(SearchListFragment.newInstance(s));
- }
- return true;
- }
-
- @Override
- public boolean onQueryTextChange(String s) {
- return false;
- }
- });
- }
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
-
- getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- String selectedTag = (String) getListAdapter().getItem(position);
- MainActivity activity = (MainActivity) getActivity();
- activity.loadChildFragment(TagFragment.newInstance(selectedTag));
- }
- });
-
- startLoadTask();
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- cancelLoadTask();
- }
-
- private AsyncTask<Void, Void, List<GpodnetTag>> loadTask;
-
- private void cancelLoadTask() {
- if (loadTask != null && !loadTask.isCancelled()) {
- loadTask.cancel(true);
- }
- }
-
- private void startLoadTask() {
- cancelLoadTask();
- loadTask = new AsyncTask<Void, Void, List<GpodnetTag>>() {
- private Exception exception;
-
- @Override
- protected List<GpodnetTag> doInBackground(Void... params) {
- GpodnetService service = new GpodnetService();
- try {
- return service.getTopTags(COUNT);
- } catch (GpodnetServiceException e) {
- e.printStackTrace();
- exception = e;
- return null;
- } finally {
- service.shutdown();
- }
- }
-
- @Override
- protected void onPreExecute() {
- super.onPreExecute();
- setListShown(false);
- }
-
- @Override
- protected void onPostExecute(List<GpodnetTag> gpodnetTags) {
- super.onPostExecute(gpodnetTags);
- final Context context = getActivity();
- if (context != null) {
- if (gpodnetTags != null) {
- List<String> tagNames = new ArrayList<String>();
- for (GpodnetTag tag : gpodnetTags) {
- tagNames.add(tag.getName());
- }
- setListAdapter(new ArrayAdapter<String>(context, android.R.layout.simple_list_item_1, tagNames));
- } else if (exception != null) {
- TextView txtvError = new TextView(getActivity());
- txtvError.setText(exception.getMessage());
- getListView().setEmptyView(txtvError);
- }
- setListShown(true);
-
- }
- }
- };
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- loadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- } else {
- loadTask.execute();
- }
- }
-}
-
diff --git a/src/de/danoeh/antennapod/gpoddernet/GpodnetService.java b/src/de/danoeh/antennapod/gpoddernet/GpodnetService.java
deleted file mode 100644
index 038b2a367..000000000
--- a/src/de/danoeh/antennapod/gpoddernet/GpodnetService.java
+++ /dev/null
@@ -1,718 +0,0 @@
-package de.danoeh.antennapod.gpoddernet;
-
-import org.apache.commons.lang3.Validate;
-import org.apache.http.Header;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.HttpStatus;
-import org.apache.http.auth.AuthenticationException;
-import org.apache.http.auth.UsernamePasswordCredentials;
-import org.apache.http.client.ClientProtocolException;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.client.methods.HttpPut;
-import org.apache.http.client.methods.HttpRequestBase;
-import org.apache.http.entity.StringEntity;
-import org.apache.http.impl.auth.BasicScheme;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-
-import de.danoeh.antennapod.gpoddernet.model.GpodnetDevice;
-import de.danoeh.antennapod.gpoddernet.model.GpodnetPodcast;
-import de.danoeh.antennapod.gpoddernet.model.GpodnetSubscriptionChange;
-import de.danoeh.antennapod.gpoddernet.model.GpodnetTag;
-import de.danoeh.antennapod.gpoddernet.model.GpodnetUploadChangesResponse;
-import de.danoeh.antennapod.preferences.GpodnetPreferences;
-import de.danoeh.antennapod.service.download.AntennapodHttpClient;
-
-/**
- * Communicates with the gpodder.net service.
- */
-public class GpodnetService {
-
- private static final String BASE_SCHEME = "https";
-
- public static final String DEFAULT_BASE_HOST = "gpodder.net";
- private final String BASE_HOST;
-
- private final HttpClient httpClient;
-
- public GpodnetService() {
- httpClient = AntennapodHttpClient.getHttpClient();
- BASE_HOST = GpodnetPreferences.getHostname();
- }
-
- /**
- * Returns the [count] most used tags.
- */
- public List<GpodnetTag> getTopTags(int count)
- throws GpodnetServiceException {
- URI uri;
- try {
- uri = new URI(BASE_SCHEME, BASE_HOST, String.format(
- "/api/2/tags/%d.json", count), null);
- } catch (URISyntaxException e1) {
- e1.printStackTrace();
- throw new IllegalStateException(e1);
- }
-
- HttpGet request = new HttpGet(uri);
- String response = executeRequest(request);
- try {
- JSONArray jsonTagList = new JSONArray(response);
- List<GpodnetTag> tagList = new ArrayList<GpodnetTag>(
- jsonTagList.length());
- for (int i = 0; i < jsonTagList.length(); i++) {
- JSONObject jObj = jsonTagList.getJSONObject(i);
- String name = jObj.getString("tag");
- int usage = jObj.getInt("usage");
- tagList.add(new GpodnetTag(name, usage));
- }
- return tagList;
- } catch (JSONException e) {
- e.printStackTrace();
- throw new GpodnetServiceException(e);
- }
- }
-
- /**
- * Returns the [count] most subscribed podcasts for the given tag.
- *
- * @throws IllegalArgumentException if tag is null
- */
- public List<GpodnetPodcast> getPodcastsForTag(GpodnetTag tag, int count)
- throws GpodnetServiceException {
- Validate.notNull(tag);
-
- try {
- URI uri = new URI(BASE_SCHEME, BASE_HOST, String.format(
- "/api/2/tag/%s/%d.json", tag.getName(), count), null);
- HttpGet request = new HttpGet(uri);
- String response = executeRequest(request);
-
- JSONArray jsonArray = new JSONArray(response);
- return readPodcastListFromJSONArray(jsonArray);
-
- } catch (JSONException e) {
- e.printStackTrace();
- throw new GpodnetServiceException(e);
- } catch (URISyntaxException e) {
- e.printStackTrace();
- throw new GpodnetServiceException(e);
-
- }
- }
-
- /**
- * Returns the toplist of podcast.
- *
- * @param count of elements that should be returned. Must be in range 1..100.
- * @throws IllegalArgumentException if count is out of range.
- */
- public List<GpodnetPodcast> getPodcastToplist(int count)
- throws GpodnetServiceException {
- Validate.isTrue(count >= 1 && count <= 100, "Count must be in range 1..100");
-
- try {
- URI uri = new URI(BASE_SCHEME, BASE_HOST, String.format(
- "/toplist/%d.json", count), null);
- HttpGet request = new HttpGet(uri);
- String response = executeRequest(request);
-
- JSONArray jsonArray = new JSONArray(response);
- return readPodcastListFromJSONArray(jsonArray);
-
- } catch (JSONException e) {
- e.printStackTrace();
- throw new GpodnetServiceException(e);
- } catch (URISyntaxException e) {
- e.printStackTrace();
- throw new IllegalStateException(e);
-
- }
- }
-
- /**
- * Returns a list of suggested podcasts for the user that is currently
- * logged in.
- * <p/>
- * This method requires authentication.
- *
- * @param count The
- * number of elements that should be returned. Must be in range
- * 1..100.
- * @throws IllegalArgumentException if count is out of range.
- * @throws GpodnetServiceAuthenticationException If there is an authentication error.
- */
- public List<GpodnetPodcast> getSuggestions(int count) throws GpodnetServiceException {
- Validate.isTrue(count >= 1 && count <= 100, "Count must be in range 1..100");
-
- try {
- URI uri = new URI(BASE_SCHEME, BASE_HOST, String.format(
- "/suggestions/%d.json", count), null);
- HttpGet request = new HttpGet(uri);
- String response = executeRequest(request);
-
- JSONArray jsonArray = new JSONArray(response);
- return readPodcastListFromJSONArray(jsonArray);
- } catch (URISyntaxException e) {
- e.printStackTrace();
- throw new IllegalStateException(e);
- } catch (JSONException e) {
- e.printStackTrace();
- throw new GpodnetServiceException(e);
- }
- }
-
- /**
- * Searches the podcast directory for a given string.
- *
- * @param query The search query
- * @param scaledLogoSize The size of the logos that are returned by the search query.
- * Must be in range 1..256. If the value is out of range, the
- * default value defined by the gpodder.net API will be used.
- */
- public List<GpodnetPodcast> searchPodcasts(String query, int scaledLogoSize)
- throws GpodnetServiceException {
- String parameters = (scaledLogoSize > 0 && scaledLogoSize <= 256) ? String
- .format("q=%s&scale_logo=%d", query, scaledLogoSize) : String
- .format("q=%s", query);
- try {
- URI uri = new URI(BASE_SCHEME, null, BASE_HOST, -1, "/search.json",
- parameters, null);
- System.out.println(uri.toASCIIString());
- HttpGet request = new HttpGet(uri);
- String response = executeRequest(request);
-
- JSONArray jsonArray = new JSONArray(response);
- return readPodcastListFromJSONArray(jsonArray);
-
- } catch (JSONException e) {
- e.printStackTrace();
- throw new GpodnetServiceException(e);
- } catch (URISyntaxException e) {
- e.printStackTrace();
- throw new IllegalStateException(e);
-
- }
- }
-
- /**
- * Returns all devices of a given user.
- * <p/>
- * This method requires authentication.
- *
- * @param username The username. Must be the same user as the one which is
- * currently logged in.
- * @throws IllegalArgumentException If username is null.
- * @throws GpodnetServiceAuthenticationException If there is an authentication error.
- */
- public List<GpodnetDevice> getDevices(String username)
- throws GpodnetServiceException {
- Validate.notNull(username);
-
- try {
- URI uri = new URI(BASE_SCHEME, BASE_HOST, String.format(
- "/api/2/devices/%s.json", username), null);
- HttpGet request = new HttpGet(uri);
- String response = executeRequest(request);
- JSONArray devicesArray = new JSONArray(response);
- List<GpodnetDevice> result = readDeviceListFromJSONArray(devicesArray);
-
- return result;
- } catch (URISyntaxException e) {
- e.printStackTrace();
- throw new IllegalStateException(e);
- } catch (JSONException e) {
- e.printStackTrace();
- throw new GpodnetServiceException(e);
- }
- }
-
- /**
- * Configures the device of a given user.
- * <p/>
- * This method requires authentication.
- *
- * @param username The username. Must be the same user as the one which is
- * currently logged in.
- * @param deviceId The ID of the device that should be configured.
- * @throws IllegalArgumentException If username or deviceId is null.
- * @throws GpodnetServiceAuthenticationException If there is an authentication error.
- */
- public void configureDevice(String username, String deviceId,
- String caption, GpodnetDevice.DeviceType type)
- throws GpodnetServiceException {
- Validate.notNull(username);
- Validate.notNull(deviceId);
-
- try {
- URI uri = new URI(BASE_SCHEME, BASE_HOST, String.format(
- "/api/2/devices/%s/%s.json", username, deviceId), null);
- HttpPost request = new HttpPost(uri);
- if (caption != null || type != null) {
- JSONObject jsonContent = new JSONObject();
- if (caption != null) {
- jsonContent.put("caption", caption);
- }
- if (type != null) {
- jsonContent.put("type", type.toString());
- }
- StringEntity strEntity = new StringEntity(
- jsonContent.toString(), "UTF-8");
- strEntity.setContentType("application/json");
- request.setEntity(strEntity);
- }
- executeRequest(request);
- } catch (URISyntaxException e) {
- e.printStackTrace();
- throw new IllegalArgumentException(e);
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- throw new IllegalStateException(e);
- } catch (JSONException e) {
- e.printStackTrace();
- throw new GpodnetServiceException(e);
- }
- }
-
- /**
- * Returns the subscriptions of a specific device.
- * <p/>
- * This method requires authentication.
- *
- * @param username The username. Must be the same user as the one which is
- * currently logged in.
- * @param deviceId The ID of the device whose subscriptions should be returned.
- * @return A list of subscriptions in OPML format.
- * @throws IllegalArgumentException If username or deviceId is null.
- * @throws GpodnetServiceAuthenticationException If there is an authentication error.
- */
- public String getSubscriptionsOfDevice(String username, String deviceId)
- throws GpodnetServiceException {
- Validate.notNull(username);
- Validate.notNull(deviceId);
-
- try {
- URI uri = new URI(BASE_SCHEME, BASE_HOST, String.format(
- "/subscriptions/%s/%s.opml", username, deviceId), null);
- HttpGet request = new HttpGet(uri);
- String response = executeRequest(request);
- return response;
- } catch (URISyntaxException e) {
- e.printStackTrace();
- throw new IllegalArgumentException(e);
- }
- }
-
- /**
- * Returns all subscriptions of a specific user.
- * <p/>
- * This method requires authentication.
- *
- * @param username The username. Must be the same user as the one which is
- * currently logged in.
- * @return A list of subscriptions in OPML format.
- * @throws IllegalArgumentException If username is null.
- * @throws GpodnetServiceAuthenticationException If there is an authentication error.
- */
- public String getSubscriptionsOfUser(String username)
- throws GpodnetServiceException {
- Validate.notNull(username);
-
- try {
- URI uri = new URI(BASE_SCHEME, BASE_HOST, String.format(
- "/subscriptions/%s.opml", username), null);
- HttpGet request = new HttpGet(uri);
- String response = executeRequest(request);
- return response;
- } catch (URISyntaxException e) {
- e.printStackTrace();
- throw new IllegalArgumentException(e);
- }
- }
-
- /**
- * Uploads the subscriptions of a specific device.
- * <p/>
- * This method requires authentication.
- *
- * @param username The username. Must be the same user as the one which is
- * currently logged in.
- * @param deviceId The ID of the device whose subscriptions should be updated.
- * @param subscriptions A list of feed URLs containing all subscriptions of the
- * device.
- * @throws IllegalArgumentException If username, deviceId or subscriptions is null.
- * @throws GpodnetServiceAuthenticationException If there is an authentication error.
- */
- public void uploadSubscriptions(String username, String deviceId,
- List<String> subscriptions) throws GpodnetServiceException {
- if (username == null || deviceId == null || subscriptions == null) {
- throw new IllegalArgumentException(
- "Username, device ID and subscriptions must not be null");
- }
- try {
- URI uri = new URI(BASE_SCHEME, BASE_HOST, String.format(
- "/subscriptions/%s/%s.txt", username, deviceId), null);
- HttpPut request = new HttpPut(uri);
- StringBuilder builder = new StringBuilder();
- for (String s : subscriptions) {
- builder.append(s);
- builder.append("\n");
- }
- StringEntity entity = new StringEntity(builder.toString(), "UTF-8");
- request.setEntity(entity);
-
- executeRequest(request);
- } catch (URISyntaxException e) {
- e.printStackTrace();
- throw new IllegalStateException(e);
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- throw new IllegalStateException(e);
- }
- }
-
- /**
- * Updates the subscription list of a specific device.
- * <p/>
- * This method requires authentication.
- *
- * @param username The username. Must be the same user as the one which is
- * currently logged in.
- * @param deviceId The ID of the device whose subscriptions should be updated.
- * @param added Collection of feed URLs of added feeds. This Collection MUST NOT contain any duplicates
- * @param removed Collection of feed URLs of removed feeds. This Collection MUST NOT contain any duplicates
- * @return a GpodnetUploadChangesResponse. See {@link de.danoeh.antennapod.gpoddernet.model.GpodnetUploadChangesResponse}
- * for details.
- * @throws java.lang.IllegalArgumentException if username, deviceId, added or removed is null.
- * @throws de.danoeh.antennapod.gpoddernet.GpodnetServiceException if added or removed contain duplicates or if there
- * is an authentication error.
- */
- public GpodnetUploadChangesResponse uploadChanges(String username, String deviceId, Collection<String> added,
- Collection<String> removed) throws GpodnetServiceException {
- Validate.notNull(username);
- Validate.notNull(deviceId);
- Validate.notNull(added);
- Validate.notNull(removed);
-
- try {
- URI uri = new URI(BASE_SCHEME, BASE_HOST, String.format(
- "/api/2/subscriptions/%s/%s.json", username, deviceId), null);
-
- final JSONObject requestObject = new JSONObject();
- requestObject.put("add", new JSONArray(added));
- requestObject.put("remove", new JSONArray(removed));
-
- HttpPost request = new HttpPost(uri);
- StringEntity entity = new StringEntity(requestObject.toString(), "UTF-8");
- request.setEntity(entity);
-
- final String response = executeRequest(request);
- return GpodnetUploadChangesResponse.fromJSONObject(response);
- } catch (URISyntaxException e) {
- e.printStackTrace();
- throw new IllegalStateException(e);
- } catch (JSONException e) {
- e.printStackTrace();
- throw new GpodnetServiceException(e);
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- throw new IllegalStateException(e);
- }
-
- }
-
- /**
- * Returns all subscription changes of a specific device.
- * <p/>
- * This method requires authentication.
- *
- * @param username The username. Must be the same user as the one which is
- * currently logged in.
- * @param deviceId The ID of the device whose subscription changes should be
- * downloaded.
- * @param timestamp A timestamp that can be used to receive all changes since a
- * specific point in time.
- * @throws IllegalArgumentException If username or deviceId is null.
- * @throws GpodnetServiceAuthenticationException If there is an authentication error.
- */
- public GpodnetSubscriptionChange getSubscriptionChanges(String username,
- String deviceId, long timestamp) throws GpodnetServiceException {
- Validate.notNull(username);
- Validate.notNull(deviceId);
-
- String params = String.format("since=%d", timestamp);
- String path = String.format("/api/2/subscriptions/%s/%s.json",
- username, deviceId);
- try {
- URI uri = new URI(BASE_SCHEME, null, BASE_HOST, -1, path, params,
- null);
- HttpGet request = new HttpGet(uri);
-
- String response = executeRequest(request);
- JSONObject changes = new JSONObject(response);
- return readSubscriptionChangesFromJSONObject(changes);
- } catch (URISyntaxException e) {
- e.printStackTrace();
- throw new IllegalStateException(e);
- } catch (JSONException e) {
- e.printStackTrace();
- throw new GpodnetServiceException(e);
- }
-
- }
-
- /**
- * Logs in a specific user. This method must be called if any of the methods
- * that require authentication is used.
- *
- * @throws IllegalArgumentException If username or password is null.
- */
- public void authenticate(String username, String password)
- throws GpodnetServiceException {
- Validate.notNull(username);
- Validate.notNull(password);
-
- URI uri;
- try {
- uri = new URI(BASE_SCHEME, BASE_HOST, String.format(
- "/api/2/auth/%s/login.json", username), null);
- } catch (URISyntaxException e) {
- e.printStackTrace();
- throw new GpodnetServiceException();
- }
- HttpPost request = new HttpPost(uri);
- executeRequestWithAuthentication(request, username, password);
- }
-
- /**
- * Shuts down the GpodnetService's HTTP client. The service will be shut down in a separate thread to avoid
- * NetworkOnMainThreadExceptions.
- */
- public void shutdown() {
- new Thread() {
- @Override
- public void run() {
- AntennapodHttpClient.cleanup();
- }
- }.start();
- }
-
- private String executeRequest(HttpRequestBase request)
- throws GpodnetServiceException {
- Validate.notNull(request);
-
- String responseString = null;
- HttpResponse response = null;
- try {
- response = httpClient.execute(request);
- checkStatusCode(response);
- responseString = getStringFromEntity(response.getEntity());
- } catch (ClientProtocolException e) {
- e.printStackTrace();
- throw new GpodnetServiceException(e);
- } catch (IOException e) {
- e.printStackTrace();
- throw new GpodnetServiceException(e);
- } finally {
- if (response != null) {
- try {
- response.getEntity().consumeContent();
- } catch (IOException e) {
- e.printStackTrace();
- throw new GpodnetServiceException(e);
- }
- }
-
- }
- return responseString;
- }
-
- private String executeRequestWithAuthentication(HttpRequestBase request,
- String username, String password) throws GpodnetServiceException {
- if (request == null || username == null || password == null) {
- throw new IllegalArgumentException(
- "request and credentials must not be null");
- }
- String result = null;
- HttpResponse response = null;
- try {
- Header auth = new BasicScheme().authenticate(
- new UsernamePasswordCredentials(username, password),
- request);
- request.addHeader(auth);
- response = httpClient.execute(request);
- checkStatusCode(response);
- result = getStringFromEntity(response.getEntity());
- } catch (ClientProtocolException e) {
- e.printStackTrace();
- throw new GpodnetServiceException(e);
- } catch (IOException e) {
- e.printStackTrace();
- throw new GpodnetServiceException(e);
- } catch (AuthenticationException e) {
- e.printStackTrace();
- throw new GpodnetServiceException(e);
- } finally {
- if (response != null) {
- try {
- response.getEntity().consumeContent();
- } catch (IOException e) {
- e.printStackTrace();
- throw new GpodnetServiceException(e);
- }
- }
- }
- return result;
- }
-
- private String getStringFromEntity(HttpEntity entity)
- throws GpodnetServiceException {
- Validate.notNull(entity);
-
- ByteArrayOutputStream outputStream;
- int contentLength = (int) entity.getContentLength();
- if (contentLength > 0) {
- outputStream = new ByteArrayOutputStream(contentLength);
- } else {
- outputStream = new ByteArrayOutputStream();
- }
- try {
- byte[] buffer = new byte[8 * 1024];
- InputStream in = entity.getContent();
- int count;
- while ((count = in.read(buffer)) > 0) {
- outputStream.write(buffer, 0, count);
- }
- } catch (IOException e) {
- e.printStackTrace();
- throw new GpodnetServiceException(e);
- }
- // System.out.println(outputStream.toString());
- return outputStream.toString();
- }
-
- private void checkStatusCode(HttpResponse response)
- throws GpodnetServiceException {
- Validate.notNull(response);
- int responseCode = response.getStatusLine().getStatusCode();
- if (responseCode != HttpStatus.SC_OK) {
- if (responseCode == HttpStatus.SC_UNAUTHORIZED) {
- throw new GpodnetServiceAuthenticationException("Wrong username or password");
- } else {
- throw new GpodnetServiceBadStatusCodeException(
- "Bad response code: " + responseCode, responseCode);
- }
- }
- }
-
- private List<GpodnetPodcast> readPodcastListFromJSONArray(JSONArray array)
- throws JSONException {
- Validate.notNull(array);
-
- List<GpodnetPodcast> result = new ArrayList<GpodnetPodcast>(
- array.length());
- for (int i = 0; i < array.length(); i++) {
- result.add(readPodcastFromJSONObject(array.getJSONObject(i)));
- }
- return result;
-
- }
-
- private GpodnetPodcast readPodcastFromJSONObject(JSONObject object)
- throws JSONException {
- String url = object.getString("url");
-
- String title;
- Object titleObj = object.opt("title");
- if (titleObj != null && titleObj instanceof String) {
- title = (String) titleObj;
- } else {
- title = url;
- }
-
- String description;
- Object descriptionObj = object.opt("description");
- if (descriptionObj != null && descriptionObj instanceof String) {
- description = (String) descriptionObj;
- } else {
- description = "";
- }
-
- int subscribers = object.getInt("subscribers");
-
- Object logoUrlObj = object.opt("logo_url");
- String logoUrl = (logoUrlObj instanceof String) ? (String) logoUrlObj
- : null;
- if (logoUrl == null) {
- Object scaledLogoUrl = object.opt("scaled_logo_url");
- if (scaledLogoUrl != null && scaledLogoUrl instanceof String) {
- logoUrl = (String) scaledLogoUrl;
- }
- }
-
- String website = null;
- Object websiteObj = object.opt("website");
- if (websiteObj != null && websiteObj instanceof String) {
- website = (String) websiteObj;
- }
- String mygpoLink = object.getString("mygpo_link");
- return new GpodnetPodcast(url, title, description, subscribers,
- logoUrl, website, mygpoLink);
- }
-
- private List<GpodnetDevice> readDeviceListFromJSONArray(JSONArray array)
- throws JSONException {
- Validate.notNull(array);
-
- List<GpodnetDevice> result = new ArrayList<GpodnetDevice>(
- array.length());
- for (int i = 0; i < array.length(); i++) {
- result.add(readDeviceFromJSONObject(array.getJSONObject(i)));
- }
- return result;
- }
-
- private GpodnetDevice readDeviceFromJSONObject(JSONObject object)
- throws JSONException {
- String id = object.getString("id");
- String caption = object.getString("caption");
- String type = object.getString("type");
- int subscriptions = object.getInt("subscriptions");
- return new GpodnetDevice(id, caption, type, subscriptions);
- }
-
- private GpodnetSubscriptionChange readSubscriptionChangesFromJSONObject(
- JSONObject object) throws JSONException {
- Validate.notNull(object);
-
- List<String> added = new LinkedList<String>();
- JSONArray jsonAdded = object.getJSONArray("add");
- for (int i = 0; i < jsonAdded.length(); i++) {
- added.add(jsonAdded.getString(i));
- }
-
- List<String> removed = new LinkedList<String>();
- JSONArray jsonRemoved = object.getJSONArray("remove");
- for (int i = 0; i < jsonRemoved.length(); i++) {
- removed.add(jsonRemoved.getString(i));
- }
-
- long timestamp = object.getLong("timestamp");
- return new GpodnetSubscriptionChange(added, removed, timestamp);
- }
-}
diff --git a/src/de/danoeh/antennapod/gpoddernet/GpodnetServiceAuthenticationException.java b/src/de/danoeh/antennapod/gpoddernet/GpodnetServiceAuthenticationException.java
deleted file mode 100644
index 3b0140826..000000000
--- a/src/de/danoeh/antennapod/gpoddernet/GpodnetServiceAuthenticationException.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package de.danoeh.antennapod.gpoddernet;
-
-public class GpodnetServiceAuthenticationException extends GpodnetServiceException {
-
- public GpodnetServiceAuthenticationException() {
- super();
- }
-
- public GpodnetServiceAuthenticationException(String message, Throwable cause) {
- super(message, cause);
- }
-
- public GpodnetServiceAuthenticationException(String message) {
- super(message);
- }
-
- public GpodnetServiceAuthenticationException(Throwable cause) {
- super(cause);
- }
-
-}
diff --git a/src/de/danoeh/antennapod/gpoddernet/GpodnetServiceBadStatusCodeException.java b/src/de/danoeh/antennapod/gpoddernet/GpodnetServiceBadStatusCodeException.java
deleted file mode 100644
index a32e9357b..000000000
--- a/src/de/danoeh/antennapod/gpoddernet/GpodnetServiceBadStatusCodeException.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package de.danoeh.antennapod.gpoddernet;
-
-public class GpodnetServiceBadStatusCodeException extends GpodnetServiceException {
- int statusCode;
-
- public GpodnetServiceBadStatusCodeException(String message, int statusCode) {
- super(message);
- this.statusCode = statusCode;
- }
-
-
-}
diff --git a/src/de/danoeh/antennapod/gpoddernet/GpodnetServiceException.java b/src/de/danoeh/antennapod/gpoddernet/GpodnetServiceException.java
deleted file mode 100644
index bdb394454..000000000
--- a/src/de/danoeh/antennapod/gpoddernet/GpodnetServiceException.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package de.danoeh.antennapod.gpoddernet;
-
-public class GpodnetServiceException extends Exception {
-
- public GpodnetServiceException() {
- }
-
- public GpodnetServiceException(String message) {
- super(message);
- }
-
- public GpodnetServiceException(Throwable cause) {
- super(cause);
- }
-
- public GpodnetServiceException(String message, Throwable cause) {
- super(message, cause);
- }
-}
diff --git a/src/de/danoeh/antennapod/gpoddernet/model/GpodnetDevice.java b/src/de/danoeh/antennapod/gpoddernet/model/GpodnetDevice.java
deleted file mode 100644
index 86a2171fa..000000000
--- a/src/de/danoeh/antennapod/gpoddernet/model/GpodnetDevice.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package de.danoeh.antennapod.gpoddernet.model;
-
-import org.apache.commons.lang3.Validate;
-
-public class GpodnetDevice {
-
- private String id;
- private String caption;
- private DeviceType type;
- private int subscriptions;
-
- public GpodnetDevice(String id, String caption, String type,
- int subscriptions) {
- Validate.notNull(id);
-
- this.id = id;
- this.caption = caption;
- this.type = DeviceType.fromString(type);
- this.subscriptions = subscriptions;
- }
-
- @Override
- public String toString() {
- return "GpodnetDevice [id=" + id + ", caption=" + caption + ", type="
- + type + ", subscriptions=" + subscriptions + "]";
- }
-
- public static enum DeviceType {
- DESKTOP, LAPTOP, MOBILE, SERVER, OTHER;
-
- static DeviceType fromString(String s) {
- if (s == null) {
- return OTHER;
- }
-
- if (s.equals("desktop")) {
- return DESKTOP;
- } else if (s.equals("laptop")) {
- return LAPTOP;
- } else if (s.equals("mobile")) {
- return MOBILE;
- } else if (s.equals("server")) {
- return SERVER;
- } else {
- return OTHER;
- }
- }
-
- @Override
- public String toString() {
- return super.toString().toLowerCase();
- }
-
- }
-
- public String getId() {
- return id;
- }
-
- public String getCaption() {
- return caption;
- }
-
- public DeviceType getType() {
- return type;
- }
-
- public int getSubscriptions() {
- return subscriptions;
- }
-
-}
diff --git a/src/de/danoeh/antennapod/gpoddernet/model/GpodnetPodcast.java b/src/de/danoeh/antennapod/gpoddernet/model/GpodnetPodcast.java
deleted file mode 100644
index b002035c9..000000000
--- a/src/de/danoeh/antennapod/gpoddernet/model/GpodnetPodcast.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package de.danoeh.antennapod.gpoddernet.model;
-
-import org.apache.commons.lang3.Validate;
-
-public class GpodnetPodcast {
- private String url;
- private String title;
- private String description;
- private int subscribers;
- private String logoUrl;
- private String website;
- private String mygpoLink;
-
- public GpodnetPodcast(String url, String title, String description,
- int subscribers, String logoUrl, String website, String mygpoLink) {
- Validate.notNull(url);
- Validate.notNull(title);
- Validate.notNull(description);
-
- this.url = url;
- this.title = title;
- this.description = description;
- this.subscribers = subscribers;
- this.logoUrl = logoUrl;
- this.website = website;
- this.mygpoLink = mygpoLink;
- }
-
- @Override
- public String toString() {
- return "GpodnetPodcast [url=" + url + ", title=" + title
- + ", description=" + description + ", subscribers="
- + subscribers + ", logoUrl=" + logoUrl + ", website=" + website
- + ", mygpoLink=" + mygpoLink + "]";
- }
-
- public String getUrl() {
- return url;
- }
-
- public String getTitle() {
- return title;
- }
-
- public String getDescription() {
- return description;
- }
-
- public int getSubscribers() {
- return subscribers;
- }
-
- public String getLogoUrl() {
- return logoUrl;
- }
-
- public String getWebsite() {
- return website;
- }
-
- public String getMygpoLink() {
- return mygpoLink;
- }
-
-}
diff --git a/src/de/danoeh/antennapod/gpoddernet/model/GpodnetSubscriptionChange.java b/src/de/danoeh/antennapod/gpoddernet/model/GpodnetSubscriptionChange.java
deleted file mode 100644
index a4617118d..000000000
--- a/src/de/danoeh/antennapod/gpoddernet/model/GpodnetSubscriptionChange.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package de.danoeh.antennapod.gpoddernet.model;
-
-import org.apache.commons.lang3.Validate;
-
-import java.util.List;
-
-public class GpodnetSubscriptionChange {
- private List<String> added;
- private List<String> removed;
- private long timestamp;
-
- public GpodnetSubscriptionChange(List<String> added, List<String> removed,
- long timestamp) {
- Validate.notNull(added);
- Validate.notNull(removed);
-
- this.added = added;
- this.removed = removed;
- this.timestamp = timestamp;
- }
-
- @Override
- public String toString() {
- return "GpodnetSubscriptionChange [added=" + added.toString()
- + ", removed=" + removed.toString() + ", timestamp="
- + timestamp + "]";
- }
-
- public List<String> getAdded() {
- return added;
- }
-
- public List<String> getRemoved() {
- return removed;
- }
-
- public long getTimestamp() {
- return timestamp;
- }
-
-}
diff --git a/src/de/danoeh/antennapod/gpoddernet/model/GpodnetTag.java b/src/de/danoeh/antennapod/gpoddernet/model/GpodnetTag.java
deleted file mode 100644
index 80b84095e..000000000
--- a/src/de/danoeh/antennapod/gpoddernet/model/GpodnetTag.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package de.danoeh.antennapod.gpoddernet.model;
-
-import org.apache.commons.lang3.Validate;
-
-import java.util.Comparator;
-
-public class GpodnetTag {
-
- private String name;
- private int usage;
-
- public GpodnetTag(String name, int usage) {
- Validate.notNull(name);
-
- this.name = name;
- this.usage = usage;
- }
-
- public GpodnetTag(String name) {
- super();
- this.name = name;
- }
-
- @Override
- public String toString() {
- return "GpodnetTag [name=" + name + ", usage=" + usage + "]";
- }
-
- public String getName() {
- return name;
- }
-
- public int getUsage() {
- return usage;
- }
-
- public static class UsageComparator implements Comparator<GpodnetTag> {
-
- @Override
- public int compare(GpodnetTag o1, GpodnetTag o2) {
- return o1.usage - o2.usage;
- }
-
- }
-
-}
diff --git a/src/de/danoeh/antennapod/gpoddernet/model/GpodnetUploadChangesResponse.java b/src/de/danoeh/antennapod/gpoddernet/model/GpodnetUploadChangesResponse.java
deleted file mode 100644
index fee8c7d28..000000000
--- a/src/de/danoeh/antennapod/gpoddernet/model/GpodnetUploadChangesResponse.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package de.danoeh.antennapod.gpoddernet.model;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Object returned by {@link de.danoeh.antennapod.gpoddernet.GpodnetService} in uploadChanges method.
- */
-public class GpodnetUploadChangesResponse {
-
- /**
- * timestamp/ID that can be used for requesting changes since this upload.
- */
- public final long timestamp;
-
- /**
- * URLs that should be updated. The key of the map is the original URL, the value of the map
- * is the sanitized URL.
- */
- public final Map<String, String> updatedUrls;
-
- public GpodnetUploadChangesResponse(long timestamp, Map<String, String> updatedUrls) {
- this.timestamp = timestamp;
- this.updatedUrls = updatedUrls;
- }
-
- /**
- * Creates a new GpodnetUploadChangesResponse-object from a JSON object that was
- * returned by an uploadChanges call.
- *
- * @throws org.json.JSONException If the method could not parse the JSONObject.
- */
- public static GpodnetUploadChangesResponse fromJSONObject(String objectString) throws JSONException {
- final JSONObject object = new JSONObject(objectString);
- final long timestamp = object.getLong("timestamp");
- Map<String, String> updatedUrls = new HashMap<String, String>();
- JSONArray urls = object.getJSONArray("update_urls");
- for (int i = 0; i < urls.length(); i++) {
- JSONArray urlPair = urls.getJSONArray(i);
- updatedUrls.put(urlPair.getString(0), urlPair.getString(1));
- }
- return new GpodnetUploadChangesResponse(timestamp, updatedUrls);
- }
-
- @Override
- public String toString() {
- return "GpodnetUploadChangesResponse{" +
- "timestamp=" + timestamp +
- ", updatedUrls=" + updatedUrls +
- '}';
- }
-}
diff --git a/src/de/danoeh/antennapod/opml/OpmlElement.java b/src/de/danoeh/antennapod/opml/OpmlElement.java
deleted file mode 100644
index 4cb563c04..000000000
--- a/src/de/danoeh/antennapod/opml/OpmlElement.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package de.danoeh.antennapod.opml;
-
-/** Represents a single feed in an OPML file. */
-public class OpmlElement {
- private String text;
- private String xmlUrl;
- private String htmlUrl;
- private String type;
-
- public OpmlElement() {
-
- }
-
- public String getText() {
- return text;
- }
-
- public void setText(String text) {
- this.text = text;
- }
-
- public String getXmlUrl() {
- return xmlUrl;
- }
-
- public void setXmlUrl(String xmlUrl) {
- this.xmlUrl = xmlUrl;
- }
-
- public String getHtmlUrl() {
- return htmlUrl;
- }
-
- public void setHtmlUrl(String htmlUrl) {
- this.htmlUrl = htmlUrl;
- }
-
- public String getType() {
- return type;
- }
-
- public void setType(String type) {
- this.type = type;
- }
-
-}
diff --git a/src/de/danoeh/antennapod/opml/OpmlReader.java b/src/de/danoeh/antennapod/opml/OpmlReader.java
deleted file mode 100644
index 19a980dee..000000000
--- a/src/de/danoeh/antennapod/opml/OpmlReader.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package de.danoeh.antennapod.opml;
-
-import android.util.Log;
-import de.danoeh.antennapod.BuildConfig;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlPullParserFactory;
-
-import java.io.IOException;
-import java.io.Reader;
-import java.util.ArrayList;
-
-/** Reads OPML documents. */
-public class OpmlReader {
- private static final String TAG = "OpmlReader";
-
- // ATTRIBUTES
- private boolean isInOpml = false;
- private ArrayList<OpmlElement> elementList;
-
- /**
- * Reads an Opml document and returns a list of all OPML elements it can
- * find
- *
- * @throws IOException
- * @throws XmlPullParserException
- */
- public ArrayList<OpmlElement> readDocument(Reader reader)
- throws XmlPullParserException, IOException {
- elementList = new ArrayList<OpmlElement>();
- XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
- factory.setNamespaceAware(true);
- XmlPullParser xpp = factory.newPullParser();
- xpp.setInput(reader);
- int eventType = xpp.getEventType();
-
- while (eventType != XmlPullParser.END_DOCUMENT) {
- switch (eventType) {
- case XmlPullParser.START_DOCUMENT:
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Reached beginning of document");
- break;
- case XmlPullParser.START_TAG:
- if (xpp.getName().equals(OpmlSymbols.OPML)) {
- isInOpml = true;
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Reached beginning of OPML tree.");
- } else if (isInOpml && xpp.getName().equals(OpmlSymbols.OUTLINE)) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Found new Opml element");
- OpmlElement element = new OpmlElement();
-
- final String title = xpp.getAttributeValue(null, OpmlSymbols.TITLE);
- if (title != null) {
- Log.i(TAG, "Using title: " + title);
- element.setText(title);
- } else {
- Log.i(TAG, "Title not found, using text");
- element.setText(xpp.getAttributeValue(null, OpmlSymbols.TEXT));
- }
- element.setXmlUrl(xpp.getAttributeValue(null, OpmlSymbols.XMLURL));
- element.setHtmlUrl(xpp.getAttributeValue(null, OpmlSymbols.HTMLURL));
- element.setType(xpp.getAttributeValue(null, OpmlSymbols.TYPE));
- if (element.getXmlUrl() != null) {
- if (element.getText() == null) {
- Log.i(TAG, "Opml element has no text attribute.");
- element.setText(element.getXmlUrl());
- }
- elementList.add(element);
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "Skipping element because of missing xml url");
- }
- }
- break;
- }
- eventType = xpp.next();
- }
-
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Parsing finished.");
-
- return elementList;
- }
-
-}
diff --git a/src/de/danoeh/antennapod/opml/OpmlSymbols.java b/src/de/danoeh/antennapod/opml/OpmlSymbols.java
deleted file mode 100644
index 4b0b7316a..000000000
--- a/src/de/danoeh/antennapod/opml/OpmlSymbols.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package de.danoeh.antennapod.opml;
-
-/** Contains symbols for reading and writing OPML documents. */
-public final class OpmlSymbols {
-
- public static final String OPML = "opml";
- public static final String BODY = "body";
- public static final String OUTLINE = "outline";
- public static final String TEXT = "text";
- public static final String XMLURL = "xmlUrl";
- public static final String HTMLURL = "htmlUrl";
- public static final String TYPE = "type";
- public static final String VERSION = "version";
- public static final String HEAD = "head";
- public static final String TITLE = "title";
-
- private OpmlSymbols() {
-
- }
-
-}
diff --git a/src/de/danoeh/antennapod/opml/OpmlWriter.java b/src/de/danoeh/antennapod/opml/OpmlWriter.java
deleted file mode 100644
index 405a5e35a..000000000
--- a/src/de/danoeh/antennapod/opml/OpmlWriter.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package de.danoeh.antennapod.opml;
-
-import android.util.Log;
-import android.util.Xml;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.feed.Feed;
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.List;
-
-/** Writes OPML documents. */
-public class OpmlWriter {
- private static final String TAG = "OpmlWriter";
- private static final String ENCODING = "UTF-8";
- private static final String OPML_VERSION = "2.0";
- private static final String OPML_TITLE = "AntennaPod Subscriptions";
-
- /**
- * Takes a list of feeds and a writer and writes those into an OPML
- * document.
- *
- * @throws IOException
- * @throws IllegalStateException
- * @throws IllegalArgumentException
- */
- public void writeDocument(List<Feed> feeds, Writer writer)
- throws IllegalArgumentException, IllegalStateException, IOException {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Starting to write document");
- XmlSerializer xs = Xml.newSerializer();
- xs.setOutput(writer);
-
- xs.startDocument(ENCODING, false);
- xs.startTag(null, OpmlSymbols.OPML);
- xs.attribute(null, OpmlSymbols.VERSION, OPML_VERSION);
-
- xs.startTag(null, OpmlSymbols.HEAD);
- xs.startTag(null, OpmlSymbols.TITLE);
- xs.text(OPML_TITLE);
- xs.endTag(null, OpmlSymbols.TITLE);
- xs.endTag(null, OpmlSymbols.HEAD);
-
- xs.startTag(null, OpmlSymbols.BODY);
- for (Feed feed : feeds) {
- xs.startTag(null, OpmlSymbols.OUTLINE);
- xs.attribute(null, OpmlSymbols.TEXT, feed.getTitle());
- xs.attribute(null, OpmlSymbols.TITLE, feed.getTitle());
- if (feed.getType() != null) {
- xs.attribute(null, OpmlSymbols.TYPE, feed.getType());
- }
- xs.attribute(null, OpmlSymbols.XMLURL, feed.getDownload_url());
- if (feed.getLink() != null) {
- xs.attribute(null, OpmlSymbols.HTMLURL, feed.getLink());
- }
- xs.endTag(null, OpmlSymbols.OUTLINE);
- }
- xs.endTag(null, OpmlSymbols.BODY);
- xs.endTag(null, OpmlSymbols.OPML);
- xs.endDocument();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Finished writing document");
- }
-}
diff --git a/src/de/danoeh/antennapod/preferences/GpodnetPreferences.java b/src/de/danoeh/antennapod/preferences/GpodnetPreferences.java
deleted file mode 100644
index bdfe297a6..000000000
--- a/src/de/danoeh/antennapod/preferences/GpodnetPreferences.java
+++ /dev/null
@@ -1,246 +0,0 @@
-package de.danoeh.antennapod.preferences;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.util.Log;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.PodcastApp;
-import de.danoeh.antennapod.gpoddernet.GpodnetService;
-import de.danoeh.antennapod.service.GpodnetSyncService;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * Manages preferences for accessing gpodder.net service
- */
-public class GpodnetPreferences {
-
- private static final String TAG = "GpodnetPreferences";
-
- private static final String PREF_NAME = "gpodder.net";
- public static final String PREF_GPODNET_USERNAME = "de.danoeh.antennapod.preferences.gpoddernet.username";
- public static final String PREF_GPODNET_PASSWORD = "de.danoeh.antennapod.preferences.gpoddernet.password";
- public static final String PREF_GPODNET_DEVICEID = "de.danoeh.antennapod.preferences.gpoddernet.deviceID";
- public static final String PREF_GPODNET_HOSTNAME = "prefGpodnetHostname";
-
-
- public static final String PREF_LAST_SYNC_TIMESTAMP = "de.danoeh.antennapod.preferences.gpoddernet.last_sync_timestamp";
- public static final String PREF_SYNC_ADDED = "de.danoeh.antennapod.preferences.gpoddernet.sync_added";
- public static final String PREF_SYNC_REMOVED = "de.danoeh.antennapod.preferences.gpoddernet.sync_removed";
-
- private static String username;
- private static String password;
- private static String deviceID;
- private static String hostname;
-
- private static ReentrantLock feedListLock = new ReentrantLock();
- private static Set<String> addedFeeds;
- private static Set<String> removedFeeds;
-
- /**
- * Last value returned by getSubscriptionChanges call. Will be used for all subsequent calls of getSubscriptionChanges.
- */
- private static long lastSyncTimestamp;
-
- private static boolean preferencesLoaded = false;
-
- private static SharedPreferences getPreferences() {
- return PodcastApp.getInstance().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
- }
-
- private static synchronized void ensurePreferencesLoaded() {
- if (!preferencesLoaded) {
- SharedPreferences prefs = getPreferences();
- username = prefs.getString(PREF_GPODNET_USERNAME, null);
- password = prefs.getString(PREF_GPODNET_PASSWORD, null);
- deviceID = prefs.getString(PREF_GPODNET_DEVICEID, null);
- lastSyncTimestamp = prefs.getLong(PREF_LAST_SYNC_TIMESTAMP, 0);
- addedFeeds = readListFromString(prefs.getString(PREF_SYNC_ADDED, ""));
- removedFeeds = readListFromString(prefs.getString(PREF_SYNC_REMOVED, ""));
- hostname = checkGpodnetHostname(prefs.getString(PREF_GPODNET_HOSTNAME, GpodnetService.DEFAULT_BASE_HOST));
-
- preferencesLoaded = true;
- }
- }
-
- private static void writePreference(String key, String value) {
- SharedPreferences.Editor editor = getPreferences().edit();
- editor.putString(key, value);
- editor.commit();
- }
-
- private static void writePreference(String key, long value) {
- SharedPreferences.Editor editor = getPreferences().edit();
- editor.putLong(key, value);
- editor.commit();
- }
-
- private static void writePreference(String key, Collection<String> value) {
- SharedPreferences.Editor editor = getPreferences().edit();
- editor.putString(key, writeListToString(value));
- editor.commit();
- }
-
- public static String getUsername() {
- ensurePreferencesLoaded();
- return username;
- }
-
- public static void setUsername(String username) {
- GpodnetPreferences.username = username;
- writePreference(PREF_GPODNET_USERNAME, username);
- }
-
- public static String getPassword() {
- ensurePreferencesLoaded();
- return password;
- }
-
- public static void setPassword(String password) {
- GpodnetPreferences.password = password;
- writePreference(PREF_GPODNET_PASSWORD, password);
- }
-
- public static String getDeviceID() {
- ensurePreferencesLoaded();
- return deviceID;
- }
-
- public static void setDeviceID(String deviceID) {
- GpodnetPreferences.deviceID = deviceID;
- writePreference(PREF_GPODNET_DEVICEID, deviceID);
- }
-
- public static long getLastSyncTimestamp() {
- ensurePreferencesLoaded();
- return lastSyncTimestamp;
- }
-
- public static void setLastSyncTimestamp(long lastSyncTimestamp) {
- GpodnetPreferences.lastSyncTimestamp = lastSyncTimestamp;
- writePreference(PREF_LAST_SYNC_TIMESTAMP, lastSyncTimestamp);
- }
-
- public static String getHostname() {
- ensurePreferencesLoaded();
- return hostname;
- }
-
- public static void setHostname(String value) {
- value = checkGpodnetHostname(value);
- if (!value.equals(hostname)) {
- logout();
- writePreference(PREF_GPODNET_HOSTNAME, value);
- hostname = value;
- }
- }
-
- public static void addAddedFeed(String feed) {
- ensurePreferencesLoaded();
- feedListLock.lock();
- if (addedFeeds.add(feed)) {
- writePreference(PREF_SYNC_ADDED, addedFeeds);
- }
- if (removedFeeds.remove(feed)) {
- writePreference(PREF_SYNC_REMOVED, removedFeeds);
- }
- feedListLock.unlock();
- GpodnetSyncService.sendSyncIntent(PodcastApp.getInstance());
- }
-
- public static void addRemovedFeed(String feed) {
- ensurePreferencesLoaded();
- feedListLock.lock();
- if (removedFeeds.add(feed)) {
- writePreference(PREF_SYNC_REMOVED, removedFeeds);
- }
- if (addedFeeds.remove(feed)) {
- writePreference(PREF_SYNC_ADDED, addedFeeds);
- }
- feedListLock.unlock();
- GpodnetSyncService.sendSyncIntent(PodcastApp.getInstance());
- }
-
- public static Set<String> getAddedFeedsCopy() {
- ensurePreferencesLoaded();
- Set<String> copy = new HashSet<String>();
- feedListLock.lock();
- copy.addAll(addedFeeds);
- feedListLock.unlock();
- return copy;
- }
-
- public static void removeAddedFeeds(Collection<String> removed) {
- ensurePreferencesLoaded();
- feedListLock.lock();
- addedFeeds.removeAll(removed);
- writePreference(PREF_SYNC_ADDED, addedFeeds);
- feedListLock.unlock();
- }
-
- public static Set<String> getRemovedFeedsCopy() {
- ensurePreferencesLoaded();
- Set<String> copy = new HashSet<String>();
- feedListLock.lock();
- copy.addAll(removedFeeds);
- feedListLock.unlock();
- return copy;
- }
-
- public static void removeRemovedFeeds(Collection<String> removed) {
- ensurePreferencesLoaded();
- removedFeeds.removeAll(removed);
- writePreference(PREF_SYNC_REMOVED, removedFeeds);
-
- }
-
- /**
- * Returns true if device ID, username and password have a non-null value
- */
- public static boolean loggedIn() {
- ensurePreferencesLoaded();
- return deviceID != null && username != null && password != null;
- }
-
- public static synchronized void logout() {
- if (BuildConfig.DEBUG) Log.d(TAG, "Logout: Clearing preferences");
- setUsername(null);
- setPassword(null);
- setDeviceID(null);
- addedFeeds.clear();
- writePreference(PREF_SYNC_ADDED, addedFeeds);
- removedFeeds.clear();
- writePreference(PREF_SYNC_REMOVED, removedFeeds);
- setLastSyncTimestamp(0);
- }
-
- private static Set<String> readListFromString(String s) {
- Set<String> result = new HashSet<String>();
- for (String item : s.split(" ")) {
- result.add(item);
- }
- return result;
- }
-
- private static String writeListToString(Collection<String> c) {
- StringBuilder result = new StringBuilder();
- for (String item : c) {
- result.append(item);
- result.append(" ");
- }
- return result.toString().trim();
- }
-
- private static String checkGpodnetHostname(String value) {
- int startIndex = 0;
- if (value.startsWith("http://")) {
- startIndex = "http://".length();
- } else if (value.startsWith("https://")) {
- startIndex = "https://".length();
- }
- return value.substring(startIndex);
- }
-}
diff --git a/src/de/danoeh/antennapod/preferences/PlaybackPreferences.java b/src/de/danoeh/antennapod/preferences/PlaybackPreferences.java
deleted file mode 100644
index 1d1ab052f..000000000
--- a/src/de/danoeh/antennapod/preferences/PlaybackPreferences.java
+++ /dev/null
@@ -1,146 +0,0 @@
-package de.danoeh.antennapod.preferences;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
-import android.util.Log;
-
-import org.apache.commons.lang3.Validate;
-
-import de.danoeh.antennapod.BuildConfig;
-
-/**
- * Provides access to preferences set by the playback service. A private
- * instance of this class must first be instantiated via createInstance() or
- * otherwise every public method will throw an Exception when called.
- */
-public class PlaybackPreferences implements
- SharedPreferences.OnSharedPreferenceChangeListener {
- private static final String TAG = "PlaybackPreferences";
-
- /**
- * Contains the feed id of the currently playing item if it is a FeedMedia
- * object.
- */
- public static final String PREF_CURRENTLY_PLAYING_FEED_ID = "de.danoeh.antennapod.preferences.lastPlayedFeedId";
-
- /**
- * Contains the id of the currently playing FeedMedia object or
- * NO_MEDIA_PLAYING if the currently playing media is no FeedMedia object.
- */
- public static final String PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID = "de.danoeh.antennapod.preferences.lastPlayedFeedMediaId";
-
- /**
- * Type of the media object that is currently being played. This preference
- * is set to NO_MEDIA_PLAYING after playback has been completed and is set
- * as soon as the 'play' button is pressed.
- */
- 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_CURRENT_EPISODE_IS_STREAM = "de.danoeh.antennapod.preferences.lastIsStream";
-
- /** True if last played media was a video. */
- 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 currentlyPlayingFeedId;
- private long currentlyPlayingFeedMediaId;
- private long currentlyPlayingMedia;
- private boolean currentEpisodeIsStream;
- private boolean currentEpisodeIsVideo;
-
- private static PlaybackPreferences instance;
- private Context context;
-
- private PlaybackPreferences(Context context) {
- this.context = context;
- loadPreferences();
- }
-
- /**
- * Sets up the UserPreferences class.
- *
- * @throws IllegalArgumentException
- * if context is null
- * */
- public static void createInstance(Context context) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Creating new instance of UserPreferences");
- Validate.notNull(context);
-
- instance = new PlaybackPreferences(context);
-
- PreferenceManager.getDefaultSharedPreferences(context)
- .registerOnSharedPreferenceChangeListener(instance);
- }
-
- private void loadPreferences() {
- SharedPreferences sp = PreferenceManager
- .getDefaultSharedPreferences(context);
- 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);
- 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_CURRENTLY_PLAYING_FEED_ID)) {
- currentlyPlayingFeedId = sp.getLong(PREF_CURRENTLY_PLAYING_FEED_ID,
- -1);
-
- } else if (key.equals(PREF_CURRENTLY_PLAYING_MEDIA)) {
- currentlyPlayingMedia = sp
- .getLong(PREF_CURRENTLY_PLAYING_MEDIA, -1);
-
- } else if (key.equals(PREF_CURRENT_EPISODE_IS_STREAM)) {
- currentEpisodeIsStream = sp.getBoolean(PREF_CURRENT_EPISODE_IS_STREAM, true);
-
- } else if (key.equals(PREF_CURRENT_EPISODE_IS_VIDEO)) {
- currentEpisodeIsVideo = sp.getBoolean(PREF_CURRENT_EPISODE_IS_VIDEO, false);
-
- } else if (key.equals(PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID)) {
- currentlyPlayingFeedMediaId = sp.getLong(
- PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID, NO_MEDIA_PLAYING);
- }
- }
-
- private static void instanceAvailable() {
- if (instance == null) {
- throw new IllegalStateException(
- "UserPreferences was used before being set up");
- }
- }
-
-
- public static long getLastPlayedFeedId() {
- instanceAvailable();
- return instance.currentlyPlayingFeedId;
- }
-
- public static long getCurrentlyPlayingMedia() {
- instanceAvailable();
- return instance.currentlyPlayingMedia;
- }
-
- public static long getCurrentlyPlayingFeedMediaId() {
- return instance.currentlyPlayingFeedMediaId;
- }
-
- public static boolean getCurrentEpisodeIsStream() {
- instanceAvailable();
- return instance.currentEpisodeIsStream;
- }
-
- public static boolean getCurrentEpisodeIsVideo() {
- instanceAvailable();
- return instance.currentEpisodeIsVideo;
- }
-
-}
diff --git a/src/de/danoeh/antennapod/preferences/UserPreferences.java b/src/de/danoeh/antennapod/preferences/UserPreferences.java
deleted file mode 100644
index 2020ddfae..000000000
--- a/src/de/danoeh/antennapod/preferences/UserPreferences.java
+++ /dev/null
@@ -1,577 +0,0 @@
-package de.danoeh.antennapod.preferences;
-
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
-import android.util.Log;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.Validate;
-import org.json.JSONArray;
-import org.json.JSONException;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.OpmlImportFromPathActivity;
-import de.danoeh.antennapod.receiver.FeedUpdateReceiver;
-
-/**
- * Provides access to preferences set by the user in the settings screen. A
- * private instance of this class must first be instantiated via
- * createInstance() or otherwise every public method will throw an Exception
- * when called.
- */
-public class UserPreferences implements
- SharedPreferences.OnSharedPreferenceChangeListener {
- private static final String TAG = "UserPreferences";
-
- public static final String PREF_PAUSE_ON_HEADSET_DISCONNECT = "prefPauseOnHeadsetDisconnect";
- public static final String PREF_FOLLOW_QUEUE = "prefFollowQueue";
- 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_DISPLAY_ONLY_EPISODES = "prefDisplayOnlyEpisodes";
- public static final String PREF_AUTO_DELETE = "prefAutoDelete";
- public static final String PREF_AUTO_FLATTR = "pref_auto_flattr";
- public static final String PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD = "prefAutoFlattrPlayedDurationThreshold";
- public static final String PREF_THEME = "prefTheme";
- public static final String PREF_DATA_FOLDER = "prefDataFolder";
- public static final String PREF_ENABLE_AUTODL = "prefEnableAutoDl";
- 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 final String PREF_PLAYBACK_SPEED = "prefPlaybackSpeed";
- private static final String PREF_PLAYBACK_SPEED_ARRAY = "prefPlaybackSpeedArray";
- public static final String PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS = "prefPauseForFocusLoss";
- private static final String PREF_SEEK_DELTA_SECS = "prefSeekDeltaSecs";
-
- // TODO: Make this value configurable
- private static final float PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD_DEFAULT = 0.8f;
-
- private static int EPISODE_CACHE_SIZE_UNLIMITED = -1;
-
- private static UserPreferences instance;
- private final Context context;
-
- // Preferences
- private boolean pauseOnHeadsetDisconnect;
- private boolean followQueue;
- private boolean downloadMediaOnWifiOnly;
- private long updateInterval;
- private boolean allowMobileUpdate;
- private boolean displayOnlyEpisodes;
- private boolean autoDelete;
- private boolean autoFlattr;
- private float autoFlattrPlayedDurationThreshold;
- private int theme;
- private boolean enableAutodownload;
- private boolean enableAutodownloadWifiFilter;
- private String[] autodownloadSelectedNetworks;
- private int episodeCacheSize;
- private String playbackSpeed;
- private String[] playbackSpeedArray;
- private boolean pauseForFocusLoss;
- private int seekDeltaSecs;
- private boolean isFreshInstall;
-
- private UserPreferences(Context context) {
- this.context = context;
- loadPreferences();
- }
-
- /**
- * Sets up the UserPreferences class.
- *
- * @throws IllegalArgumentException if context is null
- */
- public static void createInstance(Context context) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Creating new instance of UserPreferences");
- Validate.notNull(context);
-
- instance = new UserPreferences(context);
-
- createImportDirectory();
- createNoMediaFile();
- PreferenceManager.getDefaultSharedPreferences(context)
- .registerOnSharedPreferenceChangeListener(instance);
-
- }
-
- private void loadPreferences() {
- SharedPreferences sp = PreferenceManager
- .getDefaultSharedPreferences(context);
- EPISODE_CACHE_SIZE_UNLIMITED = context.getResources().getInteger(
- R.integer.episode_cache_size_unlimited);
- pauseOnHeadsetDisconnect = sp.getBoolean(
- PREF_PAUSE_ON_HEADSET_DISCONNECT, true);
- followQueue = sp.getBoolean(PREF_FOLLOW_QUEUE, false);
- downloadMediaOnWifiOnly = sp.getBoolean(
- PREF_DOWNLOAD_MEDIA_ON_WIFI_ONLY, true);
- updateInterval = readUpdateInterval(sp.getString(PREF_UPDATE_INTERVAL,
- "0"));
- allowMobileUpdate = sp.getBoolean(PREF_MOBILE_UPDATE, false);
- displayOnlyEpisodes = sp.getBoolean(PREF_DISPLAY_ONLY_EPISODES, false);
- autoDelete = sp.getBoolean(PREF_AUTO_DELETE, false);
- autoFlattr = sp.getBoolean(PREF_AUTO_FLATTR, false);
- autoFlattrPlayedDurationThreshold = sp.getFloat(PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD,
- PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD_DEFAULT);
- 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 = readEpisodeCacheSizeInternal(sp.getString(
- PREF_EPISODE_CACHE_SIZE, "20"));
- enableAutodownload = sp.getBoolean(PREF_ENABLE_AUTODL, false);
- playbackSpeed = sp.getString(PREF_PLAYBACK_SPEED, "1.0");
- playbackSpeedArray = readPlaybackSpeedArray(sp.getString(
- PREF_PLAYBACK_SPEED_ARRAY, null));
- pauseForFocusLoss = sp.getBoolean(PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS, false);
- seekDeltaSecs = Integer.valueOf(sp.getString(PREF_SEEK_DELTA_SECS, "30"));
- }
-
- private int readThemeValue(String valueFromPrefs) {
- switch (Integer.parseInt(valueFromPrefs)) {
- case 0:
- return R.style.Theme_AntennaPod_Light;
- case 1:
- return R.style.Theme_AntennaPod_Dark;
- default:
- return R.style.Theme_AntennaPod_Light;
- }
- }
-
- private long readUpdateInterval(String valueFromPrefs) {
- int hours = Integer.parseInt(valueFromPrefs);
- return TimeUnit.HOURS.toMillis(hours);
- }
-
- private int readEpisodeCacheSizeInternal(String valueFromPrefs) {
- if (valueFromPrefs.equals(context
- .getString(R.string.pref_episode_cache_unlimited))) {
- return EPISODE_CACHE_SIZE_UNLIMITED;
- } else {
- return Integer.valueOf(valueFromPrefs);
- }
- }
-
- private String[] readPlaybackSpeedArray(String valueFromPrefs) {
- String[] selectedSpeeds = null;
- // If this preference hasn't been set yet, return the default options
- if (valueFromPrefs == null) {
- String[] allSpeeds = context.getResources().getStringArray(
- R.array.playback_speed_values);
- List<String> speedList = new LinkedList<String>();
- for (String speedStr : allSpeeds) {
- float speed = Float.parseFloat(speedStr);
- if (speed < 2.0001 && speed * 10 % 1 == 0) {
- speedList.add(speedStr);
- }
- }
- selectedSpeeds = speedList.toArray(new String[speedList.size()]);
- } else {
- try {
- JSONArray jsonArray = new JSONArray(valueFromPrefs);
- selectedSpeeds = new String[jsonArray.length()];
- for (int i = 0; i < jsonArray.length(); i++) {
- selectedSpeeds[i] = jsonArray.getString(i);
- }
- } catch (JSONException e) {
- Log.e(TAG,
- "Got JSON error when trying to get speeds from JSONArray");
- e.printStackTrace();
- }
- }
- return selectedSpeeds;
- }
-
- private static void instanceAvailable() {
- if (instance == null) {
- throw new IllegalStateException(
- "UserPreferences was used before being set up");
- }
- }
-
- public static boolean isPauseOnHeadsetDisconnect() {
- instanceAvailable();
- return instance.pauseOnHeadsetDisconnect;
- }
-
- public static boolean isFollowQueue() {
- instanceAvailable();
- return instance.followQueue;
- }
-
- public static boolean isDownloadMediaOnWifiOnly() {
- instanceAvailable();
- return instance.downloadMediaOnWifiOnly;
- }
-
- public static long getUpdateInterval() {
- instanceAvailable();
- return instance.updateInterval;
- }
-
- public static boolean isAllowMobileUpdate() {
- instanceAvailable();
- return instance.allowMobileUpdate;
- }
-
- public static boolean isDisplayOnlyEpisodes() {
- instanceAvailable();
- //return instance.displayOnlyEpisodes;
- return false;
- }
-
- public static boolean isAutoDelete() {
- instanceAvailable();
- return instance.autoDelete;
- }
-
- public static boolean isAutoFlattr() {
- instanceAvailable();
- return instance.autoFlattr;
- }
-
- /**
- * Returns the time after which an episode should be auto-flattr'd in percent of the episode's
- * duration.
- */
- public static float getAutoFlattrPlayedDurationThreshold() {
- instanceAvailable();
- return instance.autoFlattrPlayedDurationThreshold;
- }
-
- public static int getTheme() {
- instanceAvailable();
- return instance.theme;
- }
-
- public static boolean isEnableAutodownloadWifiFilter() {
- instanceAvailable();
- return instance.enableAutodownloadWifiFilter;
- }
-
- public static String[] getAutodownloadSelectedNetworks() {
- instanceAvailable();
- return instance.autodownloadSelectedNetworks;
- }
-
- public static int getEpisodeCacheSizeUnlimited() {
- return EPISODE_CACHE_SIZE_UNLIMITED;
- }
-
- public static String getPlaybackSpeed() {
- instanceAvailable();
- return instance.playbackSpeed;
- }
-
- public static String[] getPlaybackSpeedArray() {
- instanceAvailable();
- return instance.playbackSpeedArray;
- }
-
- public static int getSeekDeltaMs() {
- instanceAvailable();
- return 1000 * instance.seekDeltaSecs;
- }
-
- /**
- * Returns the capacity of the episode cache. This method will return the
- * negative integer EPISODE_CACHE_SIZE_UNLIMITED if the cache size is set to
- * 'unlimited'.
- */
- public static int getEpisodeCacheSize() {
- instanceAvailable();
- return instance.episodeCacheSize;
- }
-
- public static boolean isEnableAutodownload() {
- instanceAvailable();
- return instance.enableAutodownload;
- }
-
- public static boolean shouldPauseForFocusLoss() {
- instanceAvailable();
- return instance.pauseForFocusLoss;
- }
-
- public static boolean isFreshInstall() {
- instanceAvailable();
- return instance.isFreshInstall;
- }
-
- @Override
- public void onSharedPreferenceChanged(SharedPreferences sp, String key) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Registered change of user preferences. Key: " + key);
-
- if (key.equals(PREF_DOWNLOAD_MEDIA_ON_WIFI_ONLY)) {
- downloadMediaOnWifiOnly = sp.getBoolean(
- PREF_DOWNLOAD_MEDIA_ON_WIFI_ONLY, true);
-
- } else if (key.equals(PREF_MOBILE_UPDATE)) {
- allowMobileUpdate = sp.getBoolean(PREF_MOBILE_UPDATE, false);
-
- } else if (key.equals(PREF_FOLLOW_QUEUE)) {
- followQueue = sp.getBoolean(PREF_FOLLOW_QUEUE, false);
-
- } else if (key.equals(PREF_UPDATE_INTERVAL)) {
- updateInterval = readUpdateInterval(sp.getString(
- PREF_UPDATE_INTERVAL, "0"));
- restartUpdateAlarm(updateInterval);
-
- } else if (key.equals(PREF_AUTO_DELETE)) {
- autoDelete = sp.getBoolean(PREF_AUTO_DELETE, false);
-
- } else if (key.equals(PREF_AUTO_FLATTR)) {
- autoFlattr = sp.getBoolean(PREF_AUTO_FLATTR, false);
- } 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 = readEpisodeCacheSizeInternal(sp.getString(
- PREF_EPISODE_CACHE_SIZE, "20"));
- } else if (key.equals(PREF_ENABLE_AUTODL)) {
- enableAutodownload = sp.getBoolean(PREF_ENABLE_AUTODL, false);
- } else if (key.equals(PREF_PLAYBACK_SPEED)) {
- playbackSpeed = sp.getString(PREF_PLAYBACK_SPEED, "1.0");
- } else if (key.equals(PREF_PLAYBACK_SPEED_ARRAY)) {
- playbackSpeedArray = readPlaybackSpeedArray(sp.getString(
- PREF_PLAYBACK_SPEED_ARRAY, null));
- } else if (key.equals(PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS)) {
- pauseForFocusLoss = sp.getBoolean(PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS, false);
- } else if (key.equals(PREF_SEEK_DELTA_SECS)) {
- seekDeltaSecs = Integer.valueOf(sp.getString(PREF_SEEK_DELTA_SECS, "30"));
- } else if (key.equals(PREF_PAUSE_ON_HEADSET_DISCONNECT)) {
- pauseOnHeadsetDisconnect = sp.getBoolean(PREF_PAUSE_ON_HEADSET_DISCONNECT, true);
- } else if (key.equals(PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD)) {
- autoFlattrPlayedDurationThreshold = sp.getFloat(PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD,
- PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD_DEFAULT);
- }
- }
-
- public static void setPlaybackSpeed(String speed) {
- PreferenceManager.getDefaultSharedPreferences(instance.context).edit()
- .putString(PREF_PLAYBACK_SPEED, speed).apply();
- }
-
- public static void setPlaybackSpeedArray(String[] speeds) {
- JSONArray jsonArray = new JSONArray();
- for (String speed : speeds) {
- jsonArray.put(speed);
- }
- PreferenceManager.getDefaultSharedPreferences(instance.context).edit()
- .putString(PREF_PLAYBACK_SPEED_ARRAY, jsonArray.toString())
- .apply();
- }
-
- 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();
- }
-
- /**
- * Sets the update interval value. Should only be used for testing purposes!
- */
- public static void setUpdateInterval(Context context, long newValue) {
- instanceAvailable();
- SharedPreferences.Editor editor = PreferenceManager
- .getDefaultSharedPreferences(context.getApplicationContext())
- .edit();
- editor.putString(PREF_UPDATE_INTERVAL,
- String.valueOf(newValue));
- editor.commit();
- instance.updateInterval = newValue;
- }
-
- /**
- * Change the auto-flattr settings
- *
- * @param context For accessing the shared preferences
- * @param enabled Whether automatic flattring should be enabled at all
- * @param autoFlattrThreshold The percentage of playback time after which an episode should be
- * flattrd. Must be a value between 0 and 1 (inclusive)
- * */
- public static void setAutoFlattrSettings(Context context, boolean enabled, float autoFlattrThreshold) {
- instanceAvailable();
- Validate.inclusiveBetween(0.0, 1.0, autoFlattrThreshold);
- PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext())
- .edit()
- .putBoolean(PREF_AUTO_FLATTR, enabled)
- .putFloat(PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD, autoFlattrThreshold)
- .commit();
- instance.autoFlattr = enabled;
- instance.autoFlattrPlayedDurationThreshold = autoFlattrThreshold;
- }
-
- /**
- * 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.
- *
- * @param type The name of the folder inside the data folder. May be null
- * when accessing the root of the data folder.
- * @return The data folder that has been requested or null if the folder
- * could not be created.
- */
- public static File getDataFolder(Context context, String type) {
- instanceAvailable();
- SharedPreferences prefs = PreferenceManager
- .getDefaultSharedPreferences(context.getApplicationContext());
- String strDir = prefs.getString(PREF_DATA_FOLDER, null);
- if (strDir == null) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Using default data folder");
- return context.getExternalFilesDir(type);
- } else {
- File dataDir = new File(strDir);
- if (!dataDir.exists()) {
- if (!dataDir.mkdir()) {
- Log.w(TAG, "Could not create data folder");
- return null;
- }
- }
-
- if (type == null) {
- return dataDir;
- } else {
- // handle path separators
- String[] dirs = type.split("/");
- for (int i = 0; i < dirs.length; i++) {
- if (dirs.length > 0) {
- if (i < dirs.length - 1) {
- dataDir = getDataFolder(context, dirs[i]);
- if (dataDir == null) {
- return null;
- }
- }
- type = dirs[i];
- }
- }
- File typeDir = new File(dataDir, type);
- if (!typeDir.exists()) {
- if (dataDir.canWrite()) {
- if (!typeDir.mkdir()) {
- Log.e(TAG, "Could not create data folder named "
- + type);
- return null;
- }
- }
- }
- return typeDir;
- }
-
- }
- }
-
- public static void setDataFolder(String dir) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Result from DirectoryChooser: " + dir);
- instanceAvailable();
- SharedPreferences prefs = PreferenceManager
- .getDefaultSharedPreferences(instance.context);
- SharedPreferences.Editor editor = prefs.edit();
- editor.putString(PREF_DATA_FOLDER, dir);
- editor.commit();
- createImportDirectory();
- }
-
- /**
- * Create a .nomedia file to prevent scanning by the media scanner.
- */
- private static void createNoMediaFile() {
- File f = new File(instance.context.getExternalFilesDir(null),
- ".nomedia");
- if (!f.exists()) {
- try {
- f.createNewFile();
- } catch (IOException e) {
- Log.e(TAG, "Could not create .nomedia file");
- e.printStackTrace();
- }
- if (BuildConfig.DEBUG)
- Log.d(TAG, ".nomedia file created");
- }
- }
-
- /**
- * Creates the import directory if it doesn't exist and if storage is
- * available
- */
- private static void createImportDirectory() {
- File importDir = getDataFolder(instance.context,
- OpmlImportFromPathActivity.IMPORT_DIR);
- if (importDir != null) {
- if (importDir.exists()) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Import directory already exists");
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Creating import directory");
- importDir.mkdir();
- }
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Could not access external storage.");
- }
- }
-
- /**
- * Updates alarm registered with the AlarmManager service or deactivates it.
- *
- * @param millis new value to register with AlarmManager. If millis is 0, the
- * alarm is deactivated.
- */
- public static void restartUpdateAlarm(long millis) {
- instanceAvailable();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Restarting update alarm. New value: " + millis);
- AlarmManager alarmManager = (AlarmManager) instance.context
- .getSystemService(Context.ALARM_SERVICE);
- PendingIntent updateIntent = PendingIntent.getBroadcast(
- instance.context, 0, new Intent(
- FeedUpdateReceiver.ACTION_REFRESH_FEEDS), 0
- );
- alarmManager.cancel(updateIntent);
- if (millis != 0) {
- alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, millis, millis,
- updateIntent);
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Changed alarm to new interval");
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Automatic update was deactivated");
- }
- }
-
- /**
- * Reads episode cache size as it is saved in the episode_cache_size_values array.
- */
- public static int readEpisodeCacheSize(String valueFromPrefs) {
- instanceAvailable();
- return instance.readEpisodeCacheSizeInternal(valueFromPrefs);
- }
-}
diff --git a/src/de/danoeh/antennapod/receiver/AlarmUpdateReceiver.java b/src/de/danoeh/antennapod/receiver/AlarmUpdateReceiver.java
deleted file mode 100644
index a0539e276..000000000
--- a/src/de/danoeh/antennapod/receiver/AlarmUpdateReceiver.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package de.danoeh.antennapod.receiver;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.util.Log;
-
-import org.apache.commons.lang3.StringUtils;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.preferences.UserPreferences;
-
-/** Listens for events that make it necessary to reset the update alarm. */
-public class AlarmUpdateReceiver extends BroadcastReceiver {
- private static final String TAG = "AlarmUpdateReceiver";
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Received intent");
- if (StringUtils.equals(intent.getAction(), Intent.ACTION_BOOT_COMPLETED)) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Resetting update alarm after reboot");
- } else if (StringUtils.equals(intent.getAction(), Intent.ACTION_PACKAGE_REPLACED)) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Resetting update alarm after app upgrade");
- }
-
- UserPreferences.restartUpdateAlarm(UserPreferences.getUpdateInterval());
-
- }
-
-}
diff --git a/src/de/danoeh/antennapod/receiver/ConnectivityActionReceiver.java b/src/de/danoeh/antennapod/receiver/ConnectivityActionReceiver.java
deleted file mode 100644
index 4dcf0b6aa..000000000
--- a/src/de/danoeh/antennapod/receiver/ConnectivityActionReceiver.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package de.danoeh.antennapod.receiver;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.util.Log;
-
-import org.apache.commons.lang3.StringUtils;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.storage.DBTasks;
-import de.danoeh.antennapod.storage.DownloadRequester;
-import de.danoeh.antennapod.util.NetworkUtils;
-
-public class ConnectivityActionReceiver extends BroadcastReceiver {
- private static final String TAG = "ConnectivityActionReceiver";
-
- @Override
- public void onReceive(final Context context, Intent intent) {
- if (StringUtils.equals(intent.getAction(), ConnectivityManager.CONNECTIVITY_ACTION)) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Received intent");
-
- if (NetworkUtils.autodownloadNetworkAvailable(context)) {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "auto-dl network available, starting auto-download");
- DBTasks.autodownloadUndownloadedItems(context);
- } 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 (BuildConfig.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/receiver/FeedUpdateReceiver.java b/src/de/danoeh/antennapod/receiver/FeedUpdateReceiver.java
deleted file mode 100644
index 3c283a30b..000000000
--- a/src/de/danoeh/antennapod/receiver/FeedUpdateReceiver.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package de.danoeh.antennapod.receiver;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.util.Log;
-
-import org.apache.commons.lang3.StringUtils;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.preferences.UserPreferences;
-import de.danoeh.antennapod.storage.DBTasks;
-
-/** Refreshes all feeds when it receives an intent */
-public class FeedUpdateReceiver extends BroadcastReceiver {
- private static final String TAG = "FeedUpdateReceiver";
- public static final String ACTION_REFRESH_FEEDS = "de.danoeh.antennapod.feedupdatereceiver.refreshFeeds";
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (StringUtils.equals(intent.getAction(), ACTION_REFRESH_FEEDS)) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Received intent");
- boolean mobileUpdate = UserPreferences.isAllowMobileUpdate();
- if (mobileUpdate || connectedToWifi(context)) {
- DBTasks.refreshExpiredFeeds(context);
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "Blocking automatic update: no wifi available / no mobile updates allowed");
- }
- }
- }
-
- private boolean connectedToWifi(Context context) {
- ConnectivityManager connManager = (ConnectivityManager) context
- .getSystemService(Context.CONNECTIVITY_SERVICE);
- NetworkInfo mWifi = connManager
- .getNetworkInfo(ConnectivityManager.TYPE_WIFI);
-
- return mWifi.isConnected();
- }
-
-}
diff --git a/src/de/danoeh/antennapod/receiver/MediaButtonReceiver.java b/src/de/danoeh/antennapod/receiver/MediaButtonReceiver.java
deleted file mode 100644
index 1edebd275..000000000
--- a/src/de/danoeh/antennapod/receiver/MediaButtonReceiver.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package de.danoeh.antennapod.receiver;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.util.Log;
-import android.view.KeyEvent;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.service.playback.PlaybackService;
-
-/** Receives media button events. */
-public class MediaButtonReceiver extends BroadcastReceiver {
- private static final String TAG = "MediaButtonReceiver";
- public static final String EXTRA_KEYCODE = "de.danoeh.antennapod.service.extra.MediaButtonReceiver.KEYCODE";
-
- public static final String NOTIFY_BUTTON_RECEIVER = "de.danoeh.antennapod.NOTIFY_BUTTON_RECEIVER";
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Received intent");
- KeyEvent event = (KeyEvent) intent.getExtras().get(
- Intent.EXTRA_KEY_EVENT);
- if (event.getAction() == KeyEvent.ACTION_DOWN) {
- Intent serviceIntent = new Intent(context, PlaybackService.class);
- int keycode = event.getKeyCode();
- serviceIntent.putExtra(EXTRA_KEYCODE, keycode);
- context.startService(serviceIntent);
- }
-
- }
-
-}
diff --git a/src/de/danoeh/antennapod/receiver/PlayerWidget.java b/src/de/danoeh/antennapod/receiver/PlayerWidget.java
deleted file mode 100644
index 9f8892181..000000000
--- a/src/de/danoeh/antennapod/receiver/PlayerWidget.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package de.danoeh.antennapod.receiver;
-
-import android.appwidget.AppWidgetManager;
-import android.appwidget.AppWidgetProvider;
-import android.content.Context;
-import android.content.Intent;
-import android.util.Log;
-
-import org.apache.commons.lang3.StringUtils;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.service.playback.PlayerWidgetService;
-
-public class PlayerWidget extends AppWidgetProvider {
- private static final String TAG = "PlayerWidget";
- public static final String FORCE_WIDGET_UPDATE = "de.danoeh.antennapod.FORCE_WIDGET_UPDATE";
- public static final String STOP_WIDGET_UPDATE = "de.danoeh.antennapod.STOP_WIDGET_UPDATE";
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (StringUtils.equals(intent.getAction(), FORCE_WIDGET_UPDATE)) {
- startUpdate(context);
- } else if (StringUtils.equals(intent.getAction(), STOP_WIDGET_UPDATE)) {
- stopUpdate(context);
- }
-
- }
-
- @Override
- public void onEnabled(Context context) {
- super.onEnabled(context);
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Widget enabled");
- }
-
- @Override
- public void onUpdate(Context context, AppWidgetManager appWidgetManager,
- int[] appWidgetIds) {
- startUpdate(context);
- }
-
- private void startUpdate(Context context) {
- context.startService(new Intent(context, PlayerWidgetService.class));
- }
-
- private void stopUpdate(Context context) {
- context.stopService(new Intent(context, PlayerWidgetService.class));
- }
-
-}
diff --git a/src/de/danoeh/antennapod/receiver/SPAReceiver.java b/src/de/danoeh/antennapod/receiver/SPAReceiver.java
deleted file mode 100644
index b0430d170..000000000
--- a/src/de/danoeh/antennapod/receiver/SPAReceiver.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package de.danoeh.antennapod.receiver;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.util.Log;
-import android.widget.Toast;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.feed.Feed;
-import de.danoeh.antennapod.storage.DownloadRequestException;
-import de.danoeh.antennapod.storage.DownloadRequester;
-import org.apache.commons.lang3.StringUtils;
-
-import java.util.Arrays;
-import java.util.Date;
-
-/**
- * Receives intents from AntennaPod Single Purpose apps
- */
-public class SPAReceiver extends BroadcastReceiver{
- private static final String TAG = "SPAReceiver";
-
- public static final String ACTION_SP_APPS_QUERY_FEEDS = "de.danoeh.antennapdsp.intent.SP_APPS_QUERY_FEEDS";
- public static final String ACTION_SP_APPS_QUERY_FEEDS_REPSONSE = "de.danoeh.antennapdsp.intent.SP_APPS_QUERY_FEEDS_RESPONSE";
- public static final String ACTION_SP_APPS_QUERY_FEEDS_REPSONSE_FEEDS_EXTRA = "feeds";
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (StringUtils.equals(intent.getAction(), ACTION_SP_APPS_QUERY_FEEDS_REPSONSE)) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Received SP_APPS_QUERY_RESPONSE");
- if (intent.hasExtra(ACTION_SP_APPS_QUERY_FEEDS_REPSONSE_FEEDS_EXTRA)) {
- String[] feedUrls = intent.getStringArrayExtra(ACTION_SP_APPS_QUERY_FEEDS_REPSONSE_FEEDS_EXTRA);
- if (feedUrls != null) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Received feeds list: " + Arrays.toString(feedUrls));
- for (String url : feedUrls) {
- Feed f = new Feed(url, new Date());
- try {
- DownloadRequester.getInstance().downloadFeed(context, f);
- } catch (DownloadRequestException e) {
- Log.e(TAG, "Error while trying to add feed " + url);
- e.printStackTrace();
- }
- }
- Toast.makeText(context, R.string.sp_apps_importing_feeds_msg, Toast.LENGTH_LONG).show();
-
- } else {
- Log.e(TAG, "Received invalid SP_APPS_QUERY_REPSONSE: extra was null");
- }
- } else {
- Log.e(TAG, "Received invalid SP_APPS_QUERY_RESPONSE: Contains no extra");
- }
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/service/GpodnetSyncService.java b/src/de/danoeh/antennapod/service/GpodnetSyncService.java
deleted file mode 100644
index c8c9fc31e..000000000
--- a/src/de/danoeh/antennapod/service/GpodnetSyncService.java
+++ /dev/null
@@ -1,245 +0,0 @@
-package de.danoeh.antennapod.service;
-
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.os.IBinder;
-import android.support.v4.app.NotificationCompat;
-import android.util.Log;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.MainActivity;
-import de.danoeh.antennapod.feed.Feed;
-import de.danoeh.antennapod.gpoddernet.GpodnetService;
-import de.danoeh.antennapod.gpoddernet.GpodnetServiceAuthenticationException;
-import de.danoeh.antennapod.gpoddernet.GpodnetServiceException;
-import de.danoeh.antennapod.gpoddernet.model.GpodnetSubscriptionChange;
-import de.danoeh.antennapod.gpoddernet.model.GpodnetUploadChangesResponse;
-import de.danoeh.antennapod.preferences.GpodnetPreferences;
-import de.danoeh.antennapod.storage.DBReader;
-import de.danoeh.antennapod.storage.DBTasks;
-import de.danoeh.antennapod.storage.DownloadRequestException;
-import de.danoeh.antennapod.storage.DownloadRequester;
-import de.danoeh.antennapod.util.NetworkUtils;
-
-import java.util.Date;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Synchronizes local subscriptions with gpodder.net service. The service should be started with ACTION_SYNC as an action argument.
- * This class also provides static methods for starting the GpodnetSyncService.
- */
-public class GpodnetSyncService extends Service {
- private static final String TAG = "GpodnetSyncService";
-
- private static final long WAIT_INTERVAL = 5000L;
-
- public static final String ARG_ACTION = "action";
-
- public static final String ACTION_SYNC = "de.danoeh.antennapod.intent.action.sync";
-
- private GpodnetService service;
-
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- final String action = (intent != null) ? intent.getStringExtra(ARG_ACTION) : null;
- if (action != null && action.equals(ACTION_SYNC)) {
- Log.d(TAG, String.format("Waiting %d milliseconds before uploading changes", WAIT_INTERVAL));
- syncWaiterThread.restart();
- } else {
- Log.e(TAG, "Received invalid intent: action argument is null or invalid");
- }
- return START_FLAG_REDELIVERY;
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- if (BuildConfig.DEBUG) Log.d(TAG, "onDestroy");
- syncWaiterThread.interrupt();
-
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- return null;
- }
-
- private synchronized GpodnetService tryLogin() throws GpodnetServiceException {
- if (service == null) {
- service = new GpodnetService();
- service.authenticate(GpodnetPreferences.getUsername(), GpodnetPreferences.getPassword());
- }
- return service;
- }
-
- private synchronized void syncChanges() {
- if (GpodnetPreferences.loggedIn() && NetworkUtils.networkAvailable(this)) {
- final long timestamp = GpodnetPreferences.getLastSyncTimestamp();
- try {
- final List<String> localSubscriptions = DBReader.getFeedListDownloadUrls(this);
- GpodnetService service = tryLogin();
-
- if (timestamp == 0) {
- // first sync: download all subscriptions...
- GpodnetSubscriptionChange changes =
- service.getSubscriptionChanges(GpodnetPreferences.getUsername(), GpodnetPreferences.getDeviceID(), 0);
- if (BuildConfig.DEBUG) Log.d(TAG, "Downloaded subscription changes: " + changes);
- processSubscriptionChanges(localSubscriptions, changes);
-
- // ... then upload all local subscriptions
- if (BuildConfig.DEBUG) Log.d(TAG, "Uploading subscription list: " + localSubscriptions);
- GpodnetUploadChangesResponse uploadChangesResponse =
- service.uploadChanges(GpodnetPreferences.getUsername(), GpodnetPreferences.getDeviceID(), localSubscriptions, new LinkedList<String>());
- if (BuildConfig.DEBUG) Log.d(TAG, "Uploading changes response: " + uploadChangesResponse);
- GpodnetPreferences.removeAddedFeeds(localSubscriptions);
- GpodnetPreferences.removeRemovedFeeds(GpodnetPreferences.getRemovedFeedsCopy());
- GpodnetPreferences.setLastSyncTimestamp(uploadChangesResponse.timestamp);
- } else {
- Set<String> added = GpodnetPreferences.getAddedFeedsCopy();
- Set<String> removed = GpodnetPreferences.getRemovedFeedsCopy();
-
- // download remote changes first...
- GpodnetSubscriptionChange subscriptionChanges = service.getSubscriptionChanges(GpodnetPreferences.getUsername(), GpodnetPreferences.getDeviceID(), timestamp);
- if (BuildConfig.DEBUG) Log.d(TAG, "Downloaded subscription changes: " + subscriptionChanges);
- processSubscriptionChanges(localSubscriptions, subscriptionChanges);
-
- // ... then upload changes local changes
- if (BuildConfig.DEBUG) Log.d(TAG, String.format("Uploading subscriptions, Added: %s\nRemoved: %s",
- added.toString(), removed));
- GpodnetUploadChangesResponse uploadChangesResponse = service.uploadChanges(GpodnetPreferences.getUsername(), GpodnetPreferences.getDeviceID(), added, removed);
- if (BuildConfig.DEBUG) Log.d(TAG, "Upload subscriptions response: " + uploadChangesResponse);
-
- GpodnetPreferences.removeAddedFeeds(added);
- GpodnetPreferences.removeRemovedFeeds(removed);
- GpodnetPreferences.setLastSyncTimestamp(uploadChangesResponse.timestamp);
- }
- clearErrorNotifications();
- } catch (GpodnetServiceException e) {
- e.printStackTrace();
- updateErrorNotification(e);
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- }
- }
- stopSelf();
- }
-
- private synchronized void processSubscriptionChanges(List<String> localSubscriptions, GpodnetSubscriptionChange changes) throws DownloadRequestException {
- for (String downloadUrl : changes.getAdded()) {
- if (!localSubscriptions.contains(downloadUrl)) {
- Feed feed = new Feed(downloadUrl, new Date());
- DownloadRequester.getInstance().downloadFeed(this, feed);
- }
- }
- for (String downloadUrl : changes.getRemoved()) {
- DBTasks.removeFeedWithDownloadUrl(GpodnetSyncService.this, downloadUrl);
- }
- }
-
- private void clearErrorNotifications() {
- NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
- nm.cancel(R.id.notification_gpodnet_sync_error);
- nm.cancel(R.id.notification_gpodnet_sync_autherror);
- }
-
- private void updateErrorNotification(GpodnetServiceException exception) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Posting error notification");
-
- NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
- final String title;
- final String description;
- final int id;
- if (exception instanceof GpodnetServiceAuthenticationException) {
- title = getString(R.string.gpodnetsync_auth_error_title);
- description = getString(R.string.gpodnetsync_auth_error_descr);
- id = R.id.notification_gpodnet_sync_autherror;
- } else {
- title = getString(R.string.gpodnetsync_error_title);
- description = getString(R.string.gpodnetsync_error_descr) + exception.getMessage();
- id = R.id.notification_gpodnet_sync_error;
- }
-
- PendingIntent activityIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
-
- Notification notification = builder.setContentTitle(title)
- .setContentText(description)
- .setContentIntent(activityIntent)
- .setSmallIcon(R.drawable.stat_notify_sync_error)
- .setAutoCancel(true)
- .build();
- NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- nm.notify(id, notification);
- }
-
- private WaiterThread syncWaiterThread = new WaiterThread(WAIT_INTERVAL) {
- @Override
- public void onWaitCompleted() {
- syncChanges();
- }
- };
-
- private abstract class WaiterThread {
- private long waitInterval;
- private Thread thread;
-
- private WaiterThread(long waitInterval) {
- this.waitInterval = waitInterval;
- reinit();
- }
-
- public abstract void onWaitCompleted();
-
- public void exec() {
- if (!thread.isAlive()) {
- thread.start();
- }
- }
-
- private void reinit() {
- if (thread != null && thread.isAlive()) {
- Log.d(TAG, "Interrupting waiter thread");
- thread.interrupt();
- }
- thread = new Thread() {
- @Override
- public void run() {
- try {
- Thread.sleep(waitInterval);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- if (!isInterrupted()) {
- synchronized (this) {
- onWaitCompleted();
- }
- }
- }
- };
- }
-
- public void restart() {
- reinit();
- exec();
- }
-
- public void interrupt() {
- if (thread != null && thread.isAlive()) {
- thread.interrupt();
- }
- }
- }
-
- public static void sendSyncIntent(Context context) {
- if (GpodnetPreferences.loggedIn()) {
- Intent intent = new Intent(context, GpodnetSyncService.class);
- intent.putExtra(ARG_ACTION, ACTION_SYNC);
- context.startService(intent);
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/service/download/APRedirectHandler.java b/src/de/danoeh/antennapod/service/download/APRedirectHandler.java
deleted file mode 100644
index ddf8d605d..000000000
--- a/src/de/danoeh/antennapod/service/download/APRedirectHandler.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package de.danoeh.antennapod.service.download;
-
-import android.util.Log;
-import de.danoeh.antennapod.BuildConfig;
-import org.apache.http.Header;
-import org.apache.http.HttpResponse;
-import org.apache.http.impl.client.DefaultRedirectHandler;
-import org.apache.http.protocol.HttpContext;
-
-import java.net.URI;
-
-public class APRedirectHandler extends DefaultRedirectHandler {
- // Identifier for logger
- private static final String TAG = "APRedirectHandler";
- // Header field, which has to be potentially fixed
- private static final String LOC = "Location";
- // Regular expressions for character strings, which should not appear in URLs
- private static final String CHi[] = { "\\{", "\\}", "\\|", "\\\\", "\\^", "~", "\\[", "\\]", "\\`"};
- private static final String CHo[] = { "%7B", "%7D", "%7C", "%5C", "%5E", "%7E", "%5B", "%5D", "%60"};
-
- /**
- * Workaround for broken URLs in redirection.
- * Proper solution involves LaxRedirectStrategy() which is not available in
- * current API yet.
- */
- @Override
- public URI getLocationURI(HttpResponse response, HttpContext context)
- throws org.apache.http.ProtocolException {
-
- Header h[] = response.getHeaders(LOC);
- if (h.length>0) {
- String s = h[0].getValue();
-
- // Fix broken URL
- for(int i=0; i<CHi.length;i++)
- s = s.replaceAll(CHi[i], CHo[i]);
-
- // If anything had to be fixed, then replace the header
- if (!s.equals(h[0].getValue()))
- {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Original URL: " + h[0].getValue());
-
- response.setHeader(LOC, s);
-
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Fixed URL: " + s);
- }
- }
-
- // call DefaultRedirectHandler with fixed URL
- return super.getLocationURI(response, context);
- }
-}
diff --git a/src/de/danoeh/antennapod/service/download/AntennapodHttpClient.java b/src/de/danoeh/antennapod/service/download/AntennapodHttpClient.java
deleted file mode 100644
index be331ce9b..000000000
--- a/src/de/danoeh/antennapod/service/download/AntennapodHttpClient.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package de.danoeh.antennapod.service.download;
-
-import android.util.Log;
-import de.danoeh.antennapod.AppConfig;
-import de.danoeh.antennapod.BuildConfig;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.params.HttpClientParams;
-import org.apache.http.conn.ClientConnectionManager;
-import org.apache.http.conn.params.ConnManagerPNames;
-import org.apache.http.conn.scheme.PlainSocketFactory;
-import org.apache.http.conn.scheme.Scheme;
-import org.apache.http.conn.scheme.SchemeRegistry;
-import org.apache.http.conn.ssl.SSLSocketFactory;
-import org.apache.http.impl.client.AbstractHttpClient;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
-import org.apache.http.params.BasicHttpParams;
-import org.apache.http.params.CoreProtocolPNames;
-import org.apache.http.params.HttpConnectionParams;
-import org.apache.http.params.HttpParams;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * Provides access to a HttpClient singleton.
- */
-public class AntennapodHttpClient {
- private static final String TAG = "AntennapodHttpClient";
-
- public static final long EXPIRED_CONN_TIMEOUT_SEC = 30;
-
- public static final int MAX_REDIRECTS = 5;
- public static final int CONNECTION_TIMEOUT = 30000;
- public static final int SOCKET_TIMEOUT = 30000;
-
- public static final int MAX_CONNECTIONS = 8;
-
-
- private static volatile HttpClient httpClient = null;
-
- /**
- * Returns the HttpClient singleton.
- */
- public static synchronized HttpClient getHttpClient() {
- if (httpClient == null) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Creating new instance of HTTP client");
-
- HttpParams params = new BasicHttpParams();
- params.setParameter(CoreProtocolPNames.USER_AGENT, AppConfig.USER_AGENT);
- params.setIntParameter("http.protocol.max-redirects", MAX_REDIRECTS);
- params.setBooleanParameter("http.protocol.reject-relative-redirect",
- false);
- HttpConnectionParams.setSoTimeout(params, SOCKET_TIMEOUT);
- HttpConnectionParams.setConnectionTimeout(params, CONNECTION_TIMEOUT);
- HttpClientParams.setRedirecting(params, true);
-
- httpClient = new DefaultHttpClient(createClientConnectionManager(), params);
- // Workaround for broken URLs in redirection
- ((AbstractHttpClient) httpClient)
- .setRedirectHandler(new APRedirectHandler());
- }
- return httpClient;
- }
-
- /**
- * Closes expired connections. This method should be called by the using class once has finished its work with
- * the HTTP client.
- */
- public static synchronized void cleanup() {
- if (httpClient != null) {
- httpClient.getConnectionManager().closeExpiredConnections();
- httpClient.getConnectionManager().closeIdleConnections(EXPIRED_CONN_TIMEOUT_SEC, TimeUnit.SECONDS);
- }
- }
-
-
- private static ClientConnectionManager createClientConnectionManager() {
- HttpParams params = new BasicHttpParams();
- params.setIntParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, MAX_CONNECTIONS);
- return new ThreadSafeClientConnManager(params, prepareSchemeRegistry());
- }
-
- private static SchemeRegistry prepareSchemeRegistry() {
- SchemeRegistry sr = new SchemeRegistry();
-
- Scheme http = new Scheme("http",
- PlainSocketFactory.getSocketFactory(), 80);
- sr.register(http);
- Scheme https = new Scheme("https",
- SSLSocketFactory.getSocketFactory(), 443);
- sr.register(https);
-
- return sr;
- }
-
-}
diff --git a/src/de/danoeh/antennapod/service/download/DownloadRequest.java b/src/de/danoeh/antennapod/service/download/DownloadRequest.java
deleted file mode 100644
index e803d30d4..000000000
--- a/src/de/danoeh/antennapod/service/download/DownloadRequest.java
+++ /dev/null
@@ -1,209 +0,0 @@
-package de.danoeh.antennapod.service.download;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import org.apache.commons.lang3.Validate;
-
-public class DownloadRequest implements Parcelable {
-
- private final String destination;
- private final String source;
- private final String title;
- private String username;
- private String password;
- private boolean deleteOnFailure;
- private final long feedfileId;
- private final int feedfileType;
-
- protected int progressPercent;
- protected long soFar;
- protected long size;
- protected int statusMsg;
-
- public DownloadRequest(String destination, String source, String title,
- long feedfileId, int feedfileType, String username, String password, boolean deleteOnFailure) {
- Validate.notNull(destination);
- Validate.notNull(source);
- Validate.notNull(title);
-
- this.destination = destination;
- this.source = source;
- this.title = title;
- this.feedfileId = feedfileId;
- this.feedfileType = feedfileType;
- this.username = username;
- this.password = password;
- this.deleteOnFailure = deleteOnFailure;
- }
-
- public DownloadRequest(String destination, String source, String title,
- long feedfileId, int feedfileType) {
- this(destination, source, title, feedfileId, feedfileType, null, null, true);
- }
-
- private DownloadRequest(Parcel in) {
- destination = in.readString();
- source = in.readString();
- title = in.readString();
- feedfileId = in.readLong();
- feedfileType = in.readInt();
- deleteOnFailure = (in.readByte() > 0);
- if (in.dataAvail() > 0) {
- username = in.readString();
- } else {
- username = null;
- }
- if (in.dataAvail() > 0) {
- password = in.readString();
- } else {
- password = null;
- }
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(destination);
- dest.writeString(source);
- dest.writeString(title);
- dest.writeLong(feedfileId);
- dest.writeInt(feedfileType);
- dest.writeByte((deleteOnFailure) ? (byte) 1 : 0);
- if (username != null) {
- dest.writeString(username);
- }
- if (password != null) {
- dest.writeString(password);
- }
- }
-
- public static final Parcelable.Creator<DownloadRequest> CREATOR = new Parcelable.Creator<DownloadRequest>() {
- public DownloadRequest createFromParcel(Parcel in) {
- return new DownloadRequest(in);
- }
-
- public DownloadRequest[] newArray(int size) {
- return new DownloadRequest[size];
- }
- };
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- DownloadRequest that = (DownloadRequest) o;
-
- if (deleteOnFailure != that.deleteOnFailure) return false;
- if (feedfileId != that.feedfileId) return false;
- if (feedfileType != that.feedfileType) return false;
- if (progressPercent != that.progressPercent) return false;
- if (size != that.size) return false;
- if (soFar != that.soFar) return false;
- if (statusMsg != that.statusMsg) return false;
- if (destination != null ? !destination.equals(that.destination) : that.destination != null)
- return false;
- if (password != null ? !password.equals(that.password) : that.password != null)
- return false;
- if (source != null ? !source.equals(that.source) : that.source != null) return false;
- if (title != null ? !title.equals(that.title) : that.title != null) return false;
- if (username != null ? !username.equals(that.username) : that.username != null)
- return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = destination != null ? destination.hashCode() : 0;
- result = 31 * result + (source != null ? source.hashCode() : 0);
- result = 31 * result + (title != null ? title.hashCode() : 0);
- result = 31 * result + (username != null ? username.hashCode() : 0);
- result = 31 * result + (password != null ? password.hashCode() : 0);
- result = 31 * result + (deleteOnFailure ? 1 : 0);
- result = 31 * result + (int) (feedfileId ^ (feedfileId >>> 32));
- result = 31 * result + feedfileType;
- result = 31 * result + progressPercent;
- result = 31 * result + (int) (soFar ^ (soFar >>> 32));
- result = 31 * result + (int) (size ^ (size >>> 32));
- result = 31 * result + statusMsg;
- return result;
- }
-
- public String getDestination() {
- return destination;
- }
-
- public String getSource() {
- return source;
- }
-
- public String getTitle() {
- return title;
- }
-
- public long getFeedfileId() {
- return feedfileId;
- }
-
- public int getFeedfileType() {
- return feedfileType;
- }
-
- public int getProgressPercent() {
- return progressPercent;
- }
-
- public void setProgressPercent(int progressPercent) {
- this.progressPercent = progressPercent;
- }
-
- public long getSoFar() {
- return soFar;
- }
-
- public void setSoFar(long soFar) {
- this.soFar = soFar;
- }
-
- public long getSize() {
- return size;
- }
-
- public void setSize(long size) {
- this.size = size;
- }
-
- public int getStatusMsg() {
- return statusMsg;
- }
-
- public void setStatusMsg(int statusMsg) {
- this.statusMsg = statusMsg;
- }
-
- public String getUsername() {
- return username;
- }
-
- public String getPassword() {
- return password;
- }
-
- public void setUsername(String username) {
- this.username = username;
- }
-
- public void setPassword(String password) {
- this.password = password;
- }
-
- public boolean isDeleteOnFailure() {
- return deleteOnFailure;
- }
-}
diff --git a/src/de/danoeh/antennapod/service/download/DownloadService.java b/src/de/danoeh/antennapod/service/download/DownloadService.java
deleted file mode 100644
index 63be91b57..000000000
--- a/src/de/danoeh/antennapod/service/download/DownloadService.java
+++ /dev/null
@@ -1,1230 +0,0 @@
-package de.danoeh.antennapod.service.download;
-
-import android.annotation.SuppressLint;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.media.MediaMetadataRetriever;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.support.v4.app.NotificationCompat;
-import android.util.Log;
-import android.webkit.URLUtil;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang3.ArrayUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.Validate;
-import org.apache.http.HttpStatus;
-import org.xml.sax.SAXException;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Queue;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CompletionService;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorCompletionService;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.LinkedBlockingDeque;
-import java.util.concurrent.RejectedExecutionHandler;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import javax.xml.parsers.ParserConfigurationException;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.DownloadAuthenticationActivity;
-import de.danoeh.antennapod.activity.MainActivity;
-import de.danoeh.antennapod.adapter.NavListAdapter;
-import de.danoeh.antennapod.feed.EventDistributor;
-import de.danoeh.antennapod.feed.Feed;
-import de.danoeh.antennapod.feed.FeedImage;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.feed.FeedMedia;
-import de.danoeh.antennapod.feed.FeedPreferences;
-import de.danoeh.antennapod.fragment.DownloadsFragment;
-import de.danoeh.antennapod.storage.DBReader;
-import de.danoeh.antennapod.storage.DBTasks;
-import de.danoeh.antennapod.storage.DBWriter;
-import de.danoeh.antennapod.storage.DownloadRequestException;
-import de.danoeh.antennapod.storage.DownloadRequester;
-import de.danoeh.antennapod.syndication.handler.FeedHandler;
-import de.danoeh.antennapod.syndication.handler.UnsupportedFeedtypeException;
-import de.danoeh.antennapod.util.ChapterUtils;
-import de.danoeh.antennapod.util.DownloadError;
-import de.danoeh.antennapod.util.InvalidFeedException;
-
-/**
- * Manages the download of feedfiles in the app. Downloads can be enqueued viathe startService intent.
- * The argument of the intent is an instance of DownloadRequest in the EXTRA_REQUEST field of
- * the intent.
- * After the downloads have finished, the downloaded object will be passed on to a specific handler, depending on the
- * type of the feedfile.
- */
-public class DownloadService extends Service {
- private static final String TAG = "DownloadService";
-
- /**
- * Cancels one download. The intent MUST have an EXTRA_DOWNLOAD_URL extra that contains the download URL of the
- * object whose download should be cancelled.
- */
- public static final String ACTION_CANCEL_DOWNLOAD = "action.de.danoeh.antennapod.service.cancelDownload";
-
- /**
- * Cancels all running downloads.
- */
- public static final String ACTION_CANCEL_ALL_DOWNLOADS = "action.de.danoeh.antennapod.service.cancelAllDownloads";
-
- /**
- * Extra for ACTION_CANCEL_DOWNLOAD
- */
- public static final String EXTRA_DOWNLOAD_URL = "downloadUrl";
-
- /**
- * Sent by the DownloadService when the content of the downloads list
- * changes.
- */
- public static final String ACTION_DOWNLOADS_CONTENT_CHANGED = "action.de.danoeh.antennapod.service.downloadsContentChanged";
-
- /**
- * Extra for ACTION_ENQUEUE_DOWNLOAD intent.
- */
- public static final String EXTRA_REQUEST = "request";
-
- /**
- * Stores new media files that will be queued for auto-download if possible.
- */
- private List<Long> newMediaFiles;
-
- /**
- * Contains all completed downloads that have not been included in the report yet.
- */
- private List<DownloadStatus> reportQueue;
-
- private ExecutorService syncExecutor;
- private CompletionService<Downloader> downloadExecutor;
- private FeedSyncThread feedSyncThread;
-
- /**
- * Number of threads of downloadExecutor.
- */
- private static final int NUM_PARALLEL_DOWNLOADS = 6;
-
- private DownloadRequester requester;
-
-
- private NotificationCompat.Builder notificationCompatBuilder;
- private Notification.BigTextStyle notificationBuilder;
- private int NOTIFICATION_ID = 2;
- private int REPORT_ID = 3;
-
- /**
- * Currently running downloads.
- */
- private List<Downloader> downloads;
-
- /**
- * Number of running downloads.
- */
- private AtomicInteger numberOfDownloads;
-
- /**
- * True if service is running.
- */
- public static boolean isRunning = false;
-
- private Handler handler;
-
- private NotificationUpdater notificationUpdater;
- private ScheduledFuture notificationUpdaterFuture;
- private static final int SCHED_EX_POOL_SIZE = 1;
- private ScheduledThreadPoolExecutor schedExecutor;
-
- private final IBinder mBinder = new LocalBinder();
-
- public class LocalBinder extends Binder {
- public DownloadService getService() {
- return DownloadService.this;
- }
- }
-
- private Thread downloadCompletionThread = new Thread() {
- private static final String TAG = "downloadCompletionThread";
-
- @Override
- public void run() {
- if (BuildConfig.DEBUG) Log.d(TAG, "downloadCompletionThread was started");
- while (!isInterrupted()) {
- try {
- Downloader downloader = downloadExecutor.take().get();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Received 'Download Complete' - message.");
- removeDownload(downloader);
- DownloadStatus status = downloader.getResult();
- boolean successful = status.isSuccessful();
-
- final int type = status.getFeedfileType();
- if (successful) {
- if (type == Feed.FEEDFILETYPE_FEED) {
- handleCompletedFeedDownload(downloader
- .getDownloadRequest());
- } else if (type == FeedImage.FEEDFILETYPE_FEEDIMAGE) {
- handleCompletedImageDownload(status, downloader.getDownloadRequest());
- } else if (type == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
- handleCompletedFeedMediaDownload(status, downloader.getDownloadRequest());
- }
- } else {
- numberOfDownloads.decrementAndGet();
- if (!status.isCancelled()) {
- if (status.getReason() == DownloadError.ERROR_UNAUTHORIZED) {
- postAuthenticationNotification(downloader.getDownloadRequest());
- } else if (status.getReason() == DownloadError.ERROR_HTTP_DATA_ERROR
- && Integer.valueOf(status.getReasonDetailed()) == HttpStatus.SC_REQUESTED_RANGE_NOT_SATISFIABLE) {
-
- Log.d(TAG, "Requested invalid range, restarting download from the beginning");
- FileUtils.deleteQuietly(new File(downloader.getDownloadRequest().getDestination()));
- DownloadRequester.getInstance().download(DownloadService.this, downloader.getDownloadRequest());
- } else {
- Log.e(TAG, "Download failed");
- saveDownloadStatus(status);
- handleFailedDownload(status, downloader.getDownloadRequest());
- }
- }
- sendDownloadHandledIntent();
- queryDownloadsAsync();
- }
- } catch (InterruptedException e) {
- if (BuildConfig.DEBUG) Log.d(TAG, "DownloadCompletionThread was interrupted");
- } catch (ExecutionException e) {
- e.printStackTrace();
- numberOfDownloads.decrementAndGet();
- }
- }
- if (BuildConfig.DEBUG) Log.d(TAG, "End of downloadCompletionThread");
- }
- };
-
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- if (intent.getParcelableExtra(EXTRA_REQUEST) != null) {
- onDownloadQueued(intent);
- } else if (numberOfDownloads.get() == 0) {
- stopSelf();
- }
- return Service.START_NOT_STICKY;
- }
-
- @SuppressLint("NewApi")
- @Override
- public void onCreate() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Service started");
- isRunning = true;
- handler = new Handler();
- newMediaFiles = Collections.synchronizedList(new ArrayList<Long>());
- reportQueue = Collections.synchronizedList(new ArrayList<DownloadStatus>());
- downloads = new ArrayList<Downloader>();
- numberOfDownloads = new AtomicInteger(0);
-
- IntentFilter cancelDownloadReceiverFilter = new IntentFilter();
- cancelDownloadReceiverFilter.addAction(ACTION_CANCEL_ALL_DOWNLOADS);
- cancelDownloadReceiverFilter.addAction(ACTION_CANCEL_DOWNLOAD);
- registerReceiver(cancelDownloadReceiver, cancelDownloadReceiverFilter);
- syncExecutor = Executors.newSingleThreadExecutor(new ThreadFactory() {
-
- @Override
- public Thread newThread(Runnable r) {
- Thread t = new Thread(r);
- t.setPriority(Thread.MIN_PRIORITY);
- return t;
- }
- });
- downloadExecutor = new ExecutorCompletionService<Downloader>(
- Executors.newFixedThreadPool(NUM_PARALLEL_DOWNLOADS,
- new ThreadFactory() {
-
- @Override
- public Thread newThread(Runnable r) {
- Thread t = new Thread(r);
- t.setPriority(Thread.MIN_PRIORITY);
- return t;
- }
- }
- )
- );
- schedExecutor = new ScheduledThreadPoolExecutor(SCHED_EX_POOL_SIZE,
- new ThreadFactory() {
-
- @Override
- public Thread newThread(Runnable r) {
- Thread t = new Thread(r);
- t.setPriority(Thread.MIN_PRIORITY);
- return t;
- }
- }, new RejectedExecutionHandler() {
-
- @Override
- public void rejectedExecution(Runnable r,
- ThreadPoolExecutor executor) {
- Log.w(TAG, "SchedEx rejected submission of new task");
- }
- }
- );
- downloadCompletionThread.start();
- feedSyncThread = new FeedSyncThread();
- feedSyncThread.start();
-
- setupNotificationBuilders();
- requester = DownloadRequester.getInstance();
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- return mBinder;
- }
-
- @Override
- public void onDestroy() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Service shutting down");
- isRunning = false;
- updateReport();
-
- stopForeground(true);
- NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
- nm.cancel(NOTIFICATION_ID);
-
- downloadCompletionThread.interrupt();
- syncExecutor.shutdown();
- schedExecutor.shutdown();
- feedSyncThread.shutdown();
- cancelNotificationUpdater();
- unregisterReceiver(cancelDownloadReceiver);
-
- if (!newMediaFiles.isEmpty()) {
- DBTasks.autodownloadUndownloadedItems(getApplicationContext(),
- ArrayUtils.toPrimitive(newMediaFiles.toArray(new Long[newMediaFiles.size()])));
- }
- }
-
- @SuppressLint("NewApi")
- private void setupNotificationBuilders() {
- Intent intent = new Intent(this, MainActivity.class);
- intent.putExtra(MainActivity.EXTRA_NAV_TYPE, NavListAdapter.VIEW_TYPE_NAV);
- intent.putExtra(MainActivity.EXTRA_NAV_INDEX, MainActivity.POS_DOWNLOADS);
- Bundle args = new Bundle();
- args.putInt(DownloadsFragment.ARG_SELECTED_TAB, DownloadsFragment.POS_RUNNING);
- intent.putExtra(MainActivity.EXTRA_FRAGMENT_ARGS, args);
-
- PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent,
- PendingIntent.FLAG_UPDATE_CURRENT
- );
-
-
- Bitmap icon = BitmapFactory.decodeResource(getResources(),
- R.drawable.stat_notify_sync);
-
- if (android.os.Build.VERSION.SDK_INT >= 16) {
- notificationBuilder = new Notification.BigTextStyle(
- new Notification.Builder(this).setOngoing(true)
- .setContentIntent(pIntent).setLargeIcon(icon)
- .setSmallIcon(R.drawable.stat_notify_sync)
- );
- } else {
- notificationCompatBuilder = new NotificationCompat.Builder(this)
- .setOngoing(true).setContentIntent(pIntent)
- .setLargeIcon(icon)
- .setSmallIcon(R.drawable.stat_notify_sync);
- }
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Notification set up");
- }
-
- /**
- * Updates the contents of the service's notifications. Should be called
- * before setupNotificationBuilders.
- */
- @SuppressLint("NewApi")
- private Notification updateNotifications() {
- String contentTitle = getString(R.string.download_notification_title);
- int numDownloads = requester.getNumberOfDownloads();
- String downloadsLeft;
- if (numDownloads > 0) {
- downloadsLeft = requester.getNumberOfDownloads()
- + getString(R.string.downloads_left);
- } else {
- downloadsLeft = getString(R.string.downloads_processing);
- }
- if (android.os.Build.VERSION.SDK_INT >= 16) {
-
- if (notificationBuilder != null) {
-
- StringBuilder bigText = new StringBuilder("");
- for (int i = 0; i < downloads.size(); i++) {
- Downloader downloader = downloads.get(i);
- final DownloadRequest request = downloader
- .getDownloadRequest();
- if (request.getFeedfileType() == Feed.FEEDFILETYPE_FEED) {
- if (request.getTitle() != null) {
- if (i > 0) {
- bigText.append("\n");
- }
- bigText.append("\u2022 " + request.getTitle());
- }
- } else if (request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
- if (request.getTitle() != null) {
- if (i > 0) {
- bigText.append("\n");
- }
- bigText.append("\u2022 " + request.getTitle()
- + " (" + request.getProgressPercent()
- + "%)");
- }
- }
-
- }
- notificationBuilder.setSummaryText(downloadsLeft);
- notificationBuilder.setBigContentTitle(contentTitle);
- if (bigText != null) {
- notificationBuilder.bigText(bigText.toString());
- }
- return notificationBuilder.build();
- }
- } else {
- if (notificationCompatBuilder != null) {
- notificationCompatBuilder.setContentTitle(contentTitle);
- notificationCompatBuilder.setContentText(downloadsLeft);
- return notificationCompatBuilder.build();
- }
- }
- return null;
- }
-
- private Downloader getDownloader(String downloadUrl) {
- for (Downloader downloader : downloads) {
- if (downloader.getDownloadRequest().getSource().equals(downloadUrl)) {
- return downloader;
- }
- }
- return null;
- }
-
- private BroadcastReceiver cancelDownloadReceiver = new BroadcastReceiver() {
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (StringUtils.equals(intent.getAction(), ACTION_CANCEL_DOWNLOAD)) {
- String url = intent.getStringExtra(EXTRA_DOWNLOAD_URL);
- Validate.notNull(url, "ACTION_CANCEL_DOWNLOAD intent needs download url extra");
-
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Cancelling download with url " + url);
- Downloader d = getDownloader(url);
- if (d != null) {
- d.cancel();
- } else {
- Log.e(TAG, "Could not cancel download with url " + url);
- }
-
- } else if (StringUtils.equals(intent.getAction(), ACTION_CANCEL_ALL_DOWNLOADS)) {
- for (Downloader d : downloads) {
- d.cancel();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Cancelled all downloads");
- }
- sendBroadcast(new Intent(ACTION_DOWNLOADS_CONTENT_CHANGED));
-
- }
- queryDownloads();
- }
-
- };
-
- private void onDownloadQueued(Intent intent) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Received enqueue request");
- DownloadRequest request = intent.getParcelableExtra(EXTRA_REQUEST);
- if (request == null) {
- throw new IllegalArgumentException(
- "ACTION_ENQUEUE_DOWNLOAD intent needs request extra");
- }
-
- Downloader downloader = getDownloader(request);
- if (downloader != null) {
- numberOfDownloads.incrementAndGet();
- downloads.add(downloader);
- downloadExecutor.submit(downloader);
- sendBroadcast(new Intent(ACTION_DOWNLOADS_CONTENT_CHANGED));
- }
-
- queryDownloads();
- }
-
- private Downloader getDownloader(DownloadRequest request) {
- if (URLUtil.isHttpUrl(request.getSource())
- || URLUtil.isHttpsUrl(request.getSource())) {
- return new HttpDownloader(request);
- }
- Log.e(TAG,
- "Could not find appropriate downloader for "
- + request.getSource()
- );
- return null;
- }
-
- /**
- * Remove download from the DownloadRequester list and from the
- * DownloadService list.
- */
- private void removeDownload(final Downloader d) {
- handler.post(new Runnable() {
- @Override
- public void run() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Removing downloader: "
- + d.getDownloadRequest().getSource());
- boolean rc = downloads.remove(d);
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Result of downloads.remove: " + rc);
- DownloadRequester.getInstance().removeDownload(d.getDownloadRequest());
- sendBroadcast(new Intent(ACTION_DOWNLOADS_CONTENT_CHANGED));
- }
- });
- }
-
- /**
- * Adds a new DownloadStatus object to the list of completed downloads and
- * saves it in the database
- *
- * @param status the download that is going to be saved
- */
- private void saveDownloadStatus(DownloadStatus status) {
- reportQueue.add(status);
- DBWriter.addDownloadStatus(this, status);
- }
-
- private void sendDownloadHandledIntent() {
- EventDistributor.getInstance().sendDownloadHandledBroadcast();
- }
-
- /**
- * Creates a notification at the end of the service lifecycle to notify the
- * user about the number of completed downloads. A report will only be
- * created if the number of successfully downloaded feeds is bigger than 1
- * or if there is at least one failed download which is not an image or if
- * there is at least one downloaded media file.
- */
- private void updateReport() {
- // check if report should be created
- boolean createReport = false;
- int successfulDownloads = 0;
- int failedDownloads = 0;
-
- // a download report is created if at least one download has failed
- // (excluding failed image downloads)
- for (DownloadStatus status : reportQueue) {
- if (status.isSuccessful()) {
- successfulDownloads++;
- } else if (!status.isCancelled()) {
- if (status.getFeedfileType() != FeedImage.FEEDFILETYPE_FEEDIMAGE) {
- createReport = true;
- }
- failedDownloads++;
- }
- }
-
- if (createReport) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Creating report");
- Intent intent = new Intent(this, MainActivity.class);
- intent.putExtra(MainActivity.EXTRA_NAV_TYPE, NavListAdapter.VIEW_TYPE_NAV);
- intent.putExtra(MainActivity.EXTRA_NAV_INDEX, MainActivity.POS_DOWNLOADS);
- Bundle args = new Bundle();
- args.putInt(DownloadsFragment.ARG_SELECTED_TAB, DownloadsFragment.POS_LOG);
- intent.putExtra(MainActivity.EXTRA_FRAGMENT_ARGS, args);
-
- // create notification object
- Notification notification = new NotificationCompat.Builder(this)
- .setTicker(
- getString(de.danoeh.antennapod.R.string.download_report_title))
- .setContentTitle(
- getString(de.danoeh.antennapod.R.string.download_report_title))
- .setContentText(
- String.format(
- getString(R.string.download_report_content),
- successfulDownloads, failedDownloads)
- )
- .setSmallIcon(R.drawable.stat_notify_sync)
- .setLargeIcon(
- BitmapFactory.decodeResource(getResources(),
- R.drawable.stat_notify_sync)
- )
- .setContentIntent(
- PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
- )
- .setAutoCancel(true).build();
- NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- nm.notify(REPORT_ID, notification);
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "No report is created");
- }
- reportQueue.clear();
- }
-
- /**
- * Calls query downloads on the services main thread. This method should be used instead of queryDownloads if it is
- * used from a thread other than the main thread.
- */
- void queryDownloadsAsync() {
- handler.post(new Runnable() {
- public void run() {
- queryDownloads();
- ;
- }
- });
- }
-
- /**
- * Check if there's something else to download, otherwise stop
- */
- void queryDownloads() {
- if (BuildConfig.DEBUG) {
- Log.d(TAG, numberOfDownloads.get() + " downloads left");
- }
-
- if (numberOfDownloads.get() <= 0 && DownloadRequester.getInstance().hasNoDownloads()) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Number of downloads is " + numberOfDownloads.get() + ", attempting shutdown");
- stopSelf();
- } else {
- setupNotificationUpdater();
- startForeground(NOTIFICATION_ID, updateNotifications());
- }
- }
-
- private void postAuthenticationNotification(final DownloadRequest downloadRequest) {
- handler.post(new Runnable() {
- @Override
- public void run() {
- final String resourceTitle = (downloadRequest.getTitle() != null)
- ? downloadRequest.getTitle() : downloadRequest.getSource();
-
- final Intent activityIntent = new Intent(getApplicationContext(), DownloadAuthenticationActivity.class);
- activityIntent.putExtra(DownloadAuthenticationActivity.ARG_DOWNLOAD_REQUEST, downloadRequest);
- activityIntent.putExtra(DownloadAuthenticationActivity.ARG_SEND_TO_DOWNLOAD_REQUESTER_BOOL, true);
- final PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 0, activityIntent, PendingIntent.FLAG_ONE_SHOT);
-
- NotificationCompat.Builder builder = new NotificationCompat.Builder(DownloadService.this);
- builder.setTicker(getText(R.string.authentication_notification_title))
- .setContentTitle(getText(R.string.authentication_notification_title))
- .setContentText(getText(R.string.authentication_notification_msg))
- .setStyle(new NotificationCompat.BigTextStyle().bigText(getText(R.string.authentication_notification_msg)
- + ": " + resourceTitle))
- .setSmallIcon(R.drawable.ic_stat_authentication)
- .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_stat_authentication))
- .setAutoCancel(true)
- .setContentIntent(contentIntent);
- Notification n = builder.build();
- NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- nm.notify(downloadRequest.getSource().hashCode(), n);
- }
- });
- }
-
- /**
- * Is called whenever a Feed is downloaded
- */
- private void handleCompletedFeedDownload(DownloadRequest request) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Handling completed Feed Download");
- feedSyncThread.submitCompletedDownload(request);
-
- }
-
- /**
- * Is called whenever a Feed-Image is downloaded
- */
- private void handleCompletedImageDownload(DownloadStatus status, DownloadRequest request) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Handling completed Image Download");
- syncExecutor.execute(new ImageHandlerThread(status, request));
- }
-
- /**
- * Is called whenever a FeedMedia is downloaded.
- */
- private void handleCompletedFeedMediaDownload(DownloadStatus status, DownloadRequest request) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Handling completed FeedMedia Download");
- syncExecutor.execute(new MediaHandlerThread(status, request));
- }
-
- private void handleFailedDownload(DownloadStatus status, DownloadRequest request) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Handling failed download");
- syncExecutor.execute(new FailedDownloadHandler(status, request));
- }
-
- /**
- * Takes a single Feed, parses the corresponding file and refreshes
- * information in the manager
- */
- class FeedSyncThread extends Thread {
- private static final String TAG = "FeedSyncThread";
-
- private BlockingQueue<DownloadRequest> completedRequests = new LinkedBlockingDeque<DownloadRequest>();
- private CompletionService<Feed> parserService = new ExecutorCompletionService<Feed>(Executors.newSingleThreadExecutor());
- private ExecutorService dbService = Executors.newSingleThreadExecutor();
- private Future<?> dbUpdateFuture;
- private volatile boolean isActive = true;
- private volatile boolean isCollectingRequests = false;
-
- private final long WAIT_TIMEOUT = 3000;
-
-
- /**
- * Waits for completed requests. Once the first request has been taken, the method will wait WAIT_TIMEOUT ms longer to
- * collect more completed requests.
- *
- * @return Collected feeds or null if the method has been interrupted during the first waiting period.
- */
- private List<Feed> collectCompletedRequests() {
- List<Feed> results = new LinkedList<Feed>();
- DownloadRequester requester = DownloadRequester.getInstance();
- int tasks = 0;
-
- try {
- DownloadRequest request = completedRequests.take();
- parserService.submit(new FeedParserTask(request));
- tasks++;
- } catch (InterruptedException e) {
- return null;
- }
-
- tasks += pollCompletedDownloads();
-
- isCollectingRequests = true;
-
- if (requester.isDownloadingFeeds()) {
- // wait for completion of more downloads
- long startTime = System.currentTimeMillis();
- long currentTime = startTime;
- while (requester.isDownloadingFeeds() && (currentTime - startTime) < WAIT_TIMEOUT) {
- try {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Waiting for " + (startTime + WAIT_TIMEOUT - currentTime) + " ms");
- sleep(startTime + WAIT_TIMEOUT - currentTime);
- } catch (InterruptedException e) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "interrupted while waiting for more downloads");
- tasks += pollCompletedDownloads();
- } finally {
- currentTime = System.currentTimeMillis();
- }
- }
-
- tasks += pollCompletedDownloads();
-
- }
-
- isCollectingRequests = false;
-
- for (int i = 0; i < tasks; i++) {
- try {
- Feed f = parserService.take().get();
- if (f != null) {
- results.add(f);
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
-
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
- }
-
- return results;
- }
-
- private int pollCompletedDownloads() {
- int tasks = 0;
- for (int i = 0; i < completedRequests.size(); i++) {
- parserService.submit(new FeedParserTask(completedRequests.poll()));
- tasks++;
- }
- return tasks;
- }
-
- @Override
- public void run() {
- while (isActive) {
- final List<Feed> feeds = collectCompletedRequests();
-
- if (feeds == null) {
- continue;
- }
-
- if (BuildConfig.DEBUG) Log.d(TAG, "Bundling " + feeds.size() + " feeds");
-
- for (Feed feed : feeds) {
- removeDuplicateImages(feed); // duplicate images have to removed because the DownloadRequester does not accept two downloads with the same download URL yet.
- }
-
- // Save information of feed in DB
- if (dbUpdateFuture != null) {
- try {
- dbUpdateFuture.get();
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
- }
-
- dbUpdateFuture = dbService.submit(new Runnable() {
- @Override
- public void run() {
- Feed[] savedFeeds = DBTasks.updateFeed(DownloadService.this, feeds.toArray(new Feed[feeds.size()]));
-
- for (Feed savedFeed : savedFeeds) {
- // Download Feed Image if provided and not downloaded
- if (savedFeed.getImage() != null
- && savedFeed.getImage().isDownloaded() == false) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Feed has image; Downloading....");
- savedFeed.getImage().setOwner(savedFeed);
- final Feed savedFeedRef = savedFeed;
- try {
- requester.downloadImage(DownloadService.this,
- savedFeedRef.getImage());
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- DBWriter.addDownloadStatus(
- DownloadService.this,
- new DownloadStatus(
- savedFeedRef.getImage(),
- savedFeedRef
- .getImage()
- .getHumanReadableIdentifier(),
- DownloadError.ERROR_REQUEST_ERROR,
- false, e.getMessage()
- )
- );
- }
- }
-
- // queue new media files for automatic download
- for (FeedItem item : savedFeed.getItems()) {
- if (!item.isRead() && item.hasMedia() && !item.getMedia().isDownloaded()) {
- newMediaFiles.add(item.getMedia().getId());
- }
- }
-
- numberOfDownloads.decrementAndGet();
- }
-
- sendDownloadHandledIntent();
-
- queryDownloadsAsync();
- }
- });
-
- }
-
- if (dbUpdateFuture != null) {
- try {
- dbUpdateFuture.get();
- } catch (InterruptedException e) {
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
- }
-
- if (BuildConfig.DEBUG) Log.d(TAG, "Shutting down");
-
- }
-
- private class FeedParserTask implements Callable<Feed> {
-
- private DownloadRequest request;
-
- private FeedParserTask(DownloadRequest request) {
- this.request = request;
- }
-
- @Override
- public Feed call() throws Exception {
- return parseFeed(request);
- }
- }
-
- private Feed parseFeed(DownloadRequest request) {
- Feed savedFeed = null;
-
- Feed feed = new Feed(request.getSource(), new Date());
- feed.setFile_url(request.getDestination());
- feed.setId(request.getFeedfileId());
- feed.setDownloaded(true);
- feed.setPreferences(new FeedPreferences(0, true, request.getUsername(), request.getPassword()));
-
- DownloadError reason = null;
- String reasonDetailed = null;
- boolean successful = true;
- FeedHandler feedHandler = new FeedHandler();
-
- try {
- feed = feedHandler.parseFeed(feed).feed;
- if (BuildConfig.DEBUG)
- Log.d(TAG, feed.getTitle() + " parsed");
- if (checkFeedData(feed) == false) {
- throw new InvalidFeedException();
- }
-
- } catch (SAXException e) {
- successful = false;
- e.printStackTrace();
- reason = DownloadError.ERROR_PARSER_EXCEPTION;
- reasonDetailed = e.getMessage();
- } catch (IOException e) {
- successful = false;
- e.printStackTrace();
- reason = DownloadError.ERROR_PARSER_EXCEPTION;
- reasonDetailed = e.getMessage();
- } catch (ParserConfigurationException e) {
- successful = false;
- e.printStackTrace();
- reason = DownloadError.ERROR_PARSER_EXCEPTION;
- reasonDetailed = e.getMessage();
- } catch (UnsupportedFeedtypeException e) {
- e.printStackTrace();
- successful = false;
- reason = DownloadError.ERROR_UNSUPPORTED_TYPE;
- reasonDetailed = e.getMessage();
- } catch (InvalidFeedException e) {
- e.printStackTrace();
- successful = false;
- reason = DownloadError.ERROR_PARSER_EXCEPTION;
- reasonDetailed = e.getMessage();
- }
-
- // cleanup();
- if (savedFeed == null) {
- savedFeed = feed;
- }
-
-
- if (successful) {
- return savedFeed;
- } else {
- numberOfDownloads.decrementAndGet();
- saveDownloadStatus(new DownloadStatus(savedFeed,
- savedFeed.getHumanReadableIdentifier(), reason, successful,
- reasonDetailed));
- return null;
- }
- }
-
-
- /**
- * Checks if the feed was parsed correctly.
- */
- private boolean checkFeedData(Feed feed) {
- if (feed.getTitle() == null) {
- Log.e(TAG, "Feed has no title.");
- return false;
- }
- if (!hasValidFeedItems(feed)) {
- Log.e(TAG, "Feed has invalid items");
- return false;
- }
- return true;
- }
-
- /**
- * Checks if the FeedItems of this feed have images that point
- * to the same URL. If two FeedItems have an image that points to
- * the same URL, the reference of the second item is removed, so that every image
- * reference is unique.
- */
- private void removeDuplicateImages(Feed feed) {
- for (int x = 0; x < feed.getItems().size(); x++) {
- for (int y = x + 1; y < feed.getItems().size(); y++) {
- FeedItem item1 = feed.getItems().get(x);
- FeedItem item2 = feed.getItems().get(y);
- if (item1.hasItemImage() && item2.hasItemImage()) {
- if (StringUtils.equals(item1.getImage().getDownload_url(), item2.getImage().getDownload_url())) {
- item2.setImage(null);
- }
- }
- }
- }
- }
-
- private boolean hasValidFeedItems(Feed feed) {
- for (FeedItem item : feed.getItems()) {
- if (item.getTitle() == null) {
- Log.e(TAG, "Item has no title");
- return false;
- }
- if (item.getPubDate() == null) {
- Log.e(TAG,
- "Item has no pubDate. Using current time as pubDate");
- if (item.getTitle() != null) {
- Log.e(TAG, "Title of invalid item: " + item.getTitle());
- }
- item.setPubDate(new Date());
- }
- }
- return true;
- }
-
- /**
- * Delete files that aren't needed anymore
- */
- private void cleanup(Feed feed) {
- if (feed.getFile_url() != null) {
- if (new File(feed.getFile_url()).delete())
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Successfully deleted cache file.");
- else
- Log.e(TAG, "Failed to delete cache file.");
- feed.setFile_url(null);
- } else if (BuildConfig.DEBUG) {
- Log.d(TAG, "Didn't delete cache file: File url is not set.");
- }
- }
-
- public void shutdown() {
- isActive = false;
- if (isCollectingRequests) {
- interrupt();
- }
- }
-
- public void submitCompletedDownload(DownloadRequest request) {
- completedRequests.offer(request);
- if (isCollectingRequests) {
- interrupt();
- }
- }
-
- }
-
- /**
- * Handles failed downloads.
- * <p/>
- * If the file has been partially downloaded, this handler will set the file_url of the FeedFile to the location
- * of the downloaded file.
- * <p/>
- * Currently, this handler only handles FeedMedia objects, because Feeds and FeedImages are deleted if the download fails.
- */
- class FailedDownloadHandler implements Runnable {
-
- private DownloadRequest request;
- private DownloadStatus status;
-
- FailedDownloadHandler(DownloadStatus status, DownloadRequest request) {
- this.request = request;
- this.status = status;
- }
-
- @Override
- public void run() {
- if (request.isDeleteOnFailure()) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Ignoring failed download, deleteOnFailure=true");
- } else {
- File dest = new File(request.getDestination());
- if (dest.exists() && request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
- Log.d(TAG, "File has been partially downloaded. Writing file url");
- FeedMedia media = DBReader.getFeedMedia(DownloadService.this, request.getFeedfileId());
- media.setFile_url(request.getDestination());
- try {
- DBWriter.setFeedMedia(DownloadService.this, media).get();
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
- }
- }
- }
- }
-
- /**
- * Handles a completed image download.
- */
- class ImageHandlerThread implements Runnable {
-
- private DownloadRequest request;
- private DownloadStatus status;
-
- public ImageHandlerThread(DownloadStatus status, DownloadRequest request) {
- Validate.notNull(status);
- Validate.notNull(request);
-
- this.status = status;
- this.request = request;
- }
-
- @Override
- public void run() {
- FeedImage image = DBReader.getFeedImage(DownloadService.this, request.getFeedfileId());
- if (image == null) {
- throw new IllegalStateException("Could not find downloaded image in database");
- }
-
- image.setFile_url(request.getDestination());
- image.setDownloaded(true);
-
- saveDownloadStatus(status);
- sendDownloadHandledIntent();
- DBWriter.setFeedImage(DownloadService.this, image);
- numberOfDownloads.decrementAndGet();
- queryDownloadsAsync();
- }
- }
-
- /**
- * Handles a completed media download.
- */
- class MediaHandlerThread implements Runnable {
-
- private DownloadRequest request;
- private DownloadStatus status;
-
- public MediaHandlerThread(DownloadStatus status, DownloadRequest request) {
- Validate.notNull(status);
- Validate.notNull(request);
-
- this.status = status;
- this.request = request;
- }
-
- @Override
- public void run() {
- FeedMedia media = DBReader.getFeedMedia(DownloadService.this,
- request.getFeedfileId());
- if (media == null) {
- throw new IllegalStateException(
- "Could not find downloaded media object in database");
- }
- boolean chaptersRead = false;
- media.setDownloaded(true);
- media.setFile_url(request.getDestination());
-
- // Get duration
- MediaMetadataRetriever mmr = null;
- try {
- mmr = new MediaMetadataRetriever();
- mmr.setDataSource(media.getFile_url());
- String durationStr = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
- media.setDuration(Integer.parseInt(durationStr));
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Duration of file is " + media.getDuration());
- } catch (NumberFormatException e) {
- e.printStackTrace();
- } catch (RuntimeException e) {
- e.printStackTrace();
- } finally {
- if (mmr != null) {
- mmr.release();
- }
- }
-
- if (media.getItem().getChapters() == null) {
- ChapterUtils.loadChaptersFromFileUrl(media);
- if (media.getItem().getChapters() != null) {
- chaptersRead = true;
- }
- }
-
- try {
- if (chaptersRead) {
- DBWriter.setFeedItem(DownloadService.this, media.getItem()).get();
- }
- DBWriter.setFeedMedia(DownloadService.this, media).get();
- if (!DBTasks.isInQueue(DownloadService.this, media.getItem().getId())) {
- DBWriter.addQueueItem(DownloadService.this, media.getItem().getId()).get();
- }
- } catch (ExecutionException e) {
- e.printStackTrace();
- status = new DownloadStatus(media, media.getEpisodeTitle(), DownloadError.ERROR_DB_ACCESS_ERROR, false, e.getMessage());
- } catch (InterruptedException e) {
- e.printStackTrace();
- status = new DownloadStatus(media, media.getEpisodeTitle(), DownloadError.ERROR_DB_ACCESS_ERROR, false, e.getMessage());
- }
-
- saveDownloadStatus(status);
- sendDownloadHandledIntent();
-
- numberOfDownloads.decrementAndGet();
- queryDownloadsAsync();
- }
- }
-
- /**
- * Schedules the notification updater task if it hasn't been scheduled yet.
- */
- private void setupNotificationUpdater() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Setting up notification updater");
- if (notificationUpdater == null) {
- notificationUpdater = new NotificationUpdater();
- notificationUpdaterFuture = schedExecutor.scheduleAtFixedRate(
- notificationUpdater, 5L, 5L, TimeUnit.SECONDS);
- }
- }
-
- private void cancelNotificationUpdater() {
- boolean result = false;
- if (notificationUpdaterFuture != null) {
- result = notificationUpdaterFuture.cancel(true);
- }
- notificationUpdater = null;
- notificationUpdaterFuture = null;
- Log.d(TAG, "NotificationUpdater cancelled. Result: " + result);
- }
-
- private class NotificationUpdater implements Runnable {
- public void run() {
- handler.post(new Runnable() {
- @Override
- public void run() {
- Notification n = updateNotifications();
- if (n != null) {
- NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- nm.notify(NOTIFICATION_ID, n);
- }
- }
- });
- }
- }
-
- public List<Downloader> getDownloads() {
- return downloads;
- }
-
-}
diff --git a/src/de/danoeh/antennapod/service/download/DownloadStatus.java b/src/de/danoeh/antennapod/service/download/DownloadStatus.java
deleted file mode 100644
index 1d76770bb..000000000
--- a/src/de/danoeh/antennapod/service/download/DownloadStatus.java
+++ /dev/null
@@ -1,181 +0,0 @@
-package de.danoeh.antennapod.service.download;
-
-import org.apache.commons.lang3.Validate;
-
-import de.danoeh.antennapod.feed.FeedFile;
-import de.danoeh.antennapod.util.DownloadError;
-
-import java.util.Date;
-
-/** Contains status attributes for one download */
-public class DownloadStatus {
- /**
- * Downloaders should use this constant for the size attribute if necessary
- * so that the listadapters etc. can react properly.
- */
- public static final int SIZE_UNKNOWN = -1;
-
- // ----------------------------------- ATTRIBUTES STORED IN DB
- /** Unique id for storing the object in database. */
- protected long id;
- /**
- * A human-readable string which is shown to the user so that he can
- * identify the download. Should be the title of the item/feed/media or the
- * URL if the download has no other title.
- */
- protected String title;
- protected DownloadError reason;
- /**
- * A message which can be presented to the user to give more information.
- * Should be null if Download was successful.
- */
- protected String reasonDetailed;
- protected boolean successful;
- protected Date completionDate;
- protected long feedfileId;
- /**
- * Is used to determine the type of the feedfile even if the feedfile does
- * not exist anymore. The value should be FEEDFILETYPE_FEED,
- * FEEDFILETYPE_FEEDIMAGE or FEEDFILETYPE_FEEDMEDIA
- */
- protected int feedfileType;
-
- // ------------------------------------ NOT STORED IN DB
- protected boolean done;
- protected boolean cancelled;
-
- /** Constructor for restoring Download status entries from DB. */
- public DownloadStatus(long id, String title, long feedfileId,
- int feedfileType, boolean successful, DownloadError reason,
- Date completionDate, String reasonDetailed) {
- this.id = id;
- this.title = title;
- this.done = true;
- this.feedfileId = feedfileId;
- this.reason = reason;
- this.successful = successful;
- this.completionDate = (Date) completionDate.clone();
- this.reasonDetailed = reasonDetailed;
- this.feedfileType = feedfileType;
- }
-
- public DownloadStatus(DownloadRequest request, DownloadError reason,
- boolean successful, boolean cancelled, String reasonDetailed) {
- Validate.notNull(request);
-
- this.title = request.getTitle();
- this.feedfileId = request.getFeedfileId();
- this.feedfileType = request.getFeedfileType();
- this.reason = reason;
- this.successful = successful;
- this.cancelled = cancelled;
- this.reasonDetailed = reasonDetailed;
- this.completionDate = new Date();
- }
-
- /** Constructor for creating new completed downloads. */
- public DownloadStatus(FeedFile feedfile, String title, DownloadError reason,
- boolean successful, String reasonDetailed) {
- Validate.notNull(feedfile);
-
- this.title = title;
- this.done = true;
- this.feedfileId = feedfile.getId();
- this.feedfileType = feedfile.getTypeAsInt();
- this.reason = reason;
- this.successful = successful;
- this.completionDate = new Date();
- this.reasonDetailed = reasonDetailed;
- }
-
- /** Constructor for creating new completed downloads. */
- public DownloadStatus(long feedfileId, int feedfileType, String title,
- DownloadError reason, boolean successful, String reasonDetailed) {
- this.title = title;
- this.done = true;
- this.feedfileId = feedfileId;
- this.feedfileType = feedfileType;
- this.reason = reason;
- this.successful = successful;
- this.completionDate = new Date();
- this.reasonDetailed = reasonDetailed;
- }
-
- @Override
- public String toString() {
- return "DownloadStatus [id=" + id + ", title=" + title + ", reason="
- + reason + ", reasonDetailed=" + reasonDetailed
- + ", successful=" + successful + ", completionDate="
- + completionDate + ", feedfileId=" + feedfileId
- + ", feedfileType=" + feedfileType + ", done=" + done
- + ", cancelled=" + cancelled + "]";
- }
-
- public long getId() {
- return id;
- }
-
- public String getTitle() {
- return title;
- }
-
- public DownloadError getReason() {
- return reason;
- }
-
- public String getReasonDetailed() {
- return reasonDetailed;
- }
-
- public boolean isSuccessful() {
- return successful;
- }
-
- public Date getCompletionDate() {
- return (Date) completionDate.clone();
- }
-
- public long getFeedfileId() {
- return feedfileId;
- }
-
- public int getFeedfileType() {
- return feedfileType;
- }
-
- public boolean isDone() {
- return done;
- }
-
- public boolean isCancelled() {
- return cancelled;
- }
-
- public void setSuccessful() {
- this.successful = true;
- this.reason = DownloadError.SUCCESS;
- this.done = true;
- }
-
- public void setFailed(DownloadError reason, String reasonDetailed) {
- this.successful = false;
- this.reason = reason;
- this.reasonDetailed = reasonDetailed;
- this.done = true;
- }
-
- public void setCancelled() {
- this.successful = false;
- this.reason = DownloadError.ERROR_DOWNLOAD_CANCELLED;
- this.done = true;
- this.cancelled = true;
- }
-
- public void setCompletionDate(Date completionDate) {
- this.completionDate = (Date) completionDate.clone();
- }
-
- public void setId(long id) {
- this.id = id;
- }
-} \ No newline at end of file
diff --git a/src/de/danoeh/antennapod/service/download/Downloader.java b/src/de/danoeh/antennapod/service/download/Downloader.java
deleted file mode 100644
index 80cc5b3f8..000000000
--- a/src/de/danoeh/antennapod/service/download/Downloader.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package de.danoeh.antennapod.service.download;
-
-import android.content.Context;
-import android.net.wifi.WifiManager;
-import de.danoeh.antennapod.PodcastApp;
-import de.danoeh.antennapod.R;
-
-import java.util.concurrent.Callable;
-
-/** Downloads files */
-public abstract class Downloader implements Callable<Downloader> {
- private static final String TAG = "Downloader";
-
- protected volatile boolean finished;
-
- protected volatile boolean cancelled;
-
- protected DownloadRequest request;
- protected DownloadStatus result;
-
- public Downloader(DownloadRequest request) {
- super();
- this.request = request;
- this.request.setStatusMsg(R.string.download_pending);
- this.cancelled = false;
- this.result = new DownloadStatus(request, null, false, false, null);
- }
-
- protected abstract void download();
-
- public final Downloader call() {
- WifiManager wifiManager = (WifiManager) PodcastApp.getInstance().getSystemService(Context.WIFI_SERVICE);
- WifiManager.WifiLock wifiLock = null;
- if (wifiManager != null) {
- wifiLock = wifiManager.createWifiLock(TAG);
- wifiLock.acquire();
- }
-
- download();
-
- if (wifiLock != null) {
- wifiLock.release();
- }
-
- if (result == null) {
- throw new IllegalStateException(
- "Downloader hasn't created DownloadStatus object");
- }
- finished = true;
- return this;
- }
-
- public DownloadRequest getDownloadRequest() {
- return request;
- }
-
- public DownloadStatus getResult() {
- return result;
- }
-
- public boolean isFinished() {
- return finished;
- }
-
- public void cancel() {
- cancelled = true;
- }
-
-} \ No newline at end of file
diff --git a/src/de/danoeh/antennapod/service/download/DownloaderCallback.java b/src/de/danoeh/antennapod/service/download/DownloaderCallback.java
deleted file mode 100644
index 08420e83a..000000000
--- a/src/de/danoeh/antennapod/service/download/DownloaderCallback.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package de.danoeh.antennapod.service.download;
-
-/**
- * Callback used by the Downloader-classes to notify the requester that the
- * download has completed.
- */
-public interface DownloaderCallback {
-
- public void onDownloadCompleted(Downloader downloader);
-}
diff --git a/src/de/danoeh/antennapod/service/download/HttpDownloader.java b/src/de/danoeh/antennapod/service/download/HttpDownloader.java
deleted file mode 100644
index 7ae96dc07..000000000
--- a/src/de/danoeh/antennapod/service/download/HttpDownloader.java
+++ /dev/null
@@ -1,246 +0,0 @@
-package de.danoeh.antennapod.service.download;
-
-import android.net.http.AndroidHttpClient;
-import android.util.Log;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.PodcastApp;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.feed.FeedImage;
-import de.danoeh.antennapod.util.DownloadError;
-import de.danoeh.antennapod.util.StorageUtils;
-import de.danoeh.antennapod.util.URIUtil;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.http.Header;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.HttpStatus;
-import org.apache.http.auth.UsernamePasswordCredentials;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.impl.auth.BasicScheme;
-import org.apache.http.message.BasicHeader;
-
-import java.io.*;
-import java.net.HttpURLConnection;
-import java.net.SocketTimeoutException;
-import java.net.UnknownHostException;
-
-public class HttpDownloader extends Downloader {
- private static final String TAG = "HttpDownloader";
-
- private static final int BUFFER_SIZE = 8 * 1024;
-
- public HttpDownloader(DownloadRequest request) {
- super(request);
- }
-
- @Override
- protected void download() {
- File destination = new File(request.getDestination());
- final boolean fileExists = destination.exists();
-
- if (request.isDeleteOnFailure() && fileExists) {
- Log.w(TAG, "File already exists");
- if (request.getFeedfileType() != FeedImage.FEEDFILETYPE_FEEDIMAGE) {
- onFail(DownloadError.ERROR_FILE_EXISTS, null);
- return;
- } else {
- onSuccess();
- return;
- }
- }
-
- HttpClient httpClient = AntennapodHttpClient.getHttpClient();
- RandomAccessFile out = null;
- InputStream connection = null;
- try {
- HttpGet httpGet = new HttpGet(URIUtil.getURIFromRequestUrl(request.getSource()));
-
- // add authentication information
- String userInfo = httpGet.getURI().getUserInfo();
- if (userInfo != null) {
- String[] parts = userInfo.split(":");
- if (parts.length == 2) {
- httpGet.addHeader(BasicScheme.authenticate(
- new UsernamePasswordCredentials(parts[0], parts[1]),
- "UTF-8", false));
- }
- } else if (!StringUtils.isEmpty(request.getUsername()) && request.getPassword() != null) {
- httpGet.addHeader(BasicScheme.authenticate(new UsernamePasswordCredentials(request.getUsername(),
- request.getPassword()), "UTF-8", false));
- }
-
- // add range header if necessary
- if (fileExists) {
- request.setSoFar(destination.length());
- httpGet.addHeader(new BasicHeader("Range",
- "bytes=" + request.getSoFar() + "-"));
- if (BuildConfig.DEBUG) Log.d(TAG, "Adding range header: " + request.getSoFar());
- }
-
- HttpResponse response = httpClient.execute(httpGet);
- HttpEntity httpEntity = response.getEntity();
- int responseCode = response.getStatusLine().getStatusCode();
- Header contentEncodingHeader = response.getFirstHeader("Content-Encoding");
-
- final boolean isGzip = contentEncodingHeader != null &&
- contentEncodingHeader.getValue().equalsIgnoreCase("gzip");
-
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Response code is " + responseCode);
-
- if (responseCode / 100 != 2 || httpEntity == null) {
- final DownloadError error;
- final String details;
- if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
- error = DownloadError.ERROR_UNAUTHORIZED;
- details = String.valueOf(responseCode);
- } else {
- error = DownloadError.ERROR_HTTP_DATA_ERROR;
- details = String.valueOf(responseCode);
- }
- onFail(error, details);
- return;
- }
-
- if (!StorageUtils.storageAvailable(PodcastApp.getInstance())) {
- onFail(DownloadError.ERROR_DEVICE_NOT_FOUND, null);
- return;
- }
-
- connection = new BufferedInputStream(AndroidHttpClient
- .getUngzippedContent(httpEntity));
-
- Header[] contentRangeHeaders = (fileExists) ? response.getHeaders("Content-Range") : null;
-
- if (fileExists && responseCode == HttpStatus.SC_PARTIAL_CONTENT
- && contentRangeHeaders != null && contentRangeHeaders.length > 0) {
- String start = contentRangeHeaders[0].getValue().substring("bytes ".length(),
- contentRangeHeaders[0].getValue().indexOf("-"));
- request.setSoFar(Long.valueOf(start));
- Log.d(TAG, "Starting download at position " + request.getSoFar());
-
- out = new RandomAccessFile(destination, "rw");
- out.seek(request.getSoFar());
- } else {
- destination.delete();
- destination.createNewFile();
- out = new RandomAccessFile(destination, "rw");
- }
-
-
- byte[] buffer = new byte[BUFFER_SIZE];
- int count = 0;
- request.setStatusMsg(R.string.download_running);
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Getting size of download");
- request.setSize(httpEntity.getContentLength() + request.getSoFar());
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Size is " + request.getSize());
- if (request.getSize() < 0) {
- request.setSize(DownloadStatus.SIZE_UNKNOWN);
- }
-
- long freeSpace = StorageUtils.getFreeSpaceAvailable();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Free space is " + freeSpace);
-
- if (request.getSize() != DownloadStatus.SIZE_UNKNOWN
- && request.getSize() > freeSpace) {
- onFail(DownloadError.ERROR_NOT_ENOUGH_SPACE, null);
- return;
- }
-
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Starting download");
- while (!cancelled
- && (count = connection.read(buffer)) != -1) {
- out.write(buffer, 0, count);
- request.setSoFar(request.getSoFar() + count);
- request.setProgressPercent((int) (((double) request
- .getSoFar() / (double) request
- .getSize()) * 100));
- }
- if (cancelled) {
- onCancelled();
- } else {
- // check if size specified in the response header is the same as the size of the
- // written file. This check cannot be made if compression was used
- if (!isGzip && request.getSize() != DownloadStatus.SIZE_UNKNOWN &&
- request.getSoFar() != request.getSize()) {
- onFail(DownloadError.ERROR_IO_ERROR,
- "Download completed but size: " +
- request.getSoFar() +
- " does not equal expected size " +
- request.getSize()
- );
- return;
- }
- onSuccess();
- }
-
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- onFail(DownloadError.ERROR_MALFORMED_URL, e.getMessage());
- } catch (SocketTimeoutException e) {
- e.printStackTrace();
- onFail(DownloadError.ERROR_CONNECTION_ERROR, e.getMessage());
- } catch (UnknownHostException e) {
- e.printStackTrace();
- onFail(DownloadError.ERROR_UNKNOWN_HOST, e.getMessage());
- } catch (IOException e) {
- e.printStackTrace();
- onFail(DownloadError.ERROR_IO_ERROR, e.getMessage());
- } catch (NullPointerException e) {
- // might be thrown by connection.getInputStream()
- e.printStackTrace();
- onFail(DownloadError.ERROR_CONNECTION_ERROR, request.getSource());
- } finally {
- IOUtils.closeQuietly(out);
- AntennapodHttpClient.cleanup();
- }
- }
-
- private void onSuccess() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Download was successful");
- result.setSuccessful();
- }
-
- private void onFail(DownloadError reason, String reasonDetailed) {
- if (BuildConfig.DEBUG) {
- Log.d(TAG, "Download failed");
- }
- result.setFailed(reason, reasonDetailed);
- if (request.isDeleteOnFailure()) {
- cleanup();
- }
- }
-
- private void onCancelled() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Download was cancelled");
- result.setCancelled();
- cleanup();
- }
-
- /**
- * Deletes unfinished downloads.
- */
- private void cleanup() {
- if (request.getDestination() != null) {
- File dest = new File(request.getDestination());
- if (dest.exists()) {
- boolean rc = dest.delete();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Deleted file " + dest.getName() + "; Result: "
- + rc);
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "cleanup() didn't delete file: does not exist.");
- }
- }
- }
-
-}
diff --git a/src/de/danoeh/antennapod/service/playback/PlaybackService.java b/src/de/danoeh/antennapod/service/playback/PlaybackService.java
deleted file mode 100644
index 59d7ddbb9..000000000
--- a/src/de/danoeh/antennapod/service/playback/PlaybackService.java
+++ /dev/null
@@ -1,1080 +0,0 @@
-package de.danoeh.antennapod.service.playback;
-
-import android.annotation.SuppressLint;
-import android.app.Notification;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.SharedPreferences;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.media.AudioManager;
-import android.media.MediaMetadataRetriever;
-import android.media.MediaPlayer;
-import android.media.RemoteControlClient;
-import android.media.RemoteControlClient.MetadataEditor;
-import android.os.AsyncTask;
-import android.os.Binder;
-import android.os.Build;
-import android.os.IBinder;
-import android.preference.PreferenceManager;
-import android.support.v4.app.NotificationCompat;
-import android.util.Log;
-import android.util.Pair;
-import android.view.KeyEvent;
-import android.view.SurfaceHolder;
-import android.widget.Toast;
-
-import org.apache.commons.lang3.StringUtils;
-
-import java.io.IOException;
-import java.util.List;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.AudioplayerActivity;
-import de.danoeh.antennapod.activity.VideoplayerActivity;
-import de.danoeh.antennapod.asynctask.PicassoProvider;
-import de.danoeh.antennapod.feed.Chapter;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.feed.FeedMedia;
-import de.danoeh.antennapod.feed.MediaType;
-import de.danoeh.antennapod.preferences.PlaybackPreferences;
-import de.danoeh.antennapod.preferences.UserPreferences;
-import de.danoeh.antennapod.receiver.MediaButtonReceiver;
-import de.danoeh.antennapod.receiver.PlayerWidget;
-import de.danoeh.antennapod.storage.DBTasks;
-import de.danoeh.antennapod.storage.DBWriter;
-import de.danoeh.antennapod.util.QueueAccess;
-import de.danoeh.antennapod.util.flattr.FlattrUtils;
-import de.danoeh.antennapod.util.playback.Playable;
-
-/**
- * Controls the MediaPlayer that plays a FeedMedia-file
- */
-public class PlaybackService extends Service {
- /**
- * Logging tag
- */
- private static final String TAG = "PlaybackService";
-
- /**
- * Parcelable of type Playable.
- */
- public static final String EXTRA_PLAYABLE = "PlaybackService.PlayableExtra";
- /**
- * True if media should be streamed.
- */
- public static final String EXTRA_SHOULD_STREAM = "extra.de.danoeh.antennapod.service.shouldStream";
- /**
- * True if playback should be started immediately after media has been
- * prepared.
- */
- public static final String EXTRA_START_WHEN_PREPARED = "extra.de.danoeh.antennapod.service.startWhenPrepared";
-
- public static final String EXTRA_PREPARE_IMMEDIATELY = "extra.de.danoeh.antennapod.service.prepareImmediately";
-
- public static final String ACTION_PLAYER_STATUS_CHANGED = "action.de.danoeh.antennapod.service.playerStatusChanged";
- private static final String AVRCP_ACTION_PLAYER_STATUS_CHANGED = "com.android.music.playstatechanged";
- private static final String AVRCP_ACTION_META_CHANGED = "com.android.music.metachanged";
-
- public static final String ACTION_PLAYER_NOTIFICATION = "action.de.danoeh.antennapod.service.playerNotification";
- public static final String EXTRA_NOTIFICATION_CODE = "extra.de.danoeh.antennapod.service.notificationCode";
- public static final String EXTRA_NOTIFICATION_TYPE = "extra.de.danoeh.antennapod.service.notificationType";
-
- /**
- * If the PlaybackService receives this action, it will stop playback and
- * try to shutdown.
- */
- 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;
-
- public static final int NOTIFICATION_TYPE_ERROR = 0;
- public static final int NOTIFICATION_TYPE_INFO = 1;
- public static final int NOTIFICATION_TYPE_BUFFER_UPDATE = 2;
-
- /**
- * Receivers of this intent should update their information about the curently playing media
- */
- public static final int NOTIFICATION_TYPE_RELOAD = 3;
- /**
- * The state of the sleeptimer changed.
- */
- 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;
-
- /**
- * Playback speed has changed
- */
- public static final int NOTIFICATION_TYPE_PLAYBACK_SPEED_CHANGE = 8;
-
- /**
- * Returned by getPositionSafe() or getDurationSafe() if the playbackService
- * is in an invalid state.
- */
- public static final int INVALID_TIME = -1;
-
- /**
- * Is true if service is running.
- */
- public static boolean isRunning = false;
- /**
- * Is true if service has received a valid start command.
- */
- public static boolean started = false;
-
- private static final int NOTIFICATION_ID = 1;
-
- private RemoteControlClient remoteControlClient;
- private PlaybackServiceMediaPlayer mediaPlayer;
- private PlaybackServiceTaskManager taskManager;
-
- private static volatile MediaType currentMediaType = MediaType.UNKNOWN;
-
- private final IBinder mBinder = new LocalBinder();
-
- public class LocalBinder extends Binder {
- public PlaybackService getService() {
- return PlaybackService.this;
- }
- }
-
- @Override
- public boolean onUnbind(Intent intent) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Received onUnbind event");
- return super.onUnbind(intent);
- }
-
- /**
- * Returns an intent which starts an audio- or videoplayer, depending on the
- * type of media that is being played. If the playbackservice is not
- * running, the type of the last played media will be looked up.
- */
- public static Intent getPlayerActivityIntent(Context context) {
- if (isRunning) {
- if (currentMediaType == MediaType.VIDEO) {
- return new Intent(context, VideoplayerActivity.class);
- } else {
- return new Intent(context, AudioplayerActivity.class);
- }
- } else {
- if (PlaybackPreferences.getCurrentEpisodeIsVideo()) {
- return new Intent(context, VideoplayerActivity.class);
- } else {
- return new Intent(context, AudioplayerActivity.class);
- }
- }
- }
-
- /**
- * Same as getPlayerActivityIntent(context), but here the type of activity
- * depends on the FeedMedia that is provided as an argument.
- */
- public static Intent getPlayerActivityIntent(Context context, Playable media) {
- MediaType mt = media.getMediaType();
- if (mt == MediaType.VIDEO) {
- return new Intent(context, VideoplayerActivity.class);
- } else {
- return new Intent(context, AudioplayerActivity.class);
- }
- }
-
- @SuppressLint("NewApi")
- @Override
- public void onCreate() {
- super.onCreate();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Service created.");
- isRunning = true;
-
- registerReceiver(headsetDisconnected, new IntentFilter(
- Intent.ACTION_HEADSET_PLUG));
- registerReceiver(shutdownReceiver, new IntentFilter(
- ACTION_SHUTDOWN_PLAYBACK_SERVICE));
- registerReceiver(audioBecomingNoisy, new IntentFilter(
- AudioManager.ACTION_AUDIO_BECOMING_NOISY));
- registerReceiver(skipCurrentEpisodeReceiver, new IntentFilter(
- ACTION_SKIP_CURRENT_EPISODE));
- remoteControlClient = setupRemoteControlClient();
- taskManager = new PlaybackServiceTaskManager(this, taskManagerCallback);
- mediaPlayer = new PlaybackServiceMediaPlayer(this, mediaPlayerCallback);
-
- }
-
- @SuppressLint("NewApi")
- @Override
- public void onDestroy() {
- super.onDestroy();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Service is about to be destroyed");
- isRunning = false;
- started = false;
- currentMediaType = MediaType.UNKNOWN;
-
- unregisterReceiver(headsetDisconnected);
- unregisterReceiver(shutdownReceiver);
- unregisterReceiver(audioBecomingNoisy);
- unregisterReceiver(skipCurrentEpisodeReceiver);
- mediaPlayer.shutdown();
- taskManager.shutdown();
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Received onBind event");
- return mBinder;
- }
-
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- super.onStartCommand(intent, flags, startId);
-
- if (BuildConfig.DEBUG)
- Log.d(TAG, "OnStartCommand called");
- final int keycode = intent.getIntExtra(MediaButtonReceiver.EXTRA_KEYCODE, -1);
- final Playable playable = intent.getParcelableExtra(EXTRA_PLAYABLE);
- if (keycode == -1 && playable == null) {
- Log.e(TAG, "PlaybackService was started with no arguments");
- stopSelf();
- }
-
- if ((flags & Service.START_FLAG_REDELIVERY) != 0) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "onStartCommand is a redelivered intent, calling stopForeground now.");
- stopForeground(true);
- } else {
-
- if (keycode != -1) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Received media button event");
- handleKeycode(keycode);
- } else {
- started = true;
- boolean stream = intent.getBooleanExtra(EXTRA_SHOULD_STREAM,
- true);
- boolean startWhenPrepared = intent.getBooleanExtra(EXTRA_START_WHEN_PREPARED, false);
- boolean prepareImmediately = intent.getBooleanExtra(EXTRA_PREPARE_IMMEDIATELY, false);
- sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD, 0);
- mediaPlayer.playMediaObject(playable, stream, startWhenPrepared, prepareImmediately);
- }
- }
-
- return Service.START_REDELIVER_INTENT;
- }
-
- /**
- * Handles media button events
- */
- private void handleKeycode(int keycode) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Handling keycode: " + keycode);
-
- final PlaybackServiceMediaPlayer.PSMPInfo info = mediaPlayer.getPSMPInfo();
- final PlayerStatus status = info.playerStatus;
- switch (keycode) {
- case KeyEvent.KEYCODE_HEADSETHOOK:
- case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
- if (status == PlayerStatus.PLAYING) {
- mediaPlayer.pause(true, true);
- } else if (status == PlayerStatus.PAUSED || status == PlayerStatus.PREPARED) {
- mediaPlayer.resume();
- } else if (status == PlayerStatus.PREPARING) {
- mediaPlayer.setStartWhenPrepared(!mediaPlayer.isStartWhenPrepared());
- } else if (status == PlayerStatus.INITIALIZED) {
- mediaPlayer.setStartWhenPrepared(true);
- mediaPlayer.prepare();
- }
- break;
- case KeyEvent.KEYCODE_MEDIA_PLAY:
- if (status == PlayerStatus.PAUSED || status == PlayerStatus.PREPARED) {
- mediaPlayer.resume();
- } else if (status == PlayerStatus.INITIALIZED) {
- mediaPlayer.setStartWhenPrepared(true);
- mediaPlayer.prepare();
- }
- break;
- case KeyEvent.KEYCODE_MEDIA_PAUSE:
- if (status == PlayerStatus.PLAYING) {
- mediaPlayer.pause(true, true);
- }
- break;
- case KeyEvent.KEYCODE_MEDIA_NEXT:
- case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
- mediaPlayer.seekDelta(UserPreferences.getSeekDeltaMs());
- break;
- case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
- case KeyEvent.KEYCODE_MEDIA_REWIND:
- mediaPlayer.seekDelta(-UserPreferences.getSeekDeltaMs());
- break;
- default:
- if (info.playable != null && info.playerStatus == PlayerStatus.PLAYING) { // only notify the user about an unknown key event if it is actually doing something
- String message = String.format(getResources().getString(R.string.unknown_media_key), keycode);
- Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
- }
- break;
- }
- }
-
- /**
- * Called by a mediaplayer Activity as soon as it has prepared its
- * mediaplayer.
- */
- public void setVideoSurface(SurfaceHolder sh) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Setting display");
- mediaPlayer.setVideoSurface(sh);
- }
-
- /**
- * Called when the surface holder of the mediaplayer has to be changed.
- */
- private void resetVideoSurface() {
- taskManager.cancelPositionSaver();
- mediaPlayer.resetVideoSurface();
- }
-
- public void notifyVideoSurfaceAbandoned() {
- stopForeground(true);
- mediaPlayer.resetVideoSurface();
- }
-
- private final PlaybackServiceTaskManager.PSTMCallback taskManagerCallback = new PlaybackServiceTaskManager.PSTMCallback() {
- @Override
- public void positionSaverTick() {
- saveCurrentPosition(true, PlaybackServiceTaskManager.POSITION_SAVER_WAITING_INTERVAL);
- }
-
- @Override
- public void onSleepTimerExpired() {
- mediaPlayer.pause(true, true);
- sendNotificationBroadcast(NOTIFICATION_TYPE_SLEEPTIMER_UPDATE, 0);
- }
-
-
- @Override
- public void onWidgetUpdaterTick() {
- updateWidget();
- }
-
- @Override
- public void onChapterLoaded(Playable media) {
- sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD, 0);
- }
- };
-
- private final PlaybackServiceMediaPlayer.PSMPCallback mediaPlayerCallback = new PlaybackServiceMediaPlayer.PSMPCallback() {
- @Override
- public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
- currentMediaType = mediaPlayer.getCurrentMediaType();
- switch (newInfo.playerStatus) {
- case INITIALIZED:
- writePlaybackPreferences();
- break;
-
- case PREPARED:
- taskManager.startChapterLoader(newInfo.playable);
- break;
-
- case PAUSED:
- taskManager.cancelPositionSaver();
- saveCurrentPosition(false, 0);
- taskManager.cancelWidgetUpdater();
- stopForeground(true);
- break;
-
- case STOPPED:
- //setCurrentlyPlayingMedia(PlaybackPreferences.NO_MEDIA_PLAYING);
- //stopSelf();
- break;
-
- case PLAYING:
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Audiofocus successfully requested");
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Resuming/Starting playback");
-
- taskManager.startPositionSaver();
- taskManager.startWidgetUpdater();
- setupNotification(newInfo);
- break;
- case ERROR:
- writePlaybackPreferencesNoMediaPlaying();
- break;
-
- }
-
- sendBroadcast(new Intent(ACTION_PLAYER_STATUS_CHANGED));
- updateWidget();
- refreshRemoteControlClientState(newInfo);
- bluetoothNotifyChange(newInfo, AVRCP_ACTION_PLAYER_STATUS_CHANGED);
- bluetoothNotifyChange(newInfo, AVRCP_ACTION_META_CHANGED);
- }
-
- @Override
- public void shouldStop() {
- stopSelf();
- }
-
- @Override
- public void playbackSpeedChanged(float s) {
- sendNotificationBroadcast(
- NOTIFICATION_TYPE_PLAYBACK_SPEED_CHANGE, 0);
- }
-
- @Override
- public void onBufferingUpdate(int percent) {
- sendNotificationBroadcast(NOTIFICATION_TYPE_BUFFER_UPDATE, percent);
- }
-
- @Override
- public boolean onMediaPlayerInfo(int code) {
- switch (code) {
- case MediaPlayer.MEDIA_INFO_BUFFERING_START:
- sendNotificationBroadcast(NOTIFICATION_TYPE_BUFFER_START, 0);
- return true;
- case MediaPlayer.MEDIA_INFO_BUFFERING_END:
- sendNotificationBroadcast(NOTIFICATION_TYPE_BUFFER_END, 0);
- return true;
- default:
- return false;
- }
- }
-
- @Override
- public boolean onMediaPlayerError(Object inObj, int what, int extra) {
- final String TAG = "PlaybackService.onErrorListener";
- Log.w(TAG, "An error has occured: " + what + " " + extra);
- if (mediaPlayer.getPSMPInfo().playerStatus == PlayerStatus.PLAYING) {
- mediaPlayer.pause(true, false);
- }
- sendNotificationBroadcast(NOTIFICATION_TYPE_ERROR, what);
- writePlaybackPreferencesNoMediaPlaying();
- stopSelf();
- return true;
- }
-
- @Override
- public boolean endPlayback(boolean playNextEpisode) {
- PlaybackService.this.endPlayback(true);
- return true;
- }
-
- @Override
- public RemoteControlClient getRemoteControlClient() {
- return remoteControlClient;
- }
- };
-
- private void endPlayback(boolean playNextEpisode) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Playback ended");
-
- final Playable media = mediaPlayer.getPSMPInfo().playable;
- if (media == null) {
- Log.e(TAG, "Cannot end playback: media was null");
- return;
- }
-
- taskManager.cancelPositionSaver();
-
- boolean isInQueue = false;
- FeedItem nextItem = null;
-
- if (media instanceof FeedMedia) {
- FeedItem item = ((FeedMedia) media).getItem();
- DBWriter.markItemRead(PlaybackService.this, item, true, true);
-
- try {
- final List<FeedItem> queue = taskManager.getQueue();
- isInQueue = QueueAccess.ItemListAccess(queue).contains(((FeedMedia) media).getItem().getId());
- nextItem = DBTasks.getQueueSuccessorOfItem(this, item.getId(), queue);
- } catch (InterruptedException e) {
- e.printStackTrace();
- // isInQueue remains false
- }
- if (isInQueue) {
- DBWriter.removeQueueItem(PlaybackService.this, item.getId(), true);
- }
- DBWriter.addItemToPlaybackHistory(PlaybackService.this, (FeedMedia) media);
-
- // auto-flattr if enabled
- if (isAutoFlattrable(media) && UserPreferences.getAutoFlattrPlayedDurationThreshold() == 1.0f) {
- DBTasks.flattrItemIfLoggedIn(PlaybackService.this, item);
- }
- }
-
- // 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
- Playable nextMedia = null;
- boolean loadNextItem = isInQueue && nextItem != null;
- playNextEpisode = playNextEpisode && loadNextItem
- && UserPreferences.isFollowQueue();
- if (loadNextItem) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Loading next item in queue");
- nextMedia = nextItem.getMedia();
- }
- final boolean prepareImmediately;
- final boolean startWhenPrepared;
- final boolean stream;
-
- if (playNextEpisode) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Playback of next episode will start immediately.");
- prepareImmediately = startWhenPrepared = true;
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "No more episodes available to play");
-
- prepareImmediately = startWhenPrepared = false;
- stopForeground(true);
- stopWidgetUpdater();
- }
-
- writePlaybackPreferencesNoMediaPlaying();
- if (nextMedia != null) {
- stream = !media.localFileAvailable();
- mediaPlayer.playMediaObject(nextMedia, stream, startWhenPrepared, prepareImmediately);
- sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD,
- (nextMedia.getMediaType() == MediaType.VIDEO) ? EXTRA_CODE_VIDEO : EXTRA_CODE_AUDIO);
- } else {
- sendNotificationBroadcast(NOTIFICATION_TYPE_PLAYBACK_END, 0);
- mediaPlayer.stop();
- //stopSelf();
- }
- }
-
- public void setSleepTimer(long waitingTime) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Setting sleep timer to " + Long.toString(waitingTime)
- + " milliseconds");
- taskManager.setSleepTimer(waitingTime);
- sendNotificationBroadcast(NOTIFICATION_TYPE_SLEEPTIMER_UPDATE, 0);
- }
-
- public void disableSleepTimer() {
- taskManager.disableSleepTimer();
- sendNotificationBroadcast(NOTIFICATION_TYPE_SLEEPTIMER_UPDATE, 0);
- }
-
- private void writePlaybackPreferencesNoMediaPlaying() {
- SharedPreferences.Editor editor = PreferenceManager
- .getDefaultSharedPreferences(getApplicationContext()).edit();
- 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 writePlaybackPreferences() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Writing playback preferences");
-
- SharedPreferences.Editor editor = PreferenceManager
- .getDefaultSharedPreferences(getApplicationContext()).edit();
- PlaybackServiceMediaPlayer.PSMPInfo info = mediaPlayer.getPSMPInfo();
- MediaType mediaType = mediaPlayer.getCurrentMediaType();
- boolean stream = mediaPlayer.isStreaming();
-
- if (info.playable != null) {
- editor.putLong(PlaybackPreferences.PREF_CURRENTLY_PLAYING_MEDIA,
- info.playable.getPlayableType());
- editor.putBoolean(
- PlaybackPreferences.PREF_CURRENT_EPISODE_IS_STREAM,
- stream);
- editor.putBoolean(
- PlaybackPreferences.PREF_CURRENT_EPISODE_IS_VIDEO,
- mediaType == MediaType.VIDEO);
- if (info.playable instanceof FeedMedia) {
- FeedMedia fMedia = (FeedMedia) info.playable;
- 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);
- }
- info.playable.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();
- }
-
- /**
- * Send ACTION_PLAYER_STATUS_CHANGED without changing the status attribute.
- */
- private void postStatusUpdateIntent() {
- sendBroadcast(new Intent(ACTION_PLAYER_STATUS_CHANGED));
- }
-
- private void sendNotificationBroadcast(int type, int code) {
- Intent intent = new Intent(ACTION_PLAYER_NOTIFICATION);
- intent.putExtra(EXTRA_NOTIFICATION_TYPE, type);
- intent.putExtra(EXTRA_NOTIFICATION_CODE, code);
- sendBroadcast(intent);
- }
-
- /**
- * Used by setupNotification to load notification data in another thread.
- */
- private AsyncTask<Void, Void, Void> notificationSetupTask;
-
- /**
- * Prepares notification and starts the service in the foreground.
- */
- @SuppressLint("NewApi")
- private void setupNotification(final PlaybackServiceMediaPlayer.PSMPInfo info) {
- final PendingIntent pIntent = PendingIntent.getActivity(this, 0,
- PlaybackService.getPlayerActivityIntent(this),
- PendingIntent.FLAG_UPDATE_CURRENT);
-
- if (notificationSetupTask != null) {
- notificationSetupTask.cancel(true);
- }
- notificationSetupTask = new AsyncTask<Void, Void, Void>() {
- Bitmap icon = null;
-
- @Override
- protected Void doInBackground(Void... params) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Starting background work");
- if (android.os.Build.VERSION.SDK_INT >= 11) {
- if (info.playable != null) {
- try {
- int iconSize = getResources().getDimensionPixelSize(
- android.R.dimen.notification_large_icon_width);
- icon = PicassoProvider.getMediaMetadataPicassoInstance(PlaybackService.this)
- .load(info.playable.getImageUri())
- .resize(iconSize, iconSize)
- .get();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- }
- if (icon == null) {
- icon = BitmapFactory.decodeResource(getResources(),
- R.drawable.ic_stat_antenna);
- }
-
- return null;
- }
-
- @Override
- protected void onPostExecute(Void result) {
- super.onPostExecute(result);
- if (!isCancelled() && info.playerStatus == PlayerStatus.PLAYING
- && info.playable != null) {
- String contentText = info.playable.getFeedTitle();
- String contentTitle = info.playable.getEpisodeTitle();
- Notification notification = null;
- if (android.os.Build.VERSION.SDK_INT >= 16) {
- Intent pauseButtonIntent = new Intent(
- PlaybackService.this, PlaybackService.class);
- pauseButtonIntent.putExtra(
- MediaButtonReceiver.EXTRA_KEYCODE,
- KeyEvent.KEYCODE_MEDIA_PAUSE);
- PendingIntent pauseButtonPendingIntent = PendingIntent
- .getService(PlaybackService.this, 0,
- pauseButtonIntent,
- PendingIntent.FLAG_UPDATE_CURRENT);
- Notification.Builder notificationBuilder = new Notification.Builder(
- PlaybackService.this)
- .setContentTitle(contentTitle)
- .setContentText(contentText)
- .setOngoing(true)
- .setContentIntent(pIntent)
- .setLargeIcon(icon)
- .setSmallIcon(R.drawable.ic_stat_antenna)
- .addAction(android.R.drawable.ic_media_pause,
- getString(R.string.pause_label),
- pauseButtonPendingIntent);
- notification = notificationBuilder.build();
- } else {
- NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(
- PlaybackService.this)
- .setContentTitle(contentTitle)
- .setContentText(contentText).setOngoing(true)
- .setContentIntent(pIntent).setLargeIcon(icon)
- .setSmallIcon(R.drawable.ic_stat_antenna);
- notification = notificationBuilder.getNotification();
- }
- startForeground(NOTIFICATION_ID, notification);
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Notification set up");
- }
- }
-
- };
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- notificationSetupTask
- .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- } else {
- notificationSetupTask.execute();
- }
-
- }
-
- /**
- * Saves the current position of the media file to the DB
- *
- * @param updatePlayedDuration true if played_duration should be updated. This applies only to FeedMedia objects
- * @param deltaPlayedDuration value by which played_duration should be increased.
- */
- private synchronized void saveCurrentPosition(boolean updatePlayedDuration, int deltaPlayedDuration) {
- int position = getCurrentPosition();
- int duration = getDuration();
- float playbackSpeed = getCurrentPlaybackSpeed();
- final Playable playable = mediaPlayer.getPSMPInfo().playable;
- if (position != INVALID_TIME && duration != INVALID_TIME && playable != null) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Saving current position to " + position);
- if (updatePlayedDuration && playable instanceof FeedMedia) {
- FeedMedia m = (FeedMedia) playable;
- FeedItem item = m.getItem();
- m.setPlayedDuration(m.getPlayedDuration() + ((int) (deltaPlayedDuration * playbackSpeed)));
- // Auto flattr
- if (isAutoFlattrable(m) &&
- (m.getPlayedDuration() > UserPreferences.getAutoFlattrPlayedDurationThreshold() * duration)) {
-
- if (BuildConfig.DEBUG)
- Log.d(TAG, "saveCurrentPosition: performing auto flattr since played duration " + Integer.toString(m.getPlayedDuration())
- + " is " + UserPreferences.getAutoFlattrPlayedDurationThreshold() * 100 + "% of file duration " + Integer.toString(duration));
- DBTasks.flattrItemIfLoggedIn(this, item);
- }
- }
- playable.saveCurrentPosition(PreferenceManager
- .getDefaultSharedPreferences(getApplicationContext()),
- position
- );
- }
- }
-
- private void stopWidgetUpdater() {
- taskManager.cancelWidgetUpdater();
- sendBroadcast(new Intent(PlayerWidget.STOP_WIDGET_UPDATE));
- }
-
- private void updateWidget() {
- PlaybackService.this.sendBroadcast(new Intent(
- PlayerWidget.FORCE_WIDGET_UPDATE));
- }
-
- public boolean sleepTimerActive() {
- return taskManager.isSleepTimerActive();
- }
-
- public long getSleepTimerTimeLeft() {
- return taskManager.getSleepTimerTimeLeft();
- }
-
- @SuppressLint("NewApi")
- private RemoteControlClient setupRemoteControlClient() {
- if (Build.VERSION.SDK_INT < 14) {
- return null;
- }
-
- Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
- mediaButtonIntent.setComponent(new ComponentName(getPackageName(),
- MediaButtonReceiver.class.getName()));
- PendingIntent mediaPendingIntent = PendingIntent.getBroadcast(
- getApplicationContext(), 0, mediaButtonIntent, 0);
- remoteControlClient = new RemoteControlClient(mediaPendingIntent);
- int controlFlags;
- if (android.os.Build.VERSION.SDK_INT < 16) {
- controlFlags = RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE
- | RemoteControlClient.FLAG_KEY_MEDIA_NEXT;
- } else {
- controlFlags = RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE;
- }
- remoteControlClient.setTransportControlFlags(controlFlags);
- return remoteControlClient;
- }
-
- /**
- * Refresh player status and metadata.
- */
- @SuppressLint("NewApi")
- private void refreshRemoteControlClientState(PlaybackServiceMediaPlayer.PSMPInfo info) {
- if (android.os.Build.VERSION.SDK_INT >= 14) {
- if (remoteControlClient != null) {
- switch (info.playerStatus) {
- case PLAYING:
- remoteControlClient
- .setPlaybackState(RemoteControlClient.PLAYSTATE_PLAYING);
- break;
- case PAUSED:
- case INITIALIZED:
- remoteControlClient
- .setPlaybackState(RemoteControlClient.PLAYSTATE_PAUSED);
- break;
- case STOPPED:
- remoteControlClient
- .setPlaybackState(RemoteControlClient.PLAYSTATE_STOPPED);
- break;
- case ERROR:
- remoteControlClient
- .setPlaybackState(RemoteControlClient.PLAYSTATE_ERROR);
- break;
- default:
- remoteControlClient
- .setPlaybackState(RemoteControlClient.PLAYSTATE_BUFFERING);
- }
- if (info.playable != null) {
- MetadataEditor editor = remoteControlClient
- .editMetadata(false);
- editor.putString(MediaMetadataRetriever.METADATA_KEY_TITLE,
- info.playable.getEpisodeTitle());
-
- editor.putString(MediaMetadataRetriever.METADATA_KEY_ALBUM,
- info.playable.getFeedTitle());
-
- editor.apply();
- }
- if (BuildConfig.DEBUG)
- Log.d(TAG, "RemoteControlClient state was refreshed");
- }
- }
- }
-
- private void bluetoothNotifyChange(PlaybackServiceMediaPlayer.PSMPInfo info, String whatChanged) {
- boolean isPlaying = false;
-
- if (info.playerStatus == PlayerStatus.PLAYING) {
- isPlaying = true;
- }
-
- if (info.playable != null) {
- Intent i = new Intent(whatChanged);
- i.putExtra("id", 1);
- i.putExtra("artist", "");
- i.putExtra("album", info.playable.getFeedTitle());
- i.putExtra("track", info.playable.getEpisodeTitle());
- i.putExtra("playing", isPlaying);
- final List<FeedItem> queue = taskManager.getQueueIfLoaded();
- if (queue != null) {
- i.putExtra("ListSize", queue.size());
- }
- i.putExtra("duration", info.playable.getDuration());
- i.putExtra("position", info.playable.getPosition());
- sendBroadcast(i);
- }
- }
-
- /**
- * Pauses playback when the headset is disconnected and the preference is
- * set
- */
- private BroadcastReceiver headsetDisconnected = new BroadcastReceiver() {
- private static final String TAG = "headsetDisconnected";
- private static final int UNPLUGGED = 0;
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (StringUtils.equals(intent.getAction(), Intent.ACTION_HEADSET_PLUG)) {
- int state = intent.getIntExtra("state", -1);
- if (state != -1) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Headset plug event. State is " + state);
- if (state == UNPLUGGED) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Headset was unplugged during playback.");
- pauseIfPauseOnDisconnect();
- }
- } else {
- Log.e(TAG, "Received invalid ACTION_HEADSET_PLUG intent");
- }
- }
- }
- };
-
- private BroadcastReceiver audioBecomingNoisy = new BroadcastReceiver() {
-
- @Override
- public void onReceive(Context context, Intent intent) {
- // sound is about to change, eg. bluetooth -> speaker
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Pausing playback because audio is becoming noisy");
- pauseIfPauseOnDisconnect();
- }
- // android.media.AUDIO_BECOMING_NOISY
- };
-
- /**
- * Pauses playback if PREF_PAUSE_ON_HEADSET_DISCONNECT was set to true.
- */
- private void pauseIfPauseOnDisconnect() {
- if (UserPreferences.isPauseOnHeadsetDisconnect()) {
- mediaPlayer.pause(true, true);
- }
- }
-
- private BroadcastReceiver shutdownReceiver = new BroadcastReceiver() {
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (StringUtils.equals(intent.getAction(), ACTION_SHUTDOWN_PLAYBACK_SERVICE)) {
- stopSelf();
- }
- }
-
- };
-
- private BroadcastReceiver skipCurrentEpisodeReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (StringUtils.equals(intent.getAction(), ACTION_SKIP_CURRENT_EPISODE)) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Received SKIP_CURRENT_EPISODE intent");
- mediaPlayer.endPlayback();
- }
- }
- };
-
- public static MediaType getCurrentMediaType() {
- return currentMediaType;
- }
-
- public void resume() {
- mediaPlayer.resume();
- }
-
- public void prepare() {
- mediaPlayer.prepare();
- }
-
- public void pause(boolean abandonAudioFocus, boolean reinit) {
- mediaPlayer.pause(abandonAudioFocus, reinit);
- }
-
- public void reinit() {
- mediaPlayer.reinit();
- }
-
- public PlaybackServiceMediaPlayer.PSMPInfo getPSMPInfo() {
- return mediaPlayer.getPSMPInfo();
- }
-
- public PlayerStatus getStatus() {
- return mediaPlayer.getPSMPInfo().playerStatus;
- }
-
- public Playable getPlayable() {
- return mediaPlayer.getPSMPInfo().playable;
- }
-
- public void setSpeed(float speed) {
- mediaPlayer.setSpeed(speed);
- }
-
- public boolean canSetSpeed() {
- return mediaPlayer.canSetSpeed();
- }
-
- public float getCurrentPlaybackSpeed() {
- return mediaPlayer.getPlaybackSpeed();
- }
-
- public boolean isStartWhenPrepared() {
- return mediaPlayer.isStartWhenPrepared();
- }
-
- public void setStartWhenPrepared(boolean s) {
- mediaPlayer.setStartWhenPrepared(s);
- }
-
-
- public void seekTo(final int t) {
- mediaPlayer.seekTo(t);
- }
-
-
- public void seekDelta(final int d) {
- mediaPlayer.seekDelta(d);
- }
-
- /**
- * @see de.danoeh.antennapod.service.playback.PlaybackServiceMediaPlayer#seekToChapter(de.danoeh.antennapod.feed.Chapter)
- */
- public void seekToChapter(Chapter c) {
- mediaPlayer.seekToChapter(c);
- }
-
- /**
- * call getDuration() on mediaplayer or return INVALID_TIME if player is in
- * an invalid state.
- */
- public int getDuration() {
- return mediaPlayer.getDuration();
- }
-
- /**
- * call getCurrentPosition() on mediaplayer or return INVALID_TIME if player
- * is in an invalid state.
- */
- public int getCurrentPosition() {
- return mediaPlayer.getPosition();
- }
-
- public boolean isStreaming() {
- return mediaPlayer.isStreaming();
- }
-
- public Pair<Integer, Integer> getVideoSize() {
- return mediaPlayer.getVideoSize();
- }
-
- private boolean isAutoFlattrable(Playable p) {
- if (p != null && p instanceof FeedMedia) {
- FeedMedia media = (FeedMedia) p;
- FeedItem item = ((FeedMedia) p).getItem();
- return item != null && FlattrUtils.hasToken() && UserPreferences.isAutoFlattr() && item.getPaymentLink() != null && item.getFlattrStatus().getUnflattred();
- } else {
- return false;
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/service/playback/PlaybackServiceMediaPlayer.java b/src/de/danoeh/antennapod/service/playback/PlaybackServiceMediaPlayer.java
deleted file mode 100644
index 49f20012d..000000000
--- a/src/de/danoeh/antennapod/service/playback/PlaybackServiceMediaPlayer.java
+++ /dev/null
@@ -1,979 +0,0 @@
-package de.danoeh.antennapod.service.playback;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.media.AudioManager;
-import android.media.RemoteControlClient;
-import android.net.wifi.WifiManager;
-import android.os.PowerManager;
-import android.telephony.TelephonyManager;
-import android.util.Log;
-import android.util.Pair;
-import android.view.SurfaceHolder;
-
-import org.apache.commons.lang3.Validate;
-
-import java.io.IOException;
-import java.util.concurrent.LinkedBlockingDeque;
-import java.util.concurrent.RejectedExecutionHandler;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.locks.ReentrantLock;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.feed.Chapter;
-import de.danoeh.antennapod.feed.MediaType;
-import de.danoeh.antennapod.preferences.UserPreferences;
-import de.danoeh.antennapod.receiver.MediaButtonReceiver;
-import de.danoeh.antennapod.util.playback.AudioPlayer;
-import de.danoeh.antennapod.util.playback.IPlayer;
-import de.danoeh.antennapod.util.playback.Playable;
-import de.danoeh.antennapod.util.playback.VideoPlayer;
-
-/**
- * Manages the MediaPlayer object of the PlaybackService.
- */
-public class PlaybackServiceMediaPlayer {
- public static final String TAG = "PlaybackServiceMediaPlayer";
-
- /**
- * Return value of some PSMP methods if the method call failed.
- */
- public static final int INVALID_TIME = -1;
-
- private final AudioManager audioManager;
-
- private volatile PlayerStatus playerStatus;
- private volatile PlayerStatus statusBeforeSeeking;
- private volatile IPlayer mediaPlayer;
- private volatile Playable media;
-
- private volatile boolean stream;
- private volatile MediaType mediaType;
- private volatile AtomicBoolean startWhenPrepared;
- private volatile boolean pausedBecauseOfTransientAudiofocusLoss;
- private volatile Pair<Integer, Integer> videoSize;
-
- /**
- * Some asynchronous calls might change the state of the MediaPlayer object. Therefore calls in other threads
- * have to wait until these operations have finished.
- */
- private final ReentrantLock playerLock;
-
- private final PSMPCallback callback;
- private final Context context;
-
- private final ThreadPoolExecutor executor;
-
- /**
- * A wifi-lock that is acquired if the media file is being streamed.
- */
- private WifiManager.WifiLock wifiLock;
-
- public PlaybackServiceMediaPlayer(Context context, PSMPCallback callback) {
- Validate.notNull(context);
- Validate.notNull(callback);
-
- this.context = context;
- this.callback = callback;
- this.audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
- this.playerLock = new ReentrantLock();
- this.startWhenPrepared = new AtomicBoolean(false);
- executor = new ThreadPoolExecutor(1, 1, 5, TimeUnit.MINUTES, new LinkedBlockingDeque<Runnable>(),
- new RejectedExecutionHandler() {
- @Override
- public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Rejected execution of runnable");
- }
- }
- );
-
- mediaPlayer = null;
- statusBeforeSeeking = null;
- pausedBecauseOfTransientAudiofocusLoss = false;
- mediaType = MediaType.UNKNOWN;
- playerStatus = PlayerStatus.STOPPED;
- videoSize = null;
- }
-
- /**
- * Starts or prepares playback of the specified Playable object. If another Playable object is already being played, the currently playing
- * episode will be stopped and replaced with the new Playable object. If the Playable object is already being played, the method will
- * not do anything.
- * Whether playback starts immediately depends on the given parameters. See below for more details.
- * <p/>
- * States:
- * During execution of the method, the object will be in the INITIALIZING state. The end state depends on the given parameters.
- * <p/>
- * If 'prepareImmediately' is set to true, the method will go into PREPARING state and after that into PREPARED state. If
- * 'startWhenPrepared' is set to true, the method will additionally go into PLAYING state.
- * <p/>
- * If an unexpected error occurs while loading the Playable's metadata or while setting the MediaPlayers data source, the object
- * will enter the ERROR state.
- * <p/>
- * This method is executed on an internal executor service.
- *
- * @param playable The Playable object that is supposed to be played. This parameter must not be null.
- * @param stream The type of playback. If false, the Playable object MUST provide access to a locally available file via
- * getLocalMediaUrl. If true, the Playable object MUST provide access to a resource that can be streamed by
- * the Android MediaPlayer via getStreamUrl.
- * @param startWhenPrepared Sets the 'startWhenPrepared' flag. This flag determines whether playback will start immediately after the
- * episode has been prepared for playback. Setting this flag to true does NOT mean that the episode will be prepared
- * for playback immediately (see 'prepareImmediately' parameter for more details)
- * @param prepareImmediately Set to true if the method should also prepare the episode for playback.
- */
- public void playMediaObject(final Playable playable, final boolean stream, final boolean startWhenPrepared, final boolean prepareImmediately) {
- Validate.notNull(playable);
-
- if (BuildConfig.DEBUG) Log.d(TAG, "Play media object.");
- executor.submit(new Runnable() {
- @Override
- public void run() {
- playerLock.lock();
- try {
- playMediaObject(playable, false, stream, startWhenPrepared, prepareImmediately);
- } catch (RuntimeException e) {
- e.printStackTrace();
- throw e;
- } finally {
- playerLock.unlock();
- }
- }
- });
- }
-
- /**
- * Internal implementation of playMediaObject. This method has an additional parameter that allows the caller to force a media player reset even if
- * the given playable parameter is the same object as the currently playing media.
- * <p/>
- * This method requires the playerLock and is executed on the caller's thread.
- *
- * @see #playMediaObject(de.danoeh.antennapod.util.playback.Playable, boolean, boolean, boolean)
- */
- private void playMediaObject(final Playable playable, final boolean forceReset, final boolean stream, final boolean startWhenPrepared, final boolean prepareImmediately) {
- Validate.notNull(playable);
- if (!playerLock.isHeldByCurrentThread())
- throw new IllegalStateException("method requires playerLock");
-
-
- if (media != null) {
- if (!forceReset && media.getIdentifier().equals(playable.getIdentifier())) {
- // episode is already playing -> ignore method call
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Method call to playMediaObject was ignored: media file already playing.");
- return;
- } else {
- // stop playback of this episode
- if (playerStatus == PlayerStatus.PAUSED || playerStatus == PlayerStatus.PLAYING || playerStatus == PlayerStatus.PREPARED) {
- mediaPlayer.stop();
- }
- setPlayerStatus(PlayerStatus.INDETERMINATE, null);
- }
- }
-
- this.media = playable;
- this.stream = stream;
- this.mediaType = media.getMediaType();
- this.videoSize = null;
- createMediaPlayer();
- PlaybackServiceMediaPlayer.this.startWhenPrepared.set(startWhenPrepared);
- setPlayerStatus(PlayerStatus.INITIALIZING, media);
- try {
- media.loadMetadata();
- if (stream) {
- mediaPlayer.setDataSource(media.getStreamUrl());
- } else {
- mediaPlayer.setDataSource(media.getLocalMediaUrl());
- }
- setPlayerStatus(PlayerStatus.INITIALIZED, media);
-
- if (mediaType == MediaType.VIDEO) {
- VideoPlayer vp = (VideoPlayer) mediaPlayer;
- // vp.setVideoScalingMode(MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT);
- }
-
- if (prepareImmediately) {
- setPlayerStatus(PlayerStatus.PREPARING, media);
- mediaPlayer.prepare();
- onPrepared(startWhenPrepared);
- }
-
- } catch (Playable.PlayableException e) {
- e.printStackTrace();
- setPlayerStatus(PlayerStatus.ERROR, null);
- } catch (IOException e) {
- e.printStackTrace();
- setPlayerStatus(PlayerStatus.ERROR, null);
- } catch (IllegalStateException e) {
- e.printStackTrace();
- setPlayerStatus(PlayerStatus.ERROR, null);
- }
- }
-
-
- /**
- * Resumes playback if the PSMP object is in PREPARED or PAUSED state. If the PSMP object is in an invalid state.
- * nothing will happen.
- * <p/>
- * This method is executed on an internal executor service.
- */
- public void resume() {
- executor.submit(new Runnable() {
- @Override
- public void run() {
- playerLock.lock();
- resumeSync();
- playerLock.unlock();
- }
- });
- }
-
- private void resumeSync() {
- if (playerStatus == PlayerStatus.PAUSED || playerStatus == PlayerStatus.PREPARED) {
- int focusGained = audioManager.requestAudioFocus(
- audioFocusChangeListener, AudioManager.STREAM_MUSIC,
- AudioManager.AUDIOFOCUS_GAIN);
- if (focusGained == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
- acquireWifiLockIfNecessary();
- setSpeed(Float.parseFloat(UserPreferences.getPlaybackSpeed()));
- mediaPlayer.start();
- if (playerStatus == PlayerStatus.PREPARED && media.getPosition() > 0) {
- mediaPlayer.seekTo(media.getPosition());
- }
-
- setPlayerStatus(PlayerStatus.PLAYING, media);
- pausedBecauseOfTransientAudiofocusLoss = false;
- if (android.os.Build.VERSION.SDK_INT >= 14) {
- RemoteControlClient remoteControlClient = callback.getRemoteControlClient();
- if (remoteControlClient != null) {
- audioManager
- .registerRemoteControlClient(remoteControlClient);
- }
- }
- audioManager
- .registerMediaButtonEventReceiver(new ComponentName(context.getPackageName(),
- MediaButtonReceiver.class.getName()));
- media.onPlaybackStart();
-
- } else {
- if (BuildConfig.DEBUG) Log.e(TAG, "Failed to request audio focus");
- }
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Call to resume() was ignored because current state of PSMP object is " + playerStatus);
- }
- }
-
-
- /**
- * Saves the current position and pauses playback. Note that, if audiofocus
- * is abandoned, the lockscreen controls will also disapear.
- * <p/>
- * This method is executed on an internal executor service.
- *
- * @param abandonFocus is true if the service should release audio focus
- * @param reinit is true if service should reinit after pausing if the media
- * file is being streamed
- */
- public void pause(final boolean abandonFocus, final boolean reinit) {
- executor.submit(new Runnable() {
- @Override
- public void run() {
- playerLock.lock();
- releaseWifiLockIfNecessary();
- if (playerStatus == PlayerStatus.PLAYING) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Pausing playback.");
- mediaPlayer.pause();
- setPlayerStatus(PlayerStatus.PAUSED, media);
-
- if (abandonFocus) {
- audioManager.abandonAudioFocus(audioFocusChangeListener);
- pausedBecauseOfTransientAudiofocusLoss = false;
- }
- if (stream && reinit) {
- reinit();
- }
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Ignoring call to pause: Player is in " + playerStatus + " state");
- }
-
- playerLock.unlock();
- }
- });
- }
-
- /**
- * Prepared media player for playback if the service is in the INITALIZED
- * state.
- * <p/>
- * This method is executed on an internal executor service.
- */
- public void prepare() {
- executor.submit(new Runnable() {
- @Override
- public void run() {
- playerLock.lock();
-
- if (playerStatus == PlayerStatus.INITIALIZED) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Preparing media player");
- setPlayerStatus(PlayerStatus.PREPARING, media);
- try {
- mediaPlayer.prepare();
- onPrepared(startWhenPrepared.get());
- } catch (IOException e) {
- e.printStackTrace();
- setPlayerStatus(PlayerStatus.ERROR, null);
- }
- }
- playerLock.unlock();
-
- }
- });
- }
-
- /**
- * Called after media player has been prepared. This method is executed on the caller's thread.
- */
- void onPrepared(final boolean startWhenPrepared) {
- playerLock.lock();
-
- if (playerStatus != PlayerStatus.PREPARING) {
- playerLock.unlock();
- throw new IllegalStateException("Player is not in PREPARING state");
- }
-
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Resource prepared");
-
- if (mediaType == MediaType.VIDEO) {
- VideoPlayer vp = (VideoPlayer) mediaPlayer;
- videoSize = new Pair<Integer, Integer>(vp.getVideoWidth(), vp.getVideoHeight());
- }
-
- if (media.getPosition() > 0) {
- mediaPlayer.seekTo(media.getPosition());
- }
-
- if (media.getDuration() == 0) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Setting duration of media");
- media.setDuration(mediaPlayer.getDuration());
- }
- setPlayerStatus(PlayerStatus.PREPARED, media);
-
- if (startWhenPrepared) {
- resumeSync();
- }
-
- playerLock.unlock();
- }
-
- /**
- * Resets the media player and moves it into INITIALIZED state.
- * <p/>
- * This method is executed on an internal executor service.
- */
- public void reinit() {
- executor.submit(new Runnable() {
- @Override
- public void run() {
- playerLock.lock();
- releaseWifiLockIfNecessary();
- if (media != null) {
- playMediaObject(media, true, stream, startWhenPrepared.get(), false);
- } else if (mediaPlayer != null) {
- mediaPlayer.reset();
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Call to reinit was ignored: media and mediaPlayer were null");
- }
- playerLock.unlock();
- }
- });
- }
-
-
- /**
- * Seeks to the specified position. If the PSMP object is in an invalid state, this method will do nothing.
- *
- * @param t The position to seek to in milliseconds. t < 0 will be interpreted as t = 0
- * <p/>
- * This method is executed on the caller's thread.
- */
- private void seekToSync(int t) {
- if (t < 0) {
- t = 0;
- }
- playerLock.lock();
-
- if (playerStatus == PlayerStatus.PLAYING
- || playerStatus == PlayerStatus.PAUSED
- || playerStatus == PlayerStatus.PREPARED) {
- if (stream) {
- // statusBeforeSeeking = playerStatus;
- // setPlayerStatus(PlayerStatus.SEEKING, media);
- }
- mediaPlayer.seekTo(t);
-
- } else if (playerStatus == PlayerStatus.INITIALIZED) {
- media.setPosition(t);
- startWhenPrepared.set(true);
- prepare();
- }
- playerLock.unlock();
- }
-
- /**
- * Seeks to the specified position. If the PSMP object is in an invalid state, this method will do nothing.
- * Invalid time values (< 0) will be ignored.
- * <p/>
- * This method is executed on an internal executor service.
- */
- public void seekTo(final int t) {
- executor.submit(new Runnable() {
- @Override
- public void run() {
- seekToSync(t);
- }
- });
- }
-
- /**
- * Seek a specific position from the current position
- *
- * @param d offset from current position (positive or negative)
- */
- public void seekDelta(final int d) {
- executor.submit(new Runnable() {
- @Override
- public void run() {
- playerLock.lock();
- int currentPosition = getPosition();
- if (currentPosition != INVALID_TIME) {
- seekToSync(currentPosition + d);
- } else {
- Log.e(TAG, "getPosition() returned INVALID_TIME in seekDelta");
- }
-
- playerLock.unlock();
- }
- });
- }
-
- /**
- * Seek to the start of the specified chapter.
- */
- public void seekToChapter(Chapter c) {
- Validate.notNull(c);
-
- seekTo((int) c.getStart());
- }
-
- /**
- * Returns the duration of the current media object or INVALID_TIME if the duration could not be retrieved.
- */
- public int getDuration() {
- if (!playerLock.tryLock()) {
- return INVALID_TIME;
- }
-
- int retVal = INVALID_TIME;
- if (playerStatus == PlayerStatus.PLAYING
- || playerStatus == PlayerStatus.PAUSED
- || playerStatus == PlayerStatus.PREPARED) {
- retVal = mediaPlayer.getDuration();
- } else if (media != null && media.getDuration() > 0) {
- retVal = media.getDuration();
- }
-
- playerLock.unlock();
- return retVal;
- }
-
- /**
- * Returns the position of the current media object or INVALID_TIME if the position could not be retrieved.
- */
- public int getPosition() {
- if (!playerLock.tryLock()) {
- return INVALID_TIME;
- }
-
- int retVal = INVALID_TIME;
- if (playerStatus == PlayerStatus.PLAYING
- || playerStatus == PlayerStatus.PAUSED
- || playerStatus == PlayerStatus.PREPARED) {
- retVal = mediaPlayer.getCurrentPosition();
- } else if (media != null && media.getPosition() > 0) {
- retVal = media.getPosition();
- }
-
- playerLock.unlock();
- return retVal;
- }
-
- public boolean isStartWhenPrepared() {
- return startWhenPrepared.get();
- }
-
- public void setStartWhenPrepared(boolean startWhenPrepared) {
- this.startWhenPrepared.set(startWhenPrepared);
- }
-
- /**
- * Returns true if the playback speed can be adjusted.
- */
- public boolean canSetSpeed() {
- boolean retVal = false;
- if (mediaPlayer != null && media != null && media.getMediaType() == MediaType.AUDIO) {
- retVal = (mediaPlayer).canSetSpeed();
- }
- return retVal;
- }
-
- /**
- * Sets the playback speed.
- * This method is executed on the caller's thread.
- */
- private void setSpeedSync(float speed) {
- playerLock.lock();
- if (media != null && media.getMediaType() == MediaType.AUDIO) {
- if (mediaPlayer.canSetSpeed()) {
- mediaPlayer.setPlaybackSpeed((float) speed);
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Playback speed was set to " + speed);
- callback.playbackSpeedChanged(speed);
- }
- }
- playerLock.unlock();
- }
-
- /**
- * Sets the playback speed.
- * This method is executed on an internal executor service.
- */
- public void setSpeed(final float speed) {
- executor.submit(new Runnable() {
- @Override
- public void run() {
- setSpeedSync(speed);
- }
- });
- }
-
- /**
- * Returns the current playback speed. If the playback speed could not be retrieved, 1 is returned.
- */
- public float getPlaybackSpeed() {
- if (!playerLock.tryLock()) {
- return 1;
- }
-
- float retVal = 1;
- if ((playerStatus == PlayerStatus.PLAYING
- || playerStatus == PlayerStatus.PAUSED
- || playerStatus == PlayerStatus.PREPARED) && mediaPlayer.canSetSpeed()) {
- retVal = mediaPlayer.getCurrentSpeedMultiplier();
- }
- playerLock.unlock();
- return retVal;
- }
-
- public MediaType getCurrentMediaType() {
- return mediaType;
- }
-
- public boolean isStreaming() {
- return stream;
- }
-
-
- /**
- * Releases internally used resources. This method should only be called when the object is not used anymore.
- */
- public void shutdown() {
- executor.shutdown();
- if (mediaPlayer != null) {
- mediaPlayer.release();
- }
- releaseWifiLockIfNecessary();
- }
-
- public void setVideoSurface(final SurfaceHolder surface) {
- executor.submit(new Runnable() {
- @Override
- public void run() {
- playerLock.lock();
- if (mediaPlayer != null) {
- mediaPlayer.setDisplay(surface);
- }
- playerLock.unlock();
- }
- });
- }
-
- public void resetVideoSurface() {
- executor.submit(new Runnable() {
- @Override
- public void run() {
- playerLock.lock();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Resetting video surface");
- mediaPlayer.setDisplay(null);
- reinit();
- playerLock.unlock();
- }
- });
- }
-
- /**
- * Return width and height of the currently playing video as a pair.
- *
- * @return Width and height as a Pair or null if the video size could not be determined. The method might still
- * return an invalid non-null value if the getVideoWidth() and getVideoHeight() methods of the media player return
- * invalid values.
- */
- public Pair<Integer, Integer> getVideoSize() {
- if (!playerLock.tryLock()) {
- // use cached value if lock can't be aquired
- return videoSize;
- }
- Pair<Integer, Integer> res;
- if (mediaPlayer == null || playerStatus == PlayerStatus.ERROR || mediaType != MediaType.VIDEO) {
- res = null;
- } else {
- VideoPlayer vp = (VideoPlayer) mediaPlayer;
- videoSize = new Pair<Integer, Integer>(vp.getVideoWidth(), vp.getVideoHeight());
- res = videoSize;
- }
- playerLock.unlock();
- return res;
- }
-
- /**
- * Returns a PSMInfo object that contains information about the current state of the PSMP object.
- *
- * @return The PSMPInfo object.
- */
- public synchronized PSMPInfo getPSMPInfo() {
- return new PSMPInfo(playerStatus, media);
- }
-
- /**
- * Sets the player status of the PSMP object. PlayerStatus and media attributes have to be set at the same time
- * so that getPSMPInfo can't return an invalid state (e.g. status is PLAYING, but media is null).
- * <p/>
- * This method will notify the callback about the change of the player status (even if the new status is the same
- * as the old one).
- *
- * @param newStatus The new PlayerStatus. This must not be null.
- * @param newMedia The new playable object of the PSMP object. This can be null.
- */
- private synchronized void setPlayerStatus(PlayerStatus newStatus, Playable newMedia) {
- Validate.notNull(newStatus);
-
- if (BuildConfig.DEBUG) Log.d(TAG, "Setting player status to " + newStatus);
-
- this.playerStatus = newStatus;
- this.media = newMedia;
- callback.statusChanged(new PSMPInfo(playerStatus, media));
- }
-
- private IPlayer createMediaPlayer() {
- if (mediaPlayer != null) {
- mediaPlayer.release();
- }
- if (media == null || media.getMediaType() == MediaType.VIDEO) {
- mediaPlayer = new VideoPlayer();
- } else {
- mediaPlayer = new AudioPlayer(context);
- }
- mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
- mediaPlayer.setWakeMode(context, PowerManager.PARTIAL_WAKE_LOCK);
- return setMediaPlayerListeners(mediaPlayer);
- }
-
- private final AudioManager.OnAudioFocusChangeListener audioFocusChangeListener = new AudioManager.OnAudioFocusChangeListener() {
-
- @Override
- public void onAudioFocusChange(final int focusChange) {
- executor.submit(new Runnable() {
- @Override
- public void run() {
- playerLock.lock();
-
- // If there is an incoming call, playback should be paused permanently
- TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
- final int callState = (tm != null) ? tm.getCallState() : 0;
- if (BuildConfig.DEBUG) Log.d(TAG, "Call state: " + callState);
- Log.i(TAG, "Call state:" + callState);
-
- if (focusChange == AudioManager.AUDIOFOCUS_LOSS || callState != TelephonyManager.CALL_STATE_IDLE) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Lost audio focus");
- pause(true, false);
- callback.shouldStop();
- } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Gained audio focus");
- if (pausedBecauseOfTransientAudiofocusLoss) { // we paused => play now
- resume();
- } else { // we ducked => raise audio level back
- audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
- AudioManager.ADJUST_RAISE, 0);
- }
- } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
- if (playerStatus == PlayerStatus.PLAYING) {
- if (!UserPreferences.shouldPauseForFocusLoss()) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Lost audio focus temporarily. Ducking...");
- audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
- AudioManager.ADJUST_LOWER, 0);
- pausedBecauseOfTransientAudiofocusLoss = false;
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Lost audio focus temporarily. Could duck, but won't, pausing...");
- pause(false, false);
- pausedBecauseOfTransientAudiofocusLoss = true;
- }
- }
- } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
- if (playerStatus == PlayerStatus.PLAYING) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Lost audio focus temporarily. Pausing...");
- pause(false, false);
- pausedBecauseOfTransientAudiofocusLoss = true;
- }
- playerLock.unlock();
- }
- }
- });
- }
- };
-
-
- public void endPlayback() {
- executor.submit(new Runnable() {
- @Override
- public void run() {
- playerLock.lock();
- releaseWifiLockIfNecessary();
-
- if (playerStatus != PlayerStatus.INDETERMINATE) {
- setPlayerStatus(PlayerStatus.INDETERMINATE, media);
- }
- if (mediaPlayer != null) {
- mediaPlayer.reset();
-
- }
- audioManager.abandonAudioFocus(audioFocusChangeListener);
- callback.endPlayback(true);
-
- playerLock.unlock();
- }
- });
- }
-
- /**
- * Moves the PlaybackServiceMediaPlayer into STOPPED state. This call is only valid if the player is currently in
- * INDETERMINATE state, for example after a call to endPlayback.
- * This method will only take care of changing the PlayerStatus of this object! Other tasks like
- * abandoning audio focus have to be done with other methods.
- */
- public void stop() {
- executor.submit(new Runnable() {
- @Override
- public void run() {
- playerLock.lock();
- releaseWifiLockIfNecessary();
-
- if (playerStatus == PlayerStatus.INDETERMINATE) {
- setPlayerStatus(PlayerStatus.STOPPED, null);
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Ignored call to stop: Current player state is: " + playerStatus);
- }
- playerLock.unlock();
-
- }
- });
- }
-
- private synchronized void acquireWifiLockIfNecessary() {
- if (stream) {
- if (wifiLock == null) {
- wifiLock = ((WifiManager) context.getSystemService(Context.WIFI_SERVICE))
- .createWifiLock(WifiManager.WIFI_MODE_FULL, TAG);
- wifiLock.setReferenceCounted(false);
- }
- wifiLock.acquire();
- }
- }
-
- private synchronized void releaseWifiLockIfNecessary() {
- if (wifiLock != null && wifiLock.isHeld()) {
- wifiLock.release();
- }
- }
-
- /**
- * Holds information about a PSMP object.
- */
- public class PSMPInfo {
- public PlayerStatus playerStatus;
- public Playable playable;
-
- public PSMPInfo(PlayerStatus playerStatus, Playable playable) {
- this.playerStatus = playerStatus;
- this.playable = playable;
- }
- }
-
- public static interface PSMPCallback {
- public void statusChanged(PSMPInfo newInfo);
-
- public void shouldStop();
-
- public void playbackSpeedChanged(float s);
-
- public void onBufferingUpdate(int percent);
-
- public boolean onMediaPlayerInfo(int code);
-
- public boolean onMediaPlayerError(Object inObj, int what, int extra);
-
- public boolean endPlayback(boolean playNextEpisode);
-
- public RemoteControlClient getRemoteControlClient();
- }
-
- private IPlayer setMediaPlayerListeners(IPlayer mp) {
- if (mp != null && media != null) {
- if (media.getMediaType() == MediaType.AUDIO) {
- ((AudioPlayer) mp)
- .setOnCompletionListener(audioCompletionListener);
- ((AudioPlayer) mp)
- .setOnSeekCompleteListener(audioSeekCompleteListener);
- ((AudioPlayer) mp).setOnErrorListener(audioErrorListener);
- ((AudioPlayer) mp)
- .setOnBufferingUpdateListener(audioBufferingUpdateListener);
- ((AudioPlayer) mp).setOnInfoListener(audioInfoListener);
- } else {
- ((VideoPlayer) mp)
- .setOnCompletionListener(videoCompletionListener);
- ((VideoPlayer) mp)
- .setOnSeekCompleteListener(videoSeekCompleteListener);
- ((VideoPlayer) mp).setOnErrorListener(videoErrorListener);
- ((VideoPlayer) mp)
- .setOnBufferingUpdateListener(videoBufferingUpdateListener);
- ((VideoPlayer) mp).setOnInfoListener(videoInfoListener);
- }
- }
- return mp;
- }
-
- private final com.aocate.media.MediaPlayer.OnCompletionListener audioCompletionListener = new com.aocate.media.MediaPlayer.OnCompletionListener() {
- @Override
- public void onCompletion(com.aocate.media.MediaPlayer mp) {
- genericOnCompletion();
- }
- };
-
- private final android.media.MediaPlayer.OnCompletionListener videoCompletionListener = new android.media.MediaPlayer.OnCompletionListener() {
- @Override
- public void onCompletion(android.media.MediaPlayer mp) {
- genericOnCompletion();
- }
- };
-
- private void genericOnCompletion() {
- endPlayback();
- }
-
- private final com.aocate.media.MediaPlayer.OnBufferingUpdateListener audioBufferingUpdateListener = new com.aocate.media.MediaPlayer.OnBufferingUpdateListener() {
- @Override
- public void onBufferingUpdate(com.aocate.media.MediaPlayer mp,
- int percent) {
- genericOnBufferingUpdate(percent);
- }
- };
-
- private final android.media.MediaPlayer.OnBufferingUpdateListener videoBufferingUpdateListener = new android.media.MediaPlayer.OnBufferingUpdateListener() {
- @Override
- public void onBufferingUpdate(android.media.MediaPlayer mp, int percent) {
- genericOnBufferingUpdate(percent);
- }
- };
-
- private void genericOnBufferingUpdate(int percent) {
- callback.onBufferingUpdate(percent);
- }
-
- private final com.aocate.media.MediaPlayer.OnInfoListener audioInfoListener = new com.aocate.media.MediaPlayer.OnInfoListener() {
- @Override
- public boolean onInfo(com.aocate.media.MediaPlayer mp, int what,
- int extra) {
- return genericInfoListener(what);
- }
- };
-
- private final android.media.MediaPlayer.OnInfoListener videoInfoListener = new android.media.MediaPlayer.OnInfoListener() {
- @Override
- public boolean onInfo(android.media.MediaPlayer mp, int what, int extra) {
- return genericInfoListener(what);
- }
- };
-
- private boolean genericInfoListener(int what) {
- return callback.onMediaPlayerInfo(what);
- }
-
- private final com.aocate.media.MediaPlayer.OnErrorListener audioErrorListener = new com.aocate.media.MediaPlayer.OnErrorListener() {
- @Override
- public boolean onError(com.aocate.media.MediaPlayer mp, int what,
- int extra) {
- return genericOnError(mp, what, extra);
- }
- };
-
- private final android.media.MediaPlayer.OnErrorListener videoErrorListener = new android.media.MediaPlayer.OnErrorListener() {
- @Override
- public boolean onError(android.media.MediaPlayer mp, int what, int extra) {
- return genericOnError(mp, what, extra);
- }
- };
-
- private boolean genericOnError(Object inObj, int what, int extra) {
- return callback.onMediaPlayerError(inObj, what, extra);
- }
-
- private final com.aocate.media.MediaPlayer.OnSeekCompleteListener audioSeekCompleteListener = new com.aocate.media.MediaPlayer.OnSeekCompleteListener() {
- @Override
- public void onSeekComplete(com.aocate.media.MediaPlayer mp) {
- genericSeekCompleteListener();
- }
- };
-
- private final android.media.MediaPlayer.OnSeekCompleteListener videoSeekCompleteListener = new android.media.MediaPlayer.OnSeekCompleteListener() {
- @Override
- public void onSeekComplete(android.media.MediaPlayer mp) {
- genericSeekCompleteListener();
- }
- };
-
- private final void genericSeekCompleteListener() {
- executor.submit(new Runnable() {
- @Override
- public void run() {
- playerLock.lock();
- if (playerStatus == PlayerStatus.SEEKING) {
- setPlayerStatus(statusBeforeSeeking, media);
- }
- playerLock.unlock();
- }
- });
- }
-}
diff --git a/src/de/danoeh/antennapod/service/playback/PlaybackServiceTaskManager.java b/src/de/danoeh/antennapod/service/playback/PlaybackServiceTaskManager.java
deleted file mode 100644
index 680ec2e2f..000000000
--- a/src/de/danoeh/antennapod/service/playback/PlaybackServiceTaskManager.java
+++ /dev/null
@@ -1,384 +0,0 @@
-package de.danoeh.antennapod.service.playback;
-
-import android.content.Context;
-import android.util.Log;
-
-import org.apache.commons.lang3.Validate;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.feed.EventDistributor;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.storage.DBReader;
-import de.danoeh.antennapod.util.playback.Playable;
-
-import java.util.List;
-import java.util.concurrent.*;
-
-/**
- * Manages the background tasks of PlaybackSerivce, i.e.
- * the sleep timer, the position saver, the widget updater and
- * the queue loader.
- * <p/>
- * The PlaybackServiceTaskManager(PSTM) uses a callback object (PSTMCallback)
- * to notify the PlaybackService about updates from the running tasks.
- */
-public class PlaybackServiceTaskManager {
- private static final String TAG = "PlaybackServiceTaskManager";
-
- /**
- * Update interval of position saver in milliseconds.
- */
- public static final int POSITION_SAVER_WAITING_INTERVAL = 5000;
- /**
- * Notification interval of widget updater in milliseconds.
- */
- public static final int WIDGET_UPDATER_NOTIFICATION_INTERVAL = 1500;
-
- private static final int SCHED_EX_POOL_SIZE = 2;
- private final ScheduledThreadPoolExecutor schedExecutor;
-
- private ScheduledFuture positionSaverFuture;
- private ScheduledFuture widgetUpdaterFuture;
- private ScheduledFuture sleepTimerFuture;
- private volatile Future<List<FeedItem>> queueFuture;
- private volatile Future chapterLoaderFuture;
-
- private SleepTimer sleepTimer;
-
- private final Context context;
- private final PSTMCallback callback;
-
- /**
- * Sets up a new PSTM. This method will also start the queue loader task.
- *
- * @param context
- * @param callback A PSTMCallback object for notifying the user about updates. Must not be null.
- */
- public PlaybackServiceTaskManager(Context context, PSTMCallback callback) {
- Validate.notNull(context);
- Validate.notNull(callback);
-
- this.context = context;
- this.callback = callback;
- schedExecutor = new ScheduledThreadPoolExecutor(SCHED_EX_POOL_SIZE, new ThreadFactory() {
- @Override
- public Thread newThread(Runnable r) {
- Thread t = new Thread(r);
- t.setPriority(Thread.MIN_PRIORITY);
- return t;
- }
- });
- loadQueue();
- EventDistributor.getInstance().register(eventDistributorListener);
- }
-
- private final EventDistributor.EventListener eventDistributorListener = new EventDistributor.EventListener() {
- @Override
- public void update(EventDistributor eventDistributor, Integer arg) {
- if ((EventDistributor.QUEUE_UPDATE & arg) != 0) {
- cancelQueueLoader();
- loadQueue();
- }
- }
- };
-
- private synchronized boolean isQueueLoaderActive() {
- return queueFuture != null && !queueFuture.isDone();
- }
-
- private synchronized void cancelQueueLoader() {
- if (isQueueLoaderActive()) {
- queueFuture.cancel(true);
- }
- }
-
- private synchronized void loadQueue() {
- if (!isQueueLoaderActive()) {
- queueFuture = schedExecutor.submit(new Callable<List<FeedItem>>() {
- @Override
- public List<FeedItem> call() throws Exception {
- return DBReader.getQueue(context);
- }
- });
- }
- }
-
- /**
- * Returns the queue if it is already loaded or null if it hasn't been loaded yet.
- * In order to wait until the queue has been loaded, use getQueue()
- */
- public synchronized List<FeedItem> getQueueIfLoaded() {
- if (queueFuture.isDone()) {
- try {
- return queueFuture.get();
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
- }
- return null;
- }
-
- /**
- * Returns the queue or waits until the PSTM has loaded the queue from the database.
- */
- public synchronized List<FeedItem> getQueue() throws InterruptedException {
- try {
- return queueFuture.get();
- } catch (ExecutionException e) {
- throw new IllegalArgumentException(e);
- }
- }
-
- /**
- * Starts the position saver task. If the position saver is already active, nothing will happen.
- */
- public synchronized void startPositionSaver() {
- if (!isPositionSaverActive()) {
- Runnable positionSaver = new Runnable() {
- @Override
- public void run() {
- callback.positionSaverTick();
- }
- };
- positionSaverFuture = schedExecutor.scheduleWithFixedDelay(positionSaver, POSITION_SAVER_WAITING_INTERVAL,
- POSITION_SAVER_WAITING_INTERVAL, TimeUnit.MILLISECONDS);
-
- if (BuildConfig.DEBUG) Log.d(TAG, "Started PositionSaver");
- } else {
- if (BuildConfig.DEBUG) Log.d(TAG, "Call to startPositionSaver was ignored.");
- }
- }
-
- /**
- * Returns true if the position saver is currently running.
- */
- public synchronized boolean isPositionSaverActive() {
- return positionSaverFuture != null && !positionSaverFuture.isCancelled() && !positionSaverFuture.isDone();
- }
-
- /**
- * Cancels the position saver. If the position saver is not running, nothing will happen.
- */
- public synchronized void cancelPositionSaver() {
- if (isPositionSaverActive()) {
- positionSaverFuture.cancel(false);
- if (BuildConfig.DEBUG) Log.d(TAG, "Cancelled PositionSaver");
- }
- }
-
- /**
- * Starts the widget updater task. If the widget updater is already active, nothing will happen.
- */
- public synchronized void startWidgetUpdater() {
- if (!isWidgetUpdaterActive()) {
- Runnable widgetUpdater = new Runnable() {
- @Override
- public void run() {
- callback.onWidgetUpdaterTick();
- }
- };
- widgetUpdaterFuture = schedExecutor.scheduleWithFixedDelay(widgetUpdater, WIDGET_UPDATER_NOTIFICATION_INTERVAL,
- WIDGET_UPDATER_NOTIFICATION_INTERVAL, TimeUnit.MILLISECONDS);
-
- if (BuildConfig.DEBUG) Log.d(TAG, "Started WidgetUpdater");
- } else {
- if (BuildConfig.DEBUG) Log.d(TAG, "Call to startWidgetUpdater was ignored.");
- }
- }
-
- /**
- * Starts a new sleep timer with the given waiting time. If another sleep timer is already active, it will be
- * cancelled first.
- * After waitingTime has elapsed, onSleepTimerExpired() will be called.
- *
- * @throws java.lang.IllegalArgumentException if waitingTime <= 0
- */
- public synchronized void setSleepTimer(long waitingTime) {
- Validate.isTrue(waitingTime > 0, "Waiting time <= 0");
-
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Setting sleep timer to " + Long.toString(waitingTime)
- + " milliseconds");
- if (isSleepTimerActive()) {
- sleepTimerFuture.cancel(true);
- }
- sleepTimer = new SleepTimer(waitingTime);
- sleepTimerFuture = schedExecutor.schedule(sleepTimer, 0, TimeUnit.MILLISECONDS);
- }
-
- /**
- * Returns true if the sleep timer is currently active.
- */
- public synchronized boolean isSleepTimerActive() {
- return sleepTimer != null && sleepTimerFuture != null && !sleepTimerFuture.isCancelled() && !sleepTimerFuture.isDone() && sleepTimer.isWaiting;
- }
-
- /**
- * Disables the sleep timer. If the sleep timer is not active, nothing will happen.
- */
- public synchronized void disableSleepTimer() {
- if (isSleepTimerActive()) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Disabling sleep timer");
- sleepTimerFuture.cancel(true);
- }
- }
-
- /**
- * Returns the current sleep timer time or 0 if the sleep timer is not active.
- */
- public synchronized long getSleepTimerTimeLeft() {
- if (isSleepTimerActive()) {
- return sleepTimer.getWaitingTime();
- } else {
- return 0;
- }
- }
-
-
- /**
- * Returns true if the widget updater is currently running.
- */
- public synchronized boolean isWidgetUpdaterActive() {
- return widgetUpdaterFuture != null && !widgetUpdaterFuture.isCancelled() && !widgetUpdaterFuture.isDone();
- }
-
- /**
- * Cancels the widget updater. If the widget updater is not running, nothing will happen.
- */
- public synchronized void cancelWidgetUpdater() {
- if (isWidgetUpdaterActive()) {
- widgetUpdaterFuture.cancel(false);
- if (BuildConfig.DEBUG) Log.d(TAG, "Cancelled WidgetUpdater");
- }
- }
-
- private synchronized void cancelChapterLoader() {
- if (isChapterLoaderActive()) {
- chapterLoaderFuture.cancel(true);
- }
- }
-
- private synchronized boolean isChapterLoaderActive() {
- return chapterLoaderFuture != null && !chapterLoaderFuture.isDone();
- }
-
- /**
- * Starts a new thread that loads the chapter marks from a playable object. If another chapter loader is already active,
- * it will be cancelled first.
- * On completion, the callback's onChapterLoaded method will be called.
- */
- public synchronized void startChapterLoader(final Playable media) {
- Validate.notNull(media);
-
- if (isChapterLoaderActive()) {
- cancelChapterLoader();
- }
-
- Runnable chapterLoader = new Runnable() {
- @Override
- public void run() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Chapter loader started");
- if (media.getChapters() == null) {
- media.loadChapterMarks();
- if (!Thread.currentThread().isInterrupted() && media.getChapters() != null) {
- callback.onChapterLoaded(media);
- }
- }
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Chapter loader stopped");
- }
- };
- chapterLoaderFuture = schedExecutor.submit(chapterLoader);
- }
-
-
- /**
- * Cancels all tasks. The PSTM will be in the initial state after execution of this method.
- */
- public synchronized void cancelAllTasks() {
- cancelPositionSaver();
- cancelWidgetUpdater();
- disableSleepTimer();
- cancelQueueLoader();
- cancelChapterLoader();
- }
-
- /**
- * Cancels all tasks and shuts down the internal executor service of the PSTM. The object should not be used after
- * execution of this method.
- */
- public synchronized void shutdown() {
- EventDistributor.getInstance().unregister(eventDistributorListener);
- cancelAllTasks();
- schedExecutor.shutdown();
- }
-
- /**
- * Sleeps for a given time and then pauses playback.
- */
- private class SleepTimer implements Runnable {
- private static final String TAG = "SleepTimer";
- private static final long UPDATE_INTERVALL = 1000L;
- private volatile long waitingTime;
- private volatile boolean isWaiting;
-
- public SleepTimer(long waitingTime) {
- super();
- this.waitingTime = waitingTime;
- isWaiting = true;
- }
-
- @Override
- public void run() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Starting");
- while (waitingTime > 0) {
- try {
- Thread.sleep(UPDATE_INTERVALL);
- waitingTime -= UPDATE_INTERVALL;
-
- if (waitingTime <= 0) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Waiting completed");
- postExecute();
- if (!Thread.currentThread().isInterrupted()) {
- callback.onSleepTimerExpired();
- }
-
- }
- } catch (InterruptedException e) {
- Log.d(TAG, "Thread was interrupted while waiting");
- break;
- }
- }
- postExecute();
- }
-
- protected void postExecute() {
- isWaiting = false;
- }
-
- public long getWaitingTime() {
- return waitingTime;
- }
-
- public boolean isWaiting() {
- return isWaiting;
- }
-
- }
-
- public static interface PSTMCallback {
- void positionSaverTick();
-
- void onSleepTimerExpired();
-
- void onWidgetUpdaterTick();
-
- void onChapterLoaded(Playable media);
- }
-}
diff --git a/src/de/danoeh/antennapod/service/playback/PlayerStatus.java b/src/de/danoeh/antennapod/service/playback/PlayerStatus.java
deleted file mode 100644
index 3d2b4ad39..000000000
--- a/src/de/danoeh/antennapod/service/playback/PlayerStatus.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package de.danoeh.antennapod.service.playback;
-
-public enum PlayerStatus {
- INDETERMINATE, // player is currently changing its state, listeners should wait until the player has left this state.
- ERROR,
- PREPARING,
- PAUSED,
- PLAYING,
- STOPPED,
- PREPARED,
- SEEKING,
- INITIALIZING, // playback service is loading the Playable's metadata
- INITIALIZED // playback service was started, data source of media player was set.
-}
diff --git a/src/de/danoeh/antennapod/service/playback/PlayerWidgetService.java b/src/de/danoeh/antennapod/service/playback/PlayerWidgetService.java
deleted file mode 100644
index 71bc40c2a..000000000
--- a/src/de/danoeh/antennapod/service/playback/PlayerWidgetService.java
+++ /dev/null
@@ -1,190 +0,0 @@
-package de.danoeh.antennapod.service.playback;
-
-import android.app.PendingIntent;
-import android.app.Service;
-import android.appwidget.AppWidgetManager;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.Build;
-import android.os.IBinder;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.View;
-import android.widget.RemoteViews;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.receiver.MediaButtonReceiver;
-import de.danoeh.antennapod.receiver.PlayerWidget;
-import de.danoeh.antennapod.util.Converter;
-import de.danoeh.antennapod.util.playback.Playable;
-
-/** Updates the state of the player widget */
-public class PlayerWidgetService extends Service {
- private static final String TAG = "PlayerWidgetService";
-
- private PlaybackService playbackService;
- /** True while service is updating the widget */
- private volatile boolean isUpdating;
-
- public PlayerWidgetService() {
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Service created");
- isUpdating = false;
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Service is about to be destroyed");
- try {
- unbindService(mConnection);
- } catch (IllegalArgumentException e) {
- Log.w(TAG, "IllegalArgumentException when trying to unbind service");
- }
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- return null;
- }
-
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- if (!isUpdating) {
- if (playbackService == null && PlaybackService.isRunning) {
- bindService(new Intent(this, PlaybackService.class),
- mConnection, 0);
- } else {
- startViewUpdaterIfNotRunning();
- }
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "Service was called while updating. Ignoring update request");
- }
- return Service.START_NOT_STICKY;
- }
-
- private void updateViews() {
- if (playbackService == null) {
- return;
- }
- isUpdating = true;
-
- ComponentName playerWidget = new ComponentName(this, PlayerWidget.class);
- AppWidgetManager manager = AppWidgetManager.getInstance(this);
- RemoteViews views = new RemoteViews(getPackageName(),
- R.layout.player_widget);
- PendingIntent startMediaplayer = PendingIntent.getActivity(this, 0,
- PlaybackService.getPlayerActivityIntent(this), 0);
-
- views.setOnClickPendingIntent(R.id.layout_left, startMediaplayer);
- final Playable media = playbackService.getPlayable();
- if (playbackService != null && media != null) {
- PlayerStatus status = playbackService.getStatus();
-
- views.setTextViewText(R.id.txtvTitle, media.getEpisodeTitle());
-
- if (status == PlayerStatus.PLAYING) {
- String progressString = getProgressString(playbackService);
- if (progressString != null) {
- views.setTextViewText(R.id.txtvProgress, progressString);
- }
- views.setImageViewResource(R.id.butPlay, R.drawable.av_pause_dark);
- if (Build.VERSION.SDK_INT >= 15) {
- views.setContentDescription(R.id.butPlay, getString(R.string.pause_label));
- }
- } else {
- views.setImageViewResource(R.id.butPlay, R.drawable.av_play_dark);
- if (Build.VERSION.SDK_INT >= 15) {
- views.setContentDescription(R.id.butPlay, getString(R.string.play_label));
- }
- }
- views.setOnClickPendingIntent(R.id.butPlay,
- createMediaButtonIntent());
- } else {
- views.setViewVisibility(R.id.txtvProgress, View.INVISIBLE);
- views.setTextViewText(R.id.txtvTitle,
- this.getString(R.string.no_media_playing_label));
- views.setImageViewResource(R.id.butPlay, R.drawable.av_play);
-
- }
-
- manager.updateAppWidget(playerWidget, views);
- isUpdating = false;
- }
-
- /** Creates an intent which fakes a mediabutton press */
- private PendingIntent createMediaButtonIntent() {
- KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN,
- KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
- Intent startingIntent = new Intent(
- MediaButtonReceiver.NOTIFY_BUTTON_RECEIVER);
- startingIntent.putExtra(Intent.EXTRA_KEY_EVENT, event);
-
- return PendingIntent.getBroadcast(this, 0, startingIntent, 0);
- }
-
- private String getProgressString(PlaybackService ps) {
- int position = ps.getCurrentPosition();
- int duration = ps.getDuration();
- if (position != PlaybackService.INVALID_TIME
- && duration != PlaybackService.INVALID_TIME) {
- return Converter.getDurationStringLong(position) + " / "
- + Converter.getDurationStringLong(duration);
- } else {
- return null;
- }
- }
-
- private ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Connection to service established");
- playbackService = ((PlaybackService.LocalBinder) service)
- .getService();
- startViewUpdaterIfNotRunning();
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- playbackService = null;
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Disconnected from service");
- }
-
- };
-
- private void startViewUpdaterIfNotRunning() {
- if (!isUpdating) {
- ViewUpdater updateThread = new ViewUpdater(this);
- updateThread.start();
- }
- }
-
- static class ViewUpdater extends Thread {
- private static final String THREAD_NAME = "ViewUpdater";
- private PlayerWidgetService service;
-
- public ViewUpdater(PlayerWidgetService service) {
- super();
- setName(THREAD_NAME);
- this.service = service;
-
- }
-
- @Override
- public void run() {
- service.updateViews();
- }
-
- }
-
-}
diff --git a/src/de/danoeh/antennapod/spa/SPAUtil.java b/src/de/danoeh/antennapod/spa/SPAUtil.java
deleted file mode 100644
index 75cbd8b5a..000000000
--- a/src/de/danoeh/antennapod/spa/SPAUtil.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package de.danoeh.antennapod.spa;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
-import android.util.Log;
-
-import org.apache.commons.lang3.Validate;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.receiver.SPAReceiver;
-
-/**
- * Provides methods related to AntennaPodSP (https://github.com/danieloeh/AntennaPodSP)
- */
-public class SPAUtil {
- private static final String TAG = "SPAUtil";
-
- private static final String PREF_HAS_QUERIED_SP_APPS = "prefSPAUtil.hasQueriedSPApps";
-
- private SPAUtil() {
- }
-
-
- /**
- * Sends an ACTION_SP_APPS_QUERY_FEEDS intent to all AntennaPod Single Purpose apps.
- * The receiving single purpose apps will then send their feeds back to AntennaPod via an
- * ACTION_SP_APPS_QUERY_FEEDS_RESPONSE intent.
- * This intent will only be sent once.
- *
- * @return True if an intent was sent, false otherwise (for example if the intent has already been
- * sent before.
- */
- public static synchronized boolean sendSPAppsQueryFeedsIntent(Context context) {
- if (context == null) throw new IllegalArgumentException("context = null");
- final Context appContext = context.getApplicationContext();
- if (appContext == null) {
- Log.wtf(TAG, "Unable to get application context");
- return false;
- }
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(appContext);
- if (!prefs.getBoolean(PREF_HAS_QUERIED_SP_APPS, false)) {
- appContext.sendBroadcast(new Intent(SPAReceiver.ACTION_SP_APPS_QUERY_FEEDS));
- if (BuildConfig.DEBUG) Log.d(TAG, "Sending SP_APPS_QUERY_FEEDS intent");
-
- SharedPreferences.Editor editor = prefs.edit();
- editor.putBoolean(PREF_HAS_QUERIED_SP_APPS, true);
- editor.commit();
-
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Resets all preferences created by this class. Should only be used for debug purposes.
- */
- public static void resetSPAPreferences(Context c) {
- if (BuildConfig.DEBUG) {
- Validate.notNull(c);
- SharedPreferences.Editor editor = PreferenceManager
- .getDefaultSharedPreferences(c.getApplicationContext()).edit();
- editor.putBoolean(PREF_HAS_QUERIED_SP_APPS, false);
- editor.commit();
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/storage/DBReader.java b/src/de/danoeh/antennapod/storage/DBReader.java
deleted file mode 100644
index e49ea4f83..000000000
--- a/src/de/danoeh/antennapod/storage/DBReader.java
+++ /dev/null
@@ -1,908 +0,0 @@
-package de.danoeh.antennapod.storage;
-
-import android.content.Context;
-import android.database.Cursor;
-import android.database.SQLException;
-import android.util.Log;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.feed.*;
-import de.danoeh.antennapod.service.download.DownloadStatus;
-import de.danoeh.antennapod.util.DownloadError;
-import de.danoeh.antennapod.util.comparator.DownloadStatusComparator;
-import de.danoeh.antennapod.util.comparator.FeedItemPubdateComparator;
-import de.danoeh.antennapod.util.comparator.PlaybackCompletionDateComparator;
-import de.danoeh.antennapod.util.flattr.FlattrStatus;
-import de.danoeh.antennapod.util.flattr.FlattrThing;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-
-/**
- * Provides methods for reading data from the AntennaPod database.
- * In general, all database calls in DBReader-methods are executed on the caller's thread.
- * This means that the caller should make sure that DBReader-methods are not executed on the GUI-thread.
- * This class will use the {@link de.danoeh.antennapod.feed.EventDistributor} to notify listeners about changes in the database.
- */
-public final class DBReader {
- private static final String TAG = "DBReader";
-
- /**
- * Maximum size of the list returned by {@link #getPlaybackHistory(android.content.Context)}.
- */
- public static final int PLAYBACK_HISTORY_SIZE = 50;
-
- /**
- * Maximum size of the list returned by {@link #getDownloadLog(android.content.Context)}.
- */
- public static final int DOWNLOAD_LOG_SIZE = 200;
-
-
- private DBReader() {
- }
-
- /**
- * Returns a list of Feeds, sorted alphabetically by their title.
- *
- * @param context A context that is used for opening a database connection.
- * @return A list of Feeds, sorted alphabetically by their title. A Feed-object
- * of the returned list does NOT have its list of FeedItems yet. The FeedItem-list
- * can be loaded separately with {@link #getFeedItemList(android.content.Context, de.danoeh.antennapod.feed.Feed)}.
- */
- public static List<Feed> getFeedList(final Context context) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Extracting Feedlist");
-
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- List<Feed> result = getFeedList(adapter);
- adapter.close();
- return result;
- }
-
- private static List<Feed> getFeedList(PodDBAdapter adapter) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Extracting Feedlist");
-
- Cursor feedlistCursor = adapter.getAllFeedsCursor();
- List<Feed> feeds = new ArrayList<Feed>(feedlistCursor.getCount());
-
- if (feedlistCursor.moveToFirst()) {
- do {
- Feed feed = extractFeedFromCursorRow(adapter, feedlistCursor);
- feeds.add(feed);
- } while (feedlistCursor.moveToNext());
- }
- feedlistCursor.close();
- return feeds;
- }
-
- /**
- * Returns a list with the download URLs of all feeds.
- *
- * @param context A context that is used for opening the database connection.
- * @return A list of Strings with the download URLs of all feeds.
- */
- public static List<String> getFeedListDownloadUrls(final Context context) {
- PodDBAdapter adapter = new PodDBAdapter(context);
- List<String> result = new ArrayList<String>();
- adapter.open();
- Cursor feeds = adapter.getFeedCursorDownloadUrls();
- if (feeds.moveToFirst()) {
- do {
- result.add(feeds.getString(1));
- } while (feeds.moveToNext());
- }
- feeds.close();
- adapter.close();
-
- return result;
- }
-
- /**
- * Returns a list of 'expired Feeds', i.e. Feeds that have not been updated for a certain amount of time.
- *
- * @param context A context that is used for opening a database connection.
- * @param expirationTime Time that is used for determining whether a feed is outdated or not.
- * A Feed is considered expired if 'lastUpdate < (currentTime - expirationTime)' evaluates to true.
- * @return A list of Feeds, sorted alphabetically by their title. A Feed-object
- * of the returned list does NOT have its list of FeedItems yet. The FeedItem-list
- * can be loaded separately with {@link #getFeedItemList(android.content.Context, de.danoeh.antennapod.feed.Feed)}.
- */
- public static List<Feed> getExpiredFeedsList(final Context context, final long expirationTime) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, String.format("getExpiredFeedsList(%d)", expirationTime));
-
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
-
- Cursor feedlistCursor = adapter.getExpiredFeedsCursor(expirationTime);
- List<Feed> feeds = new ArrayList<Feed>(feedlistCursor.getCount());
-
- if (feedlistCursor.moveToFirst()) {
- do {
- Feed feed = extractFeedFromCursorRow(adapter, feedlistCursor);
- feeds.add(feed);
- } while (feedlistCursor.moveToNext());
- }
- feedlistCursor.close();
- return feeds;
- }
-
- /**
- * Takes a list of FeedItems and loads their corresponding Feed-objects from the database.
- * The feedID-attribute of a FeedItem must be set to the ID of its feed or the method will
- * not find the correct feed of an item.
- *
- * @param context A context that is used for opening a database connection.
- * @param items The FeedItems whose Feed-objects should be loaded.
- */
- public static void loadFeedDataOfFeedItemlist(Context context,
- List<FeedItem> items) {
- List<Feed> feeds = getFeedList(context);
- for (FeedItem item : items) {
- for (Feed feed : feeds) {
- if (feed.getId() == item.getFeedId()) {
- item.setFeed(feed);
- break;
- }
- }
- if (item.getFeed() == null) {
- Log.w(TAG, "No match found for item with ID " + item.getId() + ". Feed ID was " + item.getFeedId());
- }
- }
- }
-
- /**
- * Loads the list of FeedItems for a certain Feed-object. This method should NOT be used if the FeedItems are not
- * used. In order to get information ABOUT the list of FeedItems, consider using {@link #getFeedStatisticsList(android.content.Context)} instead.
- *
- * @param context A context that is used for opening a database connection.
- * @param feed The Feed whose items should be loaded
- * @return A list with the FeedItems of the Feed. The Feed-attribute of the FeedItems will already be set correctly.
- * The method does NOT change the items-attribute of the feed.
- */
- public static List<FeedItem> getFeedItemList(Context context,
- final Feed feed) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Extracting Feeditems of feed " + feed.getTitle());
-
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
-
- Cursor itemlistCursor = adapter.getAllItemsOfFeedCursor(feed);
- List<FeedItem> items = extractItemlistFromCursor(adapter,
- itemlistCursor);
- itemlistCursor.close();
-
- Collections.sort(items, new FeedItemPubdateComparator());
-
- adapter.close();
-
- for (FeedItem item : items) {
- item.setFeed(feed);
- }
-
- return items;
- }
-
- static List<FeedItem> extractItemlistFromCursor(Context context, Cursor itemlistCursor) {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- List<FeedItem> result = extractItemlistFromCursor(adapter, itemlistCursor);
- adapter.close();
- return result;
- }
-
- private static List<FeedItem> extractItemlistFromCursor(
- PodDBAdapter adapter, Cursor itemlistCursor) {
- ArrayList<String> itemIds = new ArrayList<String>();
- List<FeedItem> items = new ArrayList<FeedItem>(
- itemlistCursor.getCount());
-
- if (itemlistCursor.moveToFirst()) {
- do {
- FeedItem item = new FeedItem();
-
- item.setId(itemlistCursor.getLong(PodDBAdapter.IDX_FI_SMALL_ID));
- item.setTitle(itemlistCursor
- .getString(PodDBAdapter.IDX_FI_SMALL_TITLE));
- item.setLink(itemlistCursor
- .getString(PodDBAdapter.IDX_FI_SMALL_LINK));
- item.setPubDate(new Date(itemlistCursor
- .getLong(PodDBAdapter.IDX_FI_SMALL_PUBDATE)));
- item.setPaymentLink(itemlistCursor
- .getString(PodDBAdapter.IDX_FI_SMALL_PAYMENT_LINK));
- item.setFeedId(itemlistCursor
- .getLong(PodDBAdapter.IDX_FI_SMALL_FEED));
- itemIds.add(String.valueOf(item.getId()));
-
- item.setRead((itemlistCursor
- .getInt(PodDBAdapter.IDX_FI_SMALL_READ) > 0));
- item.setItemIdentifier(itemlistCursor
- .getString(PodDBAdapter.IDX_FI_SMALL_ITEM_IDENTIFIER));
- item.setFlattrStatus(new FlattrStatus(itemlistCursor
- .getLong(PodDBAdapter.IDX_FI_SMALL_FLATTR_STATUS)));
-
- long imageIndex = itemlistCursor.getLong(PodDBAdapter.IDX_FI_SMALL_IMAGE);
- if (imageIndex != 0) {
- item.setImage(getFeedImage(adapter, imageIndex));
- }
-
- // extract chapters
- boolean hasSimpleChapters = itemlistCursor
- .getInt(PodDBAdapter.IDX_FI_SMALL_HAS_CHAPTERS) > 0;
- if (hasSimpleChapters) {
- Cursor chapterCursor = adapter
- .getSimpleChaptersOfFeedItemCursor(item);
- if (chapterCursor.moveToFirst()) {
- item.setChapters(new ArrayList<Chapter>());
- do {
- int chapterType = chapterCursor
- .getInt(PodDBAdapter.KEY_CHAPTER_TYPE_INDEX);
- Chapter chapter = null;
- long start = chapterCursor
- .getLong(PodDBAdapter.KEY_CHAPTER_START_INDEX);
- String title = chapterCursor
- .getString(PodDBAdapter.KEY_TITLE_INDEX);
- String link = chapterCursor
- .getString(PodDBAdapter.KEY_CHAPTER_LINK_INDEX);
-
- switch (chapterType) {
- case SimpleChapter.CHAPTERTYPE_SIMPLECHAPTER:
- chapter = new SimpleChapter(start, title, item,
- link);
- break;
- case ID3Chapter.CHAPTERTYPE_ID3CHAPTER:
- chapter = new ID3Chapter(start, title, item,
- link);
- break;
- case VorbisCommentChapter.CHAPTERTYPE_VORBISCOMMENT_CHAPTER:
- chapter = new VorbisCommentChapter(start,
- title, item, link);
- break;
- }
- if (chapter != null) {
- chapter.setId(chapterCursor
- .getLong(PodDBAdapter.KEY_ID_INDEX));
- item.getChapters().add(chapter);
- }
- } while (chapterCursor.moveToNext());
- }
- chapterCursor.close();
- }
- items.add(item);
- } while (itemlistCursor.moveToNext());
- }
-
- extractMediafromItemlist(adapter, items, itemIds);
- return items;
- }
-
- private static void extractMediafromItemlist(PodDBAdapter adapter,
- List<FeedItem> items, ArrayList<String> itemIds) {
-
- List<FeedItem> itemsCopy = new ArrayList<FeedItem>(items);
- Cursor cursor = adapter.getFeedMediaCursorByItemID(itemIds
- .toArray(new String[itemIds.size()]));
- if (cursor.moveToFirst()) {
- do {
- long itemId = cursor.getLong(PodDBAdapter.KEY_MEDIA_FEEDITEM_INDEX);
- // find matching feed item
- FeedItem item = getMatchingItemForMedia(itemId, itemsCopy);
- if (item != null) {
- item.setMedia(extractFeedMediaFromCursorRow(cursor));
- item.getMedia().setItem(item);
- }
- } while (cursor.moveToNext());
- cursor.close();
- }
- }
-
- private static FeedMedia extractFeedMediaFromCursorRow(final Cursor cursor) {
- long mediaId = cursor.getLong(PodDBAdapter.KEY_ID_INDEX);
- Date playbackCompletionDate = null;
- long playbackCompletionTime = cursor
- .getLong(PodDBAdapter.KEY_PLAYBACK_COMPLETION_DATE_INDEX);
- if (playbackCompletionTime > 0) {
- playbackCompletionDate = new Date(
- playbackCompletionTime);
- }
-
- return new FeedMedia(
- mediaId,
- null,
- cursor.getInt(PodDBAdapter.KEY_DURATION_INDEX),
- cursor.getInt(PodDBAdapter.KEY_POSITION_INDEX),
- cursor.getLong(PodDBAdapter.KEY_SIZE_INDEX),
- cursor.getString(PodDBAdapter.KEY_MIME_TYPE_INDEX),
- cursor.getString(PodDBAdapter.KEY_FILE_URL_INDEX),
- cursor.getString(PodDBAdapter.KEY_DOWNLOAD_URL_INDEX),
- cursor.getInt(PodDBAdapter.KEY_DOWNLOADED_INDEX) > 0,
- playbackCompletionDate,
- cursor.getInt(PodDBAdapter.KEY_PLAYED_DURATION_INDEX));
- }
-
- private static Feed extractFeedFromCursorRow(PodDBAdapter adapter,
- Cursor cursor) {
- Date lastUpdate = new Date(
- cursor.getLong(PodDBAdapter.IDX_FEED_SEL_STD_LASTUPDATE));
-
- final FeedImage image;
- long imageIndex = cursor.getLong(PodDBAdapter.IDX_FEED_SEL_STD_IMAGE);
- if (imageIndex != 0) {
- image = getFeedImage(adapter, imageIndex);
- } else {
- image = null;
- }
- Feed feed = new Feed(cursor.getLong(PodDBAdapter.IDX_FEED_SEL_STD_ID),
- lastUpdate,
- cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_TITLE),
- cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_LINK),
- cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_DESCRIPTION),
- cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_PAYMENT_LINK),
- cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_AUTHOR),
- cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_LANGUAGE),
- cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_TYPE),
- cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_FEED_IDENTIFIER),
- image,
- cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_FILE_URL),
- cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_DOWNLOAD_URL),
- cursor.getInt(PodDBAdapter.IDX_FEED_SEL_STD_DOWNLOADED) > 0,
- new FlattrStatus(cursor.getLong(PodDBAdapter.IDX_FEED_SEL_STD_FLATTR_STATUS)));
-
- if (image != null) {
- image.setOwner(feed);
- }
-
- FeedPreferences preferences = new FeedPreferences(cursor.getLong(PodDBAdapter.IDX_FEED_SEL_STD_ID),
- cursor.getInt(PodDBAdapter.IDX_FEED_SEL_PREFERENCES_AUTO_DOWNLOAD) > 0,
- cursor.getString(PodDBAdapter.IDX_FEED_SEL_PREFERENCES_USERNAME),
- cursor.getString(PodDBAdapter.IDX_FEED_SEL_PREFERENCES_PASSWORD));
-
- feed.setPreferences(preferences);
- return feed;
- }
-
- private static FeedItem getMatchingItemForMedia(long itemId,
- List<FeedItem> items) {
- for (FeedItem item : items) {
- if (item.getId() == itemId) {
- return item;
- }
- }
- return null;
- }
-
- static List<FeedItem> getQueue(Context context, PodDBAdapter adapter) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Extracting queue");
-
- Cursor itemlistCursor = adapter.getQueueCursor();
- List<FeedItem> items = extractItemlistFromCursor(adapter,
- itemlistCursor);
- itemlistCursor.close();
- loadFeedDataOfFeedItemlist(context, items);
-
- return items;
- }
-
- /**
- * Loads the IDs of the FeedItems in the queue. This method should be preferred over
- * {@link #getQueue(android.content.Context)} if the FeedItems of the queue are not needed.
- *
- * @param context A context that is used for opening a database connection.
- * @return A list of IDs sorted by the same order as the queue. The caller can wrap the returned
- * list in a {@link de.danoeh.antennapod.util.QueueAccess} object for easier access to the queue's properties.
- */
- public static List<Long> getQueueIDList(Context context) {
- PodDBAdapter adapter = new PodDBAdapter(context);
-
- adapter.open();
- List<Long> result = getQueueIDList(adapter);
- adapter.close();
-
- return result;
- }
-
- static List<Long> getQueueIDList(PodDBAdapter adapter) {
- adapter.open();
- Cursor queueCursor = adapter.getQueueIDCursor();
-
- List<Long> queueIds = new ArrayList<Long>(queueCursor.getCount());
- if (queueCursor.moveToFirst()) {
- do {
- queueIds.add(queueCursor.getLong(0));
- } while (queueCursor.moveToNext());
- }
- return queueIds;
- }
-
-
- /**
- * Loads a list of the FeedItems in the queue. If the FeedItems of the queue are not used directly, consider using
- * {@link #getQueueIDList(android.content.Context)} instead.
- *
- * @param context A context that is used for opening a database connection.
- * @return A list of FeedItems sorted by the same order as the queue. The caller can wrap the returned
- * list in a {@link de.danoeh.antennapod.util.QueueAccess} object for easier access to the queue's properties.
- */
- public static List<FeedItem> getQueue(Context context) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Extracting queue");
-
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- List<FeedItem> items = getQueue(context, adapter);
- adapter.close();
- return items;
- }
-
- /**
- * Loads a list of FeedItems whose episode has been downloaded.
- *
- * @param context A context that is used for opening a database connection.
- * @return A list of FeedItems whose episdoe has been downloaded.
- */
- public static List<FeedItem> getDownloadedItems(Context context) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Extracting downloaded items");
-
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
-
- Cursor itemlistCursor = adapter.getDownloadedItemsCursor();
- List<FeedItem> items = extractItemlistFromCursor(adapter,
- itemlistCursor);
- itemlistCursor.close();
- loadFeedDataOfFeedItemlist(context, items);
- Collections.sort(items, new FeedItemPubdateComparator());
-
- adapter.close();
- return items;
-
- }
-
- /**
- * Loads a list of FeedItems whose 'read'-attribute is set to false.
- *
- * @param context A context that is used for opening a database connection.
- * @return A list of FeedItems whose 'read'-attribute it set to false. If the FeedItems in the list are not used,
- * consider using {@link #getUnreadItemIds(android.content.Context)} instead.
- */
- public static List<FeedItem> getUnreadItemsList(Context context) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Extracting unread items list");
-
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
-
- Cursor itemlistCursor = adapter.getUnreadItemsCursor();
- List<FeedItem> items = extractItemlistFromCursor(adapter,
- itemlistCursor);
- itemlistCursor.close();
-
- loadFeedDataOfFeedItemlist(context, items);
-
- adapter.close();
-
- return items;
- }
-
- /**
- * Loads the IDs of the FeedItems whose 'read'-attribute is set to false.
- *
- * @param context A context that is used for opening a database connection.
- * @return A list of IDs of the FeedItems whose 'read'-attribute is set to false. This method should be preferred
- * over {@link #getUnreadItemsList(android.content.Context)} if the FeedItems in the UnreadItems list are not used.
- */
- public static long[] getUnreadItemIds(Context context) {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- Cursor cursor = adapter.getUnreadItemIdsCursor();
- long[] itemIds = new long[cursor.getCount()];
- int i = 0;
- if (cursor.moveToFirst()) {
- do {
- itemIds[i] = cursor.getLong(PodDBAdapter.KEY_ID_INDEX);
- i++;
- } while (cursor.moveToNext());
- }
- return itemIds;
- }
-
-
- /**
- * Loads a list of FeedItems sorted by pubDate in descending order.
- *
- * @param context A context that is used for opening a database connection.
- * @param limit The maximum number of episodes that should be loaded.
- */
- public static List<FeedItem> getRecentlyPublishedEpisodes(Context context, int limit) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Extracting recently published items list");
-
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
-
- Cursor itemlistCursor = adapter.getRecentlyPublishedItemsCursor(limit);
- List<FeedItem> items = extractItemlistFromCursor(adapter,
- itemlistCursor);
- itemlistCursor.close();
-
- loadFeedDataOfFeedItemlist(context, items);
-
- adapter.close();
-
- return items;
- }
-
- /**
- * Loads the playback history from the database. A FeedItem is in the playback history if playback of the correpsonding episode
- * has been completed at least once.
- *
- * @param context A context that is used for opening a database connection.
- * @return The playback history. The FeedItems are sorted by their media's playbackCompletionDate in descending order.
- * The size of the returned list is limited by {@link #PLAYBACK_HISTORY_SIZE}.
- */
- public static List<FeedItem> getPlaybackHistory(final Context context) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Loading playback history");
- final int PLAYBACK_HISTORY_SIZE = 50;
-
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
-
- Cursor mediaCursor = adapter.getCompletedMediaCursor(PLAYBACK_HISTORY_SIZE);
- String[] itemIds = new String[mediaCursor.getCount()];
- for (int i = 0; i < itemIds.length && mediaCursor.moveToPosition(i); i++) {
- itemIds[i] = Long.toString(mediaCursor.getLong(PodDBAdapter.KEY_MEDIA_FEEDITEM_INDEX));
- }
- mediaCursor.close();
- Cursor itemCursor = adapter.getFeedItemCursor(itemIds);
- List<FeedItem> items = extractItemlistFromCursor(adapter, itemCursor);
- loadFeedDataOfFeedItemlist(context, items);
- itemCursor.close();
- adapter.close();
-
- Collections.sort(items, new PlaybackCompletionDateComparator());
- return items;
- }
-
- /**
- * Loads the download log from the database.
- *
- * @param context A context that is used for opening a database connection.
- * @return A list with DownloadStatus objects that represent the download log.
- * The size of the returned list is limited by {@link #DOWNLOAD_LOG_SIZE}.
- */
- public static List<DownloadStatus> getDownloadLog(Context context) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Extracting DownloadLog");
-
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- Cursor logCursor = adapter.getDownloadLogCursor(DOWNLOAD_LOG_SIZE);
- List<DownloadStatus> downloadLog = new ArrayList<DownloadStatus>(
- logCursor.getCount());
-
- if (logCursor.moveToFirst()) {
- do {
- long id = logCursor.getLong(PodDBAdapter.KEY_ID_INDEX);
-
- long feedfileId = logCursor
- .getLong(PodDBAdapter.KEY_FEEDFILE_INDEX);
- int feedfileType = logCursor
- .getInt(PodDBAdapter.KEY_FEEDFILETYPE_INDEX);
- boolean successful = logCursor
- .getInt(PodDBAdapter.KEY_SUCCESSFUL_INDEX) > 0;
- int reason = logCursor.getInt(PodDBAdapter.KEY_REASON_INDEX);
- String reasonDetailed = logCursor
- .getString(PodDBAdapter.KEY_REASON_DETAILED_INDEX);
- String title = logCursor
- .getString(PodDBAdapter.KEY_DOWNLOADSTATUS_TITLE_INDEX);
- Date completionDate = new Date(
- logCursor
- .getLong(PodDBAdapter.KEY_COMPLETION_DATE_INDEX)
- );
- downloadLog.add(new DownloadStatus(id, title, feedfileId,
- feedfileType, successful, DownloadError.fromCode(reason), completionDate,
- reasonDetailed));
-
- } while (logCursor.moveToNext());
- }
- logCursor.close();
- Collections.sort(downloadLog, new DownloadStatusComparator());
- return downloadLog;
- }
-
- /**
- * Loads the FeedItemStatistics objects of all Feeds in the database. This method should be preferred over
- * {@link #getFeedItemList(android.content.Context, de.danoeh.antennapod.feed.Feed)} if only metadata about
- * the FeedItems is needed.
- *
- * @param context A context that is used for opening a database connection.
- * @return A list of FeedItemStatistics objects sorted alphabetically by their Feed's title.
- */
- public static List<FeedItemStatistics> getFeedStatisticsList(final Context context) {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- List<FeedItemStatistics> result = new ArrayList<FeedItemStatistics>();
- Cursor cursor = adapter.getFeedStatisticsCursor();
- if (cursor.moveToFirst()) {
- do {
- result.add(new FeedItemStatistics(cursor.getLong(PodDBAdapter.IDX_FEEDSTATISTICS_FEED),
- cursor.getInt(PodDBAdapter.IDX_FEEDSTATISTICS_NUM_ITEMS),
- cursor.getInt(PodDBAdapter.IDX_FEEDSTATISTICS_NEW_ITEMS),
- cursor.getInt(PodDBAdapter.IDX_FEEDSTATISTICS_IN_PROGRESS_EPISODES),
- new Date(cursor.getLong(PodDBAdapter.IDX_FEEDSTATISTICS_LATEST_EPISODE))));
- } while (cursor.moveToNext());
- }
-
- cursor.close();
- adapter.close();
- return result;
- }
-
- /**
- * Loads a specific Feed from the database.
- *
- * @param context A context that is used for opening a database connection.
- * @param feedId The ID of the Feed
- * @return The Feed or null if the Feed could not be found. The Feeds FeedItems will also be loaded from the
- * database and the items-attribute will be set correctly.
- */
- public static Feed getFeed(final Context context, final long feedId) {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- Feed result = getFeed(context, feedId, adapter);
- adapter.close();
- return result;
- }
-
- static Feed getFeed(final Context context, final long feedId, PodDBAdapter adapter) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Loading feed with id " + feedId);
- Feed feed = null;
-
- Cursor feedCursor = adapter.getFeedCursor(feedId);
- if (feedCursor.moveToFirst()) {
- feed = extractFeedFromCursorRow(adapter, feedCursor);
- feed.setItems(getFeedItemList(context, feed));
- } else {
- Log.e(TAG, "getFeed could not find feed with id " + feedId);
- }
- feedCursor.close();
- return feed;
- }
-
- static FeedItem getFeedItem(final Context context, final long itemId, PodDBAdapter adapter) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Loading feeditem with id " + itemId);
- FeedItem item = null;
-
- Cursor itemCursor = adapter.getFeedItemCursor(Long.toString(itemId));
- if (itemCursor.moveToFirst()) {
- List<FeedItem> list = extractItemlistFromCursor(adapter, itemCursor);
- if (list.size() > 0) {
- item = list.get(0);
- loadFeedDataOfFeedItemlist(context, list);
- }
- }
- return item;
-
- }
-
- /**
- * Loads a specific FeedItem from the database.
- *
- * @param context A context that is used for opening a database connection.
- * @param itemId The ID of the FeedItem
- * @return The FeedItem or null if the FeedItem could not be found. All FeedComponent-attributes of the FeedItem will
- * also be loaded from the database.
- */
- public static FeedItem getFeedItem(final Context context, final long itemId) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Loading feeditem with id " + itemId);
-
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- FeedItem item = getFeedItem(context, itemId, adapter);
- adapter.close();
- return item;
-
- }
-
- /**
- * Loads additional information about a FeedItem, e.g. shownotes
- *
- * @param context A context that is used for opening a database connection.
- * @param item The FeedItem
- */
- public static void loadExtraInformationOfFeedItem(final Context context, final FeedItem item) {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- Cursor extraCursor = adapter.getExtraInformationOfItem(item);
- if (extraCursor.moveToFirst()) {
- String description = extraCursor
- .getString(PodDBAdapter.IDX_FI_EXTRA_DESCRIPTION);
- String contentEncoded = extraCursor
- .getString(PodDBAdapter.IDX_FI_EXTRA_CONTENT_ENCODED);
- item.setDescription(description);
- item.setContentEncoded(contentEncoded);
- }
- adapter.close();
- }
-
- /**
- * Returns the number of downloaded episodes.
- *
- * @param context A context that is used for opening a database connection.
- * @return The number of downloaded episodes.
- */
- public static int getNumberOfDownloadedEpisodes(final Context context) {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- final int result = adapter.getNumberOfDownloadedEpisodes();
- adapter.close();
- return result;
- }
-
- /**
- * Returns the number of unread items.
- *
- * @param context A context that is used for opening a database connection.
- * @return The number of unread items.
- */
- public static int getNumberOfUnreadItems(final Context context) {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- final int result = adapter.getNumberOfUnreadItems();
- adapter.close();
- return result;
- }
-
- /**
- * Searches the DB for a FeedImage of the given id.
- *
- * @param context A context that is used for opening a database connection.
- * @param imageId The id of the object
- * @return The found object
- */
- public static FeedImage getFeedImage(final Context context, final long imageId) {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- FeedImage result = getFeedImage(adapter, imageId);
- adapter.close();
- return result;
- }
-
- /**
- * Searches the DB for a FeedImage of the given id.
- *
- * @param id The id of the object
- * @return The found object
- */
- static FeedImage getFeedImage(PodDBAdapter adapter, final long id) {
- Cursor cursor = adapter.getImageCursor(id);
- if ((cursor.getCount() == 0) || !cursor.moveToFirst()) {
- throw new SQLException("No FeedImage found at index: " + id);
- }
- FeedImage image = new FeedImage(id, cursor.getString(cursor
- .getColumnIndex(PodDBAdapter.KEY_TITLE)),
- cursor.getString(cursor
- .getColumnIndex(PodDBAdapter.KEY_FILE_URL)),
- cursor.getString(cursor
- .getColumnIndex(PodDBAdapter.KEY_DOWNLOAD_URL)),
- cursor.getInt(cursor
- .getColumnIndex(PodDBAdapter.KEY_DOWNLOADED)) > 0
- );
- cursor.close();
- return image;
- }
-
- /**
- * Searches the DB for a FeedMedia of the given id.
- *
- * @param context A context that is used for opening a database connection.
- * @param mediaId The id of the object
- * @return The found object
- */
- public static FeedMedia getFeedMedia(final Context context, final long mediaId) {
- PodDBAdapter adapter = new PodDBAdapter(context);
-
- adapter.open();
- Cursor mediaCursor = adapter.getSingleFeedMediaCursor(mediaId);
-
- FeedMedia media = null;
- if (mediaCursor.moveToFirst()) {
- final long itemId = mediaCursor.getLong(PodDBAdapter.KEY_MEDIA_FEEDITEM_INDEX);
- media = extractFeedMediaFromCursorRow(mediaCursor);
- FeedItem item = getFeedItem(context, itemId);
- if (media != null && item != null) {
- media.setItem(item);
- item.setMedia(media);
- }
- }
-
- mediaCursor.close();
- adapter.close();
-
- return media;
- }
-
- /**
- * Returns the flattr queue as a List of FlattrThings. The list consists of Feeds and FeedItems.
- *
- * @param context A context that is used for opening a database connection.
- * @return The flattr queue as a List.
- */
- public static List<FlattrThing> getFlattrQueue(Context context) {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- List<FlattrThing> result = new ArrayList<FlattrThing>();
-
- // load feeds
- Cursor feedCursor = adapter.getFeedsInFlattrQueueCursor();
- if (feedCursor.moveToFirst()) {
- do {
- result.add(extractFeedFromCursorRow(adapter, feedCursor));
- } while (feedCursor.moveToNext());
- }
- feedCursor.close();
-
- //load feed items
- Cursor feedItemCursor = adapter.getFeedItemsInFlattrQueueCursor();
- result.addAll(extractItemlistFromCursor(adapter, feedItemCursor));
- feedItemCursor.close();
-
- adapter.close();
- Log.d(TAG, "Returning flattrQueueIterator for queue with " + result.size() + " items.");
- return result;
- }
-
-
- /**
- * Returns true if the flattr queue is empty.
- *
- * @param context A context that is used for opening a database connection.
- */
- public static boolean getFlattrQueueEmpty(Context context) {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- boolean empty = adapter.getFlattrQueueSize() == 0;
- adapter.close();
- return empty;
- }
-
- /**
- * Returns data necessary for displaying the navigation drawer. This includes
- * the list of subscriptions, the number of items in the queue and the number of unread
- * items.
- *
- * @param context A context that is used for opening a database connection.
- */
- public static NavDrawerData getNavDrawerData(Context context) {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- List<Feed> feeds = getFeedList(adapter);
- int queueSize = adapter.getQueueSize();
- int numUnreadItems = adapter.getNumberOfUnreadItems();
- NavDrawerData result = new NavDrawerData(feeds, queueSize, numUnreadItems);
- adapter.close();
- return result;
- }
-
- public static class NavDrawerData {
- public List<Feed> feeds;
- public int queueSize;
- public int numUnreadItems;
-
- public NavDrawerData(List<Feed> feeds, int queueSize, int numUnreadItems) {
- this.feeds = feeds;
- this.queueSize = queueSize;
- this.numUnreadItems = numUnreadItems;
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/storage/DBTasks.java b/src/de/danoeh/antennapod/storage/DBTasks.java
deleted file mode 100644
index a230ba797..000000000
--- a/src/de/danoeh/antennapod/storage/DBTasks.java
+++ /dev/null
@@ -1,895 +0,0 @@
-package de.danoeh.antennapod.storage;
-
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.util.Log;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.asynctask.FlattrClickWorker;
-import de.danoeh.antennapod.asynctask.FlattrStatusFetcher;
-import de.danoeh.antennapod.feed.*;
-import de.danoeh.antennapod.preferences.UserPreferences;
-import de.danoeh.antennapod.service.GpodnetSyncService;
-import de.danoeh.antennapod.service.download.DownloadStatus;
-import de.danoeh.antennapod.service.playback.PlaybackService;
-import de.danoeh.antennapod.util.DownloadError;
-import de.danoeh.antennapod.util.NetworkUtils;
-import de.danoeh.antennapod.util.QueueAccess;
-import de.danoeh.antennapod.util.comparator.FeedItemPubdateComparator;
-import de.danoeh.antennapod.util.exception.MediaFileNotFoundException;
-import de.danoeh.antennapod.util.flattr.FlattrUtils;
-
-import java.util.*;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * Provides methods for doing common tasks that use DBReader and DBWriter.
- */
-public final class DBTasks {
- private static final String TAG = "DBTasks";
-
- /**
- * Executor service used by the autodownloadUndownloadedEpisodes method.
- */
- private static ExecutorService autodownloadExec;
-
- static {
- autodownloadExec = Executors.newSingleThreadExecutor(new ThreadFactory() {
- @Override
- public Thread newThread(Runnable r) {
- Thread t = new Thread(r);
- t.setPriority(Thread.MIN_PRIORITY);
- return t;
- }
- });
- }
-
- private DBTasks() {
- }
-
- /**
- * Removes the feed with the given download url. This method should NOT be executed on the GUI thread.
- *
- * @param context Used for accessing the db
- * @param downloadUrl URL of the feed.
- */
- public static void removeFeedWithDownloadUrl(Context context, String downloadUrl) {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- Cursor cursor = adapter.getFeedCursorDownloadUrls();
- long feedID = 0;
- if (cursor.moveToFirst()) {
- do {
- if (cursor.getString(1).equals(downloadUrl)) {
- feedID = cursor.getLong(0);
- }
- } while (cursor.moveToNext());
- }
- cursor.close();
- adapter.close();
-
- if (feedID != 0) {
- try {
- DBWriter.deleteFeed(context, feedID).get();
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
- } else {
- Log.w(TAG, "removeFeedWithDownloadUrl: Could not find feed with url: " + downloadUrl);
- }
- }
-
- /**
- * Starts playback of a FeedMedia object's file. This method will build an Intent based on the given parameters to
- * start the {@link PlaybackService}.
- *
- * @param context Used for sending starting Services and Activities.
- * @param media The FeedMedia object.
- * @param showPlayer If true, starts the appropriate player activity ({@link de.danoeh.antennapod.activity.AudioplayerActivity}
- * or {@link de.danoeh.antennapod.activity.VideoplayerActivity}
- * @param startWhenPrepared Parameter for the {@link PlaybackService} start intent. If true, playback will start as
- * soon as the PlaybackService has finished loading the FeedMedia object's file.
- * @param shouldStream Parameter for the {@link PlaybackService} start intent. If true, the FeedMedia object's file
- * will be streamed, otherwise the downloaded file will be used. If the downloaded file cannot be
- * found, the PlaybackService will shutdown and the database entry of the FeedMedia object will be
- * corrected.
- */
- public static void playMedia(final Context context, final FeedMedia media,
- boolean showPlayer, boolean startWhenPrepared, boolean shouldStream) {
- try {
- if (!shouldStream) {
- if (media.fileExists() == false) {
- throw new MediaFileNotFoundException(
- "No episode was found at " + media.getFile_url(),
- media);
- }
- }
- // Start playback Service
- Intent launchIntent = new Intent(context, PlaybackService.class);
- launchIntent.putExtra(PlaybackService.EXTRA_PLAYABLE, media);
- launchIntent.putExtra(PlaybackService.EXTRA_START_WHEN_PREPARED,
- startWhenPrepared);
- launchIntent.putExtra(PlaybackService.EXTRA_SHOULD_STREAM,
- shouldStream);
- launchIntent.putExtra(PlaybackService.EXTRA_PREPARE_IMMEDIATELY,
- true);
- context.startService(launchIntent);
- if (showPlayer) {
- // Launch media player
- context.startActivity(PlaybackService.getPlayerActivityIntent(
- context, media));
- }
- DBWriter.addQueueItemAt(context, media.getItem().getId(), 0, false);
- } catch (MediaFileNotFoundException e) {
- e.printStackTrace();
- if (media.isPlaying()) {
- context.sendBroadcast(new Intent(
- PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE));
- }
- notifyMissingFeedMediaFile(context, media);
- }
- }
-
- private static AtomicBoolean isRefreshing = new AtomicBoolean(false);
-
- /**
- * Refreshes a given list of Feeds in a separate Thread. This method might ignore subsequent calls if it is still
- * enqueuing Feeds for download from a previous call
- *
- * @param context Might be used for accessing the database
- * @param feeds List of Feeds that should be refreshed.
- */
- public static void refreshAllFeeds(final Context context,
- final List<Feed> feeds) {
- if (isRefreshing.compareAndSet(false, true)) {
- new Thread() {
- public void run() {
- if (feeds != null) {
- refreshFeeds(context, feeds);
- } else {
- refreshFeeds(context, DBReader.getFeedList(context));
- }
- isRefreshing.set(false);
-
- if (FlattrUtils.hasToken()) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Flattring all pending things.");
- new FlattrClickWorker(context).executeAsync(); // flattr pending things
-
- if (BuildConfig.DEBUG) Log.d(TAG, "Fetching flattr status.");
- new FlattrStatusFetcher(context).start();
-
- }
- GpodnetSyncService.sendSyncIntent(context);
- autodownloadUndownloadedItems(context);
- }
- }.start();
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "Ignoring request to refresh all feeds: Refresh lock is locked");
- }
- }
-
- /**
- * Used by refreshExpiredFeeds to determine which feeds should be refreshed.
- * This method will use the value specified in the UserPreferences as the
- * expiration time.
- *
- * @param context Used for DB access.
- * @return A list of expired feeds. An empty list will be returned if there
- * are no expired feeds.
- */
- public static List<Feed> getExpiredFeeds(final Context context) {
- long millis = UserPreferences.getUpdateInterval();
-
- if (millis > 0) {
-
- List<Feed> feedList = DBReader.getExpiredFeedsList(context,
- millis);
- if (feedList.size() > 0) {
- refreshFeeds(context, feedList);
- }
- return feedList;
- } else {
- return new ArrayList<Feed>();
- }
- }
-
- /**
- * Refreshes expired Feeds in the list returned by the getExpiredFeedsList(Context, long) method in DBReader.
- * The expiration date parameter is determined by the update interval specified in {@link UserPreferences}.
- *
- * @param context Used for DB access.
- */
- public static void refreshExpiredFeeds(final Context context) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Refreshing expired feeds");
-
- new Thread() {
- public void run() {
- refreshFeeds(context, getExpiredFeeds(context));
- }
- }.start();
- }
-
- private static void refreshFeeds(final Context context,
- final List<Feed> feedList) {
-
- for (Feed feed : feedList) {
- try {
- refreshFeed(context, feed);
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- DBWriter.addDownloadStatus(
- context,
- new DownloadStatus(feed, feed
- .getHumanReadableIdentifier(),
- DownloadError.ERROR_REQUEST_ERROR, false, e
- .getMessage()
- )
- );
- }
- }
-
- }
-
- /**
- * Updates a specific Feed.
- *
- * @param context Used for requesting the download.
- * @param feed The Feed object.
- */
- public static void refreshFeed(Context context, Feed feed)
- throws DownloadRequestException {
- Feed f;
- if (feed.getPreferences() == null) {
- f = new Feed(feed.getDownload_url(), new Date(), feed.getTitle());
- } else {
- f = new Feed(feed.getDownload_url(), new Date(), feed.getTitle(),
- feed.getPreferences().getUsername(), feed.getPreferences().getPassword());
- }
- f.setId(feed.getId());
- DownloadRequester.getInstance().downloadFeed(context, f);
- }
-
- /**
- * Notifies the database about a missing FeedImage file. This method will attempt to re-download the file.
- *
- * @param context Used for requesting the download.
- * @param image The FeedImage object.
- */
- public static void notifyInvalidImageFile(final Context context,
- final FeedImage image) {
- Log.i(TAG,
- "The DB was notified about an invalid image download. It will now try to re-download the image file");
- try {
- DownloadRequester.getInstance().downloadImage(context, image);
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- Log.w(TAG, "Failed to download invalid feed image");
- }
- }
-
- /**
- * Notifies the database about a missing FeedMedia file. This method will correct the FeedMedia object's values in the
- * DB and send a FeedUpdateBroadcast.
- */
- public static void notifyMissingFeedMediaFile(final Context context,
- final FeedMedia media) {
- Log.i(TAG,
- "The feedmanager was notified about a missing episode. It will update its database now.");
- media.setDownloaded(false);
- media.setFile_url(null);
- DBWriter.setFeedMedia(context, media);
- EventDistributor.getInstance().sendFeedUpdateBroadcast();
- }
-
- /**
- * Request the download of all objects in the queue. from a separate Thread.
- *
- * @param context Used for requesting the download an accessing the database.
- */
- public static void downloadAllItemsInQueue(final Context context) {
- new Thread() {
- public void run() {
- List<FeedItem> queue = DBReader.getQueue(context);
- if (!queue.isEmpty()) {
- try {
- downloadFeedItems(context,
- queue.toArray(new FeedItem[queue.size()]));
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- }
- }
- }
- }.start();
- }
-
- /**
- * Requests the download of a list of FeedItem objects.
- *
- * @param context Used for requesting the download and accessing the DB.
- * @param items The FeedItem objects.
- */
- public static void downloadFeedItems(final Context context,
- FeedItem... items) throws DownloadRequestException {
- downloadFeedItems(true, context, items);
- }
-
- private static void downloadFeedItems(boolean performAutoCleanup,
- final Context context, final FeedItem... items)
- throws DownloadRequestException {
- final DownloadRequester requester = DownloadRequester.getInstance();
-
- if (performAutoCleanup) {
- new Thread() {
-
- @Override
- public void run() {
- performAutoCleanup(context,
- getPerformAutoCleanupArgs(context, items.length));
- }
-
- }.start();
- }
- for (FeedItem item : items) {
- if (item.getMedia() != null
- && !requester.isDownloadingFile(item.getMedia())
- && !item.getMedia().isDownloaded()) {
- if (items.length > 1) {
- try {
- requester.downloadMedia(context, item.getMedia());
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- DBWriter.addDownloadStatus(context,
- new DownloadStatus(item.getMedia(), item
- .getMedia()
- .getHumanReadableIdentifier(),
- DownloadError.ERROR_REQUEST_ERROR,
- false, e.getMessage()
- )
- );
- }
- } else {
- requester.downloadMedia(context, item.getMedia());
- }
- }
- }
- }
-
- private static int getNumberOfUndownloadedEpisodes(
- final List<FeedItem> queue, final List<FeedItem> unreadItems) {
- int counter = 0;
- for (FeedItem item : queue) {
- if (item.hasMedia() && !item.getMedia().isDownloaded()
- && !item.getMedia().isPlaying()
- && item.getFeed().getPreferences().getAutoDownload()) {
- counter++;
- }
- }
- for (FeedItem item : unreadItems) {
- if (item.hasMedia() && !item.getMedia().isDownloaded()
- && item.getFeed().getPreferences().getAutoDownload()) {
- counter++;
- }
- }
- return counter;
- }
-
- /**
- * Looks for undownloaded episodes in the queue or list of unread items and request a download if
- * 1. Network is available
- * 2. There is free space in the episode cache
- * This method is executed on an internal single thread executor.
- *
- * @param context Used for accessing the DB.
- * @param mediaIds If this list is not empty, the method will only download a candidate for automatic downloading if
- * its media ID is in the mediaIds list.
- * @return A Future that can be used for waiting for the methods completion.
- */
- public static Future<?> autodownloadUndownloadedItems(final Context context, final long... mediaIds) {
- return autodownloadExec.submit(new Runnable() {
- @Override
- public void run() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Performing auto-dl of undownloaded episodes");
- if (NetworkUtils.autodownloadNetworkAvailable(context)
- && UserPreferences.isEnableAutodownload()) {
- final List<FeedItem> queue = DBReader.getQueue(context);
- final List<FeedItem> unreadItems = DBReader
- .getUnreadItemsList(context);
-
- int undownloadedEpisodes = getNumberOfUndownloadedEpisodes(queue,
- unreadItems);
- int downloadedEpisodes = DBReader
- .getNumberOfDownloadedEpisodes(context);
- int deletedEpisodes = performAutoCleanup(context,
- getPerformAutoCleanupArgs(context, undownloadedEpisodes));
- int episodeSpaceLeft = undownloadedEpisodes;
- boolean cacheIsUnlimited = UserPreferences.getEpisodeCacheSize() == UserPreferences
- .getEpisodeCacheSizeUnlimited();
-
- if (!cacheIsUnlimited
- && UserPreferences.getEpisodeCacheSize() < downloadedEpisodes
- + undownloadedEpisodes) {
- episodeSpaceLeft = UserPreferences.getEpisodeCacheSize()
- - (downloadedEpisodes - deletedEpisodes);
- }
-
- Arrays.sort(mediaIds); // sort for binary search
- final boolean ignoreMediaIds = mediaIds.length == 0;
- List<FeedItem> itemsToDownload = new ArrayList<FeedItem>();
-
- if (episodeSpaceLeft > 0 && undownloadedEpisodes > 0) {
- for (int i = 0; i < queue.size(); i++) { // ignore playing item
- FeedItem item = queue.get(i);
- long mediaId = (item.hasMedia()) ? item.getMedia().getId() : -1;
- if ((ignoreMediaIds || Arrays.binarySearch(mediaIds, mediaId) >= 0)
- && item.hasMedia()
- && !item.getMedia().isDownloaded()
- && !item.getMedia().isPlaying()
- && item.getFeed().getPreferences().getAutoDownload()) {
- itemsToDownload.add(item);
- episodeSpaceLeft--;
- undownloadedEpisodes--;
- if (episodeSpaceLeft == 0 || undownloadedEpisodes == 0) {
- break;
- }
- }
- }
- }
-
- if (episodeSpaceLeft > 0 && undownloadedEpisodes > 0) {
- for (FeedItem item : unreadItems) {
- long mediaId = (item.hasMedia()) ? item.getMedia().getId() : -1;
- if ((ignoreMediaIds || Arrays.binarySearch(mediaIds, mediaId) >= 0)
- && item.hasMedia()
- && !item.getMedia().isDownloaded()
- && item.getFeed().getPreferences().getAutoDownload()) {
- itemsToDownload.add(item);
- episodeSpaceLeft--;
- undownloadedEpisodes--;
- if (episodeSpaceLeft == 0 || undownloadedEpisodes == 0) {
- break;
- }
- }
- }
- }
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Enqueueing " + itemsToDownload.size()
- + " items for download");
-
- try {
- downloadFeedItems(false, context,
- itemsToDownload.toArray(new FeedItem[itemsToDownload
- .size()])
- );
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- }
-
- }
- }
- });
-
- }
-
- private static int getPerformAutoCleanupArgs(Context context,
- final int episodeNumber) {
- if (episodeNumber >= 0
- && UserPreferences.getEpisodeCacheSize() != UserPreferences
- .getEpisodeCacheSizeUnlimited()) {
- int downloadedEpisodes = DBReader
- .getNumberOfDownloadedEpisodes(context);
- if (downloadedEpisodes + episodeNumber >= UserPreferences
- .getEpisodeCacheSize()) {
-
- return downloadedEpisodes + episodeNumber
- - UserPreferences.getEpisodeCacheSize();
- }
- }
- return 0;
- }
-
- /**
- * Removed downloaded episodes outside of the queue if the episode cache is full. Episodes with a smaller
- * 'playbackCompletionDate'-value will be deleted first.
- * <p/>
- * This method should NOT be executed on the GUI thread.
- *
- * @param context Used for accessing the DB.
- */
- public static void performAutoCleanup(final Context context) {
- performAutoCleanup(context, getPerformAutoCleanupArgs(context, 0));
- }
-
- private static int performAutoCleanup(final Context context,
- final int episodeNumber) {
- List<FeedItem> candidates = new ArrayList<FeedItem>();
- List<FeedItem> downloadedItems = DBReader.getDownloadedItems(context);
- QueueAccess queue = QueueAccess.IDListAccess(DBReader.getQueueIDList(context));
- List<FeedItem> delete;
- for (FeedItem item : downloadedItems) {
- if (item.hasMedia() && item.getMedia().isDownloaded()
- && !queue.contains(item.getId()) && item.isRead()) {
- candidates.add(item);
- }
-
- }
-
- Collections.sort(candidates, new Comparator<FeedItem>() {
- @Override
- public int compare(FeedItem lhs, FeedItem rhs) {
- Date l = lhs.getMedia().getPlaybackCompletionDate();
- Date r = rhs.getMedia().getPlaybackCompletionDate();
-
- if (l == null) {
- l = new Date(0);
- }
- if (r == null) {
- r = new Date(0);
- }
- return l.compareTo(r);
- }
- });
-
- if (candidates.size() > episodeNumber) {
- delete = candidates.subList(0, episodeNumber);
- } else {
- delete = candidates;
- }
-
- for (FeedItem item : delete) {
- try {
- DBWriter.deleteFeedMediaOfItem(context, item.getMedia().getId()).get();
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
- }
-
- int counter = delete.size();
-
- if (BuildConfig.DEBUG)
- Log.d(TAG, String.format(
- "Auto-delete deleted %d episodes (%d requested)", counter,
- episodeNumber));
-
- return counter;
- }
-
- /**
- * Adds all FeedItem objects whose 'read'-attribute is false to the queue in a separate thread.
- */
- public static void enqueueAllNewItems(final Context context) {
- long[] unreadItems = DBReader.getUnreadItemIds(context);
- DBWriter.addQueueItem(context, unreadItems);
- }
-
- /**
- * Returns the successor of a FeedItem in the queue.
- *
- * @param context Used for accessing the DB.
- * @param itemId ID of the FeedItem
- * @param queue Used for determining the successor of the item. If this parameter is null, the method will load
- * the queue from the database in the same thread.
- * @return Successor of the FeedItem or null if the FeedItem is not in the queue or has no successor.
- */
- public static FeedItem getQueueSuccessorOfItem(Context context,
- final long itemId, List<FeedItem> queue) {
- FeedItem result = null;
- if (queue == null) {
- queue = DBReader.getQueue(context);
- }
- if (queue != null) {
- Iterator<FeedItem> iterator = queue.iterator();
- while (iterator.hasNext()) {
- FeedItem item = iterator.next();
- if (item.getId() == itemId) {
- if (iterator.hasNext()) {
- result = iterator.next();
- }
- break;
- }
- }
- }
- return result;
- }
-
- /**
- * Loads the queue from the database and checks if the specified FeedItem is in the queue.
- * This method should NOT be executed in the GUI thread.
- *
- * @param context Used for accessing the DB.
- * @param feedItemId ID of the FeedItem
- */
- public static boolean isInQueue(Context context, final long feedItemId) {
- List<Long> queue = DBReader.getQueueIDList(context);
- return QueueAccess.IDListAccess(queue).contains(feedItemId);
- }
-
- private static Feed searchFeedByIdentifyingValueOrID(Context context, PodDBAdapter adapter,
- Feed feed) {
- if (feed.getId() != 0) {
- return DBReader.getFeed(context, feed.getId(), adapter);
- } else {
- List<Feed> feeds = DBReader.getFeedList(context);
- for (Feed f : feeds) {
- if (f.getIdentifyingValue().equals(feed.getIdentifyingValue())) {
- f.setItems(DBReader.getFeedItemList(context, f));
- return f;
- }
- }
- }
- return null;
- }
-
- /**
- * Get a FeedItem by its identifying value.
- */
- private static FeedItem searchFeedItemByIdentifyingValue(Feed feed,
- String identifier) {
- for (FeedItem item : feed.getItems()) {
- if (item.getIdentifyingValue().equals(identifier)) {
- return item;
- }
- }
- return null;
- }
-
- /**
- * Adds new Feeds to the database or updates the old versions if they already exists. If another Feed with the same
- * identifying value already exists, this method will add new FeedItems from the new Feed to the existing Feed.
- * These FeedItems will be marked as unread.
- * <p/>
- * This method can update multiple feeds at once. Submitting a feed twice in the same method call can result in undefined behavior.
- * <p/>
- * This method should NOT be executed on the GUI thread.
- *
- * @param context Used for accessing the DB.
- * @param newFeeds The new Feed objects.
- * @return The updated Feeds from the database if it already existed, or the new Feed from the parameters otherwise.
- */
- public static synchronized Feed[] updateFeed(final Context context,
- final Feed... newFeeds) {
- List<Feed> newFeedsList = new ArrayList<Feed>();
- List<Feed> updatedFeedsList = new ArrayList<Feed>();
- Feed[] resultFeeds = new Feed[newFeeds.length];
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
-
- for (int feedIdx = 0; feedIdx < newFeeds.length; feedIdx++) {
-
- final Feed newFeed = newFeeds[feedIdx];
-
- // Look up feed in the feedslist
- final Feed savedFeed = searchFeedByIdentifyingValueOrID(context, adapter,
- newFeed);
- if (savedFeed == null) {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "Found no existing Feed with title "
- + newFeed.getTitle() + ". Adding as new one."
- );
- // Add a new Feed
- newFeedsList.add(newFeed);
- resultFeeds[feedIdx] = newFeed;
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Feed with title " + newFeed.getTitle()
- + " already exists. Syncing new with existing one.");
-
- Collections.sort(newFeed.getItems(), new FeedItemPubdateComparator());
- if (savedFeed.compareWithOther(newFeed)) {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "Feed has updated attribute values. Updating old feed's attributes");
- savedFeed.updateFromOther(newFeed);
- }
- if (savedFeed.getPreferences().compareWithOther(newFeed.getPreferences())) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Feed has updated preferences. Updating old feed's preferences");
- savedFeed.getPreferences().updateFromOther(newFeed.getPreferences());
- }
- // Look for new or updated Items
- for (int idx = 0; idx < newFeed.getItems().size(); idx++) {
- final FeedItem item = newFeed.getItems().get(idx);
- FeedItem oldItem = searchFeedItemByIdentifyingValue(savedFeed,
- item.getIdentifyingValue());
- if (oldItem == null) {
- // item is new
- final int i = idx;
- item.setFeed(savedFeed);
- savedFeed.getItems().add(i, item);
- item.setRead(false);
- } else {
- oldItem.updateFromOther(item);
- }
- }
- // update attributes
- savedFeed.setLastUpdate(newFeed.getLastUpdate());
- savedFeed.setType(newFeed.getType());
-
- updatedFeedsList.add(savedFeed);
- resultFeeds[feedIdx] = savedFeed;
- }
- }
-
- adapter.close();
-
- try {
- DBWriter.addNewFeed(context, newFeedsList.toArray(new Feed[newFeedsList.size()])).get();
- DBWriter.setCompleteFeed(context, updatedFeedsList.toArray(new Feed[updatedFeedsList.size()])).get();
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
-
- EventDistributor.getInstance().sendFeedUpdateBroadcast();
-
- return resultFeeds;
- }
-
- /**
- * Searches the titles of FeedItems of a specific Feed for a given
- * string.
- *
- * @param context Used for accessing the DB.
- * @param feedID The id of the feed whose items should be searched.
- * @param query The search string.
- * @return A FutureTask object that executes the search request and returns the search result as a List of FeedItems.
- */
- public static FutureTask<List<FeedItem>> searchFeedItemTitle(final Context context,
- final long feedID, final String query) {
- return new FutureTask<List<FeedItem>>(new QueryTask<List<FeedItem>>(context) {
- @Override
- public void execute(PodDBAdapter adapter) {
- Cursor searchResult = adapter.searchItemTitles(feedID,
- query);
- List<FeedItem> items = DBReader.extractItemlistFromCursor(context, searchResult);
- DBReader.loadFeedDataOfFeedItemlist(context, items);
- setResult(items);
- searchResult.close();
- }
- });
- }
-
- /**
- * Searches the descriptions of FeedItems of a specific Feed for a given
- * string.
- *
- * @param context Used for accessing the DB.
- * @param feedID The id of the feed whose items should be searched.
- * @param query The search string
- * @return A FutureTask object that executes the search request and returns the search result as a List of FeedItems.
- */
- public static FutureTask<List<FeedItem>> searchFeedItemDescription(final Context context,
- final long feedID, final String query) {
- return new FutureTask<List<FeedItem>>(new QueryTask<List<FeedItem>>(context) {
- @Override
- public void execute(PodDBAdapter adapter) {
- Cursor searchResult = adapter.searchItemDescriptions(feedID,
- query);
- List<FeedItem> items = DBReader.extractItemlistFromCursor(context, searchResult);
- DBReader.loadFeedDataOfFeedItemlist(context, items);
- setResult(items);
- searchResult.close();
- }
- });
- }
-
- /**
- * Searches the contentEncoded-value of FeedItems of a specific Feed for a given
- * string.
- *
- * @param context Used for accessing the DB.
- * @param feedID The id of the feed whose items should be searched.
- * @param query The search string
- * @return A FutureTask object that executes the search request and returns the search result as a List of FeedItems.
- */
- public static FutureTask<List<FeedItem>> searchFeedItemContentEncoded(final Context context,
- final long feedID, final String query) {
- return new FutureTask<List<FeedItem>>(new QueryTask<List<FeedItem>>(context) {
- @Override
- public void execute(PodDBAdapter adapter) {
- Cursor searchResult = adapter.searchItemContentEncoded(feedID,
- query);
- List<FeedItem> items = DBReader.extractItemlistFromCursor(context, searchResult);
- DBReader.loadFeedDataOfFeedItemlist(context, items);
- setResult(items);
- searchResult.close();
- }
- });
- }
-
- /**
- * Searches chapters of the FeedItems of a specific Feed for a given string.
- *
- * @param context Used for accessing the DB.
- * @param feedID The id of the feed whose items should be searched.
- * @param query The search string
- * @return A FutureTask object that executes the search request and returns the search result as a List of FeedItems.
- */
- public static FutureTask<List<FeedItem>> searchFeedItemChapters(final Context context,
- final long feedID, final String query) {
- return new FutureTask<List<FeedItem>>(new QueryTask<List<FeedItem>>(context) {
- @Override
- public void execute(PodDBAdapter adapter) {
- Cursor searchResult = adapter.searchItemChapters(feedID,
- query);
- List<FeedItem> items = DBReader.extractItemlistFromCursor(context, searchResult);
- DBReader.loadFeedDataOfFeedItemlist(context, items);
- setResult(items);
- searchResult.close();
- }
- });
- }
-
- /**
- * A runnable which should be used for database queries. The onCompletion
- * method is executed on the database executor to handle Cursors correctly.
- * This class automatically creates a PodDBAdapter object and closes it when
- * it is no longer in use.
- */
- static abstract class QueryTask<T> implements Callable<T> {
- private T result;
- private Context context;
-
- public QueryTask(Context context) {
- this.context = context;
- }
-
- @Override
- public T call() throws Exception {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- execute(adapter);
- adapter.close();
- return result;
- }
-
- public abstract void execute(PodDBAdapter adapter);
-
- protected void setResult(T result) {
- this.result = result;
- }
- }
-
- /**
- * Adds the given FeedItem to the flattr queue if the user is logged in. Otherwise, a dialog
- * will be opened that lets the user go either to the login screen or the website of the flattr thing.
- *
- * @param context
- * @param item
- */
- public static void flattrItemIfLoggedIn(Context context, FeedItem item) {
- if (FlattrUtils.hasToken()) {
- item.getFlattrStatus().setFlattrQueue();
- DBWriter.setFlattredStatus(context, item, true);
- } else {
- FlattrUtils.showNoTokenDialogOrRedirect(context, item.getPaymentLink());
- }
- }
-
- /**
- * Adds the given Feed to the flattr queue if the user is logged in. Otherwise, a dialog
- * will be opened that lets the user go either to the login screen or the website of the flattr thing.
- *
- * @param context
- * @param feed
- */
- public static void flattrFeedIfLoggedIn(Context context, Feed feed) {
- if (FlattrUtils.hasToken()) {
- feed.getFlattrStatus().setFlattrQueue();
- DBWriter.setFlattredStatus(context, feed, true);
- } else {
- FlattrUtils.showNoTokenDialogOrRedirect(context, feed.getPaymentLink());
- }
- }
-
-}
diff --git a/src/de/danoeh/antennapod/storage/DBWriter.java b/src/de/danoeh/antennapod/storage/DBWriter.java
deleted file mode 100644
index 9916ac97f..000000000
--- a/src/de/danoeh/antennapod/storage/DBWriter.java
+++ /dev/null
@@ -1,974 +0,0 @@
-package de.danoeh.antennapod.storage;
-
-import android.app.backup.BackupManager;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.database.Cursor;
-import android.preference.PreferenceManager;
-import android.util.Log;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.asynctask.FlattrClickWorker;
-import de.danoeh.antennapod.feed.*;
-import de.danoeh.antennapod.preferences.GpodnetPreferences;
-import de.danoeh.antennapod.preferences.PlaybackPreferences;
-import de.danoeh.antennapod.service.download.DownloadStatus;
-import de.danoeh.antennapod.service.playback.PlaybackService;
-import de.danoeh.antennapod.util.QueueAccess;
-import de.danoeh.antennapod.util.flattr.FlattrStatus;
-import de.danoeh.antennapod.util.flattr.FlattrThing;
-import de.danoeh.antennapod.util.flattr.SimpleFlattrThing;
-import org.shredzone.flattr4j.model.Flattr;
-
-import java.io.File;
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.util.Date;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.ThreadFactory;
-
-/**
- * Provides methods for writing data to AntennaPod's database.
- * In general, DBWriter-methods will be executed on an internal ExecutorService.
- * Some methods return a Future-object which the caller can use for waiting for the method's completion. The returned Future's
- * will NOT contain any results.
- * The caller can also use the {@link EventDistributor} in order to be notified about the method's completion asynchronously.
- * This class will use the {@link EventDistributor} to notify listeners about changes in the database.
- */
-public class DBWriter {
- private static final String TAG = "DBWriter";
-
- private static final ExecutorService dbExec;
-
- static {
- dbExec = Executors.newSingleThreadExecutor(new ThreadFactory() {
-
- @Override
- public Thread newThread(Runnable r) {
- Thread t = new Thread(r);
- t.setPriority(Thread.MIN_PRIORITY);
- return t;
- }
- });
- }
-
- private DBWriter() {
- }
-
- /**
- * Deletes a downloaded FeedMedia file from the storage device.
- *
- * @param context A context that is used for opening a database connection.
- * @param mediaId ID of the FeedMedia object whose downloaded file should be deleted.
- */
- public static Future<?> deleteFeedMediaOfItem(final Context context,
- final long mediaId) {
- return dbExec.submit(new Runnable() {
- @Override
- public void run() {
-
- final FeedMedia media = DBReader.getFeedMedia(context, mediaId);
- if (media != null) {
- Log.i(TAG, String.format("Requested to delete FeedMedia [id=%d, title=%s, downloaded=%s",
- media.getId(), media.getEpisodeTitle(), String.valueOf(media.isDownloaded())));
- boolean result = false;
- if (media.isDownloaded()) {
- // delete downloaded media file
- File mediaFile = new File(media.getFile_url());
- if (mediaFile.exists()) {
- result = mediaFile.delete();
- }
- media.setDownloaded(false);
- media.setFile_url(null);
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- adapter.setMedia(media);
- adapter.close();
-
- // If media is currently being played, change playback
- // type to 'stream' and shutdown playback service
- SharedPreferences prefs = PreferenceManager
- .getDefaultSharedPreferences(context);
- 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 (BuildConfig.DEBUG)
- Log.d(TAG, "Deleting File. Result: " + result);
- EventDistributor.getInstance().sendQueueUpdateBroadcast();
- EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast();
- }
- }
- });
- }
-
- /**
- * Deletes a Feed and all downloaded files of its components like images and downloaded episodes.
- *
- * @param context A context that is used for opening a database connection.
- * @param feedId ID of the Feed that should be deleted.
- */
- public static Future<?> deleteFeed(final Context context, final long feedId) {
- return dbExec.submit(new Runnable() {
- @Override
- public void run() {
- DownloadRequester requester = DownloadRequester.getInstance();
- SharedPreferences prefs = PreferenceManager
- .getDefaultSharedPreferences(context
- .getApplicationContext());
- final Feed feed = DBReader.getFeed(context, feedId);
- if (feed != null) {
- 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_CURRENTLY_PLAYING_FEED_ID,
- -1);
- editor.commit();
- }
-
- // delete image file
- if (feed.getImage() != null) {
- if (feed.getImage().isDownloaded()
- && feed.getImage().getFile_url() != null) {
- File imageFile = new File(feed.getImage()
- .getFile_url());
- imageFile.delete();
- } else if (requester.isDownloadingFile(feed.getImage())) {
- requester.cancelDownload(context, feed.getImage());
- }
- }
- // delete stored media files and mark them as read
- List<FeedItem> queue = DBReader.getQueue(context);
- boolean queueWasModified = false;
- if (feed.getItems() == null) {
- DBReader.getFeedItemList(context, feed);
- }
-
- for (FeedItem item : feed.getItems()) {
- queueWasModified |= queue.remove(item);
- if (item.getMedia() != null
- && item.getMedia().isDownloaded()) {
- File mediaFile = new File(item.getMedia()
- .getFile_url());
- mediaFile.delete();
- } else if (item.getMedia() != null
- && requester.isDownloadingFile(item.getMedia())) {
- requester.cancelDownload(context, item.getMedia());
- }
-
- if (item.hasItemImage()) {
- FeedImage image = item.getImage();
- if (image.isDownloaded() && image.getFile_url() != null) {
- File imgFile = new File(image.getFile_url());
- imgFile.delete();
- } else if (requester.isDownloadingFile(image)) {
- requester.cancelDownload(context, item.getImage());
- }
- }
- }
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- if (queueWasModified) {
- adapter.setQueue(queue);
- }
- adapter.removeFeed(feed);
- adapter.close();
-
- GpodnetPreferences.addRemovedFeed(feed.getDownload_url());
- EventDistributor.getInstance().sendFeedUpdateBroadcast();
-
- BackupManager backupManager = new BackupManager(context);
- backupManager.dataChanged();
- }
- }
- });
- }
-
- /**
- * Deletes the entire playback history.
- *
- * @param context A context that is used for opening a database connection.
- */
- public static Future<?> clearPlaybackHistory(final Context context) {
- return dbExec.submit(new Runnable() {
-
- @Override
- public void run() {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- adapter.clearPlaybackHistory();
- adapter.close();
- EventDistributor.getInstance()
- .sendPlaybackHistoryUpdateBroadcast();
- }
- });
- }
-
- /**
- * Adds a FeedMedia object to the playback history. A FeedMedia object is in the playback history if
- * its playback completion date is set to a non-null value. This method will set the playback completion date to the
- * current date regardless of the current value.
- *
- * @param context A context that is used for opening a database connection.
- * @param media FeedMedia that should be added to the playback history.
- */
- public static Future<?> addItemToPlaybackHistory(final Context context,
- final FeedMedia media) {
- return dbExec.submit(new Runnable() {
- @Override
- public void run() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Adding new item to playback history");
- media.setPlaybackCompletionDate(new Date());
- // reset played_duration to 0 so that it behaves correctly when the episode is played again
- media.setPlayedDuration(0);
-
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- adapter.setFeedMediaPlaybackCompletionDate(media);
- adapter.close();
- EventDistributor.getInstance().sendPlaybackHistoryUpdateBroadcast();
-
- }
- });
- }
-
- private static void cleanupDownloadLog(final PodDBAdapter adapter) {
- final long logSize = adapter.getDownloadLogSize();
- if (logSize > DBReader.DOWNLOAD_LOG_SIZE) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Cleaning up download log");
- adapter.removeDownloadLogItems(logSize - DBReader.DOWNLOAD_LOG_SIZE);
- }
- }
-
- /**
- * Adds a Download status object to the download log.
- *
- * @param context A context that is used for opening a database connection.
- * @param status The DownloadStatus object.
- */
- public static Future<?> addDownloadStatus(final Context context,
- final DownloadStatus status) {
- return dbExec.submit(new Runnable() {
-
- @Override
- public void run() {
-
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- adapter.setDownloadStatus(status);
- adapter.close();
- EventDistributor.getInstance().sendDownloadLogUpdateBroadcast();
- }
- });
-
- }
-
- /**
- * Inserts a FeedItem in the queue at the specified index. The 'read'-attribute of the FeedItem will be set to
- * true. If the FeedItem is already in the queue, the queue will not be modified.
- *
- * @param context A context that is used for opening a database connection.
- * @param itemId ID of the FeedItem that should be added to the queue.
- * @param index Destination index. Must be in range 0..queue.size()
- * @param performAutoDownload True if an auto-download process should be started after the operation
- * @throws IndexOutOfBoundsException if index < 0 || index >= queue.size()
- */
- public static Future<?> addQueueItemAt(final Context context, final long itemId,
- final int index, final boolean performAutoDownload) {
- return dbExec.submit(new Runnable() {
-
- @Override
- public void run() {
- final PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- final List<FeedItem> queue = DBReader
- .getQueue(context, adapter);
- FeedItem item = null;
-
- if (queue != null) {
- boolean queueModified = false;
- boolean unreadItemsModified = false;
-
- if (!itemListContains(queue, itemId)) {
- item = DBReader.getFeedItem(context, itemId);
- if (item != null) {
- queue.add(index, item);
- queueModified = true;
- if (!item.isRead()) {
- item.setRead(true);
- unreadItemsModified = true;
- }
- }
- }
- if (queueModified) {
- adapter.setQueue(queue);
- EventDistributor.getInstance()
- .sendQueueUpdateBroadcast();
- }
- if (unreadItemsModified && item != null) {
- adapter.setSingleFeedItem(item);
- EventDistributor.getInstance()
- .sendUnreadItemsUpdateBroadcast();
- }
- }
- adapter.close();
- if (performAutoDownload) {
- DBTasks.autodownloadUndownloadedItems(context);
- }
-
- }
- });
-
- }
-
- /**
- * Appends FeedItem objects to the end of the queue. The 'read'-attribute of all items will be set to true.
- * If a FeedItem is already in the queue, the FeedItem will not change its position in the queue.
- *
- * @param context A context that is used for opening a database connection.
- * @param itemIds IDs of the FeedItem objects that should be added to the queue.
- */
- public static Future<?> addQueueItem(final Context context,
- final long... itemIds) {
- return dbExec.submit(new Runnable() {
-
- @Override
- public void run() {
- if (itemIds.length > 0) {
- final PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- final List<FeedItem> queue = DBReader.getQueue(context,
- adapter);
-
- if (queue != null) {
- boolean queueModified = false;
- boolean unreadItemsModified = false;
- List<FeedItem> itemsToSave = new LinkedList<FeedItem>();
- for (int i = 0; i < itemIds.length; i++) {
- if (!itemListContains(queue, itemIds[i])) {
- final FeedItem item = DBReader.getFeedItem(
- context, itemIds[i]);
-
- if (item != null) {
- queue.add(item);
- queueModified = true;
- if (!item.isRead()) {
- item.setRead(true);
- itemsToSave.add(item);
- unreadItemsModified = true;
- }
- }
- }
- }
- if (queueModified) {
- adapter.setQueue(queue);
- EventDistributor.getInstance()
- .sendQueueUpdateBroadcast();
- }
- if (unreadItemsModified) {
- adapter.setFeedItemlist(itemsToSave);
- EventDistributor.getInstance()
- .sendUnreadItemsUpdateBroadcast();
- }
- }
- adapter.close();
- DBTasks.autodownloadUndownloadedItems(context);
- }
- }
- });
-
- }
-
- /**
- * Removes all FeedItem objects from the queue.
- *
- * @param context A context that is used for opening a database connection.
- */
- public static Future<?> clearQueue(final Context context) {
- return dbExec.submit(new Runnable() {
-
- @Override
- public void run() {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- adapter.clearQueue();
- adapter.close();
-
- EventDistributor.getInstance().sendQueueUpdateBroadcast();
- }
- });
- }
-
- /**
- * Removes a FeedItem object from the queue.
- *
- * @param context A context that is used for opening a database connection.
- * @param itemId ID of the FeedItem that should be removed.
- * @param performAutoDownload true if an auto-download process should be started after the operation.
- */
- public static Future<?> removeQueueItem(final Context context,
- final long itemId, final boolean performAutoDownload) {
- return dbExec.submit(new Runnable() {
-
- @Override
- public void run() {
- final PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- final List<FeedItem> queue = DBReader
- .getQueue(context, adapter);
- FeedItem item = null;
-
- if (queue != null) {
- boolean queueModified = false;
- QueueAccess queueAccess = QueueAccess.ItemListAccess(queue);
- if (queueAccess.contains(itemId)) {
- item = DBReader.getFeedItem(context, itemId);
- if (item != null) {
- queueModified = queueAccess.remove(itemId);
- }
- }
- if (queueModified) {
- adapter.setQueue(queue);
- EventDistributor.getInstance()
- .sendQueueUpdateBroadcast();
- } else {
- Log.w(TAG, "Queue was not modified by call to removeQueueItem");
- }
- } else {
- Log.e(TAG, "removeQueueItem: Could not load queue");
- }
- adapter.close();
- if (performAutoDownload) {
- DBTasks.autodownloadUndownloadedItems(context);
- }
- }
- });
-
- }
-
- /**
- * Moves the specified item to the top of the queue.
- *
- * @param context A context that is used for opening a database connection.
- * @param itemId The item to move to the top of the queue
- * @param broadcastUpdate true if this operation should trigger a QueueUpdateBroadcast. This option should be set to
- * false if the caller wants to avoid unexpected updates of the GUI.
- */
- public static Future<?> moveQueueItemToTop(final Context context, final long itemId, final boolean broadcastUpdate) {
- return dbExec.submit(new Runnable() {
- @Override
- public void run() {
- List<Long> queueIdList = DBReader.getQueueIDList(context);
- int currentLocation = 0;
- for (long id : queueIdList) {
- if (id == itemId) {
- moveQueueItemHelper(context, currentLocation, 0, broadcastUpdate);
- return;
- }
- currentLocation++;
- }
- Log.e(TAG, "moveQueueItemToTop: item not found");
- }
- });
- }
-
- /**
- * Moves the specified item to the bottom of the queue.
- *
- * @param context A context that is used for opening a database connection.
- * @param itemId The item to move to the bottom of the queue
- * @param broadcastUpdate true if this operation should trigger a QueueUpdateBroadcast. This option should be set to
- * false if the caller wants to avoid unexpected updates of the GUI.
- */
- public static Future<?> moveQueueItemToBottom(final Context context, final long itemId,
- final boolean broadcastUpdate) {
- return dbExec.submit(new Runnable() {
- @Override
- public void run() {
- List<Long> queueIdList = DBReader.getQueueIDList(context);
- int currentLocation = 0;
- for (long id : queueIdList) {
- if (id == itemId) {
- moveQueueItemHelper(context, currentLocation, queueIdList.size() - 1,
- broadcastUpdate);
- return;
- }
- currentLocation++;
- }
- Log.e(TAG, "moveQueueItemToBottom: item not found");
- }
- });
- }
-
- /**
- * Changes the position of a FeedItem in the queue.
- *
- * @param context A context that is used for opening a database connection.
- * @param from Source index. Must be in range 0..queue.size()-1.
- * @param to Destination index. Must be in range 0..queue.size()-1.
- * @param broadcastUpdate true if this operation should trigger a QueueUpdateBroadcast. This option should be set to
- * false if the caller wants to avoid unexpected updates of the GUI.
- * @throws IndexOutOfBoundsException if (to < 0 || to >= queue.size()) || (from < 0 || from >= queue.size())
- */
- public static Future<?> moveQueueItem(final Context context, final int from,
- final int to, final boolean broadcastUpdate) {
- return dbExec.submit(new Runnable() {
-
- @Override
- public void run() {
- moveQueueItemHelper(context, from, to, broadcastUpdate);
- }
- });
- }
-
- /**
- * Changes the position of a FeedItem in the queue.
- * <p/>
- * This function must be run using the ExecutorService (dbExec).
- *
- * @param context A context that is used for opening a database connection.
- * @param from Source index. Must be in range 0..queue.size()-1.
- * @param to Destination index. Must be in range 0..queue.size()-1.
- * @param broadcastUpdate true if this operation should trigger a QueueUpdateBroadcast. This option should be set to
- * false if the caller wants to avoid unexpected updates of the GUI.
- * @throws IndexOutOfBoundsException if (to < 0 || to >= queue.size()) || (from < 0 || from >= queue.size())
- */
- private static void moveQueueItemHelper(final Context context, final int from,
- final int to, final boolean broadcastUpdate) {
- final PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- final List<FeedItem> queue = DBReader
- .getQueue(context, adapter);
-
- if (queue != null) {
- if (from >= 0 && from < queue.size() && to >= 0
- && to < queue.size()) {
-
- final FeedItem item = queue.remove(from);
- queue.add(to, item);
-
- adapter.setQueue(queue);
- if (broadcastUpdate) {
- EventDistributor.getInstance()
- .sendQueueUpdateBroadcast();
- }
-
- }
- } else {
- Log.e(TAG, "moveQueueItemHelper: Could not load queue");
- }
- adapter.close();
- }
-
- /**
- * Sets the 'read'-attribute of a FeedItem to the specified value.
- *
- * @param context A context that is used for opening a database connection.
- * @param item The FeedItem object
- * @param read New value of the 'read'-attribute
- * @param resetMediaPosition true if this method should also reset the position of the FeedItem's FeedMedia object.
- * If the FeedItem has no FeedMedia object, this parameter will be ignored.
- */
- public static Future<?> markItemRead(Context context, FeedItem item, boolean read, boolean resetMediaPosition) {
- long mediaId = (item.hasMedia()) ? item.getMedia().getId() : 0;
- return markItemRead(context, item.getId(), read, mediaId, resetMediaPosition);
- }
-
- /**
- * Sets the 'read'-attribute of a FeedItem to the specified value.
- *
- * @param context A context that is used for opening a database connection.
- * @param itemId ID of the FeedItem
- * @param read New value of the 'read'-attribute
- */
- public static Future<?> markItemRead(final Context context, final long itemId,
- final boolean read) {
- return markItemRead(context, itemId, read, 0, false);
- }
-
- private static Future<?> markItemRead(final Context context, final long itemId,
- final boolean read, final long mediaId,
- final boolean resetMediaPosition) {
- return dbExec.submit(new Runnable() {
-
- @Override
- public void run() {
- final PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- adapter.setFeedItemRead(read, itemId, mediaId,
- resetMediaPosition);
- adapter.close();
-
- EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast();
- }
- });
- }
-
- /**
- * Sets the 'read'-attribute of all FeedItems of a specific Feed to true.
- *
- * @param context A context that is used for opening a database connection.
- * @param feedId ID of the Feed.
- */
- public static Future<?> markFeedRead(final Context context, final long feedId) {
- return dbExec.submit(new Runnable() {
-
- @Override
- public void run() {
- final PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- Cursor itemCursor = adapter.getAllItemsOfFeedCursor(feedId);
- long[] itemIds = new long[itemCursor.getCount()];
- itemCursor.moveToFirst();
- for (int i = 0; i < itemIds.length; i++) {
- itemIds[i] = itemCursor.getLong(PodDBAdapter.KEY_ID_INDEX);
- itemCursor.moveToNext();
- }
- itemCursor.close();
- adapter.setFeedItemRead(true, itemIds);
- adapter.close();
-
- EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast();
- }
- });
-
- }
-
- /**
- * Sets the 'read'-attribute of all FeedItems to true.
- *
- * @param context A context that is used for opening a database connection.
- */
- public static Future<?> markAllItemsRead(final Context context) {
- return dbExec.submit(new Runnable() {
-
- @Override
- public void run() {
- final PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- Cursor itemCursor = adapter.getUnreadItemsCursor();
- long[] itemIds = new long[itemCursor.getCount()];
- itemCursor.moveToFirst();
- for (int i = 0; i < itemIds.length; i++) {
- itemIds[i] = itemCursor.getLong(PodDBAdapter.KEY_ID_INDEX);
- itemCursor.moveToNext();
- }
- itemCursor.close();
- adapter.setFeedItemRead(true, itemIds);
- adapter.close();
-
- EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast();
- }
- });
-
- }
-
- static Future<?> addNewFeed(final Context context, final Feed... feeds) {
- return dbExec.submit(new Runnable() {
-
- @Override
- public void run() {
- final PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- adapter.setCompleteFeed(feeds);
- adapter.close();
-
- for (Feed feed : feeds) {
- GpodnetPreferences.addAddedFeed(feed.getDownload_url());
- }
-
- BackupManager backupManager = new BackupManager(context);
- backupManager.dataChanged();
- }
- });
- }
-
- static Future<?> setCompleteFeed(final Context context, final Feed... feeds) {
- return dbExec.submit(new Runnable() {
-
- @Override
- public void run() {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- adapter.setCompleteFeed(feeds);
- adapter.close();
-
- }
- });
-
- }
-
- /**
- * Saves a FeedMedia object in the database. This method will save all attributes of the FeedMedia object. The
- * contents of FeedComponent-attributes (e.g. the FeedMedia's 'item'-attribute) will not be saved.
- *
- * @param context A context that is used for opening a database connection.
- * @param media The FeedMedia object.
- */
- public static Future<?> setFeedMedia(final Context context,
- final FeedMedia media) {
- return dbExec.submit(new Runnable() {
-
- @Override
- public void run() {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- adapter.setMedia(media);
- adapter.close();
- }
- });
- }
-
- /**
- * Saves the 'position' and 'duration' attributes of a FeedMedia object
- *
- * @param context A context that is used for opening a database connection.
- * @param media The FeedMedia object.
- */
- public static Future<?> setFeedMediaPlaybackInformation(final Context context, final FeedMedia media) {
- return dbExec.submit(new Runnable() {
- @Override
- public void run() {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- adapter.setFeedMediaPlaybackInformation(media);
- adapter.close();
- }
- });
- }
-
- /**
- * Saves a FeedItem object in the database. This method will save all attributes of the FeedItem object including
- * the content of FeedComponent-attributes.
- *
- * @param context A context that is used for opening a database connection.
- * @param item The FeedItem object.
- */
- public static Future<?> setFeedItem(final Context context,
- final FeedItem item) {
- return dbExec.submit(new Runnable() {
-
- @Override
- public void run() {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- adapter.setSingleFeedItem(item);
- adapter.close();
- }
- });
- }
-
- /**
- * Saves a FeedImage object in the database. This method will save all attributes of the FeedImage object. The
- * contents of FeedComponent-attributes (e.g. the FeedImages's 'feed'-attribute) will not be saved.
- *
- * @param context A context that is used for opening a database connection.
- * @param image The FeedImage object.
- */
- public static Future<?> setFeedImage(final Context context,
- final FeedImage image) {
- return dbExec.submit(new Runnable() {
-
- @Override
- public void run() {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- adapter.setImage(image);
- adapter.close();
- }
- });
- }
-
- /**
- * Updates download URLs of feeds from a given Map. The key of the Map is the original URL of the feed
- * and the value is the updated URL
- */
- public static Future<?> updateFeedDownloadURLs(final Context context, final Map<String, String> urls) {
- return dbExec.submit(new Runnable() {
- @Override
- public void run() {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- for (String key : urls.keySet()) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Replacing URL " + key + " with url " + urls.get(key));
-
- adapter.setFeedDownloadUrl(key, urls.get(key));
- }
- adapter.close();
- }
- });
- }
-
- /**
- * Saves a FeedPreferences object in the database. The Feed ID of the FeedPreferences-object MUST NOT be 0.
- *
- * @param context Used for opening a database connection.
- * @param preferences The FeedPreferences object.
- */
- public static Future<?> setFeedPreferences(final Context context, final FeedPreferences preferences) {
- return dbExec.submit(new Runnable() {
- @Override
- public void run() {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- adapter.setFeedPreferences(preferences);
- adapter.close();
- EventDistributor.getInstance().sendFeedUpdateBroadcast();
- }
- });
- }
-
- private static boolean itemListContains(List<FeedItem> items, long itemId) {
- for (FeedItem item : items) {
- if (item.getId() == itemId) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Saves the FlattrStatus of a FeedItem object in the database.
- *
- * @param startFlattrClickWorker true if FlattrClickWorker should be started after the FlattrStatus has been saved
- */
- public static Future<?> setFeedItemFlattrStatus(final Context context,
- final FeedItem item,
- final boolean startFlattrClickWorker) {
- return dbExec.submit(new Runnable() {
-
- @Override
- public void run() {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- adapter.setFeedItemFlattrStatus(item);
- adapter.close();
- if (startFlattrClickWorker) {
- new FlattrClickWorker(context).executeAsync();
- }
- }
- });
- }
-
- /**
- * Saves the FlattrStatus of a Feed object in the database.
- *
- * @param startFlattrClickWorker true if FlattrClickWorker should be started after the FlattrStatus has been saved
- */
- private static Future<?> setFeedFlattrStatus(final Context context,
- final Feed feed,
- final boolean startFlattrClickWorker) {
- return dbExec.submit(new Runnable() {
-
- @Override
- public void run() {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- adapter.setFeedFlattrStatus(feed);
- adapter.close();
- if (startFlattrClickWorker) {
- new FlattrClickWorker(context).executeAsync();
- }
- }
- });
- }
-
- /**
- * format an url for querying the database
- * (postfix a / and apply percent-encoding)
- */
- private static String formatURIForQuery(String uri) {
- try {
- return URLEncoder.encode(uri.endsWith("/") ? uri.substring(0, uri.length() - 1) : uri, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- Log.e(TAG, e.getMessage());
- return "";
- }
- }
-
-
- /**
- * Set flattr status of the passed thing (either a FeedItem or a Feed)
- *
- * @param context
- * @param thing
- * @param startFlattrClickWorker true if FlattrClickWorker should be started after the FlattrStatus has been saved
- * @return
- */
- public static Future<?> setFlattredStatus(Context context, FlattrThing thing, boolean startFlattrClickWorker) {
- // must propagate this to back db
- if (thing instanceof FeedItem)
- return setFeedItemFlattrStatus(context, (FeedItem) thing, startFlattrClickWorker);
- else if (thing instanceof Feed)
- return setFeedFlattrStatus(context, (Feed) thing, startFlattrClickWorker);
- else if (thing instanceof SimpleFlattrThing) {
- } // SimpleFlattrThings are generated on the fly and do not have DB backing
- else
- Log.e(TAG, "flattrQueue processing - thing is neither FeedItem nor Feed nor SimpleFlattrThing");
-
- return null;
- }
-
- /**
- * Reset flattr status to unflattrd for all items
- */
- public static Future<?> clearAllFlattrStatus(final Context context) {
- Log.d(TAG, "clearAllFlattrStatus()");
- return dbExec.submit(new Runnable() {
- @Override
- public void run() {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- adapter.clearAllFlattrStatus();
- adapter.close();
- }
- });
- }
-
- /**
- * Set flattr status of the feeds/feeditems in flattrList to flattred at the given timestamp,
- * where the information has been retrieved from the flattr API
- */
- public static Future<?> setFlattredStatus(final Context context, final List<Flattr> flattrList) {
- Log.d(TAG, "setFlattredStatus to status retrieved from flattr api running with " + flattrList.size() + " items");
- // clear flattr status in db
- clearAllFlattrStatus(context);
-
- // submit list with flattred things having normalized URLs to db
- return dbExec.submit(new Runnable() {
- @Override
- public void run() {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- for (Flattr flattr : flattrList) {
- adapter.setItemFlattrStatus(formatURIForQuery(flattr.getThing().getUrl()), new FlattrStatus(flattr.getCreated().getTime()));
- }
- adapter.close();
- }
- });
- }
-}
diff --git a/src/de/danoeh/antennapod/storage/DownloadRequestException.java b/src/de/danoeh/antennapod/storage/DownloadRequestException.java
deleted file mode 100644
index 0ef766e58..000000000
--- a/src/de/danoeh/antennapod/storage/DownloadRequestException.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package de.danoeh.antennapod.storage;
-
-/**
- * Thrown by the DownloadRequester if a download request contains invalid data
- * or something went wrong while processing the request.
- */
-public class DownloadRequestException extends Exception {
-
- public DownloadRequestException() {
- super();
- }
-
- public DownloadRequestException(String detailMessage, Throwable throwable) {
- super(detailMessage, throwable);
- }
-
- public DownloadRequestException(String detailMessage) {
- super(detailMessage);
- }
-
- public DownloadRequestException(Throwable throwable) {
- super(throwable);
- }
-
-}
diff --git a/src/de/danoeh/antennapod/storage/DownloadRequester.java b/src/de/danoeh/antennapod/storage/DownloadRequester.java
deleted file mode 100644
index d305c572b..000000000
--- a/src/de/danoeh/antennapod/storage/DownloadRequester.java
+++ /dev/null
@@ -1,367 +0,0 @@
-package de.danoeh.antennapod.storage;
-
-import android.content.Context;
-import android.content.Intent;
-import android.util.Log;
-import android.webkit.URLUtil;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.feed.*;
-import de.danoeh.antennapod.preferences.UserPreferences;
-import de.danoeh.antennapod.service.download.DownloadRequest;
-import de.danoeh.antennapod.service.download.DownloadService;
-import de.danoeh.antennapod.util.FileNameGenerator;
-import de.danoeh.antennapod.util.URLChecker;
-import org.apache.commons.io.FilenameUtils;
-import org.apache.commons.lang3.StringEscapeUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.Validate;
-
-import java.io.File;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-
-/**
- * Sends download requests to the DownloadService. This class should always be used for starting downloads,
- * otherwise they won't work correctly.
- */
-public class DownloadRequester {
- private static final String TAG = "DownloadRequester";
-
- public static final String IMAGE_DOWNLOADPATH = "images/";
- public static final String FEED_DOWNLOADPATH = "cache/";
- public static final String MEDIA_DOWNLOADPATH = "media/";
-
- private static DownloadRequester downloader;
-
- Map<String, DownloadRequest> downloads;
-
- private DownloadRequester() {
- downloads = new ConcurrentHashMap<String, DownloadRequest>();
- }
-
- public static synchronized DownloadRequester getInstance() {
- if (downloader == null) {
- downloader = new DownloadRequester();
- }
- return downloader;
- }
-
- /**
- * Starts a new download with the given DownloadRequest. This method should only
- * be used from outside classes if the DownloadRequest was created by the DownloadService to
- * ensure that the data is valid. Use downloadFeed(), downloadImage() or downloadMedia() instead.
- *
- * @param context Context object for starting the DownloadService
- * @param request The DownloadRequest. If another DownloadRequest with the same source URL is already stored, this method
- * call will return false.
- * @return True if the download request was accepted, false otherwise.
- */
- public boolean download(Context context, DownloadRequest request) {
- Validate.notNull(context);
- Validate.notNull(request);
-
- if (downloads.containsKey(request.getSource())) {
- if (BuildConfig.DEBUG) Log.i(TAG, "DownloadRequest is already stored.");
- return false;
- }
- downloads.put(request.getSource(), request);
-
- Intent launchIntent = new Intent(context, DownloadService.class);
- launchIntent.putExtra(DownloadService.EXTRA_REQUEST, request);
- context.startService(launchIntent);
- EventDistributor.getInstance().sendDownloadQueuedBroadcast();
- return true;
- }
-
- private void download(Context context, FeedFile item, File dest,
- boolean overwriteIfExists, String username, String password, boolean deleteOnFailure) {
- if (!isDownloadingFile(item)) {
- if (!isFilenameAvailable(dest.toString()) || (deleteOnFailure && dest.exists())) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Filename already used.");
- if (isFilenameAvailable(dest.toString()) && overwriteIfExists) {
- boolean result = dest.delete();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Deleting file. Result: " + result);
- } else {
- // find different name
- File newDest = null;
- for (int i = 1; i < Integer.MAX_VALUE; i++) {
- String newName = FilenameUtils.getBaseName(dest
- .getName())
- + "-"
- + i
- + FilenameUtils.EXTENSION_SEPARATOR
- + FilenameUtils.getExtension(dest.getName());
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Testing filename " + newName);
- newDest = new File(dest.getParent(), newName);
- if (!newDest.exists()
- && isFilenameAvailable(newDest.toString())) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "File doesn't exist yet. Using "
- + newName);
- break;
- }
- }
- if (newDest != null) {
- dest = newDest;
- }
- }
- }
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "Requesting download of url " + item.getDownload_url());
- item.setDownload_url(URLChecker.prepareURL(item.getDownload_url()));
-
- DownloadRequest request = new DownloadRequest(dest.toString(),
- URLChecker.prepareURL(item.getDownload_url()), item.getHumanReadableIdentifier(),
- item.getId(), item.getTypeAsInt(), username, password, deleteOnFailure);
-
- download(context, request);
- } else {
- Log.e(TAG, "URL " + item.getDownload_url()
- + " is already being downloaded");
- }
- }
-
- /**
- * Returns true if a filename is available and false if it has already been
- * taken by another requested download.
- */
- private boolean isFilenameAvailable(String path) {
- for (String key : downloads.keySet()) {
- DownloadRequest r = downloads.get(key);
- if (StringUtils.equals(r.getDestination(), path)) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, path
- + " is already used by another requested download");
- return false;
- }
- }
- if (BuildConfig.DEBUG)
- Log.d(TAG, path + " is available as a download destination");
- return true;
- }
-
- public void downloadFeed(Context context, Feed feed)
- throws DownloadRequestException {
- if (feedFileValid(feed)) {
- String username = (feed.getPreferences() != null) ? feed.getPreferences().getUsername() : null;
- String password = (feed.getPreferences() != null) ? feed.getPreferences().getPassword() : null;
-
- download(context, feed, new File(getFeedfilePath(context),
- getFeedfileName(feed)), true, username, password, true);
- }
- }
-
- public void downloadImage(Context context, FeedImage image)
- throws DownloadRequestException {
- if (feedFileValid(image)) {
- download(context, image, new File(getImagefilePath(context),
- getImagefileName(image)), false, null, null, false);
- }
- }
-
- public void downloadMedia(Context context, FeedMedia feedmedia)
- throws DownloadRequestException {
- if (feedFileValid(feedmedia)) {
- Feed feed = feedmedia.getItem().getFeed();
- String username;
- String password;
- if (feed != null && feed.getPreferences() != null) {
- username = feed.getPreferences().getUsername();
- password = feed.getPreferences().getPassword();
- } else {
- username = null;
- password = null;
- }
-
- File dest;
- if (feedmedia.getFile_url() != null) {
- dest = new File(feedmedia.getFile_url());
- } else {
- dest = new File(getMediafilePath(context, feedmedia),
- getMediafilename(feedmedia));
- }
- download(context, feedmedia,
- dest, false, username, password, false
- );
- }
- }
-
- /**
- * Throws a DownloadRequestException if the feedfile or the download url of
- * the feedfile is null.
- *
- * @throws DownloadRequestException
- */
- private boolean feedFileValid(FeedFile f) throws DownloadRequestException {
- if (f == null) {
- throw new DownloadRequestException("Feedfile was null");
- } else if (f.getDownload_url() == null) {
- throw new DownloadRequestException("File has no download URL");
- } else {
- return true;
- }
- }
-
- /**
- * Cancels a running download.
- */
- public void cancelDownload(final Context context, final FeedFile f) {
- cancelDownload(context, f.getDownload_url());
- }
-
- /**
- * Cancels a running download.
- */
- public void cancelDownload(final Context context, final String downloadUrl) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Cancelling download with url " + downloadUrl);
- Intent cancelIntent = new Intent(DownloadService.ACTION_CANCEL_DOWNLOAD);
- cancelIntent.putExtra(DownloadService.EXTRA_DOWNLOAD_URL, downloadUrl);
- context.sendBroadcast(cancelIntent);
- }
-
- /**
- * Cancels all running downloads
- */
- public void cancelAllDownloads(Context context) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Cancelling all running downloads");
- context.sendBroadcast(new Intent(
- DownloadService.ACTION_CANCEL_ALL_DOWNLOADS));
- }
-
- /**
- * Returns true if there is at least one Feed in the downloads queue.
- */
- public boolean isDownloadingFeeds() {
- for (DownloadRequest r : downloads.values()) {
- if (r.getFeedfileType() == Feed.FEEDFILETYPE_FEED) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Checks if feedfile is in the downloads list
- */
- public boolean isDownloadingFile(FeedFile item) {
- if (item.getDownload_url() != null) {
- return downloads.containsKey(item.getDownload_url());
- }
- return false;
- }
-
- public DownloadRequest getDownload(String downloadUrl) {
- return downloads.get(downloadUrl);
- }
-
- /**
- * Checks if feedfile with the given download url is in the downloads list
- */
- public boolean isDownloadingFile(String downloadUrl) {
- return downloads.get(downloadUrl) != null;
- }
-
- public boolean hasNoDownloads() {
- return downloads.isEmpty();
- }
-
- /**
- * Remove an object from the downloads-list of the requester.
- */
- public void removeDownload(DownloadRequest r) {
- if (downloads.remove(r.getSource()) == null) {
- Log.e(TAG,
- "Could not remove object with url " + r.getSource());
- }
- }
-
- /**
- * Get the number of uncompleted Downloads
- */
- public int getNumberOfDownloads() {
- return downloads.size();
- }
-
- public String getFeedfilePath(Context context)
- throws DownloadRequestException {
- return getExternalFilesDirOrThrowException(context, FEED_DOWNLOADPATH)
- .toString() + "/";
- }
-
- public String getFeedfileName(Feed feed) {
- String filename = feed.getDownload_url();
- if (feed.getTitle() != null && !feed.getTitle().isEmpty()) {
- filename = feed.getTitle();
- }
- return "feed-" + FileNameGenerator.generateFileName(filename);
- }
-
- public String getImagefilePath(Context context)
- throws DownloadRequestException {
- return getExternalFilesDirOrThrowException(context, IMAGE_DOWNLOADPATH)
- .toString() + "/";
- }
-
- public String getImagefileName(FeedImage image) {
- String filename = image.getDownload_url();
- if (image.getOwner() != null && image.getOwner().getHumanReadableIdentifier() != null) {
- filename = image.getOwner().getHumanReadableIdentifier();
- }
- return "image-" + FileNameGenerator.generateFileName(filename);
- }
-
- public String getMediafilePath(Context context, FeedMedia media)
- throws DownloadRequestException {
- File externalStorage = getExternalFilesDirOrThrowException(
- context,
- MEDIA_DOWNLOADPATH
- + FileNameGenerator.generateFileName(media.getItem()
- .getFeed().getTitle()) + "/"
- );
- return externalStorage.toString();
- }
-
- private File getExternalFilesDirOrThrowException(Context context,
- String type) throws DownloadRequestException {
- File result = UserPreferences.getDataFolder(context, type);
- if (result == null) {
- throw new DownloadRequestException(
- "Failed to access external storage");
- }
- return result;
- }
-
- public String getMediafilename(FeedMedia media) {
- String filename;
- String titleBaseFilename = "";
-
- // Try to generate the filename by the item title
- if (media.getItem() != null && media.getItem().getTitle() != null) {
- String title = media.getItem().getTitle();
- // Delete reserved characters
- titleBaseFilename = title.replaceAll("[\\\\/%\\?\\*:|<>\"\\p{Cntrl}]", "");
- titleBaseFilename = titleBaseFilename.trim();
- }
-
- String URLBaseFilename = URLUtil.guessFileName(media.getDownload_url(),
- null, media.getMime_type());
- ;
-
- if (titleBaseFilename != "") {
- // Append extension
- filename = titleBaseFilename + FilenameUtils.EXTENSION_SEPARATOR +
- FilenameUtils.getExtension(URLBaseFilename);
- } else {
- // Fall back on URL file name
- filename = URLBaseFilename;
- }
- return filename;
- }
-}
diff --git a/src/de/danoeh/antennapod/storage/FeedItemStatistics.java b/src/de/danoeh/antennapod/storage/FeedItemStatistics.java
deleted file mode 100644
index 8cb040756..000000000
--- a/src/de/danoeh/antennapod/storage/FeedItemStatistics.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package de.danoeh.antennapod.storage;
-
-import java.util.Date;
-
-/**
- * Contains information about a feed's items.
- */
-public class FeedItemStatistics {
- private long feedID;
- private int numberOfItems;
- private int numberOfNewItems;
- private int numberOfInProgressItems;
- private Date lastUpdate;
- private static final Date UNKNOWN_DATE = new Date(0);
-
-
- /**
- * Creates new FeedItemStatistics object.
- *
- * @param feedID ID of the feed.
- * @param numberOfItems Number of items that this feed has.
- * @param numberOfNewItems Number of unread items this feed has.
- * @param numberOfInProgressItems Number of items that the user has started listening to.
- * @param lastUpdate pubDate of the latest episode. A lastUpdate value of 0 will be interpreted as DATE_UNKOWN if
- * numberOfItems is 0.
- */
- public FeedItemStatistics(long feedID, int numberOfItems, int numberOfNewItems, int numberOfInProgressItems, Date lastUpdate) {
- this.feedID = feedID;
- this.numberOfItems = numberOfItems;
- this.numberOfNewItems = numberOfNewItems;
- this.numberOfInProgressItems = numberOfInProgressItems;
- if (numberOfItems > 0) {
- this.lastUpdate = (lastUpdate != null) ? (Date) lastUpdate.clone() : null;
- } else {
- this.lastUpdate = UNKNOWN_DATE;
- }
- }
-
- public long getFeedID() {
- return feedID;
- }
-
- public int getNumberOfItems() {
- return numberOfItems;
- }
-
- public int getNumberOfNewItems() {
- return numberOfNewItems;
- }
-
- public int getNumberOfInProgressItems() {
- return numberOfInProgressItems;
- }
-
- /**
- * Returns the pubDate of the latest item in the feed. Users of this method
- * should check if this value is unkown or not by calling lastUpdateKnown() first.
- */
- public Date getLastUpdate() {
- return (lastUpdate != null) ? (Date) lastUpdate.clone() : null;
- }
-
- /**
- * Returns true if the lastUpdate value is known. The lastUpdate value is unkown if the
- * feed has no items.
- */
- public boolean lastUpdateKnown() {
- return lastUpdate != UNKNOWN_DATE;
- }
-}
diff --git a/src/de/danoeh/antennapod/storage/FeedSearcher.java b/src/de/danoeh/antennapod/storage/FeedSearcher.java
deleted file mode 100644
index e7aa93f83..000000000
--- a/src/de/danoeh/antennapod/storage/FeedSearcher.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package de.danoeh.antennapod.storage;
-
-import android.content.Context;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.feed.SearchResult;
-import de.danoeh.antennapod.util.comparator.SearchResultValueComparator;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.FutureTask;
-
-/**
- * Performs search on Feeds and FeedItems
- */
-public class FeedSearcher {
- private static final String TAG = "FeedSearcher";
-
-
- /**
- * Performs a search in all feeds or one specific feed.
- */
- public static List<SearchResult> performSearch(final Context context,
- final String query, final long selectedFeed) {
- final int values[] = {0, 0, 1, 2};
- final String[] subtitles = {context.getString(R.string.found_in_shownotes_label),
- context.getString(R.string.found_in_shownotes_label),
- context.getString(R.string.found_in_chapters_label),
- context.getString(R.string.found_in_title_label)};
-
- List<SearchResult> result = new ArrayList<SearchResult>();
-
- FutureTask<List<FeedItem>>[] tasks = new FutureTask[4];
- (tasks[0] = DBTasks.searchFeedItemContentEncoded(context, selectedFeed, query)).run();
- (tasks[1] = DBTasks.searchFeedItemDescription(context, selectedFeed, query)).run();
- (tasks[2] = DBTasks.searchFeedItemChapters(context, selectedFeed, query)).run();
- (tasks[3] = DBTasks.searchFeedItemTitle(context, selectedFeed, query)).run();
- try {
- for (int i = 0; i < tasks.length; i++) {
- FutureTask task = tasks[i];
- List<FeedItem> items = (List<FeedItem>) task.get();
- for (FeedItem item : items) {
- result.add(new SearchResult(item, values[i], subtitles[i]));
- }
-
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
- Collections.sort(result, new SearchResultValueComparator());
- return result;
- }
-}
diff --git a/src/de/danoeh/antennapod/storage/PodDBAdapter.java b/src/de/danoeh/antennapod/storage/PodDBAdapter.java
deleted file mode 100644
index 671ac30d5..000000000
--- a/src/de/danoeh/antennapod/storage/PodDBAdapter.java
+++ /dev/null
@@ -1,1391 +0,0 @@
-package de.danoeh.antennapod.storage;
-
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.database.MergeCursor;
-import android.database.SQLException;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteDatabase.CursorFactory;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.util.Log;
-
-import org.apache.commons.lang3.Validate;
-
-import java.util.Arrays;
-import java.util.List;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.feed.Chapter;
-import de.danoeh.antennapod.feed.Feed;
-import de.danoeh.antennapod.feed.FeedComponent;
-import de.danoeh.antennapod.feed.FeedImage;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.feed.FeedMedia;
-import de.danoeh.antennapod.feed.FeedPreferences;
-import de.danoeh.antennapod.service.download.DownloadStatus;
-import de.danoeh.antennapod.util.flattr.FlattrStatus;
-
-// TODO Remove media column from feeditem table
-
-/**
- * Implements methods for accessing the database
- */
-public class PodDBAdapter {
- private static final String TAG = "PodDBAdapter";
- private static final int DATABASE_VERSION = 12;
- public static final String DATABASE_NAME = "Antennapod.db";
-
- /**
- * Maximum number of arguments for IN-operator.
- */
- public static final int IN_OPERATOR_MAXIMUM = 800;
-
- /**
- * Maximum number of entries per search request.
- */
- public static final int SEARCH_LIMIT = 30;
-
- // ----------- Column indices
- // ----------- General indices
- public static final int KEY_ID_INDEX = 0;
- public static final int KEY_TITLE_INDEX = 1;
- public static final int KEY_FILE_URL_INDEX = 2;
- public static final int KEY_DOWNLOAD_URL_INDEX = 3;
- public static final int KEY_DOWNLOADED_INDEX = 4;
- public static final int KEY_LINK_INDEX = 5;
- public static final int KEY_DESCRIPTION_INDEX = 6;
- public static final int KEY_PAYMENT_LINK_INDEX = 7;
- // ----------- Feed indices
- public static final int KEY_LAST_UPDATE_INDEX = 8;
- public static final int KEY_LANGUAGE_INDEX = 9;
- public static final int KEY_AUTHOR_INDEX = 10;
- public static final int KEY_IMAGE_INDEX = 11;
- public static final int KEY_TYPE_INDEX = 12;
- public static final int KEY_FEED_IDENTIFIER_INDEX = 13;
- public static final int KEY_FEED_FLATTR_STATUS_INDEX = 14;
- public static final int KEY_FEED_USERNAME_INDEX = 15;
- public static final int KEY_FEED_PASSWORD_INDEX = 16;
- // ----------- FeedItem indices
- public static final int KEY_CONTENT_ENCODED_INDEX = 2;
- public static final int KEY_PUBDATE_INDEX = 3;
- public static final int KEY_READ_INDEX = 4;
- public static final int KEY_MEDIA_INDEX = 8;
- public static final int KEY_FEED_INDEX = 9;
- public static final int KEY_HAS_SIMPLECHAPTERS_INDEX = 10;
- public static final int KEY_ITEM_IDENTIFIER_INDEX = 11;
- public static final int KEY_ITEM_FLATTR_STATUS_INDEX = 12;
- // ---------- FeedMedia indices
- public static final int KEY_DURATION_INDEX = 1;
- public static final int KEY_POSITION_INDEX = 5;
- public static final int KEY_SIZE_INDEX = 6;
- public static final int KEY_MIME_TYPE_INDEX = 7;
- public static final int KEY_PLAYBACK_COMPLETION_DATE_INDEX = 8;
- public static final int KEY_MEDIA_FEEDITEM_INDEX = 9;
- public static final int KEY_PLAYED_DURATION_INDEX = 10;
- // --------- Download log indices
- public static final int KEY_FEEDFILE_INDEX = 1;
- public static final int KEY_FEEDFILETYPE_INDEX = 2;
- public static final int KEY_REASON_INDEX = 3;
- public static final int KEY_SUCCESSFUL_INDEX = 4;
- public static final int KEY_COMPLETION_DATE_INDEX = 5;
- public static final int KEY_REASON_DETAILED_INDEX = 6;
- public static final int KEY_DOWNLOADSTATUS_TITLE_INDEX = 7;
- // --------- Queue indices
- public static final int KEY_FEEDITEM_INDEX = 1;
- public static final int KEY_QUEUE_FEED_INDEX = 2;
- // --------- Chapters indices
- public static final int KEY_CHAPTER_START_INDEX = 2;
- public static final int KEY_CHAPTER_FEEDITEM_INDEX = 3;
- public static final int KEY_CHAPTER_LINK_INDEX = 4;
- public static final int KEY_CHAPTER_TYPE_INDEX = 5;
-
- // Key-constants
- public static final String KEY_ID = "id";
- public static final String KEY_TITLE = "title";
- public static final String KEY_NAME = "name";
- public static final String KEY_LINK = "link";
- public static final String KEY_DESCRIPTION = "description";
- public static final String KEY_FILE_URL = "file_url";
- public static final String KEY_DOWNLOAD_URL = "download_url";
- public static final String KEY_PUBDATE = "pubDate";
- public static final String KEY_READ = "read";
- public static final String KEY_DURATION = "duration";
- public static final String KEY_POSITION = "position";
- public static final String KEY_SIZE = "filesize";
- public static final String KEY_MIME_TYPE = "mime_type";
- public static final String KEY_IMAGE = "image";
- public static final String KEY_FEED = "feed";
- public static final String KEY_MEDIA = "media";
- public static final String KEY_DOWNLOADED = "downloaded";
- public static final String KEY_LASTUPDATE = "last_update";
- public static final String KEY_FEEDFILE = "feedfile";
- public static final String KEY_REASON = "reason";
- public static final String KEY_SUCCESSFUL = "successful";
- public static final String KEY_FEEDFILETYPE = "feedfile_type";
- public static final String KEY_COMPLETION_DATE = "completion_date";
- public static final String KEY_FEEDITEM = "feeditem";
- public static final String KEY_CONTENT_ENCODED = "content_encoded";
- public static final String KEY_PAYMENT_LINK = "payment_link";
- public static final String KEY_START = "start";
- public static final String KEY_LANGUAGE = "language";
- public static final String KEY_AUTHOR = "author";
- public static final String KEY_HAS_CHAPTERS = "has_simple_chapters";
- public static final String KEY_TYPE = "type";
- public static final String KEY_ITEM_IDENTIFIER = "item_identifier";
- public static final String KEY_FLATTR_STATUS = "flattr_status";
- public static final String KEY_FEED_IDENTIFIER = "feed_identifier";
- public static final String KEY_REASON_DETAILED = "reason_detailed";
- public static final String KEY_DOWNLOADSTATUS_TITLE = "title";
- public static final String KEY_CHAPTER_TYPE = "type";
- public static final String KEY_PLAYBACK_COMPLETION_DATE = "playback_completion_date";
- public static final String KEY_AUTO_DOWNLOAD = "auto_download";
- public static final String KEY_PLAYED_DURATION = "played_duration";
- public static final String KEY_USERNAME = "username";
- public static final String KEY_PASSWORD = "password";
-
- // Table names
- public static final String TABLE_NAME_FEEDS = "Feeds";
- public static final String TABLE_NAME_FEED_ITEMS = "FeedItems";
- public static final String TABLE_NAME_FEED_IMAGES = "FeedImages";
- public static final String TABLE_NAME_FEED_MEDIA = "FeedMedia";
- public static final String TABLE_NAME_DOWNLOAD_LOG = "DownloadLog";
- public static final String TABLE_NAME_QUEUE = "Queue";
- public static final String TABLE_NAME_SIMPLECHAPTERS = "SimpleChapters";
-
- // SQL Statements for creating new tables
- private static final String TABLE_PRIMARY_KEY = KEY_ID
- + " INTEGER PRIMARY KEY AUTOINCREMENT ,";
-
- private static final String CREATE_TABLE_FEEDS = "CREATE TABLE "
- + TABLE_NAME_FEEDS + " (" + TABLE_PRIMARY_KEY + KEY_TITLE
- + " TEXT," + KEY_FILE_URL + " TEXT," + KEY_DOWNLOAD_URL + " TEXT,"
- + KEY_DOWNLOADED + " INTEGER," + KEY_LINK + " TEXT,"
- + KEY_DESCRIPTION + " TEXT," + KEY_PAYMENT_LINK + " TEXT,"
- + KEY_LASTUPDATE + " TEXT," + KEY_LANGUAGE + " TEXT," + KEY_AUTHOR
- + " TEXT," + KEY_IMAGE + " INTEGER," + KEY_TYPE + " TEXT,"
- + KEY_FEED_IDENTIFIER + " TEXT," + KEY_AUTO_DOWNLOAD + " INTEGER DEFAULT 1,"
- + KEY_FLATTR_STATUS + " INTEGER,"
- + KEY_USERNAME + " TEXT,"
- + KEY_PASSWORD + " TEXT)";
-
- private static final String CREATE_TABLE_FEED_ITEMS = "CREATE TABLE "
- + TABLE_NAME_FEED_ITEMS + " (" + TABLE_PRIMARY_KEY + KEY_TITLE
- + " TEXT," + KEY_CONTENT_ENCODED + " TEXT," + KEY_PUBDATE
- + " INTEGER," + KEY_READ + " INTEGER," + KEY_LINK + " TEXT,"
- + KEY_DESCRIPTION + " TEXT," + KEY_PAYMENT_LINK + " TEXT,"
- + KEY_MEDIA + " INTEGER," + KEY_FEED + " INTEGER,"
- + KEY_HAS_CHAPTERS + " INTEGER," + KEY_ITEM_IDENTIFIER + " TEXT,"
- + KEY_FLATTR_STATUS + " INTEGER,"
- + KEY_IMAGE + " INTEGER)";
-
- private static final String CREATE_TABLE_FEED_IMAGES = "CREATE TABLE "
- + TABLE_NAME_FEED_IMAGES + " (" + TABLE_PRIMARY_KEY + KEY_TITLE
- + " TEXT," + KEY_FILE_URL + " TEXT," + KEY_DOWNLOAD_URL + " TEXT,"
- + KEY_DOWNLOADED + " INTEGER)";
-
- private static final String CREATE_TABLE_FEED_MEDIA = "CREATE TABLE "
- + TABLE_NAME_FEED_MEDIA + " (" + TABLE_PRIMARY_KEY + KEY_DURATION
- + " INTEGER," + KEY_FILE_URL + " TEXT," + KEY_DOWNLOAD_URL
- + " TEXT," + KEY_DOWNLOADED + " INTEGER," + KEY_POSITION
- + " INTEGER," + KEY_SIZE + " INTEGER," + KEY_MIME_TYPE + " TEXT,"
- + KEY_PLAYBACK_COMPLETION_DATE + " INTEGER,"
- + KEY_FEEDITEM + " INTEGER,"
- + KEY_PLAYED_DURATION + " INTEGER)";
-
- private static final String CREATE_TABLE_DOWNLOAD_LOG = "CREATE TABLE "
- + TABLE_NAME_DOWNLOAD_LOG + " (" + TABLE_PRIMARY_KEY + KEY_FEEDFILE
- + " INTEGER," + KEY_FEEDFILETYPE + " INTEGER," + KEY_REASON
- + " INTEGER," + KEY_SUCCESSFUL + " INTEGER," + KEY_COMPLETION_DATE
- + " INTEGER," + KEY_REASON_DETAILED + " TEXT,"
- + KEY_DOWNLOADSTATUS_TITLE + " TEXT)";
-
- private static final String CREATE_TABLE_QUEUE = "CREATE TABLE "
- + TABLE_NAME_QUEUE + "(" + KEY_ID + " INTEGER PRIMARY KEY,"
- + KEY_FEEDITEM + " INTEGER," + KEY_FEED + " INTEGER)";
-
- private static final String CREATE_TABLE_SIMPLECHAPTERS = "CREATE TABLE "
- + TABLE_NAME_SIMPLECHAPTERS + " (" + TABLE_PRIMARY_KEY + KEY_TITLE
- + " TEXT," + KEY_START + " INTEGER," + KEY_FEEDITEM + " INTEGER,"
- + KEY_LINK + " TEXT," + KEY_CHAPTER_TYPE + " INTEGER)";
-
- private SQLiteDatabase db;
- private final Context context;
- private PodDBHelper helper;
-
- /**
- * Select all columns from the feed-table
- */
- private static final String[] FEED_SEL_STD = {
- TABLE_NAME_FEEDS + "." + KEY_ID,
- TABLE_NAME_FEEDS + "." + KEY_TITLE,
- TABLE_NAME_FEEDS + "." + KEY_FILE_URL,
- TABLE_NAME_FEEDS + "." + KEY_DOWNLOAD_URL,
- TABLE_NAME_FEEDS + "." + KEY_DOWNLOADED,
- TABLE_NAME_FEEDS + "." + KEY_LINK,
- TABLE_NAME_FEEDS + "." + KEY_DESCRIPTION,
- TABLE_NAME_FEEDS + "." + KEY_PAYMENT_LINK,
- TABLE_NAME_FEEDS + "." + KEY_LASTUPDATE,
- TABLE_NAME_FEEDS + "." + KEY_LANGUAGE,
- TABLE_NAME_FEEDS + "." + KEY_AUTHOR,
- TABLE_NAME_FEEDS + "." + KEY_IMAGE,
- TABLE_NAME_FEEDS + "." + KEY_TYPE,
- TABLE_NAME_FEEDS + "." + KEY_FEED_IDENTIFIER,
- TABLE_NAME_FEEDS + "." + KEY_AUTO_DOWNLOAD,
- TABLE_NAME_FEEDS + "." + KEY_FLATTR_STATUS,
- TABLE_NAME_FEEDS + "." + KEY_USERNAME,
- TABLE_NAME_FEEDS + "." + KEY_PASSWORD
- };
-
- // column indices for FEED_SEL_STD
- public static final int IDX_FEED_SEL_STD_ID = 0;
- public static final int IDX_FEED_SEL_STD_TITLE = 1;
- public static final int IDX_FEED_SEL_STD_FILE_URL = 2;
- public static final int IDX_FEED_SEL_STD_DOWNLOAD_URL = 3;
- public static final int IDX_FEED_SEL_STD_DOWNLOADED = 4;
- public static final int IDX_FEED_SEL_STD_LINK = 5;
- public static final int IDX_FEED_SEL_STD_DESCRIPTION = 6;
- public static final int IDX_FEED_SEL_STD_PAYMENT_LINK = 7;
- public static final int IDX_FEED_SEL_STD_LASTUPDATE = 8;
- public static final int IDX_FEED_SEL_STD_LANGUAGE = 9;
- public static final int IDX_FEED_SEL_STD_AUTHOR = 10;
- public static final int IDX_FEED_SEL_STD_IMAGE = 11;
- public static final int IDX_FEED_SEL_STD_TYPE = 12;
- public static final int IDX_FEED_SEL_STD_FEED_IDENTIFIER = 13;
- public static final int IDX_FEED_SEL_PREFERENCES_AUTO_DOWNLOAD = 14;
- public static final int IDX_FEED_SEL_STD_FLATTR_STATUS = 15;
- public static final int IDX_FEED_SEL_PREFERENCES_USERNAME = 16;
- public static final int IDX_FEED_SEL_PREFERENCES_PASSWORD = 17;
-
-
- /**
- * Select all columns from the feeditems-table except description and
- * content-encoded.
- */
- private static final String[] FEEDITEM_SEL_FI_SMALL = {
- TABLE_NAME_FEED_ITEMS + "." + KEY_ID,
- TABLE_NAME_FEED_ITEMS + "." + KEY_TITLE,
- TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE,
- TABLE_NAME_FEED_ITEMS + "." + KEY_READ,
- TABLE_NAME_FEED_ITEMS + "." + KEY_LINK,
- TABLE_NAME_FEED_ITEMS + "." + KEY_PAYMENT_LINK, KEY_MEDIA,
- TABLE_NAME_FEED_ITEMS + "." + KEY_FEED,
- TABLE_NAME_FEED_ITEMS + "." + KEY_HAS_CHAPTERS,
- TABLE_NAME_FEED_ITEMS + "." + KEY_ITEM_IDENTIFIER,
- TABLE_NAME_FEED_ITEMS + "." + KEY_FLATTR_STATUS,
- TABLE_NAME_FEED_ITEMS + "." + KEY_IMAGE};
-
- /**
- * Contains FEEDITEM_SEL_FI_SMALL as comma-separated list. Useful for raw queries.
- */
- private static final String SEL_FI_SMALL_STR;
-
- static {
- String selFiSmall = Arrays.toString(FEEDITEM_SEL_FI_SMALL);
- SEL_FI_SMALL_STR = selFiSmall.substring(1, selFiSmall.length() - 1);
- }
-
- // column indices for FEEDITEM_SEL_FI_SMALL
-
- public static final int IDX_FI_SMALL_ID = 0;
- public static final int IDX_FI_SMALL_TITLE = 1;
- public static final int IDX_FI_SMALL_PUBDATE = 2;
- public static final int IDX_FI_SMALL_READ = 3;
- public static final int IDX_FI_SMALL_LINK = 4;
- public static final int IDX_FI_SMALL_PAYMENT_LINK = 5;
- public static final int IDX_FI_SMALL_MEDIA = 6;
- public static final int IDX_FI_SMALL_FEED = 7;
- public static final int IDX_FI_SMALL_HAS_CHAPTERS = 8;
- public static final int IDX_FI_SMALL_ITEM_IDENTIFIER = 9;
- public static final int IDX_FI_SMALL_FLATTR_STATUS = 10;
- public static final int IDX_FI_SMALL_IMAGE = 11;
-
- /**
- * Select id, description and content-encoded column from feeditems.
- */
- private static final String[] SEL_FI_EXTRA = {KEY_ID, KEY_DESCRIPTION,
- KEY_CONTENT_ENCODED, KEY_FEED};
-
- // column indices for SEL_FI_EXTRA
-
- public static final int IDX_FI_EXTRA_ID = 0;
- public static final int IDX_FI_EXTRA_DESCRIPTION = 1;
- public static final int IDX_FI_EXTRA_CONTENT_ENCODED = 2;
- public static final int IDX_FI_EXTRA_FEED = 3;
-
- static PodDBHelper dbHelperSingleton;
-
- private static synchronized PodDBHelper getDbHelperSingleton(Context appContext) {
- if (dbHelperSingleton == null) {
- dbHelperSingleton = new PodDBHelper(appContext, DATABASE_NAME, null, DATABASE_VERSION);
- }
- return dbHelperSingleton;
- }
-
- public PodDBAdapter(Context c) {
- this.context = c;
- helper = getDbHelperSingleton(c.getApplicationContext());
- }
-
- public PodDBAdapter open() {
- if (db == null || !db.isOpen() || db.isReadOnly()) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Opening DB");
- try {
- db = helper.getWritableDatabase();
- } catch (SQLException ex) {
- ex.printStackTrace();
- db = helper.getReadableDatabase();
- }
- }
- return this;
- }
-
- public void close() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Closing DB");
- //db.close();
- }
-
- public static boolean deleteDatabase(Context context) {
- Log.w(TAG, "Deleting database");
- dbHelperSingleton.close();
- dbHelperSingleton = null;
- return context.deleteDatabase(DATABASE_NAME);
- }
-
- /**
- * Inserts or updates a feed entry
- *
- * @return the id of the entry
- */
- public long setFeed(Feed feed) {
- ContentValues values = new ContentValues();
- values.put(KEY_TITLE, feed.getTitle());
- values.put(KEY_LINK, feed.getLink());
- values.put(KEY_DESCRIPTION, feed.getDescription());
- values.put(KEY_PAYMENT_LINK, feed.getPaymentLink());
- values.put(KEY_AUTHOR, feed.getAuthor());
- values.put(KEY_LANGUAGE, feed.getLanguage());
- if (feed.getImage() != null) {
- if (feed.getImage().getId() == 0) {
- setImage(feed.getImage());
- }
- values.put(KEY_IMAGE, feed.getImage().getId());
- }
-
- values.put(KEY_FILE_URL, feed.getFile_url());
- values.put(KEY_DOWNLOAD_URL, feed.getDownload_url());
- values.put(KEY_DOWNLOADED, feed.isDownloaded());
- values.put(KEY_LASTUPDATE, feed.getLastUpdate().getTime());
- values.put(KEY_TYPE, feed.getType());
- values.put(KEY_FEED_IDENTIFIER, feed.getFeedIdentifier());
-
- Log.d(TAG, "Setting feed with flattr status " + feed.getTitle() + ": " + feed.getFlattrStatus().toLong());
-
- values.put(KEY_FLATTR_STATUS, feed.getFlattrStatus().toLong());
- if (feed.getId() == 0) {
- // Create new entry
- if (BuildConfig.DEBUG)
- Log.d(this.toString(), "Inserting new Feed into db");
- feed.setId(db.insert(TABLE_NAME_FEEDS, null, values));
- } else {
- if (BuildConfig.DEBUG)
- Log.d(this.toString(), "Updating existing Feed in db");
- db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?",
- new String[]{String.valueOf(feed.getId())});
-
- }
- return feed.getId();
- }
-
- public void setFeedPreferences(FeedPreferences prefs) {
- if (prefs.getFeedID() == 0) {
- throw new IllegalArgumentException("Feed ID of preference must not be null");
- }
- ContentValues values = new ContentValues();
- values.put(KEY_AUTO_DOWNLOAD, prefs.getAutoDownload());
- values.put(KEY_USERNAME, prefs.getUsername());
- values.put(KEY_PASSWORD, prefs.getPassword());
- db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(prefs.getFeedID())});
- }
-
- /**
- * Inserts or updates an image entry
- *
- * @return the id of the entry
- */
- public long setImage(FeedImage image) {
- db.beginTransaction();
- ContentValues values = new ContentValues();
- values.put(KEY_TITLE, image.getTitle());
- values.put(KEY_DOWNLOAD_URL, image.getDownload_url());
- values.put(KEY_DOWNLOADED, image.isDownloaded());
- values.put(KEY_FILE_URL, image.getFile_url());
- if (image.getId() == 0) {
- image.setId(db.insert(TABLE_NAME_FEED_IMAGES, null, values));
- } else {
- db.update(TABLE_NAME_FEED_IMAGES, values, KEY_ID + "=?",
- new String[]{String.valueOf(image.getId())});
- }
-
- final FeedComponent owner = image.getOwner();
- if (owner != null && owner.getId() != 0) {
- values.clear();
- values.put(KEY_IMAGE, image.getId());
- if (owner instanceof Feed) {
- db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(image.getOwner().getId())});
- }
- }
- db.setTransactionSuccessful();
- db.endTransaction();
- return image.getId();
- }
-
- /**
- * Inserts or updates an image entry
- *
- * @return the id of the entry
- */
- public long setMedia(FeedMedia media) {
- ContentValues values = new ContentValues();
- values.put(KEY_DURATION, media.getDuration());
- values.put(KEY_POSITION, media.getPosition());
- values.put(KEY_SIZE, media.getSize());
- values.put(KEY_MIME_TYPE, media.getMime_type());
- values.put(KEY_DOWNLOAD_URL, media.getDownload_url());
- values.put(KEY_DOWNLOADED, media.isDownloaded());
- values.put(KEY_FILE_URL, media.getFile_url());
-
- if (media.getPlaybackCompletionDate() != null) {
- values.put(KEY_PLAYBACK_COMPLETION_DATE, media
- .getPlaybackCompletionDate().getTime());
- } else {
- values.put(KEY_PLAYBACK_COMPLETION_DATE, 0);
- }
- if (media.getItem() != null) {
- values.put(KEY_FEEDITEM, media.getItem().getId());
- }
- if (media.getId() == 0) {
- media.setId(db.insert(TABLE_NAME_FEED_MEDIA, null, values));
- } else {
- db.update(TABLE_NAME_FEED_MEDIA, values, KEY_ID + "=?",
- new String[]{String.valueOf(media.getId())});
- }
- return media.getId();
- }
-
- public void setFeedMediaPlaybackInformation(FeedMedia media) {
- if (media.getId() != 0) {
- ContentValues values = new ContentValues();
- values.put(KEY_POSITION, media.getPosition());
- values.put(KEY_DURATION, media.getDuration());
- values.put(KEY_PLAYED_DURATION, media.getPlayedDuration());
- db.update(TABLE_NAME_FEED_MEDIA, values, KEY_ID + "=?",
- new String[]{String.valueOf(media.getId())});
- } else {
- Log.e(TAG, "setFeedMediaPlaybackInformation: ID of media was 0");
- }
- }
-
- public void setFeedMediaPlaybackCompletionDate(FeedMedia media) {
- if (media.getId() != 0) {
- ContentValues values = new ContentValues();
- values.put(KEY_PLAYBACK_COMPLETION_DATE, media.getPlaybackCompletionDate().getTime());
- values.put(KEY_PLAYED_DURATION, media.getPlayedDuration());
- db.update(TABLE_NAME_FEED_MEDIA, values, KEY_ID + "=?",
- new String[]{String.valueOf(media.getId())});
- } else {
- Log.e(TAG, "setFeedMediaPlaybackCompletionDate: ID of media was 0");
- }
- }
-
- /**
- * Insert all FeedItems of a feed and the feed object itself in a single
- * transaction
- */
- public void setCompleteFeed(Feed... feeds) {
- db.beginTransaction();
- for (Feed feed : feeds) {
- setFeed(feed);
- if (feed.getItems() != null) {
- for (FeedItem item : feed.getItems()) {
- setFeedItem(item, false);
- }
- }
- if (feed.getPreferences() != null) {
- setFeedPreferences(feed.getPreferences());
- }
- }
- db.setTransactionSuccessful();
- db.endTransaction();
- }
-
- /**
- * Update the flattr status of a feed
- */
- public void setFeedFlattrStatus(Feed feed) {
- ContentValues values = new ContentValues();
- values.put(KEY_FLATTR_STATUS, feed.getFlattrStatus().toLong());
- db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(feed.getId())});
- }
-
- /**
- * Get all feeds in the flattr queue.
- */
- public Cursor getFeedsInFlattrQueueCursor() {
- return db.query(TABLE_NAME_FEEDS, FEED_SEL_STD, KEY_FLATTR_STATUS + "=?",
- new String[]{String.valueOf(FlattrStatus.STATUS_QUEUE)}, null, null, null);
- }
-
- /**
- * Get all feed items in the flattr queue.
- */
- public Cursor getFeedItemsInFlattrQueueCursor() {
- return db.query(TABLE_NAME_FEED_ITEMS, FEEDITEM_SEL_FI_SMALL, KEY_FLATTR_STATUS + "=?",
- new String[]{String.valueOf(FlattrStatus.STATUS_QUEUE)}, null, null, null);
- }
-
- /**
- * Counts feeds and feed items in the flattr queue
- */
- public int getFlattrQueueSize() {
- int res = 0;
- Cursor c = db.rawQuery(String.format("SELECT count(*) FROM %s WHERE %s=%s",
- TABLE_NAME_FEEDS, KEY_FLATTR_STATUS, String.valueOf(FlattrStatus.STATUS_QUEUE)), null);
- if (c.moveToFirst()) {
- res = c.getInt(0);
- c.close();
- } else {
- Log.e(TAG, "Unable to determine size of flattr queue: Could not count number of feeds");
- }
- c = db.rawQuery(String.format("SELECT count(*) FROM %s WHERE %s=%s",
- TABLE_NAME_FEED_ITEMS, KEY_FLATTR_STATUS, String.valueOf(FlattrStatus.STATUS_QUEUE)), null);
- if (c.moveToFirst()) {
- res += c.getInt(0);
- c.close();
- } else {
- Log.e(TAG, "Unable to determine size of flattr queue: Could not count number of feed items");
- }
-
- return res;
- }
-
- /**
- * Updates the download URL of a Feed.
- */
- public void setFeedDownloadUrl(String original, String updated) {
- ContentValues values = new ContentValues();
- values.put(KEY_DOWNLOAD_URL, updated);
- db.update(TABLE_NAME_FEEDS, values, KEY_DOWNLOAD_URL + "=?", new String[]{original});
- }
-
- public void setFeedItemlist(List<FeedItem> items) {
- db.beginTransaction();
- for (FeedItem item : items) {
- setFeedItem(item, true);
- }
- db.setTransactionSuccessful();
- db.endTransaction();
- }
-
- public long setSingleFeedItem(FeedItem item) {
- db.beginTransaction();
- long result = setFeedItem(item, true);
- db.setTransactionSuccessful();
- db.endTransaction();
- return result;
- }
-
- /**
- * Update the flattr status of a FeedItem
- */
- public void setFeedItemFlattrStatus(FeedItem feedItem) {
- ContentValues values = new ContentValues();
- values.put(KEY_FLATTR_STATUS, feedItem.getFlattrStatus().toLong());
- db.update(TABLE_NAME_FEED_ITEMS, values, KEY_ID + "=?", new String[]{String.valueOf(feedItem.getId())});
- }
-
- /**
- * Update the flattr status of a feed or feed item specified by its payment link
- * and the new flattr status to use
- */
- public void setItemFlattrStatus(String url, FlattrStatus status) {
- //Log.d(TAG, "setItemFlattrStatus(" + url + ") = " + status.toString());
- ContentValues values = new ContentValues();
- values.put(KEY_FLATTR_STATUS, status.toLong());
-
- // regexps in sqlite would be neat!
- String[] query_urls = new String[]{
- "*" + url + "&*",
- "*" + url + "%2F&*",
- "*" + url + "",
- "*" + url + "%2F"
- };
-
- if (db.update(TABLE_NAME_FEEDS, values,
- KEY_PAYMENT_LINK + " GLOB ?"
- + " OR " + KEY_PAYMENT_LINK + " GLOB ?"
- + " OR " + KEY_PAYMENT_LINK + " GLOB ?"
- + " OR " + KEY_PAYMENT_LINK + " GLOB ?", query_urls
- ) > 0) {
- Log.i(TAG, "setItemFlattrStatus found match for " + url + " = " + status.toLong() + " in Feeds table");
- return;
- }
- if (db.update(TABLE_NAME_FEED_ITEMS, values,
- KEY_PAYMENT_LINK + " GLOB ?"
- + " OR " + KEY_PAYMENT_LINK + " GLOB ?"
- + " OR " + KEY_PAYMENT_LINK + " GLOB ?"
- + " OR " + KEY_PAYMENT_LINK + " GLOB ?", query_urls
- ) > 0) {
- Log.i(TAG, "setItemFlattrStatus found match for " + url + " = " + status.toLong() + " in FeedsItems table");
- }
- }
-
- /**
- * Reset flattr status to unflattrd for all items
- */
- public void clearAllFlattrStatus() {
- ContentValues values = new ContentValues();
- values.put(KEY_FLATTR_STATUS, 0);
- db.update(TABLE_NAME_FEEDS, values, null, null);
- db.update(TABLE_NAME_FEED_ITEMS, values, null, null);
- }
-
- /**
- * Inserts or updates a feeditem entry
- *
- * @param item The FeedItem
- * @param saveFeed true if the Feed of the item should also be saved. This should be set to
- * false if the method is executed on a list of FeedItems of the same Feed.
- * @return the id of the entry
- */
- private long setFeedItem(FeedItem item, boolean saveFeed) {
- ContentValues values = new ContentValues();
- values.put(KEY_TITLE, item.getTitle());
- values.put(KEY_LINK, item.getLink());
- if (item.getDescription() != null) {
- values.put(KEY_DESCRIPTION, item.getDescription());
- }
- if (item.getContentEncoded() != null) {
- values.put(KEY_CONTENT_ENCODED, item.getContentEncoded());
- }
- values.put(KEY_PUBDATE, item.getPubDate().getTime());
- values.put(KEY_PAYMENT_LINK, item.getPaymentLink());
- if (saveFeed && item.getFeed() != null) {
- setFeed(item.getFeed());
- }
- values.put(KEY_FEED, item.getFeed().getId());
- values.put(KEY_READ, item.isRead());
- values.put(KEY_HAS_CHAPTERS, item.getChapters() != null);
- values.put(KEY_ITEM_IDENTIFIER, item.getItemIdentifier());
- values.put(KEY_FLATTR_STATUS, item.getFlattrStatus().toLong());
- if (item.hasItemImage()) {
- if (item.getImage().getId() == 0) {
- setImage(item.getImage());
- }
- values.put(KEY_IMAGE, item.getImage().getId());
- }
-
- if (item.getId() == 0) {
- item.setId(db.insert(TABLE_NAME_FEED_ITEMS, null, values));
- } else {
- db.update(TABLE_NAME_FEED_ITEMS, values, KEY_ID + "=?",
- new String[]{String.valueOf(item.getId())});
- }
- if (item.getMedia() != null) {
- setMedia(item.getMedia());
- }
- if (item.getChapters() != null) {
- setChapters(item);
- }
- return item.getId();
- }
-
- public void setFeedItemRead(boolean read, long itemId, long mediaId,
- boolean resetMediaPosition) {
- db.beginTransaction();
- ContentValues values = new ContentValues();
-
- values.put(KEY_READ, read);
- db.update(TABLE_NAME_FEED_ITEMS, values, KEY_ID + "=?", new String[]{String.valueOf(itemId)});
-
- if (resetMediaPosition) {
- values.clear();
- values.put(KEY_POSITION, 0);
- db.update(TABLE_NAME_FEED_MEDIA, values, KEY_ID + "=?", new String[]{String.valueOf(mediaId)});
- }
-
- db.setTransactionSuccessful();
- db.endTransaction();
- }
-
- public void setFeedItemRead(boolean read, long... itemIds) {
- db.beginTransaction();
- ContentValues values = new ContentValues();
- for (long id : itemIds) {
- values.clear();
- values.put(KEY_READ, read);
- db.update(TABLE_NAME_FEED_ITEMS, values, KEY_ID + "=?", new String[]{String.valueOf(id)});
- }
- db.setTransactionSuccessful();
- db.endTransaction();
- }
-
- public void setChapters(FeedItem item) {
- ContentValues values = new ContentValues();
- for (Chapter chapter : item.getChapters()) {
- values.put(KEY_TITLE, chapter.getTitle());
- values.put(KEY_START, chapter.getStart());
- values.put(KEY_FEEDITEM, item.getId());
- values.put(KEY_LINK, chapter.getLink());
- values.put(KEY_CHAPTER_TYPE, chapter.getChapterType());
- if (chapter.getId() == 0) {
- chapter.setId(db
- .insert(TABLE_NAME_SIMPLECHAPTERS, null, values));
- } else {
- db.update(TABLE_NAME_SIMPLECHAPTERS, values, KEY_ID + "=?",
- new String[]{String.valueOf(chapter.getId())});
- }
- }
- }
-
- /**
- * Inserts or updates a download status.
- */
- public long setDownloadStatus(DownloadStatus status) {
- ContentValues values = new ContentValues();
- values.put(KEY_FEEDFILE, status.getFeedfileId());
- values.put(KEY_FEEDFILETYPE, status.getFeedfileType());
- values.put(KEY_REASON, status.getReason().getCode());
- values.put(KEY_SUCCESSFUL, status.isSuccessful());
- values.put(KEY_COMPLETION_DATE, status.getCompletionDate().getTime());
- values.put(KEY_REASON_DETAILED, status.getReasonDetailed());
- values.put(KEY_DOWNLOADSTATUS_TITLE, status.getTitle());
- if (status.getId() == 0) {
- status.setId(db.insert(TABLE_NAME_DOWNLOAD_LOG, null, values));
- } else {
- db.update(TABLE_NAME_DOWNLOAD_LOG, values, KEY_ID + "=?",
- new String[]{String.valueOf(status.getId())});
- }
- return status.getId();
- }
-
- public long getDownloadLogSize() {
- final String query = String.format("SELECT COUNT(%s) FROM %s", KEY_ID, TABLE_NAME_DOWNLOAD_LOG);
- Cursor result = db.rawQuery(query, null);
- long count = 0;
- if (result.moveToFirst()) {
- count = result.getLong(0);
- }
- result.close();
- return count;
- }
-
- public void removeDownloadLogItems(long count) {
- if (count > 0) {
- final String sql = String.format("DELETE FROM %s WHERE %s in (SELECT %s from %s ORDER BY %s ASC LIMIT %d)",
- TABLE_NAME_DOWNLOAD_LOG, KEY_ID, KEY_ID, TABLE_NAME_DOWNLOAD_LOG, KEY_COMPLETION_DATE, count);
- db.execSQL(sql, null);
- }
- }
-
- public void setQueue(List<FeedItem> queue) {
- ContentValues values = new ContentValues();
- db.beginTransaction();
- db.delete(TABLE_NAME_QUEUE, null, null);
- for (int i = 0; i < queue.size(); i++) {
- FeedItem item = queue.get(i);
- values.put(KEY_ID, i);
- values.put(KEY_FEEDITEM, item.getId());
- values.put(KEY_FEED, item.getFeed().getId());
- db.insertWithOnConflict(TABLE_NAME_QUEUE, null, values,
- SQLiteDatabase.CONFLICT_REPLACE);
- }
- db.setTransactionSuccessful();
- db.endTransaction();
- }
-
- public void clearQueue() {
- db.delete(TABLE_NAME_QUEUE, null, null);
- }
-
- public void removeFeedMedia(FeedMedia media) {
- db.delete(TABLE_NAME_FEED_MEDIA, KEY_ID + "=?",
- new String[]{String.valueOf(media.getId())});
- }
-
- public void removeChaptersOfItem(FeedItem item) {
- db.delete(TABLE_NAME_SIMPLECHAPTERS, KEY_FEEDITEM + "=?",
- new String[]{String.valueOf(item.getId())});
- }
-
- public void removeFeedImage(FeedImage image) {
- db.delete(TABLE_NAME_FEED_IMAGES, KEY_ID + "=?",
- new String[]{String.valueOf(image.getId())});
- }
-
- /**
- * Remove a FeedItem and its FeedMedia entry.
- */
- public void removeFeedItem(FeedItem item) {
- if (item.getMedia() != null) {
- removeFeedMedia(item.getMedia());
- }
- if (item.getChapters() != null) {
- removeChaptersOfItem(item);
- }
- if (item.hasItemImage()) {
- removeFeedImage(item.getImage());
- }
- db.delete(TABLE_NAME_FEED_ITEMS, KEY_ID + "=?",
- new String[]{String.valueOf(item.getId())});
- }
-
- /**
- * Remove a feed with all its FeedItems and Media entries.
- */
- public void removeFeed(Feed feed) {
- db.beginTransaction();
- if (feed.getImage() != null) {
- removeFeedImage(feed.getImage());
- }
- if (feed.getItems() != null) {
- for (FeedItem item : feed.getItems()) {
- removeFeedItem(item);
- }
- }
-
- db.delete(TABLE_NAME_FEEDS, KEY_ID + "=?",
- new String[]{String.valueOf(feed.getId())});
- db.setTransactionSuccessful();
- db.endTransaction();
- }
-
- public void removeDownloadStatus(DownloadStatus remove) {
- db.delete(TABLE_NAME_DOWNLOAD_LOG, KEY_ID + "=?",
- new String[]{String.valueOf(remove.getId())});
- }
-
- public void clearPlaybackHistory() {
- ContentValues values = new ContentValues();
- values.put(KEY_PLAYBACK_COMPLETION_DATE, 0);
- db.update(TABLE_NAME_FEED_MEDIA, values, null, null);
- }
-
- /**
- * Get all Feeds from the Feed Table.
- *
- * @return The cursor of the query
- */
- public final Cursor getAllFeedsCursor() {
- Cursor c = db.query(TABLE_NAME_FEEDS, FEED_SEL_STD, null, null, null, null,
- KEY_TITLE + " COLLATE NOCASE ASC");
- return c;
- }
-
- public final Cursor getFeedCursorDownloadUrls() {
- return db.query(TABLE_NAME_FEEDS, new String[]{KEY_ID, KEY_DOWNLOAD_URL}, null, null, null, null, null);
- }
-
- public final Cursor getExpiredFeedsCursor(long expirationTime) {
- Cursor c = db.query(TABLE_NAME_FEEDS, FEED_SEL_STD, KEY_LASTUPDATE + " < " + String.valueOf(System.currentTimeMillis() - expirationTime),
- null, null, null,
- null);
- return c;
- }
-
- /**
- * Returns a cursor with all FeedItems of a Feed. Uses FEEDITEM_SEL_FI_SMALL
- *
- * @param feed The feed you want to get the FeedItems from.
- * @return The cursor of the query
- */
- public final Cursor getAllItemsOfFeedCursor(final Feed feed) {
- return getAllItemsOfFeedCursor(feed.getId());
- }
-
- public final Cursor getAllItemsOfFeedCursor(final long feedId) {
- Cursor c = db.query(TABLE_NAME_FEED_ITEMS, FEEDITEM_SEL_FI_SMALL, KEY_FEED
- + "=?", new String[]{String.valueOf(feedId)}, null, null,
- null
- );
- return c;
- }
-
- /**
- * Return a cursor with the SEL_FI_EXTRA selection of a single feeditem.
- */
- public final Cursor getExtraInformationOfItem(final FeedItem item) {
- Cursor c = db
- .query(TABLE_NAME_FEED_ITEMS, SEL_FI_EXTRA, KEY_ID + "=?",
- new String[]{String.valueOf(item.getId())}, null,
- null, null);
- return c;
- }
-
- /**
- * Returns a cursor for a DB query in the FeedMedia table for a given ID.
- *
- * @param item The item you want to get the FeedMedia from
- * @return The cursor of the query
- */
- public final Cursor getFeedMediaOfItemCursor(final FeedItem item) {
- Cursor c = db.query(TABLE_NAME_FEED_MEDIA, null, KEY_ID + "=?",
- new String[]{String.valueOf(item.getMedia().getId())}, null,
- null, null);
- return c;
- }
-
- /**
- * Returns a cursor for a DB query in the FeedImages table for a given ID.
- *
- * @param id ID of the FeedImage
- * @return The cursor of the query
- */
- public final Cursor getImageCursor(final long id) {
- Cursor c = db.query(TABLE_NAME_FEED_IMAGES, null, KEY_ID + "=?",
- new String[]{String.valueOf(id)}, null, null, null);
- return c;
- }
-
- public final Cursor getSimpleChaptersOfFeedItemCursor(final FeedItem item) {
- Cursor c = db.query(TABLE_NAME_SIMPLECHAPTERS, null, KEY_FEEDITEM
- + "=?", new String[]{String.valueOf(item.getId())}, null,
- null, null
- );
- return c;
- }
-
- public final Cursor getDownloadLogCursor(final int limit) {
- Cursor c = db.query(TABLE_NAME_DOWNLOAD_LOG, null, null, null, null,
- null, KEY_COMPLETION_DATE + " DESC LIMIT " + limit);
- return c;
- }
-
- /**
- * Returns a cursor which contains all feed items in the queue. The returned
- * cursor uses the FEEDITEM_SEL_FI_SMALL selection.
- */
- public final Cursor getQueueCursor() {
- Object[] args = (Object[]) new String[]{
- SEL_FI_SMALL_STR + "," + TABLE_NAME_QUEUE + "." + KEY_ID,
- TABLE_NAME_FEED_ITEMS, TABLE_NAME_QUEUE,
- TABLE_NAME_FEED_ITEMS + "." + KEY_ID,
- TABLE_NAME_QUEUE + "." + KEY_FEEDITEM,
- TABLE_NAME_QUEUE + "." + KEY_ID};
- String query = String.format(
- "SELECT %s FROM %s INNER JOIN %s ON %s=%s ORDER BY %s", args);
- Cursor c = db.rawQuery(query, null);
- /*
- * Cursor c = db.query(TABLE_NAME_FEED_ITEMS, FEEDITEM_SEL_FI_SMALL,
- * "INNER JOIN ? ON ?=?", new String[] { TABLE_NAME_QUEUE,
- * TABLE_NAME_FEED_ITEMS + "." + KEY_ID, TABLE_NAME_QUEUE + "." +
- * KEY_FEEDITEM }, null, null, TABLE_NAME_QUEUE + "." + KEY_FEEDITEM);
- */
- return c;
- }
-
- public Cursor getQueueIDCursor() {
- Cursor c = db.query(TABLE_NAME_QUEUE, new String[]{KEY_FEEDITEM}, null, null, null, null, KEY_ID + " ASC", null);
- return c;
- }
-
- /**
- * Returns a cursor which contains all feed items in the unread items list.
- * The returned cursor uses the FEEDITEM_SEL_FI_SMALL selection.
- */
- public final Cursor getUnreadItemsCursor() {
- Cursor c = db.query(TABLE_NAME_FEED_ITEMS, FEEDITEM_SEL_FI_SMALL, KEY_READ
- + "=0", null, null, null, KEY_PUBDATE + " DESC");
- return c;
- }
-
- public final Cursor getUnreadItemIdsCursor() {
- Cursor c = db.query(TABLE_NAME_FEED_ITEMS, new String[]{KEY_ID},
- KEY_READ + "=0", null, null, null, KEY_PUBDATE + " DESC");
- return c;
-
- }
-
- public final Cursor getRecentlyPublishedItemsCursor(int limit) {
- Cursor c = db.query(TABLE_NAME_FEED_ITEMS, FEEDITEM_SEL_FI_SMALL, null, null, null, null, KEY_PUBDATE + " DESC LIMIT " + limit);
- return c;
- }
-
- public Cursor getDownloadedItemsCursor() {
- final String query = "SELECT " + SEL_FI_SMALL_STR + " FROM " + TABLE_NAME_FEED_ITEMS
- + " INNER JOIN " + TABLE_NAME_FEED_MEDIA + " ON "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
- + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM + " WHERE "
- + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + ">0";
- Cursor c = db.rawQuery(query, null);
- return c;
- }
-
- /**
- * Returns a cursor which contains feed media objects with a playback
- * completion date in ascending order.
- *
- * @param limit The maximum row count of the returned cursor. Must be an
- * integer >= 0.
- * @throws IllegalArgumentException if limit < 0
- */
- public final Cursor getCompletedMediaCursor(int limit) {
- Validate.isTrue(limit >= 0, "Limit must be >= 0");
-
- Cursor c = db.query(TABLE_NAME_FEED_MEDIA, null,
- KEY_PLAYBACK_COMPLETION_DATE + " > 0 LIMIT " + limit, null, null,
- null, null);
- return c;
- }
-
- public final Cursor getSingleFeedMediaCursor(long id) {
- return db.query(TABLE_NAME_FEED_MEDIA, null, KEY_ID + "=?", new String[]{String.valueOf(id)}, null, null, null);
- }
-
- public final Cursor getFeedMediaCursorByItemID(String... mediaIds) {
- int length = mediaIds.length;
- if (length > IN_OPERATOR_MAXIMUM) {
- Log.w(TAG, "Length of id array is larger than "
- + IN_OPERATOR_MAXIMUM + ". Creating multiple cursors");
- int numCursors = (int) (((double) length) / (IN_OPERATOR_MAXIMUM)) + 1;
- Cursor[] cursors = new Cursor[numCursors];
- for (int i = 0; i < numCursors; i++) {
- int neededLength = 0;
- String[] parts = null;
- final int elementsLeft = length - i * IN_OPERATOR_MAXIMUM;
-
- if (elementsLeft >= IN_OPERATOR_MAXIMUM) {
- neededLength = IN_OPERATOR_MAXIMUM;
- parts = Arrays.copyOfRange(mediaIds, i
- * IN_OPERATOR_MAXIMUM, (i + 1)
- * IN_OPERATOR_MAXIMUM);
- } else {
- neededLength = elementsLeft;
- parts = Arrays.copyOfRange(mediaIds, i
- * IN_OPERATOR_MAXIMUM, (i * IN_OPERATOR_MAXIMUM)
- + neededLength);
- }
-
- cursors[i] = db.rawQuery("SELECT * FROM "
- + TABLE_NAME_FEED_MEDIA + " WHERE " + KEY_FEEDITEM + " IN "
- + buildInOperator(neededLength), parts);
- }
- return new MergeCursor(cursors);
- } else {
- return db.query(TABLE_NAME_FEED_MEDIA, null, KEY_FEEDITEM + " IN "
- + buildInOperator(length), mediaIds, null, null, null);
- }
- }
-
- /**
- * Builds an IN-operator argument depending on the number of items.
- */
- private String buildInOperator(int size) {
- if (size == 1) {
- return "(?)";
- }
- StringBuffer buffer = new StringBuffer("(");
- for (int i = 0; i < size - 1; i++) {
- buffer.append("?,");
- }
- buffer.append("?)");
- return buffer.toString();
- }
-
- public final Cursor getFeedCursor(final long id) {
- Cursor c = db.query(TABLE_NAME_FEEDS, FEED_SEL_STD, KEY_ID + "=" + id, null,
- null, null, null);
- return c;
- }
-
- public final Cursor getFeedItemCursor(final String... ids) {
- if (ids.length > IN_OPERATOR_MAXIMUM) {
- throw new IllegalArgumentException(
- "number of IDs must not be larger than "
- + IN_OPERATOR_MAXIMUM
- );
- }
-
- return db.query(TABLE_NAME_FEED_ITEMS, FEEDITEM_SEL_FI_SMALL, KEY_ID + " IN "
- + buildInOperator(ids.length), ids, null, null, null);
-
- }
-
- public int getQueueSize() {
- final String query = String.format("SELECT COUNT(%s) FROM %s", KEY_ID, TABLE_NAME_QUEUE);
- Cursor c = db.rawQuery(query, null);
- int result = 0;
- if (c.moveToFirst()) {
- result = c.getInt(0);
- }
- c.close();
- return result;
- }
-
- public final int getNumberOfUnreadItems() {
- final String query = "SELECT COUNT(DISTINCT " + KEY_ID + ") AS count FROM " + TABLE_NAME_FEED_ITEMS +
- " WHERE " + KEY_READ + " = 0";
- Cursor c = db.rawQuery(query, null);
- int result = 0;
- if (c.moveToFirst()) {
- result = c.getInt(0);
- }
- c.close();
- return result;
- }
-
- public final int getNumberOfDownloadedEpisodes() {
- final String query = "SELECT COUNT(DISTINCT " + KEY_ID + ") AS count FROM " + TABLE_NAME_FEED_MEDIA +
- " WHERE " + KEY_DOWNLOADED + " > 0";
-
- Cursor c = db.rawQuery(query, null);
- int result = 0;
- if (c.moveToFirst()) {
- result = c.getInt(0);
- }
- c.close();
- return result;
- }
-
- /**
- * Uses DatabaseUtils to escape a search query and removes ' at the
- * beginning and the end of the string returned by the escape method.
- */
- private String prepareSearchQuery(String query) {
- StringBuilder builder = new StringBuilder();
- DatabaseUtils.appendEscapedSQLString(builder, query);
- builder.deleteCharAt(0);
- builder.deleteCharAt(builder.length() - 1);
- return builder.toString();
- }
-
- /**
- * Searches for the given query in the description of all items or the items
- * of a specified feed.
- *
- * @return A cursor with all search results in SEL_FI_EXTRA selection.
- */
- public Cursor searchItemDescriptions(long feedID, String query) {
- if (feedID != 0) {
- // search items in specific feed
- return db.query(TABLE_NAME_FEED_ITEMS, FEEDITEM_SEL_FI_SMALL, KEY_FEED
- + "=? AND " + KEY_DESCRIPTION + " LIKE '%"
- + prepareSearchQuery(query) + "%'",
- new String[]{String.valueOf(feedID)}, null, null,
- null
- );
- } else {
- // search through all items
- return db.query(TABLE_NAME_FEED_ITEMS, FEEDITEM_SEL_FI_SMALL,
- KEY_DESCRIPTION + " LIKE '%" + prepareSearchQuery(query)
- + "%'", null, null, null, null
- );
- }
- }
-
- /**
- * Searches for the given query in the content-encoded field of all items or
- * the items of a specified feed.
- *
- * @return A cursor with all search results in SEL_FI_EXTRA selection.
- */
- public Cursor searchItemContentEncoded(long feedID, String query) {
- if (feedID != 0) {
- // search items in specific feed
- return db.query(TABLE_NAME_FEED_ITEMS, FEEDITEM_SEL_FI_SMALL, KEY_FEED
- + "=? AND " + KEY_CONTENT_ENCODED + " LIKE '%"
- + prepareSearchQuery(query) + "%'",
- new String[]{String.valueOf(feedID)}, null, null,
- null
- );
- } else {
- // search through all items
- return db.query(TABLE_NAME_FEED_ITEMS, FEEDITEM_SEL_FI_SMALL,
- KEY_CONTENT_ENCODED + " LIKE '%"
- + prepareSearchQuery(query) + "%'", null, null,
- null, null
- );
- }
- }
-
- public Cursor searchItemTitles(long feedID, String query) {
- if (feedID != 0) {
- // search items in specific feed
- return db.query(TABLE_NAME_FEED_ITEMS, FEEDITEM_SEL_FI_SMALL, KEY_FEED
- + "=? AND " + KEY_TITLE + " LIKE '%"
- + prepareSearchQuery(query) + "%'",
- new String[]{String.valueOf(feedID)}, null, null,
- null
- );
- } else {
- // search through all items
- return db.query(TABLE_NAME_FEED_ITEMS, FEEDITEM_SEL_FI_SMALL,
- KEY_TITLE + " LIKE '%"
- + prepareSearchQuery(query) + "%'", null, null,
- null, null
- );
- }
- }
-
- public Cursor searchItemChapters(long feedID, String searchQuery) {
- final String query;
- if (feedID != 0) {
- query = "SELECT " + SEL_FI_SMALL_STR + " FROM " + TABLE_NAME_FEED_ITEMS + " INNER JOIN " +
- TABLE_NAME_SIMPLECHAPTERS + " ON " + TABLE_NAME_SIMPLECHAPTERS + "." + KEY_FEEDITEM + "=" +
- TABLE_NAME_FEED_ITEMS + "." + KEY_ID + " WHERE " + TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + "=" +
- feedID + " AND " + TABLE_NAME_SIMPLECHAPTERS + "." + KEY_TITLE + " LIKE '%"
- + prepareSearchQuery(searchQuery) + "%'";
- } else {
- query = "SELECT " + SEL_FI_SMALL_STR + " FROM " + TABLE_NAME_FEED_ITEMS + " INNER JOIN " +
- TABLE_NAME_SIMPLECHAPTERS + " ON " + TABLE_NAME_SIMPLECHAPTERS + "." + KEY_FEEDITEM + "=" +
- TABLE_NAME_FEED_ITEMS + "." + KEY_ID + " WHERE " + TABLE_NAME_SIMPLECHAPTERS + "." + KEY_TITLE + " LIKE '%"
- + prepareSearchQuery(searchQuery) + "%'";
- }
- return db.rawQuery(query, null);
- }
-
-
- public static final int IDX_FEEDSTATISTICS_FEED = 0;
- public static final int IDX_FEEDSTATISTICS_NUM_ITEMS = 1;
- public static final int IDX_FEEDSTATISTICS_NEW_ITEMS = 2;
- public static final int IDX_FEEDSTATISTICS_LATEST_EPISODE = 3;
- public static final int IDX_FEEDSTATISTICS_IN_PROGRESS_EPISODES = 4;
-
- /**
- * Select number of items, new items, the date of the latest episode and the number of episodes in progress. The result
- * is sorted by the title of the feed.
- */
- private static final String FEED_STATISTICS_QUERY = "SELECT Feeds.id, num_items, new_items, latest_episode, in_progress FROM " +
- " Feeds LEFT JOIN " +
- "(SELECT feed,count(*) AS num_items," +
- " COUNT(CASE WHEN read=0 THEN 1 END) AS new_items," +
- " MAX(pubDate) AS latest_episode," +
- " COUNT(CASE WHEN position>0 THEN 1 END) AS in_progress," +
- " COUNT(CASE WHEN downloaded=1 THEN 1 END) AS episodes_downloaded " +
- " FROM FeedItems LEFT JOIN FeedMedia ON FeedItems.id=FeedMedia.feeditem GROUP BY FeedItems.feed)" +
- " ON Feeds.id = feed ORDER BY Feeds.title COLLATE NOCASE ASC;";
-
- public Cursor getFeedStatisticsCursor() {
- return db.rawQuery(FEED_STATISTICS_QUERY, null);
- }
-
- /**
- * Helper class for opening the Antennapod database.
- */
- private static class PodDBHelper extends SQLiteOpenHelper {
- /**
- * Constructor.
- *
- * @param context Context to use
- * @param name Name of the database
- * @param factory to use for creating cursor objects
- * @param version number of the database
- */
- public PodDBHelper(final Context context, final String name,
- final CursorFactory factory, final int version) {
- super(context, name, factory, version);
- }
-
- @Override
- public void onCreate(final SQLiteDatabase db) {
- db.execSQL(CREATE_TABLE_FEEDS);
- db.execSQL(CREATE_TABLE_FEED_ITEMS);
- db.execSQL(CREATE_TABLE_FEED_IMAGES);
- db.execSQL(CREATE_TABLE_FEED_MEDIA);
- db.execSQL(CREATE_TABLE_DOWNLOAD_LOG);
- db.execSQL(CREATE_TABLE_QUEUE);
- db.execSQL(CREATE_TABLE_SIMPLECHAPTERS);
- }
-
- @Override
- public void onUpgrade(final SQLiteDatabase db, final int oldVersion,
- final int newVersion) {
- Log.w("DBAdapter", "Upgrading from version " + oldVersion + " to "
- + newVersion + ".");
- if (oldVersion <= 1) {
- db.execSQL("ALTER TABLE " + TABLE_NAME_FEEDS + " ADD COLUMN "
- + KEY_TYPE + " TEXT");
- }
- if (oldVersion <= 2) {
- db.execSQL("ALTER TABLE " + TABLE_NAME_SIMPLECHAPTERS
- + " ADD COLUMN " + KEY_LINK + " TEXT");
- }
- if (oldVersion <= 3) {
- db.execSQL("ALTER TABLE " + TABLE_NAME_FEED_ITEMS
- + " ADD COLUMN " + KEY_ITEM_IDENTIFIER + " TEXT");
- }
- if (oldVersion <= 4) {
- db.execSQL("ALTER TABLE " + TABLE_NAME_FEEDS + " ADD COLUMN "
- + KEY_FEED_IDENTIFIER + " TEXT");
- }
- if (oldVersion <= 5) {
- db.execSQL("ALTER TABLE " + TABLE_NAME_DOWNLOAD_LOG
- + " ADD COLUMN " + KEY_REASON_DETAILED + " TEXT");
- db.execSQL("ALTER TABLE " + TABLE_NAME_DOWNLOAD_LOG
- + " ADD COLUMN " + KEY_DOWNLOADSTATUS_TITLE + " TEXT");
- }
- if (oldVersion <= 6) {
- db.execSQL("ALTER TABLE " + TABLE_NAME_SIMPLECHAPTERS
- + " ADD COLUMN " + KEY_CHAPTER_TYPE + " INTEGER");
- }
- if (oldVersion <= 7) {
- db.execSQL("ALTER TABLE " + TABLE_NAME_FEED_MEDIA
- + " ADD COLUMN " + KEY_PLAYBACK_COMPLETION_DATE
- + " INTEGER");
- }
- if (oldVersion <= 8) {
- final int KEY_ID_POSITION = 0;
- final int KEY_MEDIA_POSITION = 1;
-
- // Add feeditem column to feedmedia table
- db.execSQL("ALTER TABLE " + TABLE_NAME_FEED_MEDIA
- + " ADD COLUMN " + KEY_FEEDITEM
- + " INTEGER");
- Cursor feeditemCursor = db.query(TABLE_NAME_FEED_ITEMS, new String[]{KEY_ID, KEY_MEDIA}, "? > 0", new String[]{KEY_MEDIA}, null, null, null);
- if (feeditemCursor.moveToFirst()) {
- db.beginTransaction();
- ContentValues contentValues = new ContentValues();
- do {
- long mediaId = feeditemCursor.getLong(KEY_MEDIA_POSITION);
- contentValues.put(KEY_FEEDITEM, feeditemCursor.getLong(KEY_ID_POSITION));
- db.update(TABLE_NAME_FEED_MEDIA, contentValues, KEY_ID + "=?", new String[]{String.valueOf(mediaId)});
- contentValues.clear();
- } while (feeditemCursor.moveToNext());
- db.setTransactionSuccessful();
- db.endTransaction();
- }
- feeditemCursor.close();
- }
- if (oldVersion <= 9) {
- db.execSQL("ALTER TABLE " + TABLE_NAME_FEEDS
- + " ADD COLUMN " + KEY_AUTO_DOWNLOAD
- + " INTEGER DEFAULT 1");
- }
- if (oldVersion <= 10) {
- db.execSQL("ALTER TABLE " + TABLE_NAME_FEEDS
- + " ADD COLUMN " + KEY_FLATTR_STATUS
- + " INTEGER");
- db.execSQL("ALTER TABLE " + TABLE_NAME_FEED_ITEMS
- + " ADD COLUMN " + KEY_FLATTR_STATUS
- + " INTEGER");
- db.execSQL("ALTER TABLE " + TABLE_NAME_FEED_MEDIA
- + " ADD COLUMN " + KEY_PLAYED_DURATION
- + " INTEGER");
- }
- if (oldVersion <= 11) {
- db.execSQL("ALTER TABLE " + TABLE_NAME_FEEDS
- + " ADD COLUMN " + KEY_USERNAME
- + " TEXT");
- db.execSQL("ALTER TABLE " + TABLE_NAME_FEEDS
- + " ADD COLUMN " + KEY_PASSWORD
- + " TEXT");
- db.execSQL("ALTER TABLE " + TABLE_NAME_FEED_ITEMS
- + " ADD COLUMN " + KEY_IMAGE
- + " INTEGER");
- }
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/syndication/handler/FeedHandler.java b/src/de/danoeh/antennapod/syndication/handler/FeedHandler.java
deleted file mode 100644
index aafa1c209..000000000
--- a/src/de/danoeh/antennapod/syndication/handler/FeedHandler.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package de.danoeh.antennapod.syndication.handler;
-
-import de.danoeh.antennapod.feed.Feed;
-import org.apache.commons.io.input.XmlStreamReader;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-import java.io.File;
-import java.io.IOException;
-import java.io.Reader;
-
-public class FeedHandler {
-
- public FeedHandlerResult parseFeed(Feed feed) throws SAXException, IOException,
- ParserConfigurationException, UnsupportedFeedtypeException {
- TypeGetter tg = new TypeGetter();
- TypeGetter.Type type = tg.getType(feed);
- SyndHandler handler = new SyndHandler(feed, type);
-
- SAXParserFactory factory = SAXParserFactory.newInstance();
- factory.setNamespaceAware(true);
- SAXParser saxParser = factory.newSAXParser();
- File file = new File(feed.getFile_url());
- Reader inputStreamReader = new XmlStreamReader(file);
- InputSource inputSource = new InputSource(inputStreamReader);
-
- saxParser.parse(inputSource, handler);
- inputStreamReader.close();
- return new FeedHandlerResult(handler.state.feed, handler.state.alternateUrls);
- }
-}
diff --git a/src/de/danoeh/antennapod/syndication/handler/FeedHandlerResult.java b/src/de/danoeh/antennapod/syndication/handler/FeedHandlerResult.java
deleted file mode 100644
index 41aa29b52..000000000
--- a/src/de/danoeh/antennapod/syndication/handler/FeedHandlerResult.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package de.danoeh.antennapod.syndication.handler;
-
-import de.danoeh.antennapod.feed.Feed;
-
-import java.util.Map;
-
-/**
- * Container for results returned by the Feed parser
- */
-public class FeedHandlerResult {
-
- public Feed feed;
- public Map<String, String> alternateFeedUrls;
-
- public FeedHandlerResult(Feed feed, Map<String, String> alternateFeedUrls) {
- this.feed = feed;
- this.alternateFeedUrls = alternateFeedUrls;
- }
-}
diff --git a/src/de/danoeh/antennapod/syndication/handler/HandlerState.java b/src/de/danoeh/antennapod/syndication/handler/HandlerState.java
deleted file mode 100644
index 17f84724f..000000000
--- a/src/de/danoeh/antennapod/syndication/handler/HandlerState.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package de.danoeh.antennapod.syndication.handler;
-
-import de.danoeh.antennapod.feed.Feed;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.syndication.namespace.Namespace;
-import de.danoeh.antennapod.syndication.namespace.SyndElement;
-
-import java.util.*;
-
-/**
- * Contains all relevant information to describe the current state of a
- * SyndHandler.
- */
-public class HandlerState {
-
- /**
- * Feed that the Handler is currently processing.
- */
- protected Feed feed;
- /**
- * Contains links to related feeds, e.g. feeds with enclosures in other formats. The key of the map is the
- * URL of the feed, the value is the title
- */
- protected Map<String, String> alternateUrls;
- protected ArrayList<FeedItem> items;
- protected FeedItem currentItem;
- protected Stack<SyndElement> tagstack;
- /**
- * Namespaces that have been defined so far.
- */
- protected HashMap<String, Namespace> namespaces;
- protected Stack<Namespace> defaultNamespaces;
- /**
- * Buffer for saving characters.
- */
- protected StringBuffer contentBuf;
-
- public HandlerState(Feed feed) {
- this.feed = feed;
- alternateUrls = new LinkedHashMap<String, String>();
- items = new ArrayList<FeedItem>();
- tagstack = new Stack<SyndElement>();
- namespaces = new HashMap<String, Namespace>();
- defaultNamespaces = new Stack<Namespace>();
- }
-
- public Feed getFeed() {
- return feed;
- }
-
- public ArrayList<FeedItem> getItems() {
- return items;
- }
-
- public FeedItem getCurrentItem() {
- return currentItem;
- }
-
- public Stack<SyndElement> getTagstack() {
- return tagstack;
- }
-
- public void setFeed(Feed feed) {
- this.feed = feed;
- }
-
- public void setCurrentItem(FeedItem currentItem) {
- this.currentItem = currentItem;
- }
-
- /**
- * Returns the SyndElement that comes after the top element of the tagstack.
- */
- public SyndElement getSecondTag() {
- SyndElement top = tagstack.pop();
- SyndElement second = tagstack.peek();
- tagstack.push(top);
- return second;
- }
-
- public SyndElement getThirdTag() {
- SyndElement top = tagstack.pop();
- SyndElement second = tagstack.pop();
- SyndElement third = tagstack.peek();
- tagstack.push(second);
- tagstack.push(top);
- return third;
- }
-
- public StringBuffer getContentBuf() {
- return contentBuf;
- }
-
- public void addAlternateFeedUrl(String title, String url) {
- alternateUrls.put(url, title);
- }
-
-}
diff --git a/src/de/danoeh/antennapod/syndication/handler/SyndHandler.java b/src/de/danoeh/antennapod/syndication/handler/SyndHandler.java
deleted file mode 100644
index 15dc94d65..000000000
--- a/src/de/danoeh/antennapod/syndication/handler/SyndHandler.java
+++ /dev/null
@@ -1,126 +0,0 @@
-package de.danoeh.antennapod.syndication.handler;
-
-import android.util.Log;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.feed.Feed;
-import de.danoeh.antennapod.syndication.namespace.*;
-import de.danoeh.antennapod.syndication.namespace.atom.NSAtom;
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
-
-/** Superclass for all SAX Handlers which process Syndication formats */
-public class SyndHandler extends DefaultHandler {
- private static final String TAG = "SyndHandler";
- private static final String DEFAULT_PREFIX = "";
- protected HandlerState state;
-
- public SyndHandler(Feed feed, TypeGetter.Type type) {
- state = new HandlerState(feed);
- if (type == TypeGetter.Type.RSS20 || type == TypeGetter.Type.RSS091) {
- state.defaultNamespaces.push(new NSRSS20());
- }
- }
-
- @Override
- public void startElement(String uri, String localName, String qName,
- Attributes attributes) throws SAXException {
- state.contentBuf = new StringBuffer();
- Namespace handler = getHandlingNamespace(uri, qName);
- if (handler != null) {
- SyndElement element = handler.handleElementStart(localName, state,
- attributes);
- state.tagstack.push(element);
-
- }
- }
-
- @Override
- public void characters(char[] ch, int start, int length)
- throws SAXException {
- if (!state.tagstack.empty()) {
- if (state.getTagstack().size() >= 2) {
- if (state.contentBuf != null) {
- state.contentBuf.append(ch, start, length);
- }
- }
- }
- }
-
- @Override
- public void endElement(String uri, String localName, String qName)
- throws SAXException {
- Namespace handler = getHandlingNamespace(uri, qName);
- if (handler != null) {
- handler.handleElementEnd(localName, state);
- state.tagstack.pop();
-
- }
- state.contentBuf = null;
-
- }
-
- @Override
- public void endPrefixMapping(String prefix) throws SAXException {
- if (state.defaultNamespaces.size() > 1 && prefix.equals(DEFAULT_PREFIX)) {
- state.defaultNamespaces.pop();
- }
- }
-
- @Override
- public void startPrefixMapping(String prefix, String uri)
- throws SAXException {
- // Find the right namespace
- if (!state.namespaces.containsKey(uri)) {
- if (uri.equals(NSAtom.NSURI)) {
- if (prefix.equals(DEFAULT_PREFIX)) {
- state.defaultNamespaces.push(new NSAtom());
- } else if (prefix.equals(NSAtom.NSTAG)) {
- state.namespaces.put(uri, new NSAtom());
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Recognized Atom namespace");
- }
- } else if (uri.equals(NSContent.NSURI)
- && prefix.equals(NSContent.NSTAG)) {
- state.namespaces.put(uri, new NSContent());
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Recognized Content namespace");
- } else if (uri.equals(NSITunes.NSURI)
- && prefix.equals(NSITunes.NSTAG)) {
- state.namespaces.put(uri, new NSITunes());
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Recognized ITunes namespace");
- } else if (uri.equals(NSSimpleChapters.NSURI)
- && prefix.matches(NSSimpleChapters.NSTAG)) {
- state.namespaces.put(uri, new NSSimpleChapters());
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Recognized SimpleChapters namespace");
- } else if (uri.equals(NSMedia.NSURI)
- && prefix.equals(NSMedia.NSTAG)) {
- state.namespaces.put(uri, new NSMedia());
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Recognized media namespace");
- }
- }
- }
-
- private Namespace getHandlingNamespace(String uri, String qName) {
- Namespace handler = state.namespaces.get(uri);
- if (handler == null && !state.defaultNamespaces.empty()
- && !qName.contains(":")) {
- handler = state.defaultNamespaces.peek();
- }
- return handler;
- }
-
- @Override
- public void endDocument() throws SAXException {
- super.endDocument();
- state.getFeed().setItems(state.getItems());
- }
-
- public HandlerState getState() {
- return state;
- }
-
-}
diff --git a/src/de/danoeh/antennapod/syndication/handler/TypeGetter.java b/src/de/danoeh/antennapod/syndication/handler/TypeGetter.java
deleted file mode 100644
index 2496e112a..000000000
--- a/src/de/danoeh/antennapod/syndication/handler/TypeGetter.java
+++ /dev/null
@@ -1,112 +0,0 @@
-package de.danoeh.antennapod.syndication.handler;
-
-import android.util.Log;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.feed.Feed;
-import org.apache.commons.io.input.XmlStreamReader;
-import org.jsoup.Jsoup;
-import org.jsoup.nodes.Document;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlPullParserFactory;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.Reader;
-
-/** Gets the type of a specific feed by reading the root element. */
-public class TypeGetter {
- private static final String TAG = "TypeGetter";
-
- public enum Type {
- RSS20, RSS091, ATOM, INVALID
- }
-
- private static final String ATOM_ROOT = "feed";
- private static final String RSS_ROOT = "rss";
-
- public Type getType(Feed feed) throws UnsupportedFeedtypeException {
- XmlPullParserFactory factory;
- if (feed.getFile_url() != null) {
- try {
- factory = XmlPullParserFactory.newInstance();
- factory.setNamespaceAware(true);
- XmlPullParser xpp = factory.newPullParser();
- xpp.setInput(createReader(feed));
- int eventType = xpp.getEventType();
-
- while (eventType != XmlPullParser.END_DOCUMENT) {
- if (eventType == XmlPullParser.START_TAG) {
- String tag = xpp.getName();
- if (tag.equals(ATOM_ROOT)) {
- feed.setType(Feed.TYPE_ATOM1);
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Recognized type Atom");
- return Type.ATOM;
- } else if (tag.equals(RSS_ROOT)) {
- String strVersion = xpp.getAttributeValue(null,
- "version");
- if (strVersion != null) {
-
- if (strVersion.equals("2.0")) {
- feed.setType(Feed.TYPE_RSS2);
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Recognized type RSS 2.0");
- return Type.RSS20;
- } else if (strVersion.equals("0.91")
- || strVersion.equals("0.92")) {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "Recognized type RSS 0.91/0.92");
- return Type.RSS091;
- }
- }
- throw new UnsupportedFeedtypeException(Type.INVALID);
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Type is invalid");
- throw new UnsupportedFeedtypeException(Type.INVALID, tag);
- }
- } else {
- eventType = xpp.next();
- }
- }
-
- } catch (XmlPullParserException e) {
- e.printStackTrace();
- // XML document might actually be a HTML document -> try to parse as HTML
- String rootElement = null;
- try {
- if (Jsoup.parse(new File(feed.getFile_url()), null) != null) {
- rootElement = "html";
- }
- } catch (IOException e1) {
- e1.printStackTrace();
- } finally {
- throw new UnsupportedFeedtypeException(Type.INVALID, rootElement);
- }
-
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Type is invalid");
- throw new UnsupportedFeedtypeException(Type.INVALID);
- }
-
- private Reader createReader(Feed feed) {
- Reader reader;
- try {
- reader = new XmlStreamReader(new File(feed.getFile_url()));
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- return null;
- } catch (IOException e) {
- e.printStackTrace();
- return null;
- }
- return reader;
- }
-}
diff --git a/src/de/danoeh/antennapod/syndication/handler/UnsupportedFeedtypeException.java b/src/de/danoeh/antennapod/syndication/handler/UnsupportedFeedtypeException.java
deleted file mode 100644
index 605dad2fb..000000000
--- a/src/de/danoeh/antennapod/syndication/handler/UnsupportedFeedtypeException.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package de.danoeh.antennapod.syndication.handler;
-
-import de.danoeh.antennapod.syndication.handler.TypeGetter.Type;
-
-public class UnsupportedFeedtypeException extends Exception {
- private static final long serialVersionUID = 9105878964928170669L;
- private TypeGetter.Type type;
- private String rootElement;
-
- public UnsupportedFeedtypeException(Type type) {
- super();
- this.type = type;
- }
-
- public UnsupportedFeedtypeException(Type type, String rootElement) {
- this.type = type;
- this.rootElement = rootElement;
- }
-
- public TypeGetter.Type getType() {
- return type;
- }
-
- public String getRootElement() {
- return rootElement;
- }
-
- @Override
- public String getMessage() {
- if (type == TypeGetter.Type.INVALID) {
- return "Invalid type";
- } else {
- return "Type " + type + " not supported";
- }
- }
-
-
-}
diff --git a/src/de/danoeh/antennapod/syndication/namespace/NSContent.java b/src/de/danoeh/antennapod/syndication/namespace/NSContent.java
deleted file mode 100644
index 9ad3026be..000000000
--- a/src/de/danoeh/antennapod/syndication/namespace/NSContent.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package de.danoeh.antennapod.syndication.namespace;
-
-import de.danoeh.antennapod.syndication.handler.HandlerState;
-import org.xml.sax.Attributes;
-
-public class NSContent extends Namespace {
- public static final String NSTAG = "content";
- public static final String NSURI = "http://purl.org/rss/1.0/modules/content/";
-
- private static final String ENCODED = "encoded";
-
- @Override
- public SyndElement handleElementStart(String localName, HandlerState state,
- Attributes attributes) {
- return new SyndElement(localName, this);
- }
-
- @Override
- public void handleElementEnd(String localName, HandlerState state) {
- if (localName.equals(ENCODED)) {
- state.getCurrentItem().setContentEncoded(state.getContentBuf().toString());
- }
- }
-
-}
diff --git a/src/de/danoeh/antennapod/syndication/namespace/NSITunes.java b/src/de/danoeh/antennapod/syndication/namespace/NSITunes.java
deleted file mode 100644
index d8cbe040b..000000000
--- a/src/de/danoeh/antennapod/syndication/namespace/NSITunes.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package de.danoeh.antennapod.syndication.namespace;
-
-import de.danoeh.antennapod.feed.FeedImage;
-import de.danoeh.antennapod.syndication.handler.HandlerState;
-import org.xml.sax.Attributes;
-
-public class NSITunes extends Namespace {
- public static final String NSTAG = "itunes";
- public static final String NSURI = "http://www.itunes.com/dtds/podcast-1.0.dtd";
-
- private static final String IMAGE = "image";
- private static final String IMAGE_TITLE = "image";
- private static final String IMAGE_HREF = "href";
-
- private static final String AUTHOR = "author";
-
-
- @Override
- public SyndElement handleElementStart(String localName, HandlerState state,
- Attributes attributes) {
- if (localName.equals(IMAGE)) {
- FeedImage image = new FeedImage();
- image.setTitle(IMAGE_TITLE);
- image.setDownload_url(attributes.getValue(IMAGE_HREF));
-
- if (state.getCurrentItem() != null) {
- // this is an items image
- image.setTitle(state.getCurrentItem().getTitle() + IMAGE_TITLE);
- state.getCurrentItem().setImage(image);
-
- } else {
- // this is the feed image
- if (state.getFeed().getImage() == null) {
- state.getFeed().setImage(image);
- }
- }
-
- }
-
- return new SyndElement(localName, this);
- }
-
- @Override
- public void handleElementEnd(String localName, HandlerState state) {
- if (localName.equals(AUTHOR)) {
- state.getFeed().setAuthor(state.getContentBuf().toString());
- }
-
- }
-
-}
diff --git a/src/de/danoeh/antennapod/syndication/namespace/NSMedia.java b/src/de/danoeh/antennapod/syndication/namespace/NSMedia.java
deleted file mode 100644
index cc23167c1..000000000
--- a/src/de/danoeh/antennapod/syndication/namespace/NSMedia.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package de.danoeh.antennapod.syndication.namespace;
-
-import android.util.Log;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.feed.FeedMedia;
-import de.danoeh.antennapod.syndication.handler.HandlerState;
-import de.danoeh.antennapod.syndication.util.SyndTypeUtils;
-import org.xml.sax.Attributes;
-
-import java.util.concurrent.TimeUnit;
-
-/** Processes tags from the http://search.yahoo.com/mrss/ namespace. */
-public class NSMedia extends Namespace {
- private static final String TAG = "NSMedia";
-
- public static final String NSTAG = "media";
- public static final String NSURI = "http://search.yahoo.com/mrss/";
-
- private static final String CONTENT = "content";
- private static final String DOWNLOAD_URL = "url";
- private static final String SIZE = "fileSize";
- private static final String MIME_TYPE = "type";
- private static final String DURATION = "duration";
-
- @Override
- public SyndElement handleElementStart(String localName, HandlerState state,
- Attributes attributes) {
- if (localName.equals(CONTENT)) {
- String url = attributes.getValue(DOWNLOAD_URL);
- String type = attributes.getValue(MIME_TYPE);
- if (state.getCurrentItem().getMedia() == null
- && url != null
- && (SyndTypeUtils.enclosureTypeValid(type) || ((type = SyndTypeUtils
- .getValidMimeTypeFromUrl(url)) != null))) {
-
- long size = 0;
- try {
- size = Long.parseLong(attributes.getValue(SIZE));
- } catch (NumberFormatException e) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Length attribute could not be parsed.");
- }
-
- int duration = 0;
- try {
- String durationStr = attributes.getValue(DURATION);
- if (durationStr != null) {
- duration = (int) TimeUnit.MILLISECONDS.convert(
- Long.parseLong(durationStr), TimeUnit.SECONDS);
- }
- } catch (NumberFormatException e) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Duration attribute could not be parsed");
- }
-
- state.getCurrentItem().setMedia(
- new FeedMedia(state.getCurrentItem(), url, size, type));
- }
- }
- return new SyndElement(localName, this);
- }
-
- @Override
- public void handleElementEnd(String localName, HandlerState state) {
-
- }
-
-}
diff --git a/src/de/danoeh/antennapod/syndication/namespace/NSRSS20.java b/src/de/danoeh/antennapod/syndication/namespace/NSRSS20.java
deleted file mode 100644
index 9572f87ae..000000000
--- a/src/de/danoeh/antennapod/syndication/namespace/NSRSS20.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package de.danoeh.antennapod.syndication.namespace;
-
-import android.util.Log;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.feed.FeedImage;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.feed.FeedMedia;
-import de.danoeh.antennapod.syndication.handler.HandlerState;
-import de.danoeh.antennapod.syndication.util.SyndDateUtils;
-import de.danoeh.antennapod.syndication.util.SyndTypeUtils;
-import org.xml.sax.Attributes;
-
-/**
- * SAX-Parser for reading RSS-Feeds
- *
- * @author daniel
- *
- */
-public class NSRSS20 extends Namespace {
- private static final String TAG = "NSRSS20";
- public static final String NSTAG = "rss";
- public static final String NSURI = "";
-
- public final static String CHANNEL = "channel";
- public final static String ITEM = "item";
- public final static String GUID = "guid";
- public final static String TITLE = "title";
- public final static String LINK = "link";
- public final static String DESCR = "description";
- public final static String PUBDATE = "pubDate";
- public final static String ENCLOSURE = "enclosure";
- public final static String IMAGE = "image";
- public final static String URL = "url";
- public final static String LANGUAGE = "language";
-
- public final static String ENC_URL = "url";
- public final static String ENC_LEN = "length";
- public final static String ENC_TYPE = "type";
-
- @Override
- public SyndElement handleElementStart(String localName, HandlerState state,
- Attributes attributes) {
- if (localName.equals(ITEM)) {
- state.setCurrentItem(new FeedItem());
- state.getItems().add(state.getCurrentItem());
- state.getCurrentItem().setFeed(state.getFeed());
-
- } else if (localName.equals(ENCLOSURE)) {
- String type = attributes.getValue(ENC_TYPE);
- String url = attributes.getValue(ENC_URL);
- if (state.getCurrentItem().getMedia() == null
- && (SyndTypeUtils.enclosureTypeValid(type) || ((type = SyndTypeUtils
- .getValidMimeTypeFromUrl(url)) != null))) {
-
- long size = 0;
- try {
- size = Long.parseLong(attributes.getValue(ENC_LEN));
- } catch (NumberFormatException e) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Length attribute could not be parsed.");
- }
- state.getCurrentItem().setMedia(
- new FeedMedia(state.getCurrentItem(), url, size, type));
- }
-
- } else if (localName.equals(IMAGE)) {
- if (state.getTagstack().size() >= 1) {
- String parent = state.getTagstack().peek().getName();
- if (parent.equals(CHANNEL)) {
- state.getFeed().setImage(new FeedImage());
- }
- }
- }
- return new SyndElement(localName, this);
- }
-
- @Override
- public void handleElementEnd(String localName, HandlerState state) {
- if (localName.equals(ITEM)) {
- if (state.getCurrentItem() != null) {
- // the title tag is optional in RSS 2.0. The description is used
- // as a
- // title if the item has no title-tag.
- if (state.getCurrentItem().getTitle() == null) {
- state.getCurrentItem().setTitle(
- state.getCurrentItem().getDescription());
- }
- }
- state.setCurrentItem(null);
- } else if (state.getTagstack().size() >= 2
- && state.getContentBuf() != null) {
- String content = state.getContentBuf().toString();
- SyndElement topElement = state.getTagstack().peek();
- String top = topElement.getName();
- SyndElement secondElement = state.getSecondTag();
- String second = secondElement.getName();
- String third = null;
- if (state.getTagstack().size() >= 3) {
- third = state.getThirdTag().getName();
- }
-
- if (top.equals(GUID) && second.equals(ITEM)) {
- // some feed creators include an empty or non-standard guid-element in their feed, which should be ignored
- if (!content.isEmpty()) {
- state.getCurrentItem().setItemIdentifier(content);
- }
- } else if (top.equals(TITLE)) {
- if (second.equals(ITEM)) {
- state.getCurrentItem().setTitle(content);
- } else if (second.equals(CHANNEL)) {
- state.getFeed().setTitle(content);
- } else if (second.equals(IMAGE) && third != null
- && third.equals(CHANNEL)) {
- state.getFeed().getImage().setTitle(content);
- }
- } else if (top.equals(LINK)) {
- if (second.equals(CHANNEL)) {
- state.getFeed().setLink(content);
- } else if (second.equals(ITEM)) {
- state.getCurrentItem().setLink(content);
- }
- } else if (top.equals(PUBDATE) && second.equals(ITEM)) {
- state.getCurrentItem().setPubDate(
- SyndDateUtils.parseRFC822Date(content));
- } else if (top.equals(URL) && second.equals(IMAGE) && third != null
- && third.equals(CHANNEL)) {
- state.getFeed().getImage().setDownload_url(content);
- } else if (localName.equals(DESCR)) {
- if (second.equals(CHANNEL)) {
- state.getFeed().setDescription(content);
- } else if (second.equals(ITEM)) {
- state.getCurrentItem().setDescription(content);
- }
-
- } else if (localName.equals(LANGUAGE)) {
- state.getFeed().setLanguage(content.toLowerCase());
- }
- }
- }
-
-}
diff --git a/src/de/danoeh/antennapod/syndication/namespace/NSSimpleChapters.java b/src/de/danoeh/antennapod/syndication/namespace/NSSimpleChapters.java
deleted file mode 100644
index 3f983ee88..000000000
--- a/src/de/danoeh/antennapod/syndication/namespace/NSSimpleChapters.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package de.danoeh.antennapod.syndication.namespace;
-
-import de.danoeh.antennapod.feed.Chapter;
-import de.danoeh.antennapod.feed.SimpleChapter;
-import de.danoeh.antennapod.syndication.handler.HandlerState;
-import de.danoeh.antennapod.syndication.util.SyndDateUtils;
-import org.xml.sax.Attributes;
-
-import java.util.ArrayList;
-
-public class NSSimpleChapters extends Namespace {
- public static final String NSTAG = "psc|sc";
- public static final String NSURI = "http://podlove.org/simple-chapters";
-
- public static final String CHAPTERS = "chapters";
- public static final String CHAPTER = "chapter";
- public static final String START = "start";
- public static final String TITLE = "title";
- public static final String HREF = "href";
-
- @Override
- public SyndElement handleElementStart(String localName, HandlerState state,
- Attributes attributes) {
- if (localName.equals(CHAPTERS)) {
- state.getCurrentItem().setChapters(new ArrayList<Chapter>());
- } else if (localName.equals(CHAPTER)) {
- state.getCurrentItem()
- .getChapters()
- .add(new SimpleChapter(SyndDateUtils
- .parseTimeString(attributes.getValue(START)),
- attributes.getValue(TITLE), state.getCurrentItem(),
- attributes.getValue(HREF)));
- }
-
- return new SyndElement(localName, this);
- }
-
- @Override
- public void handleElementEnd(String localName, HandlerState state) {
- }
-
-}
diff --git a/src/de/danoeh/antennapod/syndication/namespace/Namespace.java b/src/de/danoeh/antennapod/syndication/namespace/Namespace.java
deleted file mode 100644
index 910131feb..000000000
--- a/src/de/danoeh/antennapod/syndication/namespace/Namespace.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package de.danoeh.antennapod.syndication.namespace;
-
-import de.danoeh.antennapod.syndication.handler.HandlerState;
-import org.xml.sax.Attributes;
-
-
-public abstract class Namespace {
- public static final String NSTAG = null;
- public static final String NSURI = null;
-
- /** Called by a Feedhandler when in startElement and it detects a namespace element
- * @return The SyndElement to push onto the stack
- * */
- public abstract SyndElement handleElementStart(String localName, HandlerState state, Attributes attributes);
-
- /** Called by a Feedhandler when in endElement and it detects a namespace element
- * @return true if namespace handled the element, false if it ignored it
- * */
- public abstract void handleElementEnd(String localName, HandlerState state);
-
-}
diff --git a/src/de/danoeh/antennapod/syndication/namespace/SyndElement.java b/src/de/danoeh/antennapod/syndication/namespace/SyndElement.java
deleted file mode 100644
index 187312c9e..000000000
--- a/src/de/danoeh/antennapod/syndication/namespace/SyndElement.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package de.danoeh.antennapod.syndication.namespace;
-
-/** Defines a XML Element that is pushed on the tagstack */
-public class SyndElement {
- protected String name;
- protected Namespace namespace;
-
- public SyndElement(String name, Namespace namespace) {
- this.name = name;
- this.namespace = namespace;
- }
-
- public Namespace getNamespace() {
- return namespace;
- }
-
- public String getName() {
- return name;
- }
-
-
-}
diff --git a/src/de/danoeh/antennapod/syndication/namespace/atom/AtomText.java b/src/de/danoeh/antennapod/syndication/namespace/atom/AtomText.java
deleted file mode 100644
index 86b80d2ed..000000000
--- a/src/de/danoeh/antennapod/syndication/namespace/atom/AtomText.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package de.danoeh.antennapod.syndication.namespace.atom;
-
-import de.danoeh.antennapod.syndication.namespace.Namespace;
-import de.danoeh.antennapod.syndication.namespace.SyndElement;
-import org.apache.commons.lang3.StringEscapeUtils;
-
-/** Represents Atom Element which contains text (content, title, summary). */
-public class AtomText extends SyndElement {
- public static final String TYPE_TEXT = "text";
- public static final String TYPE_HTML = "html";
- public static final String TYPE_XHTML = "xhtml";
-
- private String type;
- private String content;
-
- public AtomText(String name, Namespace namespace, String type) {
- super(name, namespace);
- this.type = type;
- }
-
- /** Processes the content according to the type and returns it. */
- public String getProcessedContent() {
- if (type == null) {
- return content;
- } else if (type.equals(TYPE_HTML)) {
- return StringEscapeUtils.unescapeHtml4(content);
- } else if (type.equals(TYPE_XHTML)) {
- return content;
- } else { // Handle as text by default
- return content;
- }
- }
-
- public String getContent() {
- return content;
- }
-
- public void setContent(String content) {
- this.content = content;
- }
-
- public String getType() {
- return type;
- }
-
-}
diff --git a/src/de/danoeh/antennapod/syndication/namespace/atom/NSAtom.java b/src/de/danoeh/antennapod/syndication/namespace/atom/NSAtom.java
deleted file mode 100644
index 2c8e232ff..000000000
--- a/src/de/danoeh/antennapod/syndication/namespace/atom/NSAtom.java
+++ /dev/null
@@ -1,194 +0,0 @@
-package de.danoeh.antennapod.syndication.namespace.atom;
-
-import android.util.Log;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.feed.FeedImage;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.feed.FeedMedia;
-import de.danoeh.antennapod.syndication.handler.HandlerState;
-import de.danoeh.antennapod.syndication.namespace.NSRSS20;
-import de.danoeh.antennapod.syndication.namespace.Namespace;
-import de.danoeh.antennapod.syndication.namespace.SyndElement;
-import de.danoeh.antennapod.syndication.util.SyndDateUtils;
-import de.danoeh.antennapod.syndication.util.SyndTypeUtils;
-import org.xml.sax.Attributes;
-
-public class NSAtom extends Namespace {
- private static final String TAG = "NSAtom";
- public static final String NSTAG = "atom";
- public static final String NSURI = "http://www.w3.org/2005/Atom";
-
- private static final String FEED = "feed";
- private static final String ID = "id";
- private static final String TITLE = "title";
- private static final String ENTRY = "entry";
- private static final String LINK = "link";
- private static final String UPDATED = "updated";
- private static final String AUTHOR = "author";
- private static final String CONTENT = "content";
- private static final String IMAGE = "logo";
- private static final String SUBTITLE = "subtitle";
- private static final String PUBLISHED = "published";
-
- private static final String TEXT_TYPE = "type";
- // Link
- private static final String LINK_HREF = "href";
- private static final String LINK_REL = "rel";
- private static final String LINK_TYPE = "type";
- private static final String LINK_TITLE = "title";
- private static final String LINK_LENGTH = "length";
- // rel-values
- private static final String LINK_REL_ALTERNATE = "alternate";
- private static final String LINK_REL_ENCLOSURE = "enclosure";
- private static final String LINK_REL_PAYMENT = "payment";
- private static final String LINK_REL_RELATED = "related";
- private static final String LINK_REL_SELF = "self";
- // type-values
- private static final String LINK_TYPE_ATOM = "application/atom+xml";
- private static final String LINK_TYPE_HTML = "text/html";
- private static final String LINK_TYPE_XHTML = "application/xml+xhtml";
-
- private static final String LINK_TYPE_RSS = "application/rss+xml";
-
- /**
- * Regexp to test whether an Element is a Text Element.
- */
- private static final String isText = TITLE + "|" + CONTENT + "|" + "|"
- + SUBTITLE;
-
- public static final String isFeed = FEED + "|" + NSRSS20.CHANNEL;
- public static final String isFeedItem = ENTRY + "|" + NSRSS20.ITEM;
-
- @Override
- public SyndElement handleElementStart(String localName, HandlerState state,
- Attributes attributes) {
- if (localName.equals(ENTRY)) {
- state.setCurrentItem(new FeedItem());
- state.getItems().add(state.getCurrentItem());
- state.getCurrentItem().setFeed(state.getFeed());
- } else if (localName.matches(isText)) {
- String type = attributes.getValue(TEXT_TYPE);
- return new AtomText(localName, this, type);
- } else if (localName.equals(LINK)) {
- String href = attributes.getValue(LINK_HREF);
- String rel = attributes.getValue(LINK_REL);
- SyndElement parent = state.getTagstack().peek();
- if (parent.getName().matches(isFeedItem)) {
- if (rel == null || rel.equals(LINK_REL_ALTERNATE)) {
- state.getCurrentItem().setLink(href);
- } else if (rel.equals(LINK_REL_ENCLOSURE)) {
- String strSize = attributes.getValue(LINK_LENGTH);
- long size = 0;
- try {
- if (strSize != null) {
- size = Long.parseLong(strSize);
- }
- } catch (NumberFormatException e) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Length attribute could not be parsed.");
- }
- String type = attributes.getValue(LINK_TYPE);
- if (SyndTypeUtils.enclosureTypeValid(type)
- || (type = SyndTypeUtils
- .getValidMimeTypeFromUrl(href)) != null) {
- state.getCurrentItem().setMedia(
- new FeedMedia(state.getCurrentItem(), href,
- size, type)
- );
- }
- } else if (rel.equals(LINK_REL_PAYMENT)) {
- state.getCurrentItem().setPaymentLink(href);
- }
- } else if (parent.getName().matches(isFeed)) {
- if (rel == null || rel.equals(LINK_REL_ALTERNATE)) {
- String type = attributes.getValue(LINK_TYPE);
- /*
- * Use as link if a) no type-attribute is given and
- * feed-object has no link yet b) type of link is
- * LINK_TYPE_HTML or LINK_TYPE_XHTML
- */
- if ((type == null && state.getFeed().getLink() == null)
- || (type != null && (type.equals(LINK_TYPE_HTML) || type.equals(LINK_TYPE_XHTML)))) {
- state.getFeed().setLink(href);
- } else if (type != null && (type.equals(LINK_TYPE_ATOM) || type.equals(LINK_TYPE_RSS))) {
- // treat as podlove alternate feed
- String title = attributes.getValue(LINK_TITLE);
- if (title == null) {
- title = href;
- }
- state.addAlternateFeedUrl(title, href);
- }
- } else if (rel.equals(LINK_REL_PAYMENT)) {
- state.getFeed().setPaymentLink(href);
- }
- }
- }
- return new SyndElement(localName, this);
- }
-
- @Override
- public void handleElementEnd(String localName, HandlerState state) {
- if (localName.equals(ENTRY)) {
- state.setCurrentItem(null);
- }
-
- if (state.getTagstack().size() >= 2) {
- AtomText textElement = null;
- String content;
- if (state.getContentBuf() != null) {
- content = state.getContentBuf().toString();
- } else {
- content = "";
- }
- SyndElement topElement = state.getTagstack().peek();
- String top = topElement.getName();
- SyndElement secondElement = state.getSecondTag();
- String second = secondElement.getName();
-
- if (top.matches(isText)) {
- textElement = (AtomText) topElement;
- textElement.setContent(content);
- }
-
- if (top.equals(ID)) {
- if (second.equals(FEED)) {
- state.getFeed().setFeedIdentifier(content);
- } else if (second.equals(ENTRY)) {
- state.getCurrentItem().setItemIdentifier(content);
- }
- } else if (top.equals(TITLE)) {
-
- if (second.equals(FEED)) {
- state.getFeed().setTitle(textElement.getProcessedContent());
- } else if (second.equals(ENTRY)) {
- state.getCurrentItem().setTitle(
- textElement.getProcessedContent());
- }
- } else if (top.equals(SUBTITLE)) {
- if (second.equals(FEED)) {
- state.getFeed().setDescription(
- textElement.getProcessedContent());
- }
- } else if (top.equals(CONTENT)) {
- if (second.equals(ENTRY)) {
- state.getCurrentItem().setDescription(
- textElement.getProcessedContent());
- }
- } else if (top.equals(UPDATED)) {
- if (second.equals(ENTRY)
- && state.getCurrentItem().getPubDate() == null) {
- state.getCurrentItem().setPubDate(
- SyndDateUtils.parseRFC3339Date(content));
- }
- } else if (top.equals(PUBLISHED)) {
- if (second.equals(ENTRY)) {
- state.getCurrentItem().setPubDate(
- SyndDateUtils.parseRFC3339Date(content));
- }
- } else if (top.equals(IMAGE)) {
- state.getFeed().setImage(new FeedImage(content, null));
- }
-
- }
- }
-
-}
diff --git a/src/de/danoeh/antennapod/syndication/util/SyndDateUtils.java b/src/de/danoeh/antennapod/syndication/util/SyndDateUtils.java
deleted file mode 100644
index 3138f087a..000000000
--- a/src/de/danoeh/antennapod/syndication/util/SyndDateUtils.java
+++ /dev/null
@@ -1,153 +0,0 @@
-package de.danoeh.antennapod.syndication.util;
-
-import android.util.Log;
-
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-
-/** Parses several date formats. */
-public class SyndDateUtils {
- private static final String TAG = "DateUtils";
-
- private static final String[] RFC822DATES = { "dd MMM yy HH:mm:ss Z", };
-
- /** RFC 3339 date format for UTC dates. */
- public static final String RFC3339UTC = "yyyy-MM-dd'T'HH:mm:ss'Z'";
-
- /** RFC 3339 date format for localtime dates with offset. */
- public static final String RFC3339LOCAL = "yyyy-MM-dd'T'HH:mm:ssZ";
-
- private static ThreadLocal<SimpleDateFormat> RFC822Formatter = new ThreadLocal<SimpleDateFormat>() {
- @Override
- protected SimpleDateFormat initialValue() {
- return new SimpleDateFormat(RFC822DATES[0], Locale.US);
- }
-
- };
-
- private static ThreadLocal<SimpleDateFormat> RFC3339Formatter = new ThreadLocal<SimpleDateFormat>() {
- @Override
- protected SimpleDateFormat initialValue() {
- return new SimpleDateFormat(RFC3339UTC, Locale.US);
- }
-
- };
-
- public static Date parseRFC822Date(String date) {
- Date result = null;
- if (date.contains("PDT")) {
- date = date.replace("PDT", "PST8PDT");
- }
- if (date.contains(",")) {
- // Remove day of the week
- date = date.substring(date.indexOf(",") + 1).trim();
- }
- SimpleDateFormat format = RFC822Formatter.get();
- for (int i = 0; i < RFC822DATES.length; i++) {
- try {
- format.applyPattern(RFC822DATES[i]);
- result = format.parse(date);
- break;
- } catch (ParseException e) {
- e.printStackTrace();
- }
- }
- if (result == null) {
- Log.e(TAG, "Unable to parse feed date correctly");
- }
-
- return result;
- }
-
- public static Date parseRFC3339Date(String date) {
- Date result = null;
- SimpleDateFormat format = RFC3339Formatter.get();
- boolean isLocal = date.endsWith("Z");
- if (date.contains(".")) {
- // remove secfrac
- int fracIndex = date.indexOf(".");
- String first = date.substring(0, fracIndex);
- String second = null;
- if (isLocal) {
- second = date.substring(date.length() - 1);
- } else {
- if (date.contains("+")) {
- second = date.substring(date.indexOf("+"));
- } else {
- second = date.substring(date.indexOf("-"));
- }
- }
-
- date = first + second;
- }
- if (isLocal) {
- try {
- result = format.parse(date);
- } catch (ParseException e) {
- e.printStackTrace();
- }
- } else {
- format.applyPattern(RFC3339LOCAL);
- // remove last colon
- StringBuffer buf = new StringBuffer(date.length() - 1);
- int colonIdx = date.lastIndexOf(':');
- for (int x = 0; x < date.length(); x++) {
- if (x != colonIdx)
- buf.append(date.charAt(x));
- }
- String bufStr = buf.toString();
- try {
- result = format.parse(bufStr);
- } catch (ParseException e) {
- e.printStackTrace();
- Log.e(TAG, "Unable to parse date");
- } finally {
- format.applyPattern(RFC3339UTC);
- }
-
- }
-
- return result;
-
- }
-
- /**
- * Takes a string of the form [HH:]MM:SS[.mmm] and converts it to
- * milliseconds.
- */
- public static long parseTimeString(final String time) {
- String[] parts = time.split(":");
- long result = 0;
- int idx = 0;
- if (parts.length == 3) {
- // string has hours
- result += Integer.valueOf(parts[idx]) * 3600000L;
- idx++;
- }
- result += Integer.valueOf(parts[idx]) * 60000L;
- idx++;
- result += (Float.valueOf(parts[idx])) * 1000L;
- return result;
- }
-
- public static String formatRFC822Date(Date date) {
- SimpleDateFormat format = RFC822Formatter.get();
- return format.format(date);
- }
-
- public static String formatRFC3339Local(Date date) {
- SimpleDateFormat format = RFC3339Formatter.get();
- format.applyPattern(RFC3339LOCAL);
- String result = format.format(date);
- format.applyPattern(RFC3339UTC);
- return result;
- }
-
- public static String formatRFC3339UTC(Date date) {
- SimpleDateFormat format = RFC3339Formatter.get();
- format.applyPattern(RFC3339UTC);
- return format.format(date);
- }
-}
diff --git a/src/de/danoeh/antennapod/syndication/util/SyndTypeUtils.java b/src/de/danoeh/antennapod/syndication/util/SyndTypeUtils.java
deleted file mode 100644
index d0fa3a5fc..000000000
--- a/src/de/danoeh/antennapod/syndication/util/SyndTypeUtils.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package de.danoeh.antennapod.syndication.util;
-
-import android.webkit.MimeTypeMap;
-import org.apache.commons.io.FilenameUtils;
-
-/** Utility class for handling MIME-Types of enclosures */
-public class SyndTypeUtils {
-
- private final static String VALID_MIMETYPE = "audio/.*" + "|" + "video/.*"
- + "|" + "application/ogg";
-
- private SyndTypeUtils() {
-
- }
-
- public static boolean enclosureTypeValid(String type) {
- if (type == null) {
- return false;
- } else {
- return type.matches(VALID_MIMETYPE);
- }
- }
-
- /**
- * Should be used if mime-type of enclosure tag is not supported. This
- * method will check if the mime-type of the file extension is supported. If
- * the type is not supported, this method will return null.
- */
- public static String getValidMimeTypeFromUrl(String url) {
- if (url != null) {
- String extension = FilenameUtils.getExtension(url);
- if (extension != null) {
- String type = MimeTypeMap.getSingleton()
- .getMimeTypeFromExtension(extension);
- if (type != null && enclosureTypeValid(type)) {
- return type;
- }
- }
- }
- return null;
- }
-}
diff --git a/src/de/danoeh/antennapod/util/ChapterUtils.java b/src/de/danoeh/antennapod/util/ChapterUtils.java
deleted file mode 100644
index 9e1c50674..000000000
--- a/src/de/danoeh/antennapod/util/ChapterUtils.java
+++ /dev/null
@@ -1,261 +0,0 @@
-package de.danoeh.antennapod.util;
-
-import android.util.Log;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.feed.Chapter;
-import de.danoeh.antennapod.util.comparator.ChapterStartTimeComparator;
-import de.danoeh.antennapod.util.id3reader.ChapterReader;
-import de.danoeh.antennapod.util.id3reader.ID3ReaderException;
-import de.danoeh.antennapod.util.playback.Playable;
-import de.danoeh.antennapod.util.vorbiscommentreader.VorbisCommentChapterReader;
-import de.danoeh.antennapod.util.vorbiscommentreader.VorbisCommentReaderException;
-import org.apache.commons.io.IOUtils;
-
-import java.io.*;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Collections;
-import java.util.List;
-
-/** Utility class for getting chapter data from media files. */
-public class ChapterUtils {
- private static final String TAG = "ChapterUtils";
-
- private ChapterUtils() {
- }
-
- /**
- * Uses the download URL of a media object of a feeditem to read its ID3
- * chapters.
- */
- public static void readID3ChaptersFromPlayableStreamUrl(Playable p) {
- if (p != null && p.getStreamUrl() != null) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Reading id3 chapters from item " + p.getEpisodeTitle());
- InputStream in = null;
- try {
- URL url = new URL(p.getStreamUrl());
- ChapterReader reader = new ChapterReader();
-
- in = url.openStream();
- reader.readInputStream(in);
- List<Chapter> chapters = reader.getChapters();
-
- if (chapters != null) {
- Collections
- .sort(chapters, new ChapterStartTimeComparator());
- processChapters(chapters, p);
- if (chaptersValid(chapters)) {
- p.setChapters(chapters);
- Log.i(TAG, "Chapters loaded");
- } else {
- Log.e(TAG, "Chapter data was invalid");
- }
- } else {
- Log.i(TAG, "ChapterReader could not find any ID3 chapters");
- }
- } catch (MalformedURLException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } catch (ID3ReaderException e) {
- e.printStackTrace();
- } finally {
- if (in != null) {
- try {
- in.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- } else {
- Log.e(TAG,
- "Unable to read ID3 chapters: media or download URL was null");
- }
- }
-
- /**
- * Uses the file URL of a media object of a feeditem to read its ID3
- * chapters.
- */
- public static void readID3ChaptersFromPlayableFileUrl(Playable p) {
- if (p != null && p.localFileAvailable() && p.getLocalMediaUrl() != null) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Reading id3 chapters from item " + p.getEpisodeTitle());
- File source = new File(p.getLocalMediaUrl());
- if (source.exists()) {
- ChapterReader reader = new ChapterReader();
- InputStream in = null;
-
- try {
- in = new BufferedInputStream(new FileInputStream(source));
- reader.readInputStream(in);
- List<Chapter> chapters = reader.getChapters();
-
- if (chapters != null) {
- Collections.sort(chapters,
- new ChapterStartTimeComparator());
- processChapters(chapters, p);
- if (chaptersValid(chapters)) {
- p.setChapters(chapters);
- Log.i(TAG, "Chapters loaded");
- } else {
- Log.e(TAG, "Chapter data was invalid");
- }
- } else {
- Log.i(TAG,
- "ChapterReader could not find any ID3 chapters");
- }
- } catch (IOException e) {
- e.printStackTrace();
- } catch (ID3ReaderException e) {
- e.printStackTrace();
- } finally {
- if (in != null) {
- try {
- in.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- } else {
- Log.e(TAG, "Unable to read id3 chapters: Source doesn't exist");
- }
- }
- }
-
- public static void readOggChaptersFromPlayableStreamUrl(Playable media) {
- if (media != null && media.streamAvailable()) {
- InputStream input = null;
- try {
- URL url = new URL(media.getStreamUrl());
- input = url.openStream();
- if (input != null) {
- readOggChaptersFromInputStream(media, input);
- }
- } catch (MalformedURLException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- IOUtils.closeQuietly(input);
- }
- }
- }
-
- public static void readOggChaptersFromPlayableFileUrl(Playable media) {
- if (media != null && media.getLocalMediaUrl() != null) {
- File source = new File(media.getLocalMediaUrl());
- if (source.exists()) {
- InputStream input = null;
- try {
- input = new BufferedInputStream(new FileInputStream(source));
- readOggChaptersFromInputStream(media, input);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } finally {
- IOUtils.closeQuietly(input);
- }
- }
- }
- }
-
- private static void readOggChaptersFromInputStream(Playable p,
- InputStream input) {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "Trying to read chapters from item with title "
- + p.getEpisodeTitle());
- try {
- VorbisCommentChapterReader reader = new VorbisCommentChapterReader();
- reader.readInputStream(input);
- List<Chapter> chapters = reader.getChapters();
- if (chapters != null) {
- Collections.sort(chapters, new ChapterStartTimeComparator());
- processChapters(chapters, p);
- if (chaptersValid(chapters)) {
- p.setChapters(chapters);
- Log.i(TAG, "Chapters loaded");
- } else {
- Log.e(TAG, "Chapter data was invalid");
- }
- } else {
- Log.i(TAG,
- "ChapterReader could not find any Ogg vorbis chapters");
- }
- } catch (VorbisCommentReaderException e) {
- e.printStackTrace();
- }
- }
-
- /** Makes sure that chapter does a title and an item attribute. */
- private static void processChapters(List<Chapter> chapters, Playable p) {
- for (int i = 0; i < chapters.size(); i++) {
- Chapter c = chapters.get(i);
- if (c.getTitle() == null) {
- c.setTitle(Integer.toString(i));
- }
- }
- }
-
- private static boolean chaptersValid(List<Chapter> chapters) {
- if (chapters.isEmpty()) {
- return false;
- }
- for (Chapter c : chapters) {
- if (c.getTitle() == null) {
- return false;
- }
- if (c.getStart() < 0) {
- return false;
- }
- }
- return true;
- }
-
- /** Calls getCurrentChapter with current position. */
- public static Chapter getCurrentChapter(Playable media) {
- if (media.getChapters() != null) {
- List<Chapter> chapters = media.getChapters();
- Chapter current = null;
- if (chapters != null) {
- current = chapters.get(0);
- for (Chapter sc : chapters) {
- if (sc.getStart() > media.getPosition()) {
- break;
- } else {
- current = sc;
- }
- }
- }
- return current;
- } else {
- return null;
- }
- }
-
- public static void loadChaptersFromStreamUrl(Playable media) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Starting chapterLoader thread");
- ChapterUtils.readID3ChaptersFromPlayableStreamUrl(media);
- if (media.getChapters() == null) {
- ChapterUtils.readOggChaptersFromPlayableStreamUrl(media);
- }
-
- if (BuildConfig.DEBUG)
- Log.d(TAG, "ChapterLoaderThread has finished");
- }
-
- public static void loadChaptersFromFileUrl(Playable media) {
- if (media.localFileAvailable()) {
- ChapterUtils.readID3ChaptersFromPlayableFileUrl(media);
- if (media.getChapters() == null) {
- ChapterUtils.readOggChaptersFromPlayableFileUrl(media);
- }
- } else {
- Log.e(TAG, "Could not load chapters from file url: local file not available");
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/util/Converter.java b/src/de/danoeh/antennapod/util/Converter.java
deleted file mode 100644
index f4c2b2f66..000000000
--- a/src/de/danoeh/antennapod/util/Converter.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package de.danoeh.antennapod.util;
-
-import android.util.Log;
-
-/** Provides methods for converting various units. */
-public final class Converter {
- /** Class shall not be instantiated. */
- private Converter() {
- }
-
- /** Logging tag. */
- private static final String TAG = "Converter";
-
-
- /** Indicates that the value is in the Byte range.*/
- private static final int B_RANGE = 0;
- /** Indicates that the value is in the Kilobyte range.*/
- private static final int KB_RANGE = 1;
- /** Indicates that the value is in the Megabyte range.*/
- private static final int MB_RANGE = 2;
- /** Indicates that the value is in the Gigabyte range.*/
- private static final int GB_RANGE = 3;
- /** Determines the length of the number for best readability.*/
- private static final int NUM_LENGTH = 1024;
-
-
- private static final int HOURS_MIL = 3600000;
- private static final int MINUTES_MIL = 60000;
- private static final int SECONDS_MIL = 1000;
-
- /** Takes a byte-value and converts it into a more readable
- * String.
- * @param input The value to convert
- * @return The converted String with a unit
- * */
- public static String byteToString(final long input) {
- int i = 0;
- int result = 0;
-
- for (i = 0; i < GB_RANGE + 1; i++) {
- result = (int) (input / Math.pow(1024, i));
- if (result < NUM_LENGTH) {
- break;
- }
- }
-
- switch (i) {
- case B_RANGE:
- return result + " B";
- case KB_RANGE:
- return result + " KB";
- case MB_RANGE:
- return result + " MB";
- case GB_RANGE:
- return result + " GB";
- default:
- Log.e(TAG, "Error happened in byteToString");
- return "ERROR";
- }
- }
-
- /** Converts milliseconds to a string containing hours, minutes and seconds */
- public static String getDurationStringLong(int duration) {
- int h = duration / HOURS_MIL;
- int rest = duration - h * HOURS_MIL;
- int m = rest / MINUTES_MIL;
- rest -= m * MINUTES_MIL;
- int s = rest / SECONDS_MIL;
-
- return String.format("%02d:%02d:%02d", h, m, s);
- }
-
- /** Converts milliseconds to a string containing hours and minutes */
- public static String getDurationStringShort(int duration) {
- int h = duration / HOURS_MIL;
- int rest = duration - h * HOURS_MIL;
- int m = rest / MINUTES_MIL;
-
- return String.format("%02d:%02d", h, m);
- }
-
- /** Converts long duration string (HH:MM:SS) to milliseconds. */
- public static int durationStringLongToMs(String input) {
- String[] parts = input.split(":");
- if (parts.length != 3) {
- return 0;
- }
- return Integer.valueOf(parts[0]) * 3600 * 1000 +
- Integer.valueOf(parts[1]) * 60 * 1000 +
- Integer.valueOf(parts[2]) * 1000;
- }
-
- /** Converts short duration string (HH:MM) to milliseconds. */
- public static int durationStringShortToMs(String input) {
- String[] parts = input.split(":");
- if (parts.length != 2) {
- return 0;
- }
- return Integer.valueOf(parts[0]) * 3600 * 1000 +
- Integer.valueOf(parts[1]) * 1000 * 60;
- }
-
-}
diff --git a/src/de/danoeh/antennapod/util/DownloadError.java b/src/de/danoeh/antennapod/util/DownloadError.java
deleted file mode 100644
index 1a64991a6..000000000
--- a/src/de/danoeh/antennapod/util/DownloadError.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package de.danoeh.antennapod.util;
-
-import android.content.Context;
-import de.danoeh.antennapod.R;
-
-/** Utility class for Download Errors. */
-public enum DownloadError {
- SUCCESS(0, R.string.download_successful),
- ERROR_PARSER_EXCEPTION(1, R.string.download_error_parser_exception),
- ERROR_UNSUPPORTED_TYPE(2, R.string.download_error_unsupported_type),
- ERROR_CONNECTION_ERROR(3, R.string.download_error_connection_error),
- ERROR_MALFORMED_URL(4, R.string.download_error_error_unknown),
- ERROR_IO_ERROR(5, R.string.download_error_io_error),
- ERROR_FILE_EXISTS(6, R.string.download_error_error_unknown),
- ERROR_DOWNLOAD_CANCELLED(7, R.string.download_error_error_unknown),
- ERROR_DEVICE_NOT_FOUND(8, R.string.download_error_device_not_found),
- ERROR_HTTP_DATA_ERROR(9, R.string.download_error_http_data_error),
- ERROR_NOT_ENOUGH_SPACE(10, R.string.download_error_insufficient_space),
- ERROR_UNKNOWN_HOST(11, R.string.download_error_unknown_host),
- ERROR_REQUEST_ERROR(12, R.string.download_error_request_error),
- ERROR_DB_ACCESS_ERROR(13, R.string.download_error_db_access),
- ERROR_UNAUTHORIZED(14, R.string.download_error_unauthorized);
-
- private final int code;
- private final int resId;
-
- private DownloadError(int code, int resId) {
- this.code = code;
- this.resId = resId;
- }
-
- /** Return DownloadError from its associated code. */
- public static DownloadError fromCode(int code) {
- for (DownloadError reason : values()) {
- if (reason.getCode() == code) {
- return reason;
- }
- }
- throw new IllegalArgumentException("unknown code: " + code);
- }
-
- /** Get machine-readable code. */
- public int getCode() {
- return code;
- }
-
- /** Get a human-readable string. */
- public String getErrorString(Context context) {
- return context.getString(resId);
- }
-
-}
diff --git a/src/de/danoeh/antennapod/util/DuckType.java b/src/de/danoeh/antennapod/util/DuckType.java
deleted file mode 100644
index 163110418..000000000
--- a/src/de/danoeh/antennapod/util/DuckType.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/* Adapted from: http://thinking-in-code.blogspot.com/2008/11/duck-typing-in-java-using-dynamic.html */
-
-package de.danoeh.antennapod.util;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-
-import de.danoeh.antennapod.BuildConfig;
-
-/**
- * Allows "duck typing" or dynamic invocation based on method signature rather
- * than type hierarchy. In other words, rather than checking whether something
- * IS-a duck, check whether it WALKS-like-a duck or QUACKS-like a duck.
- *
- * To use first use the coerce static method to indicate the object you want to
- * do Duck Typing for, then specify an interface to the to method which you want
- * to coerce the type to, e.g:
- *
- * public interface Foo { void aMethod(); } class Bar { ... public void
- * aMethod() { ... } ... } Bar bar = ...; Foo foo =
- * DuckType.coerce(bar).to(Foo.class); foo.aMethod();
- *
- *
- */
-public class DuckType {
-
- private final Object objectToCoerce;
-
- private DuckType(Object objectToCoerce) {
- this.objectToCoerce = objectToCoerce;
- }
-
- private class CoercedProxy implements InvocationHandler {
- @Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- Method delegateMethod = findMethodBySignature(method);
- assert delegateMethod != null;
- return delegateMethod.invoke(DuckType.this.objectToCoerce, args);
- }
- }
-
- /**
- * Specify the duck typed object to coerce.
- *
- * @param object
- * the object to coerce
- * @return
- */
- public static DuckType coerce(Object object) {
- return new DuckType(object);
- }
-
- /**
- * Coerce the Duck Typed object to the given interface providing it
- * implements all the necessary methods.
- *
- * @param
- * @param iface
- * @return an instance of the given interface that wraps the duck typed
- * class
- * @throws ClassCastException
- * if the object being coerced does not implement all the
- * methods in the given interface.
- */
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public <T> T to(Class iface) {
- if (BuildConfig.DEBUG && !iface.isInterface()) throw new AssertionError("cannot coerce object to a class, must be an interface");
- if (isA(iface)) {
- return (T) iface.cast(objectToCoerce);
- }
- if (quacksLikeA(iface)) {
- return generateProxy(iface);
- }
- throw new ClassCastException("Could not coerce object of type " + objectToCoerce.getClass() + " to " + iface);
- }
-
- @SuppressWarnings("rawtypes")
- private boolean isA(Class iface) {
- return objectToCoerce.getClass().isInstance(iface);
- }
-
- /**
- * Determine whether the duck typed object can be used with the given
- * interface.
- *
- * @param Type
- * of the interface to check.
- * @param iface
- * Interface class to check
- * @return true if the object will support all the methods in the interface,
- * false otherwise.
- */
- @SuppressWarnings("rawtypes")
- public boolean quacksLikeA(Class iface) {
- for (Method method : iface.getMethods()) {
- if (findMethodBySignature(method) == null) {
- return false;
- }
- }
- return true;
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- private <T> T generateProxy(Class iface) {
- return (T) Proxy.newProxyInstance(iface.getClassLoader(), new Class[] { iface }, new CoercedProxy());
- }
-
- private Method findMethodBySignature(Method method) {
- try {
- return objectToCoerce.getClass().getMethod(method.getName(), method.getParameterTypes());
- } catch (NoSuchMethodException e) {
- return null;
- }
- }
-
-} \ No newline at end of file
diff --git a/src/de/danoeh/antennapod/util/EpisodeFilter.java b/src/de/danoeh/antennapod/util/EpisodeFilter.java
deleted file mode 100644
index 115913bca..000000000
--- a/src/de/danoeh/antennapod/util/EpisodeFilter.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package de.danoeh.antennapod.util;
-
-import de.danoeh.antennapod.feed.FeedItem;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class EpisodeFilter {
- private EpisodeFilter() {
-
- }
-
- /** Return a copy of the itemlist without items which have no media. */
- public static ArrayList<FeedItem> getEpisodeList(List<FeedItem> items) {
- ArrayList<FeedItem> episodes = new ArrayList<FeedItem>(items);
- for (FeedItem item : items) {
- if (item.getMedia() == null) {
- episodes.remove(item);
- }
- }
- return episodes;
- }
-
- public static int countItemsWithEpisodes(List<FeedItem> items) {
- int count = 0;
- for (FeedItem item : items) {
- if (item.getMedia() != null) {
- count++;
- }
- }
- return count;
- }
-
- public static FeedItem accessEpisodeByIndex(List<FeedItem> items,
- int position) {
- int count = 0;
- for (FeedItem item : items) {
-
- if (item.getMedia() != null) {
- if (count == position) {
- return item;
- } else {
- count++;
- }
- }
- }
- return null;
- }
-}
diff --git a/src/de/danoeh/antennapod/util/FeedtitleComparator.java b/src/de/danoeh/antennapod/util/FeedtitleComparator.java
deleted file mode 100644
index 112b6678d..000000000
--- a/src/de/danoeh/antennapod/util/FeedtitleComparator.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package de.danoeh.antennapod.util;
-
-import de.danoeh.antennapod.feed.Feed;
-
-import java.util.Comparator;
-
-/** Compares the title of two feeds for sorting. */
-public class FeedtitleComparator implements Comparator<Feed> {
-
- @Override
- public int compare(Feed lhs, Feed rhs) {
- return lhs.getTitle().compareToIgnoreCase(rhs.getTitle());
- }
-
-}
diff --git a/src/de/danoeh/antennapod/util/FileNameGenerator.java b/src/de/danoeh/antennapod/util/FileNameGenerator.java
deleted file mode 100644
index 702df62b8..000000000
--- a/src/de/danoeh/antennapod/util/FileNameGenerator.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package de.danoeh.antennapod.util;
-
-import java.util.Arrays;
-
-/** Generates valid filenames for a given string. */
-public class FileNameGenerator {
-
- private static final char[] ILLEGAL_CHARACTERS = { '/', '\\', '?', '%',
- '*', ':', '|', '"', '<', '>' };
- static {
- Arrays.sort(ILLEGAL_CHARACTERS);
- }
-
- private FileNameGenerator() {
-
- }
-
- /**
- * This method will return a new string that doesn't contain any illegal
- * characters of the given string.
- */
- public static String generateFileName(String string) {
- StringBuilder builder = new StringBuilder();
- for (int i = 0; i < string.length(); i++) {
- char c = string.charAt(i);
- if (Arrays.binarySearch(ILLEGAL_CHARACTERS, c) < 0) {
- builder.append(c);
- }
- }
- return builder.toString().replaceFirst(" *$","");
- }
-
- public static long generateLong(final String str) {
- return str.hashCode();
- }
-}
diff --git a/src/de/danoeh/antennapod/util/InvalidFeedException.java b/src/de/danoeh/antennapod/util/InvalidFeedException.java
deleted file mode 100644
index 50adae216..000000000
--- a/src/de/danoeh/antennapod/util/InvalidFeedException.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package de.danoeh.antennapod.util;
-
-/** Thrown if a feed has invalid attribute values. */
-public class InvalidFeedException extends Exception {
-
- public InvalidFeedException() {
- }
-
- public InvalidFeedException(String detailMessage) {
- super(detailMessage);
- }
-
- public InvalidFeedException(Throwable throwable) {
- super(throwable);
- }
-
- public InvalidFeedException(String detailMessage, Throwable throwable) {
- super(detailMessage, throwable);
- }
-
-}
diff --git a/src/de/danoeh/antennapod/util/LangUtils.java b/src/de/danoeh/antennapod/util/LangUtils.java
deleted file mode 100644
index e6e1d8399..000000000
--- a/src/de/danoeh/antennapod/util/LangUtils.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package de.danoeh.antennapod.util;
-
-import java.nio.charset.Charset;
-import java.util.HashMap;
-
-public class LangUtils {
- public static final Charset UTF_8 = Charset.forName("UTF-8");
-
- private static HashMap<String, String> languages;
- static {
- languages = new HashMap<String, String>();
- languages.put("af", "Afrikaans");
- languages.put("sq", "Albanian");
- languages.put("sq", "Albanian");
- languages.put("eu", "Basque");
- languages.put("be", "Belarusian");
- languages.put("bg", "Bulgarian");
- languages.put("ca", "Catalan");
- languages.put("Chinese (Simplified)", "zh-cn");
- languages.put("Chinese (Traditional)", "zh-tw");
- languages.put("hr", "Croatian");
- languages.put("cs", "Czech");
- languages.put("da", "Danish");
- languages.put("nl", "Dutch");
- languages.put("nl-be", "Dutch (Belgium)");
- languages.put("nl-nl", "Dutch (Netherlands)");
- languages.put("en", "English");
- languages.put("en-au", "English (Australia)");
- languages.put("en-bz", "English (Belize)");
- languages.put("en-ca", "English (Canada)");
- languages.put("en-ie", "English (Ireland)");
- languages.put("en-jm", "English (Jamaica)");
- languages.put("en-nz", "English (New Zealand)");
- languages.put("en-ph", "English (Phillipines)");
- languages.put("en-za", "English (South Africa)");
- languages.put("en-tt", "English (Trinidad)");
- languages.put("en-gb", "English (United Kingdom)");
- languages.put("en-us", "English (United States)");
- languages.put("en-zw", "English (Zimbabwe)");
- languages.put("et", "Estonian");
- languages.put("fo", "Faeroese");
- languages.put("fi", "Finnish");
- languages.put("fr", "French");
- languages.put("fr-be", "French (Belgium)");
- languages.put("fr-ca", "French (Canada)");
- languages.put("fr-fr", "French (France)");
- languages.put("fr-lu", "French (Luxembourg)");
- languages.put("fr-mc", "French (Monaco)");
- languages.put("fr-ch", "French (Switzerland)");
- languages.put("gl", "Galician");
- languages.put("gd", "Gaelic");
- languages.put("de", "German");
- languages.put("de-at", "German (Austria)");
- languages.put("de-de", "German (Germany)");
- languages.put("de-li", "German (Liechtenstein)");
- languages.put("de-lu", "German (Luxembourg)");
- languages.put("de-ch", "German (Switzerland)");
- languages.put("el", "Greek");
- languages.put("haw", "Hawaiian");
- languages.put("hu", "Hungarian");
- languages.put("is", "Icelandic");
- languages.put("in", "Indonesian");
- languages.put("ga", "Irish");
- languages.put("it", "Italian");
- languages.put("it-it", "Italian (Italy)");
- languages.put("it-ch", "Italian (Switzerland)");
- languages.put("ja", "Japanese");
- languages.put("ko", "Korean");
- languages.put("mk", "Macedonian");
- languages.put("no", "Norwegian");
- languages.put("pl", "Polish");
- languages.put("pt", "Portugese");
- languages.put("pt-br", "Portugese (Brazil)");
- languages.put("pt-pt", "Portugese (Portugal");
- languages.put("ro", "Romanian");
- languages.put("ro-mo", "Romanian (Moldova)");
- languages.put("ro-ro", "Romanian (Romania");
- languages.put("ru", "Russian");
- languages.put("ru-mo", "Russian (Moldova)");
- languages.put("ru-ru", "Russian (Russia)");
- languages.put("sr", "Serbian");
- languages.put("sk", "Slovak");
- languages.put("sl", "Slovenian");
- languages.put("es", "Spanish");
- languages.put("es-ar", "Spanish (Argentinia)");
- languages.put("es=bo", "Spanish (Bolivia)");
- languages.put("es-cl", "Spanish (Chile)");
- languages.put("es-co", "Spanish (Colombia)");
- languages.put("es-cr", "Spanish (Costa Rica)");
- languages.put("es-do", "Spanish (Dominican Republic)");
- languages.put("es-ec", "Spanish (Ecuador)");
- languages.put("es-sv", "Spanish (El Salvador)");
- languages.put("es-gt", "Spanish (Guatemala)");
- languages.put("es-hn", "Spanish (Honduras)");
- languages.put("es-mx", "Spanish (Mexico)");
- languages.put("es-ni", "Spanish (Nicaragua)");
- languages.put("es-pa", "Spanish (Panama)");
- languages.put("es-py", "Spanish (Paraguay)");
- languages.put("es-pe", "Spanish (Peru)");
- languages.put("es-pr", "Spanish (Puerto Rico)");
- languages.put("es-es", "Spanish (Spain)");
- languages.put("es-uy", "Spanish (Uruguay)");
- languages.put("es-ve", "Spanish (Venezuela)");
- languages.put("sv", "Swedish");
- languages.put("sv-fi", "Swedish (Finland)");
- languages.put("sv-se", "Swedish (Sweden)");
- languages.put("tr", "Turkish");
- languages.put("uk", "Ukranian");
- }
-
- /** Finds language string for key or returns the language key if it can't be found. */
- public static String getLanguageString(String key) {
- String language = languages.get(key);
- if (language != null) {
- return language;
- } else {
- return key;
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/util/NetworkUtils.java b/src/de/danoeh/antennapod/util/NetworkUtils.java
deleted file mode 100644
index 0c8065e94..000000000
--- a/src/de/danoeh/antennapod/util/NetworkUtils.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package de.danoeh.antennapod.util;
-
-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;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.preferences.UserPreferences;
-
-import java.util.Arrays;
-import java.util.List;
-
-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 (BuildConfig.DEBUG)
- Log.d(TAG, "Device is connected to Wi-Fi");
- if (networkInfo.isConnected()) {
- if (!UserPreferences.isEnableAutodownloadWifiFilter()) {
- if (BuildConfig.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<String> selectedNetworks = Arrays
- .asList(UserPreferences
- .getAutodownloadSelectedNetworks());
- if (selectedNetworks.contains(Integer.toString(wifiInfo
- .getNetworkId()))) {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "Current network is on the selected networks list");
- return true;
- }
- }
- }
- }
- }
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Network for auto-dl is not available");
- return false;
- }
-
- public static boolean networkAvailable(Context context) {
- ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
- NetworkInfo info = cm.getActiveNetworkInfo();
- return info != null && info.isConnected();
- }
-}
diff --git a/src/de/danoeh/antennapod/util/QueueAccess.java b/src/de/danoeh/antennapod/util/QueueAccess.java
deleted file mode 100644
index 7a1c7fef2..000000000
--- a/src/de/danoeh/antennapod/util/QueueAccess.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package de.danoeh.antennapod.util;
-
-import de.danoeh.antennapod.feed.FeedItem;
-
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * Provides methods for accessing the queue. It is possible to load only a part of the information about the queue that
- * is stored in the database (e.g. sometimes the user just has to test if a specific item is contained in the List.
- * QueueAccess provides an interface for accessing the queue without having to care about the type of the queue
- * representation.
- */
-public abstract class QueueAccess {
- /**
- * Returns true if the item is in the queue, false otherwise.
- */
- public abstract boolean contains(long id);
-
- /**
- * Removes the item from the queue.
- *
- * @return true if the queue was modified by this operation.
- */
- public abstract boolean remove(long id);
-
- private QueueAccess() {
-
- }
-
- public static QueueAccess IDListAccess(final List<Long> ids) {
- return new QueueAccess() {
- @Override
- public boolean contains(long id) {
- return (ids != null) && ids.contains(id);
- }
-
- @Override
- public boolean remove(long id) {
- return ids.remove(id);
- }
-
-
- };
- }
-
- public static QueueAccess ItemListAccess(final List<FeedItem> items) {
- return new QueueAccess() {
- @Override
- public boolean contains(long id) {
- if (items == null) {
- return false;
- }
- for (FeedItem item : items) {
- if (item.getId() == id) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public boolean remove(long id) {
- Iterator<FeedItem> it = items.iterator();
- FeedItem item;
- while (it.hasNext()) {
- item = it.next();
- if (item.getId() == id) {
- it.remove();
- return true;
- }
- }
- return false;
- }
- };
- }
-
- public static QueueAccess NotInQueueAccess() {
- return new QueueAccess() {
- @Override
- public boolean contains(long id) {
- return false;
- }
-
- @Override
- public boolean remove(long id) {
- return false;
- }
- };
-
- }
-
-}
diff --git a/src/de/danoeh/antennapod/util/ShareUtils.java b/src/de/danoeh/antennapod/util/ShareUtils.java
deleted file mode 100644
index 941fc62ae..000000000
--- a/src/de/danoeh/antennapod/util/ShareUtils.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package de.danoeh.antennapod.util;
-
-import android.content.Context;
-import android.content.Intent;
-import de.danoeh.antennapod.feed.Feed;
-import de.danoeh.antennapod.feed.FeedItem;
-
-/** Utility methods for sharing data */
-public class ShareUtils {
- private static final String TAG = "ShareUtils";
-
- private ShareUtils() {}
-
- public static void shareLink(Context context, String link) {
- Intent i = new Intent(Intent.ACTION_SEND);
- i.setType("text/plain");
- i.putExtra(Intent.EXTRA_SUBJECT, "Sharing URL");
- i.putExtra(Intent.EXTRA_TEXT, link);
- context.startActivity(Intent.createChooser(i, "Share URL"));
- }
-
- public static void shareFeedItemLink(Context context, FeedItem item) {
- shareLink(context, item.getLink());
- }
-
- public static void shareFeedDownloadLink(Context context, Feed feed) {
- shareLink(context, feed.getDownload_url());
- }
-
- public static void shareFeedlink(Context context, Feed feed) {
- shareLink(context, feed.getLink());
- }
-
-}
diff --git a/src/de/danoeh/antennapod/util/ShownotesProvider.java b/src/de/danoeh/antennapod/util/ShownotesProvider.java
deleted file mode 100644
index 8345ca34d..000000000
--- a/src/de/danoeh/antennapod/util/ShownotesProvider.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package de.danoeh.antennapod.util;
-
-import java.util.concurrent.Callable;
-
-/**
- * Created by daniel on 04.08.13.
- */
-public interface ShownotesProvider {
- /**
- * Loads shownotes. If the shownotes have to be loaded from a file or from a
- * database, it should be done in a separate thread. After the shownotes
- * have been loaded, callback.onShownotesLoaded should be called.
- */
- public Callable<String> loadShownotes();
-
-}
diff --git a/src/de/danoeh/antennapod/util/StorageUtils.java b/src/de/danoeh/antennapod/util/StorageUtils.java
deleted file mode 100644
index ff0bde280..000000000
--- a/src/de/danoeh/antennapod/util/StorageUtils.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package de.danoeh.antennapod.util;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Build;
-import android.os.StatFs;
-import android.util.Log;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.PodcastApp;
-import de.danoeh.antennapod.activity.StorageErrorActivity;
-import de.danoeh.antennapod.preferences.UserPreferences;
-
-import java.io.File;
-
-/** Utility functions for handling storage errors */
-public class StorageUtils {
- private static final String TAG = "StorageUtils";
-
- public static boolean storageAvailable(Context context) {
- File dir = UserPreferences.getDataFolder(context, null);
- if (dir != null) {
- return dir.exists() && dir.canRead() && dir.canWrite();
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Storage not available: data folder is null");
- return false;
- }
- }
-
- /**
- * Checks if external storage is available. If external storage isn't
- * available, the current activity is finsished an an error activity is
- * launched.
- *
- * @param activity
- * the activity which would be finished if no storage is
- * available
- * @return true if external storage is available
- */
- public static boolean checkStorageAvailability(Activity activity) {
- boolean storageAvailable = storageAvailable(activity);
- if (!storageAvailable) {
- activity.finish();
- activity.startActivity(new Intent(activity,
- StorageErrorActivity.class));
- }
- return storageAvailable;
- }
-
- /** Get the number of free bytes that are available on the external storage. */
- public static long getFreeSpaceAvailable() {
- StatFs stat = new StatFs(UserPreferences.getDataFolder(
- PodcastApp.getInstance(), null).getAbsolutePath());
- long availableBlocks;
- long blockSize;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
- availableBlocks = stat.getAvailableBlocksLong();
- blockSize = stat.getBlockSizeLong();
- } else {
- availableBlocks = stat.getAvailableBlocks();
- blockSize = stat.getBlockSize();
- }
- return availableBlocks * blockSize;
- }
-}
diff --git a/src/de/danoeh/antennapod/util/ThemeUtils.java b/src/de/danoeh/antennapod/util/ThemeUtils.java
deleted file mode 100644
index 8e593f3fb..000000000
--- a/src/de/danoeh/antennapod/util/ThemeUtils.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package de.danoeh.antennapod.util;
-
-import android.util.Log;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.preferences.UserPreferences;
-
-public class ThemeUtils {
- private static final String TAG = "ThemeUtils";
-
- public static int getSelectionBackgroundColor() {
- switch (UserPreferences.getTheme()) {
- case R.style.Theme_AntennaPod_Dark:
- return R.color.selection_background_color_dark;
- case R.style.Theme_AntennaPod_Light:
- return R.color.selection_background_color_light;
- default:
- Log.e(TAG,
- "getSelectionBackgroundColor could not match the current theme to any color!");
- return R.color.selection_background_color_light;
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/util/URIUtil.java b/src/de/danoeh/antennapod/util/URIUtil.java
deleted file mode 100644
index 5af40d591..000000000
--- a/src/de/danoeh/antennapod/util/URIUtil.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package de.danoeh.antennapod.util;
-
-import android.util.Log;
-import de.danoeh.antennapod.BuildConfig;
-
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-
-/**
- * Utility methods for dealing with URL encoding.
- */
-public class URIUtil {
- private static final String TAG = "URIUtil";
-
- private URIUtil() {}
-
- public static URI getURIFromRequestUrl(String source) {
- // try without encoding the URI
- try {
- return new URI(source);
- } catch (URISyntaxException e) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Source is not encoded, encoding now");
- }
- try {
- URL url = new URL(source);
- return new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
- } catch (MalformedURLException e) {
- throw new IllegalArgumentException(e);
- } catch (URISyntaxException e) {
- throw new IllegalArgumentException(e);
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/util/URLChecker.java b/src/de/danoeh/antennapod/util/URLChecker.java
deleted file mode 100644
index 9997daaf7..000000000
--- a/src/de/danoeh/antennapod/util/URLChecker.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package de.danoeh.antennapod.util;
-
-import android.util.Log;
-
-import org.apache.commons.lang3.StringUtils;
-
-import de.danoeh.antennapod.BuildConfig;
-
-/**
- * Provides methods for checking and editing a URL.
- */
-public final class URLChecker {
-
- /**
- * Class shall not be instantiated.
- */
- private URLChecker() {
- }
-
- /**
- * Logging tag.
- */
- private static final String TAG = "URLChecker";
-
- /**
- * Checks if URL is valid and modifies it if necessary.
- *
- * @param url The url which is going to be prepared
- * @return The prepared url
- */
- public static String prepareURL(String url) {
- StringBuilder builder = new StringBuilder();
- url = StringUtils.trim(url);
- if (url.startsWith("feed://")) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Replacing feed:// with http://");
- url = url.replaceFirst("feed://", "http://");
- } else if (url.startsWith("pcast://")) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Replacing pcast:// with http://");
- url = url.replaceFirst("pcast://", "http://");
- } else if (url.startsWith("itpc")) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Replacing itpc:// with http://");
- url = url.replaceFirst("itpc://", "http://");
- } else if (!(url.startsWith("http://") || url.startsWith("https://"))) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Adding http:// at the beginning of the URL");
- builder.append("http://");
- }
- builder.append(url);
-
- return builder.toString();
- }
-}
diff --git a/src/de/danoeh/antennapod/util/UndoBarController.java b/src/de/danoeh/antennapod/util/UndoBarController.java
deleted file mode 100644
index 332cc22e0..000000000
--- a/src/de/danoeh/antennapod/util/UndoBarController.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright 2012 Roman Nurik
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.danoeh.antennapod.util;
-
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.view.View;
-import android.widget.TextView;
-import com.nineoldandroids.animation.Animator;
-import com.nineoldandroids.animation.AnimatorListenerAdapter;
-import com.nineoldandroids.view.ViewHelper;
-import com.nineoldandroids.view.ViewPropertyAnimator;
-import de.danoeh.antennapod.R;
-
-import static com.nineoldandroids.view.ViewPropertyAnimator.animate;
-
-public class UndoBarController {
- private View mBarView;
- private TextView mMessageView;
- private ViewPropertyAnimator mBarAnimator;
- private Handler mHideHandler = new Handler();
-
- private UndoListener mUndoListener;
-
- // State objects
- private Parcelable mUndoToken;
- private CharSequence mUndoMessage;
-
- public interface UndoListener {
- void onUndo(Parcelable token);
- }
-
- public UndoBarController(View undoBarView, UndoListener undoListener) {
- mBarView = undoBarView;
- mBarAnimator = animate(mBarView);
- mUndoListener = undoListener;
-
- mMessageView = (TextView) mBarView.findViewById(R.id.undobar_message);
- mBarView.findViewById(R.id.undobar_button)
- .setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- hideUndoBar(false);
- mUndoListener.onUndo(mUndoToken);
- }
- });
-
- hideUndoBar(true);
- }
-
- public void showUndoBar(boolean immediate, CharSequence message, Parcelable undoToken) {
- mUndoToken = undoToken;
- mUndoMessage = message;
- mMessageView.setText(mUndoMessage);
-
- mHideHandler.removeCallbacks(mHideRunnable);
- mHideHandler.postDelayed(mHideRunnable,
- mBarView.getResources().getInteger(R.integer.undobar_hide_delay));
-
- mBarView.setVisibility(View.VISIBLE);
- if (immediate) {
- ViewHelper.setAlpha(mBarView, 1);
- } else {
- mBarAnimator.cancel();
- mBarAnimator
- .alpha(1)
- .setDuration(
- mBarView.getResources()
- .getInteger(android.R.integer.config_shortAnimTime))
- .setListener(null);
- }
- }
-
- public void hideUndoBar(boolean immediate) {
- mHideHandler.removeCallbacks(mHideRunnable);
- if (immediate) {
- mBarView.setVisibility(View.GONE);
- ViewHelper.setAlpha(mBarView, 0);
- mUndoMessage = null;
- mUndoToken = null;
-
- } else {
- mBarAnimator.cancel();
- mBarAnimator
- .alpha(0)
- .setDuration(mBarView.getResources()
- .getInteger(android.R.integer.config_shortAnimTime))
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mBarView.setVisibility(View.GONE);
- mUndoMessage = null;
- mUndoToken = null;
- }
- });
- }
- }
-
- public void onSaveInstanceState(Bundle outState) {
- outState.putCharSequence("undo_message", mUndoMessage);
- outState.putParcelable("undo_token", mUndoToken);
- }
-
- public void onRestoreInstanceState(Bundle savedInstanceState) {
- if (savedInstanceState != null) {
- mUndoMessage = savedInstanceState.getCharSequence("undo_message");
- mUndoToken = savedInstanceState.getParcelable("undo_token");
-
- if (mUndoToken != null || !TextUtils.isEmpty(mUndoMessage)) {
- showUndoBar(true, mUndoMessage, mUndoToken);
- }
- }
- }
-
- private Runnable mHideRunnable = new Runnable() {
- @Override
- public void run() {
- hideUndoBar(false);
- }
- };
-}
diff --git a/src/de/danoeh/antennapod/util/comparator/ChapterStartTimeComparator.java b/src/de/danoeh/antennapod/util/comparator/ChapterStartTimeComparator.java
deleted file mode 100644
index bfc2fd057..000000000
--- a/src/de/danoeh/antennapod/util/comparator/ChapterStartTimeComparator.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package de.danoeh.antennapod.util.comparator;
-
-import de.danoeh.antennapod.feed.Chapter;
-
-import java.util.Comparator;
-
-public class ChapterStartTimeComparator implements Comparator<Chapter> {
-
- @Override
- public int compare(Chapter lhs, Chapter rhs) {
- if (lhs.getStart() == rhs.getStart()) {
- return 0;
- } else if (lhs.getStart() < rhs.getStart()) {
- return -1;
- } else {
- return 1;
- }
- }
-
-}
diff --git a/src/de/danoeh/antennapod/util/comparator/DownloadStatusComparator.java b/src/de/danoeh/antennapod/util/comparator/DownloadStatusComparator.java
deleted file mode 100644
index 14b8f1194..000000000
--- a/src/de/danoeh/antennapod/util/comparator/DownloadStatusComparator.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package de.danoeh.antennapod.util.comparator;
-
-import de.danoeh.antennapod.service.download.DownloadStatus;
-
-import java.util.Comparator;
-
-/** Compares the completion date of two Downloadstatus objects. */
-public class DownloadStatusComparator implements Comparator<DownloadStatus> {
-
- @Override
- public int compare(DownloadStatus lhs, DownloadStatus rhs) {
- return rhs.getCompletionDate().compareTo(lhs.getCompletionDate());
- }
-
-}
diff --git a/src/de/danoeh/antennapod/util/comparator/FeedItemPubdateComparator.java b/src/de/danoeh/antennapod/util/comparator/FeedItemPubdateComparator.java
deleted file mode 100644
index f92c23d05..000000000
--- a/src/de/danoeh/antennapod/util/comparator/FeedItemPubdateComparator.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package de.danoeh.antennapod.util.comparator;
-
-import de.danoeh.antennapod.feed.FeedItem;
-
-import java.util.Comparator;
-
-/** Compares the pubDate of two FeedItems for sorting*/
-public class FeedItemPubdateComparator implements Comparator<FeedItem> {
-
- /** Returns a new instance of this comparator in reverse order.
- public static FeedItemPubdateComparator newInstance() {
- FeedItemPubdateComparator
- }*/
- @Override
- public int compare(FeedItem lhs, FeedItem rhs) {
- return rhs.getPubDate().compareTo(lhs.getPubDate());
- }
-
-}
diff --git a/src/de/danoeh/antennapod/util/comparator/PlaybackCompletionDateComparator.java b/src/de/danoeh/antennapod/util/comparator/PlaybackCompletionDateComparator.java
deleted file mode 100644
index 0147e0cdc..000000000
--- a/src/de/danoeh/antennapod/util/comparator/PlaybackCompletionDateComparator.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package de.danoeh.antennapod.util.comparator;
-
-import de.danoeh.antennapod.feed.FeedItem;
-
-import java.util.Comparator;
-
-public class PlaybackCompletionDateComparator implements Comparator<FeedItem> {
-
- public int compare(FeedItem lhs, FeedItem rhs) {
- if (lhs.getMedia() != null
- && lhs.getMedia().getPlaybackCompletionDate() != null
- && rhs.getMedia() != null
- && rhs.getMedia().getPlaybackCompletionDate() != null) {
- return rhs.getMedia().getPlaybackCompletionDate()
- .compareTo(lhs.getMedia().getPlaybackCompletionDate());
- }
- return 0;
- }
-}
diff --git a/src/de/danoeh/antennapod/util/comparator/SearchResultValueComparator.java b/src/de/danoeh/antennapod/util/comparator/SearchResultValueComparator.java
deleted file mode 100644
index 02b084a01..000000000
--- a/src/de/danoeh/antennapod/util/comparator/SearchResultValueComparator.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package de.danoeh.antennapod.util.comparator;
-
-import de.danoeh.antennapod.feed.SearchResult;
-
-import java.util.Comparator;
-
-public class SearchResultValueComparator implements Comparator<SearchResult> {
-
- @Override
- public int compare(SearchResult lhs, SearchResult rhs) {
- return rhs.getValue() - lhs.getValue();
- }
-
-}
diff --git a/src/de/danoeh/antennapod/util/exception/MediaFileNotFoundException.java b/src/de/danoeh/antennapod/util/exception/MediaFileNotFoundException.java
deleted file mode 100644
index 4586cea87..000000000
--- a/src/de/danoeh/antennapod/util/exception/MediaFileNotFoundException.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package de.danoeh.antennapod.util.exception;
-
-import de.danoeh.antennapod.feed.FeedMedia;
-
-public class MediaFileNotFoundException extends Exception {
- private static final long serialVersionUID = 1L;
-
- private FeedMedia media;
-
- public MediaFileNotFoundException(String msg, FeedMedia media) {
- super(msg);
- this.media = media;
- }
-
- public MediaFileNotFoundException(FeedMedia media) {
- super();
- this.media = media;
- }
-
- public FeedMedia getMedia() {
- return media;
- }
-}
diff --git a/src/de/danoeh/antennapod/util/flattr/FlattrServiceCreator.java b/src/de/danoeh/antennapod/util/flattr/FlattrServiceCreator.java
deleted file mode 100644
index eda83b7aa..000000000
--- a/src/de/danoeh/antennapod/util/flattr/FlattrServiceCreator.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package de.danoeh.antennapod.util.flattr;
-
-import android.util.Log;
-import de.danoeh.antennapod.BuildConfig;
-import org.shredzone.flattr4j.FlattrFactory;
-import org.shredzone.flattr4j.FlattrService;
-import org.shredzone.flattr4j.oauth.AccessToken;
-
-/** Ensures that only one instance of the FlattrService class exists at a time */
-
-public class FlattrServiceCreator {
- public static final String TAG = "FlattrServiceCreator";
-
- private static volatile FlattrService flattrService;
-
- public static FlattrService getService(AccessToken token) {
- return FlattrFactory.getInstance().createFlattrService(token);
- }
-
- public static void deleteFlattrService() {
- if (BuildConfig.DEBUG) Log.d(TAG, "Deleting service instance");
- flattrService = null;
- }
-}
-
diff --git a/src/de/danoeh/antennapod/util/flattr/FlattrStatus.java b/src/de/danoeh/antennapod/util/flattr/FlattrStatus.java
deleted file mode 100644
index a1d6d3bc4..000000000
--- a/src/de/danoeh/antennapod/util/flattr/FlattrStatus.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package de.danoeh.antennapod.util.flattr;
-
-import java.util.Calendar;
-
-public class FlattrStatus {
- public static final int STATUS_UNFLATTERED = 0;
- public static final int STATUS_QUEUE = 1;
- public static final int STATUS_FLATTRED = 2;
-
- private int status = STATUS_UNFLATTERED;
- private Calendar lastFlattred;
-
- public FlattrStatus() {
- status = STATUS_UNFLATTERED;
- lastFlattred = Calendar.getInstance();
- }
-
- public FlattrStatus(long status) {
- lastFlattred = Calendar.getInstance();
- fromLong(status);
- }
-
- public void setFlattred() {
- status = STATUS_FLATTRED;
- lastFlattred = Calendar.getInstance();
- }
-
- public void setUnflattred() {
- status = STATUS_UNFLATTERED;
- }
-
- public boolean getUnflattred() {
- return status == STATUS_UNFLATTERED;
- }
-
- public void setFlattrQueue() {
- if (flattrable())
- status = STATUS_QUEUE;
- }
-
- public void fromLong(long status) {
- if (status == STATUS_UNFLATTERED || status == STATUS_QUEUE)
- this.status = (int) status;
- else {
- this.status = STATUS_FLATTRED;
- lastFlattred.setTimeInMillis(status);
- }
- }
-
- public long toLong() {
- if (status == STATUS_UNFLATTERED || status == STATUS_QUEUE)
- return status;
- else {
- return lastFlattred.getTimeInMillis();
- }
- }
-
- public boolean flattrable() {
- Calendar firstOfMonth = Calendar.getInstance();
- firstOfMonth.set(Calendar.DAY_OF_MONTH, Calendar.getInstance().getActualMinimum(Calendar.DAY_OF_MONTH));
-
- return (status == STATUS_UNFLATTERED) || (status == STATUS_FLATTRED && firstOfMonth.after(lastFlattred) );
- }
-
- public boolean getFlattrQueue() {
- return status == STATUS_QUEUE;
- }
-}
diff --git a/src/de/danoeh/antennapod/util/flattr/FlattrThing.java b/src/de/danoeh/antennapod/util/flattr/FlattrThing.java
deleted file mode 100644
index f17ef1d83..000000000
--- a/src/de/danoeh/antennapod/util/flattr/FlattrThing.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package de.danoeh.antennapod.util.flattr;
-
-public interface FlattrThing {
- public String getTitle();
- public String getPaymentLink();
- public FlattrStatus getFlattrStatus();
-}
diff --git a/src/de/danoeh/antennapod/util/flattr/FlattrUtils.java b/src/de/danoeh/antennapod/util/flattr/FlattrUtils.java
deleted file mode 100644
index 3e2ea3132..000000000
--- a/src/de/danoeh/antennapod/util/flattr/FlattrUtils.java
+++ /dev/null
@@ -1,305 +0,0 @@
-package de.danoeh.antennapod.util.flattr;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.net.Uri;
-import android.preference.PreferenceManager;
-import android.util.Log;
-
-import org.apache.commons.lang3.StringUtils;
-import org.shredzone.flattr4j.FlattrService;
-import org.shredzone.flattr4j.exception.FlattrException;
-import org.shredzone.flattr4j.model.Flattr;
-import org.shredzone.flattr4j.model.Thing;
-import org.shredzone.flattr4j.oauth.AccessToken;
-import org.shredzone.flattr4j.oauth.AndroidAuthenticator;
-import org.shredzone.flattr4j.oauth.Scope;
-
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.TimeZone;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.PodcastApp;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.FlattrAuthActivity;
-import de.danoeh.antennapod.asynctask.FlattrTokenFetcher;
-import de.danoeh.antennapod.storage.DBWriter;
-
-/**
- * Utility methods for doing something with flattr.
- */
-
-public class FlattrUtils {
- private static final String TAG = "FlattrUtils";
-
- private static final String HOST_NAME = "de.danoeh.antennapod";
-
- private static final String PREF_ACCESS_TOKEN = "de.danoeh.antennapod.preference.flattrAccessToken";
-
- // Flattr URL for this app.
- public static final String APP_URL = "http://antennapod.com";
- // Human-readable flattr-page.
- public static final String APP_LINK = "https://flattr.com/thing/745609/";
- public static final String APP_THING_ID = "745609";
-
- private static volatile AccessToken cachedToken;
-
- private static AndroidAuthenticator createAuthenticator() {
- return new AndroidAuthenticator(HOST_NAME, BuildConfig.FLATTR_APP_KEY,
- BuildConfig.FLATTR_APP_SECRET);
- }
-
- public static void startAuthProcess(Context context) throws FlattrException {
- AndroidAuthenticator auth = createAuthenticator();
- auth.setScope(EnumSet.of(Scope.FLATTR));
- Intent intent = auth.createAuthenticateIntent();
- context.startActivity(intent);
- }
-
- private static AccessToken retrieveToken() {
- if (cachedToken == null) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Retrieving access token");
- String token = PreferenceManager.getDefaultSharedPreferences(
- PodcastApp.getInstance())
- .getString(PREF_ACCESS_TOKEN, null);
- if (token != null) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Found access token. Caching.");
- cachedToken = new AccessToken(token);
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "No access token found");
- return null;
- }
- }
- return cachedToken;
-
- }
-
- /**
- * Returns true if FLATTR_APP_KEY and FLATTR_APP_SECRET in BuildConfig are not null and not empty
- */
- public static boolean hasAPICredentials() {
- return StringUtils.isNotEmpty(BuildConfig.FLATTR_APP_KEY)
- && StringUtils.isNotEmpty(BuildConfig.FLATTR_APP_SECRET);
- }
-
- public static boolean hasToken() {
- return retrieveToken() != null;
- }
-
- public static void storeToken(AccessToken token) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Storing token");
- SharedPreferences.Editor editor = PreferenceManager
- .getDefaultSharedPreferences(PodcastApp.getInstance()).edit();
- if (token != null) {
- editor.putString(PREF_ACCESS_TOKEN, token.getToken());
- } else {
- editor.putString(PREF_ACCESS_TOKEN, null);
- }
- editor.commit();
- cachedToken = token;
- }
-
- public static void deleteToken() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Deleting flattr token");
- storeToken(null);
- }
-
- public static Thing getAppThing(Context context) {
- FlattrService fs = FlattrServiceCreator.getService(retrieveToken());
- try {
- Thing thing = fs.getThing(Thing.withId(APP_THING_ID));
- return thing;
- } catch (FlattrException e) {
- e.printStackTrace();
- showErrorDialog(context, e.getMessage());
- return null;
- }
- }
-
- public static void clickUrl(Context context, String url)
- throws FlattrException {
- if (hasToken()) {
- FlattrService fs = FlattrServiceCreator.getService(retrieveToken());
- fs.click(url);
- } else {
- Log.e(TAG, "clickUrl was called with null access token");
- }
- }
-
- public static List<Flattr> retrieveFlattredThings()
- throws FlattrException {
- ArrayList<Flattr> myFlattrs = new ArrayList<Flattr>();
-
- if (hasToken()) {
- FlattrService fs = FlattrServiceCreator.getService(retrieveToken());
-
- Calendar firstOfMonth = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
- firstOfMonth.set(Calendar.MILLISECOND, 0);
- firstOfMonth.set(Calendar.SECOND, 0);
- firstOfMonth.set(Calendar.MINUTE, 0);
- firstOfMonth.set(Calendar.HOUR_OF_DAY, 0);
- firstOfMonth.set(Calendar.DAY_OF_MONTH, Calendar.getInstance().getActualMinimum(Calendar.DAY_OF_MONTH));
-
- Date firstOfMonthDate = firstOfMonth.getTime();
-
- // subscriptions some times get flattrd slightly before midnight - give it an hour leeway
- firstOfMonthDate = new Date(firstOfMonthDate.getTime() - 60 * 60 * 1000);
-
- final int FLATTR_COUNT = 30;
- final int FLATTR_MAXPAGE = 5;
-
- for (int page = 0; page < FLATTR_MAXPAGE; page++) {
- for (Flattr fl : fs.getMyFlattrs(FLATTR_COUNT, page)) {
- if (fl.getCreated().after(firstOfMonthDate))
- myFlattrs.add(fl);
- else
- break;
- }
- }
-
- if (BuildConfig.DEBUG) {
- Log.d(TAG, "Got my flattrs list of length " + Integer.toString(myFlattrs.size()) + " comparison date" + firstOfMonthDate);
-
- for (Flattr fl : myFlattrs) {
- Thing thing = fl.getThing();
- Log.d(TAG, "Flattr thing: " + fl.getThingId() + " name: " + thing.getTitle() + " url: " + thing.getUrl() + " on: " + fl.getCreated());
- }
- }
-
- } else {
- Log.e(TAG, "retrieveFlattrdThings was called with null access token");
- }
-
- return myFlattrs;
- }
-
- public static void handleCallback(Context context, Uri uri) {
- AndroidAuthenticator auth = createAuthenticator();
- new FlattrTokenFetcher(context, auth, uri).executeAsync();
- }
-
- public static void revokeAccessToken(Context context) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Revoking access token");
- deleteToken();
- FlattrServiceCreator.deleteFlattrService();
- showRevokeDialog(context);
- DBWriter.clearAllFlattrStatus(context);
- }
-
- // ------------------------------------------------ DIALOGS
-
- public static void showRevokeDialog(final Context context) {
- AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle(R.string.access_revoked_title);
- builder.setMessage(R.string.access_revoked_info);
- builder.setNeutralButton(android.R.string.ok, new OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.cancel();
- }
- });
- builder.create().show();
- }
-
- /**
- * Opens a dialog that ask the user to either connect the app with flattr or to be redirected to
- * the thing's website.
- * If no API credentials are available, the user will immediately be redirected to the thing's website.
- * */
- public static void showNoTokenDialogOrRedirect(final Context context, final String url) {
- if (hasAPICredentials()) {
- AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle(R.string.no_flattr_token_title);
- builder.setMessage(R.string.no_flattr_token_msg);
- builder.setPositiveButton(R.string.authenticate_now_label,
- new OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- context.startActivity(new Intent(context,
- FlattrAuthActivity.class));
- }
-
- }
- );
-
- builder.setNegativeButton(R.string.visit_website_label,
- new OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- Uri uri = Uri.parse(url);
- context.startActivity(new Intent(Intent.ACTION_VIEW,
- uri));
- }
-
- }
- );
- builder.create().show();
- } else {
- Uri uri = Uri.parse(url);
- context.startActivity(new Intent(Intent.ACTION_VIEW, uri));
- }
- }
-
- public static void showForbiddenDialog(final Context context,
- final String url) {
- AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle(R.string.action_forbidden_title);
- builder.setMessage(R.string.action_forbidden_msg);
- builder.setPositiveButton(R.string.authenticate_now_label,
- new OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- context.startActivity(new Intent(context,
- FlattrAuthActivity.class));
- }
-
- }
- );
- builder.setNegativeButton(R.string.visit_website_label,
- new OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- Uri uri = Uri.parse(url);
- context.startActivity(new Intent(Intent.ACTION_VIEW,
- uri));
- }
-
- }
- );
- builder.create().show();
- }
-
- public static void showErrorDialog(final Context context, final String msg) {
- AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle(R.string.error_label);
- builder.setMessage(msg);
- builder.setNeutralButton(android.R.string.ok, new OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.cancel();
- }
- });
- builder.create().show();
- }
-
-} \ No newline at end of file
diff --git a/src/de/danoeh/antennapod/util/flattr/SimpleFlattrThing.java b/src/de/danoeh/antennapod/util/flattr/SimpleFlattrThing.java
deleted file mode 100644
index 296610871..000000000
--- a/src/de/danoeh/antennapod/util/flattr/SimpleFlattrThing.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package de.danoeh.antennapod.util.flattr;
-
-/* SimpleFlattrThing is a trivial implementation of the FlattrThing interface */
-public class SimpleFlattrThing implements FlattrThing {
- public SimpleFlattrThing(String title, String url, FlattrStatus status)
- {
- this.title = title;
- this.url = url;
- this.status = status;
- }
-
- public String getTitle()
- {
- return this.title;
- }
-
- public String getPaymentLink()
- {
- return this.url;
- }
-
- public FlattrStatus getFlattrStatus()
- {
- return this.status;
- }
-
- private String title;
- private String url;
- private FlattrStatus status;
-}
diff --git a/src/de/danoeh/antennapod/util/gui/FeedItemUndoToken.java b/src/de/danoeh/antennapod/util/gui/FeedItemUndoToken.java
deleted file mode 100644
index b920559db..000000000
--- a/src/de/danoeh/antennapod/util/gui/FeedItemUndoToken.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package de.danoeh.antennapod.util.gui;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import de.danoeh.antennapod.feed.FeedItem;
-
-/**
- * Used by an UndoBarController for saving a removed FeedItem
- */
-public class FeedItemUndoToken implements Parcelable {
- private long itemId;
- private long feedId;
- private int position;
-
- public FeedItemUndoToken(FeedItem item, int position) {
- this.itemId = item.getId();
- this.feedId = item.getFeed().getId();
- this.position = position;
- }
-
- private FeedItemUndoToken(Parcel in) {
- itemId = in.readLong();
- feedId = in.readLong();
- position = in.readInt();
- }
-
- public static final Parcelable.Creator<FeedItemUndoToken> CREATOR = new Parcelable.Creator<FeedItemUndoToken>() {
- public FeedItemUndoToken createFromParcel(Parcel in) {
- return new FeedItemUndoToken(in);
- }
-
- public FeedItemUndoToken[] newArray(int size) {
- return new FeedItemUndoToken[size];
- }
- };
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel out, int flags) {
- out.writeLong(itemId);
- out.writeLong(feedId);
- out.writeInt(position);
- }
-
- public long getFeedItemId() {
- return itemId;
- }
-
- public int getPosition() {
- return position;
- }
-}
-
diff --git a/src/de/danoeh/antennapod/util/id3reader/ChapterReader.java b/src/de/danoeh/antennapod/util/id3reader/ChapterReader.java
deleted file mode 100644
index 257635129..000000000
--- a/src/de/danoeh/antennapod/util/id3reader/ChapterReader.java
+++ /dev/null
@@ -1,118 +0,0 @@
-package de.danoeh.antennapod.util.id3reader;
-
-import android.util.Log;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.feed.Chapter;
-import de.danoeh.antennapod.feed.ID3Chapter;
-import de.danoeh.antennapod.util.id3reader.model.FrameHeader;
-import de.danoeh.antennapod.util.id3reader.model.TagHeader;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URLDecoder;
-import java.util.ArrayList;
-import java.util.List;
-
-public class ChapterReader extends ID3Reader {
- private static final String TAG = "ID3ChapterReader";
-
- private static final String FRAME_ID_CHAPTER = "CHAP";
- private static final String FRAME_ID_TITLE = "TIT2";
- private static final String FRAME_ID_LINK = "WXXX";
-
- private List<Chapter> chapters;
- private ID3Chapter currentChapter;
-
- @Override
- public int onStartTagHeader(TagHeader header) {
- chapters = new ArrayList<Chapter>();
- System.out.println(header.toString());
- return ID3Reader.ACTION_DONT_SKIP;
- }
-
- @Override
- public int onStartFrameHeader(FrameHeader header, InputStream input)
- throws IOException, ID3ReaderException {
- System.out.println(header.toString());
- if (header.getId().equals(FRAME_ID_CHAPTER)) {
- if (currentChapter != null) {
- if (!hasId3Chapter(currentChapter)) {
- chapters.add(currentChapter);
- if (BuildConfig.DEBUG) Log.d(TAG, "Found chapter: " + currentChapter);
- currentChapter = null;
- }
- }
- StringBuffer elementId = new StringBuffer();
- readISOString(elementId, input, Integer.MAX_VALUE);
- char[] startTimeSource = readBytes(input, 4);
- long startTime = ((int) startTimeSource[0] << 24)
- | ((int) startTimeSource[1] << 16)
- | ((int) startTimeSource[2] << 8) | startTimeSource[3];
- currentChapter = new ID3Chapter(elementId.toString(), startTime);
- skipBytes(input, 12);
- return ID3Reader.ACTION_DONT_SKIP;
- } else if (header.getId().equals(FRAME_ID_TITLE)) {
- if (currentChapter != null && currentChapter.getTitle() == null) {
- StringBuffer title = new StringBuffer();
- readString(title, input, header.getSize());
- currentChapter
- .setTitle(title.toString());
- if (BuildConfig.DEBUG) Log.d(TAG, "Found title: " + currentChapter.getTitle());
-
- return ID3Reader.ACTION_DONT_SKIP;
- }
- } else if (header.getId().equals(FRAME_ID_LINK)) {
- if (currentChapter != null) {
- // skip description
- int descriptionLength = readString(null, input, header.getSize());
- StringBuffer link = new StringBuffer();
- readISOString(link, input, header.getSize() - descriptionLength);
- String decodedLink = URLDecoder.decode(link.toString(), "UTF-8");
-
- currentChapter.setLink(decodedLink);
-
- if (BuildConfig.DEBUG) Log.d(TAG, "Found link: " + currentChapter.getLink());
- return ID3Reader.ACTION_DONT_SKIP;
- }
- } else if (header.getId().equals("APIC")) {
- Log.d(TAG, header.toString());
- }
-
- return super.onStartFrameHeader(header, input);
- }
-
- private boolean hasId3Chapter(ID3Chapter chapter) {
- for (Chapter c : chapters) {
- if (((ID3Chapter) c).getId3ID().equals(chapter.getId3ID())) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public void onEndTag() {
- if (currentChapter != null) {
- if (!hasId3Chapter(currentChapter)) {
- chapters.add(currentChapter);
- }
- }
- System.out.println("Reached end of tag");
- if (chapters != null) {
- for (Chapter c : chapters) {
- System.out.println(c.toString());
- }
- }
- }
-
- @Override
- public void onNoTagHeaderFound() {
- System.out.println("No tag header found");
- super.onNoTagHeaderFound();
- }
-
- public List<Chapter> getChapters() {
- return chapters;
- }
-
-}
diff --git a/src/de/danoeh/antennapod/util/id3reader/ID3Reader.java b/src/de/danoeh/antennapod/util/id3reader/ID3Reader.java
deleted file mode 100644
index 252d64107..000000000
--- a/src/de/danoeh/antennapod/util/id3reader/ID3Reader.java
+++ /dev/null
@@ -1,250 +0,0 @@
-package de.danoeh.antennapod.util.id3reader;
-
-import de.danoeh.antennapod.util.id3reader.model.FrameHeader;
-import de.danoeh.antennapod.util.id3reader.model.TagHeader;
-import org.apache.commons.io.IOUtils;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.ByteBuffer;
-import java.nio.charset.Charset;
-
-/**
- * Reads the ID3 Tag of a given file. In order to use this class, you should
- * create a subclass of it and overwrite the onStart* - or onEnd* - methods.
- */
-public class ID3Reader {
- private static final int HEADER_LENGTH = 10;
- private static final int ID3_LENGTH = 3;
- private static final int FRAME_ID_LENGTH = 4;
-
- protected static final int ACTION_SKIP = 1;
- protected static final int ACTION_DONT_SKIP = 2;
-
- protected int readerPosition;
-
- private static final byte ENCODING_UTF16_WITH_BOM = 1;
- private static final byte ENCODING_UTF16_WITHOUT_BOM = 2;
- private static final byte ENCODING_UTF8 = 3;
-
- private TagHeader tagHeader;
-
- public ID3Reader() {
- }
-
- public final void readInputStream(InputStream input) throws IOException,
- ID3ReaderException {
- int rc;
- readerPosition = 0;
- char[] tagHeaderSource = readBytes(input, HEADER_LENGTH);
- tagHeader = createTagHeader(tagHeaderSource);
- if (tagHeader == null) {
- onNoTagHeaderFound();
- } else {
- rc = onStartTagHeader(tagHeader);
- if (rc == ACTION_SKIP) {
- onEndTag();
- } else {
- while (readerPosition < tagHeader.getSize()) {
- FrameHeader frameHeader = createFrameHeader(readBytes(
- input, HEADER_LENGTH));
- if (checkForNullString(frameHeader.getId())) {
- break;
- } else {
- rc = onStartFrameHeader(frameHeader, input);
- if (rc == ACTION_SKIP) {
-
- if (frameHeader.getSize() + readerPosition > tagHeader
- .getSize()) {
- break;
- } else {
- skipBytes(input, frameHeader.getSize());
- }
- }
- }
- }
- onEndTag();
- }
- }
- }
-
- /** Returns true if string only contains null-bytes. */
- private boolean checkForNullString(String s) {
- if (!s.isEmpty()) {
- int i = 0;
- if (s.charAt(i) == 0) {
- for (i = 1; i < s.length(); i++) {
- if (s.charAt(i) != 0) {
- return false;
- }
- }
- return true;
- }
- return false;
- } else {
- return true;
- }
-
- }
-
- /**
- * Read a certain number of bytes from the given input stream. This method
- * changes the readerPosition-attribute.
- */
- protected char[] readBytes(InputStream input, int number)
- throws IOException, ID3ReaderException {
- char[] header = new char[number];
- for (int i = 0; i < number; i++) {
- int b = input.read();
- readerPosition++;
- if (b != -1) {
- header[i] = (char) b;
- } else {
- throw new ID3ReaderException("Unexpected end of stream");
- }
- }
- return header;
- }
-
- /**
- * Skip a certain number of bytes on the given input stream. This method
- * changes the readerPosition-attribute.
- */
- protected void skipBytes(InputStream input, int number) throws IOException {
- if (number <= 0) {
- number = 1;
- }
- IOUtils.skipFully(input, number);
-
- readerPosition += number;
- }
-
- private TagHeader createTagHeader(char[] source) throws ID3ReaderException {
- boolean hasTag = (source[0] == 0x49) && (source[1] == 0x44)
- && (source[2] == 0x33);
- if (source.length != HEADER_LENGTH) {
- throw new ID3ReaderException("Length of header must be "
- + HEADER_LENGTH);
- }
- if (hasTag) {
- String id = new String(source, 0, ID3_LENGTH);
- char version = (char) ((source[3] << 8) | source[4]);
- byte flags = (byte) source[5];
- int size = (source[6] << 24) | (source[7] << 16) | (source[8] << 8)
- | source[9];
- size = unsynchsafe(size);
- return new TagHeader(id, size, version, flags);
- } else {
- return null;
- }
- }
-
- private FrameHeader createFrameHeader(char[] source)
- throws ID3ReaderException {
- if (source.length != HEADER_LENGTH) {
- throw new ID3ReaderException("Length of header must be "
- + HEADER_LENGTH);
- }
- String id = new String(source, 0, FRAME_ID_LENGTH);
-
- int size = (((int) source[4]) << 24) | (((int) source[5]) << 16)
- | (((int) source[6]) << 8) | source[7];
- if (tagHeader != null && tagHeader.getVersion() >= 0x0400) {
- size = unsynchsafe(size);
- }
- char flags = (char) ((source[8] << 8) | source[9]);
- return new FrameHeader(id, size, flags);
- }
-
- private int unsynchsafe(int in) {
- int out = 0;
- int mask = 0x7F000000;
-
- while (mask != 0) {
- out >>= 1;
- out |= in & mask;
- mask >>= 8;
- }
-
- return out;
- }
-
- protected int readString(StringBuffer buffer, InputStream input, int max) throws IOException,
- ID3ReaderException {
- if (max > 0) {
- char[] encoding = readBytes(input, 1);
- max--;
-
- if (encoding[0] == ENCODING_UTF16_WITH_BOM || encoding[0] == ENCODING_UTF16_WITHOUT_BOM) {
- return readUnicodeString(buffer, input, max, Charset.forName("UTF-16")) + 1; // take encoding byte into account
- } else if (encoding[0] == ENCODING_UTF8) {
- return readUnicodeString(buffer, input, max, Charset.forName("UTF-8")) + 1; // take encoding byte into account
- } else {
- return readISOString(buffer, input, max) + 1; // take encoding byte into account
- }
- } else {
- if (buffer != null) {
- buffer.append("");
- }
- return 0;
- }
- }
-
- protected int readISOString(StringBuffer buffer, InputStream input, int max)
- throws IOException, ID3ReaderException {
-
- int bytesRead = 0;
- char c;
- while (++bytesRead <= max && (c = (char) input.read()) > 0) {
- if (buffer != null) {
- buffer.append(c);
- }
- }
- return bytesRead;
- }
-
- private int readUnicodeString(StringBuffer strBuffer, InputStream input, int max, Charset charset)
- throws IOException, ID3ReaderException {
- byte[] buffer = new byte[max];
- int c, cZero = -1;
- int i = 0;
- for (; i < max; i++) {
- c = input.read();
- if (c == -1) {
- break;
- } else if (c == 0) {
- if (cZero == 0) {
- // termination character found
- break;
- } else {
- cZero = 0;
- }
- } else {
- buffer[i] = (byte) c;
- cZero = -1;
- }
- }
- if (strBuffer != null) {
- strBuffer.append(charset.newDecoder().decode(ByteBuffer.wrap(buffer)).toString());
- }
- return i;
- }
-
- public int onStartTagHeader(TagHeader header) {
- return ACTION_SKIP;
- }
-
- public int onStartFrameHeader(FrameHeader header, InputStream input)
- throws IOException, ID3ReaderException {
- return ACTION_SKIP;
- }
-
- public void onEndTag() {
-
- }
-
- public void onNoTagHeaderFound() {
-
- }
-
-}
diff --git a/src/de/danoeh/antennapod/util/id3reader/ID3ReaderException.java b/src/de/danoeh/antennapod/util/id3reader/ID3ReaderException.java
deleted file mode 100644
index c458540ee..000000000
--- a/src/de/danoeh/antennapod/util/id3reader/ID3ReaderException.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package de.danoeh.antennapod.util.id3reader;
-
-public class ID3ReaderException extends Exception {
-
- public ID3ReaderException() {
- }
-
- public ID3ReaderException(String arg0) {
- super(arg0);
- }
-
- public ID3ReaderException(Throwable arg0) {
- super(arg0);
- }
-
- public ID3ReaderException(String arg0, Throwable arg1) {
- super(arg0, arg1);
- }
-
-}
diff --git a/src/de/danoeh/antennapod/util/id3reader/model/FrameHeader.java b/src/de/danoeh/antennapod/util/id3reader/model/FrameHeader.java
deleted file mode 100644
index df73393a5..000000000
--- a/src/de/danoeh/antennapod/util/id3reader/model/FrameHeader.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package de.danoeh.antennapod.util.id3reader.model;
-
-public class FrameHeader extends Header {
-
- protected char flags;
-
- public FrameHeader(String id, int size, char flags) {
- super(id, size);
- this.flags = flags;
- }
-
- @Override
- public String toString() {
- return String.format("FrameHeader [flags=%s, id=%s, size=%s]", Integer.toBinaryString(flags), id, Integer.toBinaryString(size));
- }
-
-}
diff --git a/src/de/danoeh/antennapod/util/id3reader/model/Header.java b/src/de/danoeh/antennapod/util/id3reader/model/Header.java
deleted file mode 100644
index 22d5b6376..000000000
--- a/src/de/danoeh/antennapod/util/id3reader/model/Header.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package de.danoeh.antennapod.util.id3reader.model;
-
-public abstract class Header {
-
- protected String id;
- protected int size;
-
- public Header(String id, int size) {
- super();
- this.id = id;
- this.size = size;
- }
-
- public String getId() {
- return id;
- }
-
- public int getSize() {
- return size;
- }
-
- @Override
- public String toString() {
- return "Header [id=" + id + ", size=" + size + "]";
- }
-
-
-
-}
diff --git a/src/de/danoeh/antennapod/util/id3reader/model/TagHeader.java b/src/de/danoeh/antennapod/util/id3reader/model/TagHeader.java
deleted file mode 100644
index ec99ef14e..000000000
--- a/src/de/danoeh/antennapod/util/id3reader/model/TagHeader.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package de.danoeh.antennapod.util.id3reader.model;
-
-public class TagHeader extends Header {
-
- protected char version;
- protected byte flags;
-
- public TagHeader(String id, int size, char version, byte flags) {
- super(id, size);
- this.version = version;
- this.flags = flags;
- }
-
- @Override
- public String toString() {
- return "TagHeader [version=" + version + ", flags=" + flags + ", id="
- + id + ", size=" + size + "]";
- }
-
- public char getVersion() {
- return version;
- }
-
-
-
-}
diff --git a/src/de/danoeh/antennapod/util/menuhandler/FeedItemMenuHandler.java b/src/de/danoeh/antennapod/util/menuhandler/FeedItemMenuHandler.java
deleted file mode 100644
index 2c7a7f074..000000000
--- a/src/de/danoeh/antennapod/util/menuhandler/FeedItemMenuHandler.java
+++ /dev/null
@@ -1,191 +0,0 @@
-package de.danoeh.antennapod.util.menuhandler;
-
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.service.playback.PlaybackService;
-import de.danoeh.antennapod.storage.DBTasks;
-import de.danoeh.antennapod.storage.DBWriter;
-import de.danoeh.antennapod.storage.DownloadRequestException;
-import de.danoeh.antennapod.storage.DownloadRequester;
-import de.danoeh.antennapod.util.QueueAccess;
-import de.danoeh.antennapod.util.ShareUtils;
-
-/**
- * Handles interactions with the FeedItemMenu.
- */
-public class FeedItemMenuHandler {
- private static final String TAG = "FeedItemMenuHandler";
-
- private FeedItemMenuHandler() {
-
- }
-
- /**
- * Used by the MenuHandler to access different types of menus through one
- * interface
- */
- public interface MenuInterface {
- /**
- * Implementations of this method should call findItem(id) on their
- * menu-object and call setVisibility(visibility) on the returned
- * MenuItem object.
- */
- abstract void setItemVisibility(int id, boolean visible);
- }
-
- /**
- * This method should be called in the prepare-methods of menus. It changes
- * the visibility of the menu items depending on a FeedItem's attributes.
- *
- * @param mi An instance of MenuInterface that the method uses to change a
- * MenuItem's visibility
- * @param selectedItem The FeedItem for which the menu is supposed to be prepared
- * @param showExtendedMenu True if MenuItems that let the user share information about
- * the FeedItem and visit its website should be set visible. This
- * parameter should be set to false if the menu space is limited.
- * @param queueAccess Used for testing if the queue contains the selected item
- * @return Returns true if selectedItem is not null.
- */
- public static boolean onPrepareMenu(MenuInterface mi,
- FeedItem selectedItem, boolean showExtendedMenu, QueueAccess queueAccess) {
- if (selectedItem == null) {
- return false;
- }
- DownloadRequester requester = DownloadRequester.getInstance();
- boolean hasMedia = selectedItem.getMedia() != null;
- boolean downloaded = hasMedia && selectedItem.getMedia().isDownloaded();
- boolean downloading = hasMedia
- && requester.isDownloadingFile(selectedItem.getMedia());
- boolean notLoadedAndNotLoading = hasMedia && (!downloaded)
- && (!downloading);
- boolean isPlaying = hasMedia
- && selectedItem.getState() == FeedItem.State.PLAYING;
-
- FeedItem.State state = selectedItem.getState();
-
- 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) | isPlaying) {
- mi.setItemVisibility(R.id.stream_item, false);
- }
- if (!downloading) {
- mi.setItemVisibility(R.id.cancel_download_item, false);
- }
-
- boolean isInQueue = queueAccess.contains(selectedItem.getId());
- if (!isInQueue || isPlaying) {
- mi.setItemVisibility(R.id.remove_from_queue_item, false);
- }
- if (!(!isInQueue && selectedItem.getMedia() != null)) {
- mi.setItemVisibility(R.id.add_to_queue_item, false);
- }
- if (!showExtendedMenu || selectedItem.getLink() == null) {
- mi.setItemVisibility(R.id.share_link_item, false);
- }
-
- if (!BuildConfig.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)) {
- mi.setItemVisibility(R.id.mark_read_item, false);
- }
-
- if (!showExtendedMenu || selectedItem.getLink() == null) {
- mi.setItemVisibility(R.id.visit_website_item, false);
- }
-
- if (selectedItem.getPaymentLink() == null || !selectedItem.getFlattrStatus().flattrable()) {
- mi.setItemVisibility(R.id.support_item, false);
- }
- return true;
- }
-
- /**
- * The same method as onPrepareMenu(MenuInterface, FeedItem, boolean, QueueAccess), but lets the
- * caller also specify a list of menu items that should not be shown.
- *
- * @param excludeIds Menu item that should be excluded
- * @return true if selectedItem is not null.
- */
- public static boolean onPrepareMenu(MenuInterface mi,
- FeedItem selectedItem, boolean showExtendedMenu, QueueAccess queueAccess, int... excludeIds) {
- boolean rc = onPrepareMenu(mi, selectedItem, showExtendedMenu, queueAccess);
- if (rc && excludeIds != null) {
- for (int id : excludeIds) {
- mi.setItemVisibility(id, false);
- }
- }
-
- return rc;
- }
-
- public static boolean onMenuItemClicked(Context context, int menuItemId,
- FeedItem selectedItem) throws DownloadRequestException {
- DownloadRequester requester = DownloadRequester.getInstance();
- switch (menuItemId) {
- case R.id.skip_episode_item:
- context.sendBroadcast(new Intent(
- PlaybackService.ACTION_SKIP_CURRENT_EPISODE));
- break;
- case R.id.download_item:
- DBTasks.downloadFeedItems(context, selectedItem);
- break;
- case R.id.play_item:
- DBTasks.playMedia(context, selectedItem.getMedia(), true, true,
- false);
- break;
- case R.id.remove_item:
- DBWriter.deleteFeedMediaOfItem(context, selectedItem.getMedia().getId());
- break;
- case R.id.cancel_download_item:
- requester.cancelDownload(context, selectedItem.getMedia());
- break;
- case R.id.mark_read_item:
- DBWriter.markItemRead(context, selectedItem, true, true);
- break;
- case R.id.mark_unread_item:
- DBWriter.markItemRead(context, selectedItem, false, true);
- break;
- case R.id.add_to_queue_item:
- DBWriter.addQueueItem(context, selectedItem.getId());
- break;
- case R.id.remove_from_queue_item:
- DBWriter.removeQueueItem(context, selectedItem.getId(), true);
- break;
- case R.id.stream_item:
- DBTasks.playMedia(context, selectedItem.getMedia(), true, true,
- true);
- break;
- case R.id.visit_website_item:
- Uri uri = Uri.parse(selectedItem.getLink());
- context.startActivity(new Intent(Intent.ACTION_VIEW, uri));
- break;
- case R.id.support_item:
- DBTasks.flattrItemIfLoggedIn(context, selectedItem);
- break;
- case R.id.share_link_item:
- ShareUtils.shareFeedItemLink(context, selectedItem);
- break;
- default:
- return false;
- }
- // Refresh menu state
-
- return true;
- }
-
-}
diff --git a/src/de/danoeh/antennapod/util/menuhandler/FeedMenuHandler.java b/src/de/danoeh/antennapod/util/menuhandler/FeedMenuHandler.java
deleted file mode 100644
index a3adec66d..000000000
--- a/src/de/danoeh/antennapod/util/menuhandler/FeedMenuHandler.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package de.danoeh.antennapod.util.menuhandler;
-
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.FeedInfoActivity;
-import de.danoeh.antennapod.feed.Feed;
-import de.danoeh.antennapod.service.download.DownloadService;
-import de.danoeh.antennapod.storage.DBTasks;
-import de.danoeh.antennapod.storage.DBWriter;
-import de.danoeh.antennapod.storage.DownloadRequestException;
-import de.danoeh.antennapod.storage.DownloadRequester;
-import de.danoeh.antennapod.util.ShareUtils;
-
-/** Handles interactions with the FeedItemMenu. */
-public class FeedMenuHandler {
- private static final String TAG = "FeedMenuHandler";
-
- public static boolean onCreateOptionsMenu(MenuInflater inflater, Menu menu) {
- inflater.inflate(R.menu.feedlist, menu);
- return true;
- }
-
- public static boolean onPrepareOptionsMenu(Menu menu, Feed selectedFeed) {
- if (selectedFeed == null) {
- return true;
- }
-
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Preparing options menu");
- menu.findItem(R.id.mark_all_read_item).setVisible(
- selectedFeed.hasNewItems(true));
- if (selectedFeed.getPaymentLink() != null && selectedFeed.getFlattrStatus().flattrable())
- menu.findItem(R.id.support_item).setVisible(true);
- else
- menu.findItem(R.id.support_item).setVisible(false);
- MenuItem refresh = menu.findItem(R.id.refresh_item);
- if (DownloadService.isRunning
- && DownloadRequester.getInstance().isDownloadingFile(
- selectedFeed)) {
- refresh.setVisible(false);
- } else {
- refresh.setVisible(true);
- }
-
- return true;
- }
-
- /**
- * NOTE: This method does not handle clicks on the 'remove feed' - item.
- *
- * @throws DownloadRequestException
- */
- public static boolean onOptionsItemClicked(Context context, MenuItem item,
- Feed selectedFeed) throws DownloadRequestException {
- switch (item.getItemId()) {
- case R.id.refresh_item:
- DBTasks.refreshFeed(context, selectedFeed);
- break;
- case R.id.mark_all_read_item:
- DBWriter.markFeedRead(context, selectedFeed.getId());
- break;
- case R.id.visit_website_item:
- Uri uri = Uri.parse(selectedFeed.getLink());
- context.startActivity(new Intent(Intent.ACTION_VIEW, uri));
- break;
- case R.id.support_item:
- DBTasks.flattrFeedIfLoggedIn(context, selectedFeed);
- break;
- case R.id.share_link_item:
- ShareUtils.shareFeedlink(context, selectedFeed);
- break;
- case R.id.share_source_item:
- ShareUtils.shareFeedDownloadLink(context, selectedFeed);
- break;
- default:
- return false;
- }
- return true;
- }
-}
diff --git a/src/de/danoeh/antennapod/util/menuhandler/MenuItemUtils.java b/src/de/danoeh/antennapod/util/menuhandler/MenuItemUtils.java
deleted file mode 100644
index 7aa04d24c..000000000
--- a/src/de/danoeh/antennapod/util/menuhandler/MenuItemUtils.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package de.danoeh.antennapod.util.menuhandler;
-
-import android.support.v4.view.MenuItemCompat;
-import android.support.v7.widget.SearchView;
-import android.view.Menu;
-import android.view.MenuItem;
-
-import de.danoeh.antennapod.R;
-
-/**
- * Utilities for menu items
- */
-public class MenuItemUtils {
-
- public static MenuItem addSearchItem(Menu menu, SearchView searchView) {
- MenuItem item = menu.add(Menu.NONE, R.id.search_item, Menu.NONE, R.string.search_label);
- MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
- MenuItemCompat.setActionView(item, searchView);
- return item;
- }
-
- /**
- * Checks if the navigation drawer of the DrawerActivity is opened. This can be useful for Fragments
- * that hide their menu if the navigation drawer is open.
- *
- * @return True if the drawer is open, false otherwise (also if the parameter is null)
- */
- public static boolean isActivityDrawerOpen(NavDrawerActivity activity) {
- return activity != null && activity.isDrawerOpen();
- }
-}
diff --git a/src/de/danoeh/antennapod/util/menuhandler/NavDrawerActivity.java b/src/de/danoeh/antennapod/util/menuhandler/NavDrawerActivity.java
deleted file mode 100644
index 9c611a452..000000000
--- a/src/de/danoeh/antennapod/util/menuhandler/NavDrawerActivity.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package de.danoeh.antennapod.util.menuhandler;
-
-/**
- * Defines useful methods for activities that have a navigation drawer
- */
-public interface NavDrawerActivity {
-
- public boolean isDrawerOpen();
-}
diff --git a/src/de/danoeh/antennapod/util/playback/AudioPlayer.java b/src/de/danoeh/antennapod/util/playback/AudioPlayer.java
deleted file mode 100644
index bd49b0d18..000000000
--- a/src/de/danoeh/antennapod/util/playback/AudioPlayer.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package de.danoeh.antennapod.util.playback;
-
-import android.content.Context;
-import android.util.Log;
-import android.view.SurfaceHolder;
-import com.aocate.media.MediaPlayer;
-
-public class AudioPlayer extends MediaPlayer implements IPlayer {
- private static final String TAG = "AudioPlayer";
-
- public AudioPlayer(Context context) {
- super(context);
- }
-
- @Override
- public void setScreenOnWhilePlaying(boolean screenOn) {
- Log.e(TAG, "Setting screen on while playing not supported in Audio Player");
- throw new UnsupportedOperationException("Setting screen on while playing not supported in Audio Player");
-
- }
-
- @Override
- public void setDisplay(SurfaceHolder sh) {
- if (sh != null) {
- Log.e(TAG, "Setting display not supported in Audio Player");
- throw new UnsupportedOperationException("Setting display not supported in Audio Player");
- }
- }
-
- @Override
- public void setVideoScalingMode(int mode) {
- throw new UnsupportedOperationException("Setting scaling mode is not supported in Audio Player");
- }
-}
diff --git a/src/de/danoeh/antennapod/util/playback/ExternalMedia.java b/src/de/danoeh/antennapod/util/playback/ExternalMedia.java
deleted file mode 100644
index 3f6e6ae0a..000000000
--- a/src/de/danoeh/antennapod/util/playback/ExternalMedia.java
+++ /dev/null
@@ -1,237 +0,0 @@
-package de.danoeh.antennapod.util.playback;
-
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
-import android.media.MediaMetadataRetriever;
-import android.net.Uri;
-import android.os.Parcel;
-import android.os.Parcelable;
-import de.danoeh.antennapod.feed.Chapter;
-import de.danoeh.antennapod.feed.MediaType;
-import de.danoeh.antennapod.util.ChapterUtils;
-
-import java.io.File;
-import java.io.InputStream;
-import java.util.List;
-import java.util.concurrent.Callable;
-
-/** Represents a media file that is stored on the local storage device. */
-public class ExternalMedia implements Playable {
-
- public static final int PLAYABLE_TYPE_EXTERNAL_MEDIA = 2;
- public static final String PREF_SOURCE_URL = "ExternalMedia.PrefSourceUrl";
- public static final String PREF_POSITION = "ExternalMedia.PrefPosition";
- public static final String PREF_MEDIA_TYPE = "ExternalMedia.PrefMediaType";
-
- private String source;
-
- private String episodeTitle;
- private String feedTitle;
- private MediaType mediaType = MediaType.AUDIO;
- private List<Chapter> chapters;
- private int duration;
- private int position;
-
- public ExternalMedia(String source, MediaType mediaType) {
- super();
- this.source = source;
- this.mediaType = mediaType;
- }
-
- public ExternalMedia(String source, MediaType mediaType, int position) {
- this(source, mediaType);
- this.position = position;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(source);
- dest.writeString(mediaType.toString());
- dest.writeInt(position);
- }
-
- @Override
- public void writeToPreferences(Editor prefEditor) {
- prefEditor.putString(PREF_SOURCE_URL, source);
- prefEditor.putString(PREF_MEDIA_TYPE, mediaType.toString());
- prefEditor.putInt(PREF_POSITION, position);
- }
-
- @Override
- public void loadMetadata() throws PlayableException {
- MediaMetadataRetriever mmr = new MediaMetadataRetriever();
- try {
- mmr.setDataSource(source);
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- throw new PlayableException(
- "IllegalArgumentException when setting up MediaMetadataReceiver");
- } catch (RuntimeException e) {
- // http://code.google.com/p/android/issues/detail?id=39770
- e.printStackTrace();
- throw new PlayableException(
- "RuntimeException when setting up MediaMetadataRetriever");
- }
- episodeTitle = mmr
- .extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
- feedTitle = mmr
- .extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
- try {
- duration = Integer.parseInt(mmr
- .extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));
- } catch (NumberFormatException e) {
- e.printStackTrace();
- throw new PlayableException("NumberFormatException when reading duration of media file");
- }
- ChapterUtils.loadChaptersFromFileUrl(this);
- }
-
- @Override
- public void loadChapterMarks() {
-
- }
-
- @Override
- public String getEpisodeTitle() {
- return episodeTitle;
- }
-
- @Override
- public Callable<String> loadShownotes() {
- return new Callable<String>() {
- @Override
- public String call() throws Exception {
- return "";
- }
- };
- }
-
- @Override
- public List<Chapter> getChapters() {
- return chapters;
- }
-
- @Override
- public String getWebsiteLink() {
- return null;
- }
-
- @Override
- public String getPaymentLink() {
- return null;
- }
-
- @Override
- public String getFeedTitle() {
- return feedTitle;
- }
-
- @Override
- public Object getIdentifier() {
- return source;
- }
-
- @Override
- public int getDuration() {
- return duration;
- }
-
- @Override
- public int getPosition() {
- return position;
- }
-
- @Override
- public MediaType getMediaType() {
- return mediaType;
- }
-
- @Override
- public String getLocalMediaUrl() {
- return source;
- }
-
- @Override
- public String getStreamUrl() {
- return null;
- }
-
- @Override
- public boolean localFileAvailable() {
- return true;
- }
-
- @Override
- public boolean streamAvailable() {
- return false;
- }
-
- @Override
- public void saveCurrentPosition(SharedPreferences pref, int newPosition) {
- SharedPreferences.Editor editor = pref.edit();
- editor.putInt(PREF_POSITION, newPosition);
- position = newPosition;
- editor.commit();
- }
-
- @Override
- public void setPosition(int newPosition) {
- position = newPosition;
- }
-
- @Override
- public void setDuration(int newDuration) {
- duration = newDuration;
- }
-
- @Override
- public void onPlaybackStart() {
-
- }
-
- @Override
- public void onPlaybackCompleted() {
-
- }
-
- @Override
- public int getPlayableType() {
- return PLAYABLE_TYPE_EXTERNAL_MEDIA;
- }
-
- @Override
- public void setChapters(List<Chapter> chapters) {
- this.chapters = chapters;
- }
-
- public static final Parcelable.Creator<ExternalMedia> CREATOR = new Parcelable.Creator<ExternalMedia>() {
- public ExternalMedia createFromParcel(Parcel in) {
- String source = in.readString();
- MediaType type = MediaType.valueOf(in.readString());
- int position = 0;
- if (in.dataAvail() > 0) {
- position = in.readInt();
- }
- ExternalMedia extMedia = new ExternalMedia(source, type, position);
- return extMedia;
- }
-
- public ExternalMedia[] newArray(int size) {
- return new ExternalMedia[size];
- }
- };
-
- @Override
- public Uri getImageUri() {
- if (localFileAvailable()) {
- return new Uri.Builder().scheme(SCHEME_MEDIA).encodedPath(getLocalMediaUrl()).build();
- } else {
- return null;
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/util/playback/IPlayer.java b/src/de/danoeh/antennapod/util/playback/IPlayer.java
deleted file mode 100644
index 2d4551b13..000000000
--- a/src/de/danoeh/antennapod/util/playback/IPlayer.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package de.danoeh.antennapod.util.playback;
-
-import android.content.Context;
-import android.view.SurfaceHolder;
-
-import java.io.IOException;
-
-public interface IPlayer {
- boolean canSetPitch();
-
- boolean canSetSpeed();
-
- float getCurrentPitchStepsAdjustment();
-
- int getCurrentPosition();
-
- float getCurrentSpeedMultiplier();
-
- int getDuration();
-
- float getMaxSpeedMultiplier();
-
- float getMinSpeedMultiplier();
-
- boolean isLooping();
-
- boolean isPlaying();
-
- void pause();
-
- void prepare() throws IllegalStateException, IOException;
-
- void prepareAsync();
-
- void release();
-
- void reset();
-
- void seekTo(int msec);
-
- void setAudioStreamType(int streamtype);
-
- void setScreenOnWhilePlaying(boolean screenOn);
-
- void setDataSource(String path) throws IllegalStateException, IOException,
- IllegalArgumentException, SecurityException;
-
- void setDisplay(SurfaceHolder sh);
-
- void setEnableSpeedAdjustment(boolean enableSpeedAdjustment);
-
- void setLooping(boolean looping);
-
- void setPitchStepsAdjustment(float pitchSteps);
-
- void setPlaybackPitch(float f);
-
- void setPlaybackSpeed(float f);
-
- void setVolume(float left, float right);
-
- void start();
-
- void stop();
-
- public void setVideoScalingMode(int mode);
-
- public void setWakeMode(Context context, int mode);
-}
diff --git a/src/de/danoeh/antennapod/util/playback/MediaPlayerError.java b/src/de/danoeh/antennapod/util/playback/MediaPlayerError.java
deleted file mode 100644
index 23ead581f..000000000
--- a/src/de/danoeh/antennapod/util/playback/MediaPlayerError.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package de.danoeh.antennapod.util.playback;
-
-import android.content.Context;
-import android.media.MediaPlayer;
-import de.danoeh.antennapod.R;
-
-/** Utility class for MediaPlayer errors. */
-public class MediaPlayerError {
-
- /** Get a human-readable string for a specific error code. */
- public static String getErrorString(Context context, int code) {
- int resId;
- switch(code) {
- case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
- resId = R.string.playback_error_server_died;
- break;
- default:
- resId = R.string.playback_error_unknown;
- break;
- }
- return context.getString(resId);
- }
-}
diff --git a/src/de/danoeh/antennapod/util/playback/Playable.java b/src/de/danoeh/antennapod/util/playback/Playable.java
deleted file mode 100644
index 004ae56bb..000000000
--- a/src/de/danoeh/antennapod/util/playback/Playable.java
+++ /dev/null
@@ -1,207 +0,0 @@
-package de.danoeh.antennapod.util.playback;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.os.Parcelable;
-import android.util.Log;
-
-import java.util.List;
-
-import de.danoeh.antennapod.asynctask.PicassoImageResource;
-import de.danoeh.antennapod.feed.Chapter;
-import de.danoeh.antennapod.feed.FeedMedia;
-import de.danoeh.antennapod.feed.MediaType;
-import de.danoeh.antennapod.storage.DBReader;
-import de.danoeh.antennapod.util.ShownotesProvider;
-
-/**
- * Interface for objects that can be played by the PlaybackService.
- */
-public interface Playable extends Parcelable,
- ShownotesProvider, PicassoImageResource {
-
- /**
- * Save information about the playable in a preference so that it can be
- * restored later via PlayableUtils.createInstanceFromPreferences.
- * Implementations must NOT call commit() after they have written the values
- * to the preferences file.
- */
- public void writeToPreferences(SharedPreferences.Editor prefEditor);
-
- /**
- * This method is called from a separate thread by the PlaybackService.
- * Playable objects should load their metadata in this method. This method
- * should execute as quickly as possible and NOT load chapter marks if no
- * local file is available.
- */
- public void loadMetadata() throws PlayableException;
-
- /**
- * This method is called from a separate thread by the PlaybackService.
- * Playable objects should load their chapter marks in this method if no
- * local file was available when loadMetadata() was called.
- */
- public void loadChapterMarks();
-
- /**
- * Returns the title of the episode that this playable represents
- */
- public String getEpisodeTitle();
-
- /**
- * Returns a list of chapter marks or null if this Playable has no chapters.
- */
- public List<Chapter> getChapters();
-
- /**
- * Returns a link to a website that is meant to be shown in a browser
- */
- public String getWebsiteLink();
-
- public String getPaymentLink();
-
- /**
- * Returns the title of the feed this Playable belongs to.
- */
- public String getFeedTitle();
-
- /**
- * Returns a unique identifier, for example a file url or an ID from a
- * database.
- */
- public Object getIdentifier();
-
- /**
- * Return duration of object or 0 if duration is unknown.
- */
- public int getDuration();
-
- /**
- * Return position of object or 0 if position is unknown.
- */
- public int getPosition();
-
- /**
- * Returns the type of media. This method should return the correct value
- * BEFORE loadMetadata() is called.
- */
- public MediaType getMediaType();
-
- /**
- * Returns an url to a local file that can be played or null if this file
- * does not exist.
- */
- public String getLocalMediaUrl();
-
- /**
- * Returns an url to a file that can be streamed by the player or null if
- * this url is not known.
- */
- public String getStreamUrl();
-
- /**
- * Returns true if a local file that can be played is available. getFileUrl
- * MUST return a non-null string if this method returns true.
- */
- public boolean localFileAvailable();
-
- /**
- * Returns true if a streamable file is available. getStreamUrl MUST return
- * a non-null string if this method returns true.
- */
- public boolean streamAvailable();
-
- /**
- * Saves the current position of this object. Implementations can use the
- * provided SharedPreference to save this information and retrieve it later
- * via PlayableUtils.createInstanceFromPreferences.
- */
- public void saveCurrentPosition(SharedPreferences pref, int newPosition);
-
- public void setPosition(int newPosition);
-
- public void setDuration(int newDuration);
-
- /**
- * Is called by the PlaybackService when playback starts.
- */
- public void onPlaybackStart();
-
- /**
- * Is called by the PlaybackService when playback is completed.
- */
- public void onPlaybackCompleted();
-
- /**
- * Returns an integer that must be unique among all Playable classes. The
- * return value is later used by PlayableUtils to determine the type of the
- * Playable object that is restored.
- */
- public int getPlayableType();
-
- public void setChapters(List<Chapter> chapters);
-
- /**
- * Provides utility methods for Playable objects.
- */
- public static class PlayableUtils {
- private static final String TAG = "PlayableUtils";
-
- /**
- * Restores a playable object from a sharedPreferences file. This method might load data from the database,
- * depending on the type of playable that was restored.
- *
- * @param type An integer that represents the type of the Playable object
- * that is restored.
- * @param pref The SharedPreferences file from which the Playable object
- * is restored
- * @return The restored Playable object
- */
- public static Playable createInstanceFromPreferences(Context context, int type,
- SharedPreferences pref) {
- // ADD new Playable types here:
- switch (type) {
- case FeedMedia.PLAYABLE_TYPE_FEEDMEDIA:
- long mediaId = pref.getLong(FeedMedia.PREF_MEDIA_ID, -1);
- if (mediaId != -1) {
- return DBReader.getFeedMedia(context, mediaId);
- }
- break;
- case ExternalMedia.PLAYABLE_TYPE_EXTERNAL_MEDIA:
- String source = pref.getString(ExternalMedia.PREF_SOURCE_URL,
- null);
- String mediaType = pref.getString(
- ExternalMedia.PREF_MEDIA_TYPE, null);
- if (source != null && mediaType != null) {
- int position = pref.getInt(ExternalMedia.PREF_POSITION, 0);
- return new ExternalMedia(source,
- MediaType.valueOf(mediaType), position);
- }
- break;
- }
- Log.e(TAG, "Could not restore Playable object from preferences");
- return null;
- }
- }
-
- public static class PlayableException extends Exception {
- private static final long serialVersionUID = 1L;
-
- public PlayableException() {
- super();
- }
-
- public PlayableException(String detailMessage, Throwable throwable) {
- super(detailMessage, throwable);
- }
-
- public PlayableException(String detailMessage) {
- super(detailMessage);
- }
-
- public PlayableException(Throwable throwable) {
- super(throwable);
- }
-
- }
-}
diff --git a/src/de/danoeh/antennapod/util/playback/PlaybackController.java b/src/de/danoeh/antennapod/util/playback/PlaybackController.java
deleted file mode 100644
index 64dbf4868..000000000
--- a/src/de/danoeh/antennapod/util/playback/PlaybackController.java
+++ /dev/null
@@ -1,784 +0,0 @@
-package de.danoeh.antennapod.util.playback;
-
-import android.app.Activity;
-import android.content.*;
-import android.content.res.TypedArray;
-import android.media.MediaPlayer;
-import android.os.AsyncTask;
-import android.os.IBinder;
-import android.preference.PreferenceManager;
-import android.util.Log;
-import android.util.Pair;
-import android.view.SurfaceHolder;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.ImageButton;
-import android.widget.SeekBar;
-import android.widget.TextView;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.Validate;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.feed.Chapter;
-import de.danoeh.antennapod.feed.FeedMedia;
-import de.danoeh.antennapod.feed.MediaType;
-import de.danoeh.antennapod.preferences.PlaybackPreferences;
-import de.danoeh.antennapod.preferences.UserPreferences;
-import de.danoeh.antennapod.service.playback.PlaybackService;
-import de.danoeh.antennapod.service.playback.PlaybackServiceMediaPlayer;
-import de.danoeh.antennapod.service.playback.PlayerStatus;
-import de.danoeh.antennapod.storage.DBTasks;
-import de.danoeh.antennapod.util.Converter;
-import de.danoeh.antennapod.util.playback.Playable.PlayableUtils;
-
-import java.util.concurrent.*;
-
-/**
- * Communicates with the playback service. GUI classes should use this class to
- * control playback instead of communicating with the PlaybackService directly.
- */
-public abstract class PlaybackController {
- private static final String TAG = "PlaybackController";
-
- public static final int INVALID_TIME = -1;
-
- private final Activity activity;
-
- private PlaybackService playbackService;
- private Playable media;
- private PlayerStatus status;
-
- private ScheduledThreadPoolExecutor schedExecutor;
- private static final int SCHED_EX_POOLSIZE = 1;
-
- protected MediaPositionObserver positionObserver;
- protected ScheduledFuture positionObserverFuture;
-
- private boolean mediaInfoLoaded = false;
- private boolean released = false;
-
- /**
- * True if controller should reinit playback service if 'pause' button is
- * pressed.
- */
- private boolean reinitOnPause;
-
- public PlaybackController(Activity activity, boolean reinitOnPause) {
- Validate.notNull(activity);
-
- this.activity = activity;
- this.reinitOnPause = reinitOnPause;
- schedExecutor = new ScheduledThreadPoolExecutor(SCHED_EX_POOLSIZE,
- new ThreadFactory() {
-
- @Override
- public Thread newThread(Runnable r) {
- Thread t = new Thread(r);
- t.setPriority(Thread.MIN_PRIORITY);
- return t;
- }
- }, new RejectedExecutionHandler() {
-
- @Override
- public void rejectedExecution(Runnable r,
- ThreadPoolExecutor executor) {
- Log.w(TAG,
- "Rejected execution of runnable in schedExecutor");
- }
- }
- );
- }
-
- /**
- * Creates a new connection to the playbackService. Should be called in the
- * activity's onResume() method.
- */
- public void init() {
- activity.registerReceiver(statusUpdate, new IntentFilter(
- PlaybackService.ACTION_PLAYER_STATUS_CHANGED));
-
- activity.registerReceiver(notificationReceiver, new IntentFilter(
- PlaybackService.ACTION_PLAYER_NOTIFICATION));
-
- activity.registerReceiver(shutdownReceiver, new IntentFilter(
- PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE));
-
- if (!released) {
- bindToService();
- } else {
- throw new IllegalStateException(
- "Can't call init() after release() has been called");
- }
- }
-
- /**
- * Should be called if the PlaybackController is no longer needed, for
- * example in the activity's onStop() method.
- */
- public void release() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Releasing PlaybackController");
-
- try {
- activity.unregisterReceiver(statusUpdate);
- } catch (IllegalArgumentException e) {
- // ignore
- }
-
- try {
- activity.unregisterReceiver(notificationReceiver);
- } catch (IllegalArgumentException e) {
- // ignore
- }
-
- try {
- activity.unbindService(mConnection);
- } catch (IllegalArgumentException e) {
- // ignore
- }
-
- try {
- activity.unregisterReceiver(shutdownReceiver);
- } catch (IllegalArgumentException e) {
- // ignore
- }
- cancelPositionObserver();
- schedExecutor.shutdownNow();
- media = null;
- released = true;
-
- }
-
- /**
- * Should be called in the activity's onPause() method.
- */
- public void pause() {
- mediaInfoLoaded = false;
- }
-
- /**
- * Tries to establish a connection to the PlaybackService. If it isn't
- * running, the PlaybackService will be started with the last played media
- * as the arguments of the launch intent.
- */
- private void bindToService() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Trying to connect to service");
- AsyncTask<Void, Void, Intent> intentLoader = new AsyncTask<Void, Void, Intent>() {
- @Override
- protected Intent doInBackground(Void... voids) {
- return getPlayLastPlayedMediaIntent();
- }
-
- @Override
- protected void onPostExecute(Intent serviceIntent) {
- boolean bound = false;
- if (!PlaybackService.started) {
- if (serviceIntent != null) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Calling start service");
- activity.startService(serviceIntent);
- bound = activity.bindService(serviceIntent, mConnection, 0);
- } else {
- status = PlayerStatus.STOPPED;
- setupGUI();
- handleStatus();
- }
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "PlaybackService is running, trying to connect without start command.");
- bound = activity.bindService(new Intent(activity,
- PlaybackService.class), mConnection, 0);
- }
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Result for service binding: " + bound);
- }
- };
- intentLoader.execute();
- }
-
- /**
- * Returns an intent that starts the PlaybackService and plays the last
- * played media or null if no last played media could be found.
- */
- private Intent getPlayLastPlayedMediaIntent() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Trying to restore last played media");
- SharedPreferences prefs = PreferenceManager
- .getDefaultSharedPreferences(activity.getApplicationContext());
- long currentlyPlayingMedia = PlaybackPreferences
- .getCurrentlyPlayingMedia();
- if (currentlyPlayingMedia != PlaybackPreferences.NO_MEDIA_PLAYING) {
- Playable media = PlayableUtils.createInstanceFromPreferences(activity,
- (int) currentlyPlayingMedia, prefs);
- if (media != null) {
- Intent serviceIntent = new Intent(activity,
- PlaybackService.class);
- serviceIntent.putExtra(PlaybackService.EXTRA_PLAYABLE, media);
- serviceIntent.putExtra(
- PlaybackService.EXTRA_START_WHEN_PREPARED, false);
- serviceIntent.putExtra(
- PlaybackService.EXTRA_PREPARE_IMMEDIATELY, false);
- boolean fileExists = media.localFileAvailable();
- boolean lastIsStream = PlaybackPreferences
- .getCurrentEpisodeIsStream();
- if (!fileExists && !lastIsStream && media instanceof FeedMedia) {
- DBTasks.notifyMissingFeedMediaFile(
- activity, (FeedMedia) media);
- }
- serviceIntent.putExtra(PlaybackService.EXTRA_SHOULD_STREAM,
- lastIsStream || !fileExists);
- return serviceIntent;
- }
- }
- if (BuildConfig.DEBUG)
- Log.d(TAG, "No last played media found");
- return null;
- }
-
- public abstract void setupGUI();
-
- private void setupPositionObserver() {
- if ((positionObserverFuture != null && positionObserverFuture
- .isCancelled())
- || (positionObserverFuture != null && positionObserverFuture
- .isDone()) || positionObserverFuture == null) {
-
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Setting up position observer");
- positionObserver = new MediaPositionObserver();
- positionObserverFuture = schedExecutor.scheduleWithFixedDelay(
- positionObserver, MediaPositionObserver.WAITING_INTERVALL,
- MediaPositionObserver.WAITING_INTERVALL,
- TimeUnit.MILLISECONDS);
- }
- }
-
- private void cancelPositionObserver() {
- if (positionObserverFuture != null) {
- boolean result = positionObserverFuture.cancel(true);
- if (BuildConfig.DEBUG)
- Log.d(TAG, "PositionObserver cancelled. Result: " + result);
- }
- }
-
- public abstract void onPositionObserverUpdate();
-
- private ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- playbackService = ((PlaybackService.LocalBinder) service)
- .getService();
- if (!released) {
- queryService();
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Connection to Service established");
- } else {
- Log.i(TAG, "Connection to playback service has been established, but controller has already been released");
- }
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- playbackService = null;
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Disconnected from Service");
-
- }
- };
-
- protected BroadcastReceiver statusUpdate = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Received statusUpdate Intent.");
- if (isConnectedToPlaybackService()) {
- PlaybackServiceMediaPlayer.PSMPInfo info = playbackService.getPSMPInfo();
- status = info.playerStatus;
- media = info.playable;
- handleStatus();
- } else {
- Log.w(TAG,
- "Couldn't receive status update: playbackService was null");
- bindToService();
- }
- }
- };
-
- protected BroadcastReceiver notificationReceiver = new BroadcastReceiver() {
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (isConnectedToPlaybackService()) {
- int type = intent.getIntExtra(
- PlaybackService.EXTRA_NOTIFICATION_TYPE, -1);
- int code = intent.getIntExtra(
- PlaybackService.EXTRA_NOTIFICATION_CODE, -1);
- if (code != -1 && type != -1) {
- switch (type) {
- case PlaybackService.NOTIFICATION_TYPE_ERROR:
- handleError(code);
- break;
- case PlaybackService.NOTIFICATION_TYPE_BUFFER_UPDATE:
- float progress = ((float) code) / 100;
- onBufferUpdate(progress);
- break;
- case PlaybackService.NOTIFICATION_TYPE_RELOAD:
- cancelPositionObserver();
- mediaInfoLoaded = false;
- queryService();
- onReloadNotification(intent.getIntExtra(
- PlaybackService.EXTRA_NOTIFICATION_CODE, -1));
- break;
- case PlaybackService.NOTIFICATION_TYPE_SLEEPTIMER_UPDATE:
- onSleepTimerUpdate();
- break;
- case PlaybackService.NOTIFICATION_TYPE_BUFFER_START:
- onBufferStart();
- break;
- case PlaybackService.NOTIFICATION_TYPE_BUFFER_END:
- onBufferEnd();
- break;
- case PlaybackService.NOTIFICATION_TYPE_PLAYBACK_END:
- onPlaybackEnd();
- break;
- case PlaybackService.NOTIFICATION_TYPE_PLAYBACK_SPEED_CHANGE:
- onPlaybackSpeedChange();
- break;
- }
-
- } else {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Bad arguments. Won't handle intent");
- }
- } else {
- bindToService();
- }
- }
-
- };
-
- private BroadcastReceiver shutdownReceiver = new BroadcastReceiver() {
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (isConnectedToPlaybackService()) {
- if (StringUtils.equals(intent.getAction(),
- PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE)) {
- release();
- onShutdownNotification();
- }
- }
- }
- };
-
- public abstract void onPlaybackSpeedChange();
-
- public abstract void onShutdownNotification();
-
- /**
- * Called when the currently displayed information should be refreshed.
- */
- public abstract void onReloadNotification(int code);
-
- public abstract void onBufferStart();
-
- public abstract void onBufferEnd();
-
- public abstract void onBufferUpdate(float progress);
-
- 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
- * should be used to update the GUI or start/cancel background threads.
- */
- private void handleStatus() {
- final int playResource;
- final int pauseResource;
- final CharSequence playText = activity.getString(R.string.play_label);
- final CharSequence pauseText = activity.getString(R.string.pause_label);
-
- if (PlaybackService.getCurrentMediaType() == MediaType.AUDIO) {
- TypedArray res = activity.obtainStyledAttributes(new int[]{
- R.attr.av_play, R.attr.av_pause});
- playResource = res.getResourceId(0, R.drawable.av_play);
- pauseResource = res.getResourceId(1, R.drawable.av_pause);
- res.recycle();
- } else {
- playResource = R.drawable.ic_action_play_over_video;
- pauseResource = R.drawable.ic_action_pause_over_video;
- }
-
- switch (status) {
-
- case ERROR:
- postStatusMsg(R.string.player_error_msg);
- handleError(MediaPlayer.MEDIA_ERROR_UNKNOWN);
- break;
- case PAUSED:
- clearStatusMsg();
- checkMediaInfoLoaded();
- cancelPositionObserver();
- updatePlayButtonAppearance(playResource, playText);
- if (PlaybackService.getCurrentMediaType() == MediaType.VIDEO) {
- setScreenOn(false);
- }
- break;
- case PLAYING:
- clearStatusMsg();
- checkMediaInfoLoaded();
- if (PlaybackService.getCurrentMediaType() == MediaType.VIDEO) {
- onAwaitingVideoSurface();
- setScreenOn(true);
- }
- setupPositionObserver();
- updatePlayButtonAppearance(pauseResource, pauseText);
- break;
- case PREPARING:
- postStatusMsg(R.string.player_preparing_msg);
- checkMediaInfoLoaded();
- if (playbackService != null) {
- if (playbackService.isStartWhenPrepared()) {
- updatePlayButtonAppearance(pauseResource, pauseText);
- } else {
- updatePlayButtonAppearance(playResource, playText);
- }
- }
- break;
- case STOPPED:
- postStatusMsg(R.string.player_stopped_msg);
- break;
- case PREPARED:
- checkMediaInfoLoaded();
- postStatusMsg(R.string.player_ready_msg);
- updatePlayButtonAppearance(playResource, playText);
- break;
- case SEEKING:
- postStatusMsg(R.string.player_seeking_msg);
- break;
- case INITIALIZED:
- checkMediaInfoLoaded();
- clearStatusMsg();
- updatePlayButtonAppearance(playResource, playText);
- break;
- }
- }
-
- private void checkMediaInfoLoaded() {
- mediaInfoLoaded = (mediaInfoLoaded || loadMediaInfo());
- }
-
- private void updatePlayButtonAppearance(int resource, CharSequence contentDescription) {
- ImageButton butPlay = getPlayButton();
- butPlay.setImageResource(resource);
- butPlay.setContentDescription(contentDescription);
- }
-
- public abstract ImageButton getPlayButton();
-
- public abstract void postStatusMsg(int msg);
-
- public abstract void clearStatusMsg();
-
- public abstract boolean loadMediaInfo();
-
- public abstract void onAwaitingVideoSurface();
-
- /**
- * Called when connection to playback service has been established or
- * information has to be refreshed
- */
- void queryService() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Querying service info");
- if (playbackService != null) {
- status = playbackService.getStatus();
- media = playbackService.getPlayable();
- /*
- if (media == null) {
- Log.w(TAG,
- "PlaybackService has no media object. Trying to restore last played media.");
- Intent serviceIntent = getPlayLastPlayedMediaIntent();
- if (serviceIntent != null) {
- activity.startService(serviceIntent);
- }
- }
- */
- onServiceQueried();
-
- setupGUI();
- handleStatus();
- // make sure that new media is loaded if it's available
- mediaInfoLoaded = false;
-
- } else {
- Log.e(TAG,
- "queryService() was called without an existing connection to playbackservice");
- }
- }
-
- public abstract void onServiceQueried();
-
- /**
- * Should be used by classes which implement the OnSeekBarChanged interface.
- */
- public float onSeekBarProgressChanged(SeekBar seekBar, int progress,
- boolean fromUser, TextView txtvPosition) {
- if (fromUser && playbackService != null && media != null) {
- float prog = progress / ((float) seekBar.getMax());
- int duration = media.getDuration();
- txtvPosition.setText(Converter
- .getDurationStringLong((int) (prog * duration)));
- return prog;
- }
- return 0;
-
- }
-
- /**
- * Should be used by classes which implement the OnSeekBarChanged interface.
- */
- public void onSeekBarStartTrackingTouch(SeekBar seekBar) {
- // interrupt position Observer, restart later
- cancelPositionObserver();
- }
-
- /**
- * Should be used by classes which implement the OnSeekBarChanged interface.
- */
- public void onSeekBarStopTrackingTouch(SeekBar seekBar, float prog) {
- if (playbackService != null) {
- playbackService.seekTo((int) (prog * media.getDuration()));
- setupPositionObserver();
- }
- }
-
- /**
- * Should be implemented by classes that show a video. The default implementation
- * does nothing
- *
- * @param enable True if the screen should be kept on, false otherwise
- */
- protected void setScreenOn(boolean enable) {
-
- }
-
- public OnClickListener newOnPlayButtonClickListener() {
- return new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (playbackService != null) {
- switch (status) {
- case PLAYING:
- playbackService.pause(true, reinitOnPause);
- break;
- case PAUSED:
- case PREPARED:
- playbackService.resume();
- break;
- case PREPARING:
- playbackService.setStartWhenPrepared(!playbackService
- .isStartWhenPrepared());
- if (reinitOnPause
- && playbackService.isStartWhenPrepared() == false) {
- playbackService.reinit();
- }
- break;
- case INITIALIZED:
- playbackService.setStartWhenPrepared(true);
- playbackService.prepare();
- break;
- }
- } else {
- Log.w(TAG,
- "Play/Pause button was pressed, but playbackservice was null!");
- }
- }
-
- };
- }
-
- public OnClickListener newOnRevButtonClickListener() {
- return new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (status == PlayerStatus.PLAYING) {
- playbackService.seekDelta(-UserPreferences.getSeekDeltaMs());
- }
- }
- };
- }
-
- public OnClickListener newOnFFButtonClickListener() {
- return new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (status == PlayerStatus.PLAYING) {
- playbackService.seekDelta(UserPreferences.getSeekDeltaMs());
- }
- }
- };
- }
-
- public boolean serviceAvailable() {
- return playbackService != null;
- }
-
- public int getPosition() {
- if (playbackService != null) {
- return playbackService.getCurrentPosition();
- } else {
- return PlaybackService.INVALID_TIME;
- }
- }
-
- public int getDuration() {
- if (playbackService != null) {
- return playbackService.getDuration();
- } else {
- return PlaybackService.INVALID_TIME;
- }
- }
-
- public Playable getMedia() {
- return media;
- }
-
- public boolean sleepTimerActive() {
- return playbackService != null && playbackService.sleepTimerActive();
- }
-
- public boolean sleepTimerNotActive() {
- return playbackService != null && !playbackService.sleepTimerActive();
- }
-
- public void disableSleepTimer() {
- if (playbackService != null) {
- playbackService.disableSleepTimer();
- }
- }
-
- public long getSleepTimerTimeLeft() {
- if (playbackService != null) {
- return playbackService.getSleepTimerTimeLeft();
- } else {
- return INVALID_TIME;
- }
- }
-
- public void setSleepTimer(long time) {
- if (playbackService != null) {
- playbackService.setSleepTimer(time);
- }
- }
-
- public void seekToChapter(Chapter chapter) {
- if (playbackService != null) {
- playbackService.seekToChapter(chapter);
- }
- }
-
- public void seekTo(int time) {
- if (playbackService != null) {
- playbackService.seekTo(time);
- }
- }
-
- public void setVideoSurface(SurfaceHolder holder) {
- if (playbackService != null) {
- playbackService.setVideoSurface(holder);
- }
- }
-
- public PlayerStatus getStatus() {
- return status;
- }
-
- public boolean canSetPlaybackSpeed() {
- return playbackService != null && playbackService.canSetSpeed();
- }
-
- public void setPlaybackSpeed(float speed) {
- if (playbackService != null) {
- playbackService.setSpeed(speed);
- }
- }
-
- public float getCurrentPlaybackSpeedMultiplier() {
- if (canSetPlaybackSpeed()) {
- return playbackService.getCurrentPlaybackSpeed();
- } else {
- return -1;
- }
- }
-
- public boolean isPlayingVideo() {
- if (playbackService != null) {
- return PlaybackService.getCurrentMediaType() == MediaType.VIDEO;
- }
- return false;
- }
-
- public Pair<Integer, Integer> getVideoSize() {
- if (playbackService != null) {
- return playbackService.getVideoSize();
- } else {
- return null;
- }
- }
-
-
- /**
- * Returns true if PlaybackController can communicate with the playback
- * service.
- */
- public boolean isConnectedToPlaybackService() {
- return playbackService != null;
- }
-
- public void notifyVideoSurfaceAbandoned() {
- if (playbackService != null) {
- playbackService.notifyVideoSurfaceAbandoned();
- }
- }
-
- /**
- * Move service into INITIALIZED state if it's paused to save bandwidth
- */
- public void reinitServiceIfPaused() {
- if (playbackService != null
- && playbackService.isStreaming()
- && (playbackService.getStatus() == PlayerStatus.PAUSED || (playbackService
- .getStatus() == PlayerStatus.PREPARING && playbackService
- .isStartWhenPrepared() == false))) {
- playbackService.reinit();
- }
- }
-
- /**
- * Refreshes the current position of the media file that is playing.
- */
- public class MediaPositionObserver implements Runnable {
-
- public static final int WAITING_INTERVALL = 1000;
-
- @Override
- public void run() {
- if (playbackService != null && playbackService.getStatus() == PlayerStatus.PLAYING) {
- activity.runOnUiThread(new Runnable() {
-
- @Override
- public void run() {
- onPositionObserverUpdate();
- }
- });
- }
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/util/playback/Timeline.java b/src/de/danoeh/antennapod/util/playback/Timeline.java
deleted file mode 100644
index ceed68183..000000000
--- a/src/de/danoeh/antennapod/util/playback/Timeline.java
+++ /dev/null
@@ -1,161 +0,0 @@
-package de.danoeh.antennapod.util.playback;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.Log;
-import android.util.TypedValue;
-
-import org.apache.commons.lang3.Validate;
-import org.jsoup.Jsoup;
-import org.jsoup.nodes.Document;
-import org.jsoup.nodes.Element;
-import org.jsoup.select.Elements;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.util.Converter;
-import de.danoeh.antennapod.util.ShownotesProvider;
-
-/**
- * Connects chapter information and shownotes of a shownotesProvider, for example by making it possible to use the
- * shownotes to navigate to another position in the podcast or by highlighting certain parts of the shownotesProvider's
- * shownotes.
- * <p/>
- * A timeline object needs a shownotesProvider from which the chapter information is retrieved and shownotes are generated.
- */
-public class Timeline {
- private static final String TAG = "Timeline";
-
- private static final String WEBVIEW_STYLE = "@font-face { font-family: 'Roboto-Light'; src: url('file:///android_asset/Roboto-Light.ttf'); } * { color: %s; font-family: roboto-Light; font-size: 11pt; } a { font-style: normal; text-decoration: none; font-weight: normal; color: #00A8DF; } a.timecode { color: #669900; } img { display: block; margin: 10 auto; max-width: %s; height: auto; } body { margin: %dpx %dpx %dpx %dpx; }";
-
-
- private ShownotesProvider shownotesProvider;
-
-
- private final String colorString;
- private final int pageMargin;
-
- public Timeline(Context context, ShownotesProvider shownotesProvider) {
- if (shownotesProvider == null) throw new IllegalArgumentException("shownotesProvider = null");
- this.shownotesProvider = shownotesProvider;
-
- TypedArray res = context
- .getTheme()
- .obtainStyledAttributes(
- new int[]{android.R.attr.textColorPrimary});
- int colorResource = res.getColor(0, 0);
- colorString = String.format("#%06X",
- 0xFFFFFF & colorResource);
- res.recycle();
-
- pageMargin = (int) TypedValue.applyDimension(
- TypedValue.COMPLEX_UNIT_DIP, 8, context.getResources()
- .getDisplayMetrics()
- );
- }
-
- private static final Pattern TIMECODE_LINK_REGEX = Pattern.compile("antennapod://timecode/((\\d+))");
- private static final String TIMECODE_LINK = "<a class=\"timecode\" href=\"antennapod://timecode/%d\">%s</a>";
- private static final Pattern TIMECODE_REGEX = Pattern.compile("\\b(?:(?:(([0-9][0-9])):))?(([0-9][0-9])):(([0-9][0-9]))\\b");
-
- /**
- * Applies an app-specific CSS stylesheet and adds timecode links (optional).
- * <p/>
- * This method does NOT change the original shownotes string of the shownotesProvider object and it should
- * also not be changed by the caller.
- *
- * @param addTimecodes True if this method should add timecode links
- * @return The processed HTML string.
- */
- public String processShownotes(final boolean addTimecodes) {
- final Playable playable = (shownotesProvider instanceof Playable) ? (Playable) shownotesProvider : null;
-
- // load shownotes
-
- String shownotes;
- try {
- shownotes = shownotesProvider.loadShownotes().call();
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- if (shownotes == null) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "shownotesProvider contained no shownotes. Returning empty string");
- return "";
- }
-
- Document document = Jsoup.parse(shownotes);
-
- // apply style
- String styleStr = String.format(WEBVIEW_STYLE, colorString, "100%", pageMargin,
- pageMargin, pageMargin, pageMargin);
- document.head().appendElement("style").attr("type", "text/css").text(styleStr);
-
- // apply timecode links
- if (addTimecodes) {
- Elements elementsWithTimeCodes = document.body().getElementsMatchingOwnText(TIMECODE_REGEX);
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Recognized " + elementsWithTimeCodes.size() + " timecodes");
- for (Element element : elementsWithTimeCodes) {
- Matcher matcherLong = TIMECODE_REGEX.matcher(element.text());
- StringBuffer buffer = new StringBuffer();
- while (matcherLong.find()) {
- String h = matcherLong.group(1);
- String group = matcherLong.group(0);
- int time = (h != null) ? Converter.durationStringLongToMs(group) :
- Converter.durationStringShortToMs(group);
-
- String rep;
- if (playable == null || playable.getDuration() > time) {
- rep = String.format(TIMECODE_LINK, time, group);
- } else {
- rep = group;
- }
- matcherLong.appendReplacement(buffer, rep);
- }
- matcherLong.appendTail(buffer);
-
- element.html(buffer.toString());
- }
- }
-
- Log.i(TAG, "Out: " + document.toString());
- return document.toString();
- }
-
-
- /**
- * Returns true if the given link is a timecode link.
- */
- public static boolean isTimecodeLink(String link) {
- return link != null && link.matches(TIMECODE_LINK_REGEX.pattern());
- }
-
- /**
- * Returns the time in milliseconds that is attached to this link or -1
- * if the link is no valid timecode link.
- */
- public static int getTimecodeLinkTime(String link) {
- if (isTimecodeLink(link)) {
- Matcher m = TIMECODE_LINK_REGEX.matcher(link);
-
- try {
- if (m.find()) {
- return Integer.valueOf(m.group(1));
- }
- } catch (NumberFormatException e) {
- e.printStackTrace();
- }
- }
- return -1;
- }
-
-
- public void setShownotesProvider(ShownotesProvider shownotesProvider) {
- Validate.notNull(shownotesProvider);
- this.shownotesProvider = shownotesProvider;
- }
-}
diff --git a/src/de/danoeh/antennapod/util/playback/VideoPlayer.java b/src/de/danoeh/antennapod/util/playback/VideoPlayer.java
deleted file mode 100644
index ea9c692ab..000000000
--- a/src/de/danoeh/antennapod/util/playback/VideoPlayer.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package de.danoeh.antennapod.util.playback;
-
-import android.media.MediaPlayer;
-import android.util.Log;
-
-public class VideoPlayer extends MediaPlayer implements IPlayer {
- private static final String TAG = "VideoPlayer";
-
- @Override
- public boolean canSetPitch() {
- return false;
- }
-
- @Override
- public boolean canSetSpeed() {
- return false;
- }
-
- @Override
- public float getCurrentPitchStepsAdjustment() {
- return 1;
- }
-
- @Override
- public float getCurrentSpeedMultiplier() {
- return 1;
- }
-
- @Override
- public float getMaxSpeedMultiplier() {
- return 1;
- }
-
- @Override
- public float getMinSpeedMultiplier() {
- return 1;
- }
-
- @Override
- public void setEnableSpeedAdjustment(boolean enableSpeedAdjustment) throws UnsupportedOperationException {
- Log.e(TAG, "Setting enable speed adjustment unsupported in video player");
- throw new UnsupportedOperationException("Setting enable speed adjustment unsupported in video player");
- }
-
- @Override
- public void setPitchStepsAdjustment(float pitchSteps) {
- Log.e(TAG, "Setting pitch steps adjustment unsupported in video player");
- throw new UnsupportedOperationException("Setting pitch steps adjustment unsupported in video player");
- }
-
- @Override
- public void setPlaybackPitch(float f) {
- Log.e(TAG, "Setting playback pitch unsupported in video player");
- throw new UnsupportedOperationException("Setting playback pitch unsupported in video player");
- }
-
- @Override
- public void setPlaybackSpeed(float f) {
- Log.e(TAG, "Setting playback speed unsupported in video player");
- throw new UnsupportedOperationException("Setting playback speed unsupported in video player");
- }
-
- @Override
- public void setVideoScalingMode(int mode) {
- super.setVideoScalingMode(mode);
- }
-}
diff --git a/src/de/danoeh/antennapod/util/syndication/FeedDiscoverer.java b/src/de/danoeh/antennapod/util/syndication/FeedDiscoverer.java
deleted file mode 100644
index ac38ec876..000000000
--- a/src/de/danoeh/antennapod/util/syndication/FeedDiscoverer.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package de.danoeh.antennapod.util.syndication;
-
-import android.net.Uri;
-import org.apache.commons.lang3.StringUtils;
-import org.jsoup.Jsoup;
-import org.jsoup.nodes.Document;
-import org.jsoup.nodes.Element;
-import org.jsoup.select.Elements;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-/**
- * Finds RSS/Atom URLs in a HTML document using the auto-discovery techniques described here:
- * <p/>
- * http://www.rssboard.org/rss-autodiscovery
- * <p/>
- * http://blog.whatwg.org/feed-autodiscovery
- */
-public class FeedDiscoverer {
-
- private static final String MIME_RSS = "application/rss+xml";
- private static final String MIME_ATOM = "application/atom+xml";
-
- /**
- * Discovers links to RSS and Atom feeds in the given File which must be a HTML document.
- *
- * @return A map which contains the feed URLs as keys and titles as values (the feed URL is also used as a title if
- * a title cannot be found).
- */
- public Map<String, String> findLinks(File in, String baseUrl) throws IOException {
- return findLinks(Jsoup.parse(in, null), baseUrl);
- }
-
- /**
- * Discovers links to RSS and Atom feeds in the given File which must be a HTML document.
- *
- * @return A map which contains the feed URLs as keys and titles as values (the feed URL is also used as a title if
- * a title cannot be found).
- */
- public Map<String, String> findLinks(String in, String baseUrl) throws IOException {
- return findLinks(Jsoup.parse(in), baseUrl);
- }
-
- private Map<String, String> findLinks(Document document, String baseUrl) {
- Map<String, String> res = new LinkedHashMap<String, String>();
- Elements links = document.head().getElementsByTag("link");
- for (Element link : links) {
- String rel = link.attr("rel");
- String href = link.attr("href");
- if (!StringUtils.isEmpty(href) &&
- (rel.equals("alternate") || rel.equals("feed"))) {
- String type = link.attr("type");
- if (type.equals(MIME_RSS) || type.equals(MIME_ATOM)) {
- String title = link.attr("title");
- String processedUrl = processURL(baseUrl, href);
- if (processedUrl != null) {
- res.put(processedUrl,
- (StringUtils.isEmpty(title)) ? href : title);
- }
- }
- }
- }
- return res;
- }
-
- private String processURL(String baseUrl, String strUrl) {
- Uri uri = Uri.parse(strUrl);
- if (uri.isRelative()) {
- Uri res = Uri.parse(baseUrl).buildUpon().path(strUrl).build();
- return (res != null) ? res.toString() : null;
- } else {
- return strUrl;
- }
- }
-}
diff --git a/src/de/danoeh/antennapod/util/vorbiscommentreader/OggInputStream.java b/src/de/danoeh/antennapod/util/vorbiscommentreader/OggInputStream.java
deleted file mode 100644
index 767034ed2..000000000
--- a/src/de/danoeh/antennapod/util/vorbiscommentreader/OggInputStream.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package de.danoeh.antennapod.util.vorbiscommentreader;
-
-import org.apache.commons.io.IOUtils;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Arrays;
-
-public class OggInputStream extends InputStream {
- private InputStream input;
-
- /** True if OggInputStream is currently inside an Ogg page. */
- private boolean isInPage;
- private long bytesLeft;
-
- public OggInputStream(InputStream input) {
- super();
- isInPage = false;
- this.input = input;
- }
-
- @Override
- public int read() throws IOException {
- if (!isInPage) {
- readOggPage();
- }
-
- if (isInPage && bytesLeft > 0) {
- int result = input.read();
- bytesLeft -= 1;
- if (bytesLeft == 0) {
- isInPage = false;
- }
- return result;
- }
- return -1;
- }
-
- private void readOggPage() throws IOException {
- // find OggS
- int[] buffer = new int[4];
- int c = 0;
- boolean isInOggS = false;
- while ((c = input.read()) != -1) {
- switch (c) {
- case 'O':
- isInOggS = true;
- buffer[0] = c;
- break;
- case 'g':
- if (buffer[1] != c) {
- buffer[1] = c;
- } else {
- buffer[2] = c;
- }
- break;
- case 'S':
- buffer[3] = c;
- break;
- default:
- if (isInOggS) {
- Arrays.fill(buffer, 0);
- isInOggS = false;
- }
- }
- if (buffer[0] == 'O' && buffer[1] == 'g' && buffer[2] == 'g'
- && buffer[3] == 'S') {
- break;
- }
- }
- // read segments
- IOUtils.skipFully(input, 22);
- bytesLeft = 0;
- int numSegments = input.read();
- for (int i = 0; i < numSegments; i++) {
- bytesLeft += input.read();
- }
- isInPage = true;
- }
-
-}
diff --git a/src/de/danoeh/antennapod/util/vorbiscommentreader/VorbisCommentChapterReader.java b/src/de/danoeh/antennapod/util/vorbiscommentreader/VorbisCommentChapterReader.java
deleted file mode 100644
index b2f149ddd..000000000
--- a/src/de/danoeh/antennapod/util/vorbiscommentreader/VorbisCommentChapterReader.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package de.danoeh.antennapod.util.vorbiscommentreader;
-
-import android.util.Log;
-import de.danoeh.antennapod.BuildConfig;
-import de.danoeh.antennapod.feed.Chapter;
-import de.danoeh.antennapod.feed.VorbisCommentChapter;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class VorbisCommentChapterReader extends VorbisCommentReader {
- private static final String TAG = "VorbisCommentChapterReader";
-
- private static final String CHAPTER_KEY = "chapter\\d\\d\\d.*";
- private static final String CHAPTER_ATTRIBUTE_TITLE = "name";
- private static final String CHAPTER_ATTRIBUTE_LINK = "url";
-
- private List<Chapter> chapters;
-
- public VorbisCommentChapterReader() {
- }
-
- @Override
- public void onVorbisCommentFound() {
- System.out.println("Vorbis comment found");
- }
-
- @Override
- public void onVorbisCommentHeaderFound(VorbisCommentHeader header) {
- chapters = new ArrayList<Chapter>();
- System.out.println(header.toString());
- }
-
- @Override
- public boolean onContentVectorKey(String content) {
- return content.matches(CHAPTER_KEY);
- }
-
- @Override
- public void onContentVectorValue(String key, String value)
- throws VorbisCommentReaderException {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Key: " + key + ", value: " + value);
- String attribute = VorbisCommentChapter.getAttributeTypeFromKey(key);
- int id = VorbisCommentChapter.getIDFromKey(key);
- Chapter chapter = getChapterById(id);
- if (attribute == null) {
- if (getChapterById(id) == null) {
- // new chapter
- long start = VorbisCommentChapter.getStartTimeFromValue(value);
- chapter = new VorbisCommentChapter(id);
- chapter.setStart(start);
- chapters.add(chapter);
- } else {
- throw new VorbisCommentReaderException(
- "Found chapter with duplicate ID (" + key + ", "
- + value + ")");
- }
- } else if (attribute.equals(CHAPTER_ATTRIBUTE_TITLE)) {
- if (chapter != null) {
- chapter.setTitle(value);
- }
- } else if (attribute.equals(CHAPTER_ATTRIBUTE_LINK)) {
- if (chapter != null) {
- chapter.setLink(value);
- }
- }
- }
-
- @Override
- public void onNoVorbisCommentFound() {
- System.out.println("No vorbis comment found");
- }
-
- @Override
- public void onEndOfComment() {
- System.out.println("End of comment");
- for (Chapter c : chapters) {
- System.out.println(c.toString());
- }
- }
-
- @Override
- public void onError(VorbisCommentReaderException exception) {
- exception.printStackTrace();
- }
-
- private Chapter getChapterById(long id) {
- for (Chapter c : chapters) {
- if (((VorbisCommentChapter) c).getVorbisCommentId() == id) {
- return c;
- }
- }
- return null;
- }
-
- public List<Chapter> getChapters() {
- return chapters;
- }
-
-}
diff --git a/src/de/danoeh/antennapod/util/vorbiscommentreader/VorbisCommentHeader.java b/src/de/danoeh/antennapod/util/vorbiscommentreader/VorbisCommentHeader.java
deleted file mode 100644
index 8c47393c9..000000000
--- a/src/de/danoeh/antennapod/util/vorbiscommentreader/VorbisCommentHeader.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package de.danoeh.antennapod.util.vorbiscommentreader;
-public class VorbisCommentHeader {
- private String vendorString;
- private long userCommentLength;
-
- public VorbisCommentHeader(String vendorString, long userCommentLength) {
- super();
- this.vendorString = vendorString;
- this.userCommentLength = userCommentLength;
- }
-
- @Override
- public String toString() {
- return "VorbisCommentHeader [vendorString=" + vendorString
- + ", userCommentLength=" + userCommentLength + "]";
- }
-
- public String getVendorString() {
- return vendorString;
- }
-
- public long getUserCommentLength() {
- return userCommentLength;
- }
-
-}
diff --git a/src/de/danoeh/antennapod/util/vorbiscommentreader/VorbisCommentReader.java b/src/de/danoeh/antennapod/util/vorbiscommentreader/VorbisCommentReader.java
deleted file mode 100644
index 718a4f30f..000000000
--- a/src/de/danoeh/antennapod/util/vorbiscommentreader/VorbisCommentReader.java
+++ /dev/null
@@ -1,194 +0,0 @@
-package de.danoeh.antennapod.util.vorbiscommentreader;
-
-import org.apache.commons.io.EndianUtils;
-import org.apache.commons.io.IOUtils;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-import java.nio.ByteBuffer;
-import java.nio.charset.Charset;
-import java.util.Arrays;
-
-
-public abstract class VorbisCommentReader {
- /** Length of first page in an ogg file in bytes. */
- private static final int FIRST_PAGE_LENGTH = 58;
- private static final int SECOND_PAGE_MAX_LENGTH = 64 * 1024 * 1024;
- private static final int PACKET_TYPE_IDENTIFICATION = 1;
- private static final int PACKET_TYPE_COMMENT = 3;
-
- /** Called when Reader finds identification header. */
- public abstract void onVorbisCommentFound();
-
- public abstract void onVorbisCommentHeaderFound(VorbisCommentHeader header);
-
- /**
- * Is called every time the Reader finds a content vector. The handler
- * should return true if it wants to handle the content vector.
- */
- public abstract boolean onContentVectorKey(String content);
-
- /**
- * Is called if onContentVectorKey returned true for the key.
- *
- * @throws VorbisCommentReaderException
- */
- public abstract void onContentVectorValue(String key, String value)
- throws VorbisCommentReaderException;
-
- public abstract void onNoVorbisCommentFound();
-
- public abstract void onEndOfComment();
-
- public abstract void onError(VorbisCommentReaderException exception);
-
- public void readInputStream(InputStream input)
- throws VorbisCommentReaderException {
- try {
- // look for identification header
- if (findIdentificationHeader(input)) {
-
- onVorbisCommentFound();
- input = new OggInputStream(input);
- if (findCommentHeader(input)) {
- VorbisCommentHeader commentHeader = readCommentHeader(input);
- if (commentHeader != null) {
- onVorbisCommentHeaderFound(commentHeader);
- for (int i = 0; i < commentHeader
- .getUserCommentLength(); i++) {
- try {
- long vectorLength = EndianUtils
- .readSwappedUnsignedInteger(input);
- String key = readContentVectorKey(input,
- vectorLength).toLowerCase();
- boolean readValue = onContentVectorKey(key);
- if (readValue) {
- String value = readUTF8String(
- input,
- (int) (vectorLength - key.length() - 1));
- onContentVectorValue(key, value);
- } else {
- IOUtils.skipFully(input,
- vectorLength - key.length() - 1);
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- onEndOfComment();
- }
-
- } else {
- onError(new VorbisCommentReaderException(
- "No comment header found"));
- }
- } else {
- onNoVorbisCommentFound();
- }
- } catch (IOException e) {
- onError(new VorbisCommentReaderException(e));
- }
- }
-
- private String readUTF8String(InputStream input, long length)
- throws IOException {
- byte[] buffer = new byte[(int) length];
-
- IOUtils.readFully(input, buffer);
- Charset charset = Charset.forName("UTF-8");
- return charset.newDecoder().decode(ByteBuffer.wrap(buffer)).toString();
- }
-
- /**
- * Looks for an identification header in the first page of the file. If an
- * identification header is found, it will be skipped completely and the
- * method will return true, otherwise false.
- *
- * @throws IOException
- */
- private boolean findIdentificationHeader(InputStream input)
- throws IOException {
- byte[] buffer = new byte[FIRST_PAGE_LENGTH];
- IOUtils.readFully(input, buffer);
- int i;
- for (i = 6; i < buffer.length; i++) {
- if (buffer[i - 5] == 'v' && buffer[i - 4] == 'o'
- && buffer[i - 3] == 'r' && buffer[i - 2] == 'b'
- && buffer[i - 1] == 'i' && buffer[i] == 's'
- && buffer[i - 6] == PACKET_TYPE_IDENTIFICATION) {
- return true;
- }
- }
- return false;
- }
-
- private boolean findCommentHeader(InputStream input) throws IOException {
- char[] buffer = new char["vorbis".length() + 1];
- for (int bytesRead = 0; bytesRead < SECOND_PAGE_MAX_LENGTH; bytesRead++) {
- char c = (char) input.read();
- int dest = -1;
- switch (c) {
- case PACKET_TYPE_COMMENT:
- dest = 0;
- break;
- case 'v':
- dest = 1;
- break;
- case 'o':
- dest = 2;
- break;
- case 'r':
- dest = 3;
- break;
- case 'b':
- dest = 4;
- break;
- case 'i':
- dest = 5;
- break;
- case 's':
- dest = 6;
- break;
- }
- if (dest >= 0) {
- buffer[dest] = c;
- if (buffer[1] == 'v' && buffer[2] == 'o' && buffer[3] == 'r'
- && buffer[4] == 'b' && buffer[5] == 'i'
- && buffer[6] == 's' && buffer[0] == PACKET_TYPE_COMMENT) {
- return true;
- }
- } else {
- Arrays.fill(buffer, (char) 0);
- }
- }
- return false;
- }
-
- private VorbisCommentHeader readCommentHeader(InputStream input)
- throws IOException, VorbisCommentReaderException {
- try {
- long vendorLength = EndianUtils.readSwappedUnsignedInteger(input);
- String vendorName = readUTF8String(input, vendorLength);
- long userCommentLength = EndianUtils
- .readSwappedUnsignedInteger(input);
- return new VorbisCommentHeader(vendorName, userCommentLength);
- } catch (UnsupportedEncodingException e) {
- throw new VorbisCommentReaderException(e);
- }
- }
-
- private String readContentVectorKey(InputStream input, long vectorLength)
- throws IOException {
- StringBuffer buffer = new StringBuffer();
- for (int i = 0; i < vectorLength; i++) {
- char c = (char) input.read();
- if (c == '=') {
- return buffer.toString();
- } else {
- buffer.append(c);
- }
- }
- return null; // no key found
- }
-}
diff --git a/src/de/danoeh/antennapod/util/vorbiscommentreader/VorbisCommentReaderException.java b/src/de/danoeh/antennapod/util/vorbiscommentreader/VorbisCommentReaderException.java
deleted file mode 100644
index 574373241..000000000
--- a/src/de/danoeh/antennapod/util/vorbiscommentreader/VorbisCommentReaderException.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package de.danoeh.antennapod.util.vorbiscommentreader;
-public class VorbisCommentReaderException extends Exception {
-
- public VorbisCommentReaderException() {
- super();
- // TODO Auto-generated constructor stub
- }
-
- public VorbisCommentReaderException(String arg0, Throwable arg1) {
- super(arg0, arg1);
- // TODO Auto-generated constructor stub
- }
-
- public VorbisCommentReaderException(String arg0) {
- super(arg0);
- // TODO Auto-generated constructor stub
- }
-
- public VorbisCommentReaderException(Throwable arg0) {
- super(arg0);
- // TODO Auto-generated constructor stub
- }
-
-}
diff --git a/src/de/danoeh/antennapod/view/AspectRatioVideoView.java b/src/de/danoeh/antennapod/view/AspectRatioVideoView.java
deleted file mode 100644
index f930c912a..000000000
--- a/src/de/danoeh/antennapod/view/AspectRatioVideoView.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package de.danoeh.antennapod.view;
-
-/*
- * Copyright (C) Google Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.VideoView;
-
-public class AspectRatioVideoView extends VideoView {
-
-
- private int mVideoWidth;
- private int mVideoHeight;
-
- public AspectRatioVideoView(Context context) {
- this(context, null);
- }
-
- public AspectRatioVideoView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public AspectRatioVideoView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- mVideoWidth = 0;
- mVideoHeight = 0;
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- if (mVideoWidth <= 0 || mVideoHeight <= 0) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- return;
- }
-
- float heightRatio = (float) mVideoHeight / (float) getHeight();
- float widthRatio = (float) mVideoWidth / (float) getWidth();
-
- int scaledHeight;
- int scaledWidth;
-
- if (heightRatio > widthRatio) {
- scaledHeight = (int) Math.ceil((float) mVideoHeight
- / heightRatio);
- scaledWidth = (int) Math.ceil((float) mVideoWidth
- / heightRatio);
- } else {
- scaledHeight = (int) Math.ceil((float) mVideoHeight
- / widthRatio);
- scaledWidth = (int) Math.ceil((float) mVideoWidth
- / widthRatio);
- }
-
- setMeasuredDimension(scaledWidth, scaledHeight);
- }
-
- /**
- * Source code originally from:
- * http://clseto.mysinablog.com/index.php?op=ViewArticle&articleId=2992625
- *
- * @param videoWidth
- * @param videoHeight
- */
- public void setVideoSize(int videoWidth, int videoHeight) {
- // Set the new video size
- mVideoWidth = videoWidth;
- mVideoHeight = videoHeight;
-
- /**
- * If this isn't set the video is stretched across the
- * SurfaceHolders display surface (i.e. the SurfaceHolder
- * as the same size and the video is drawn to fit this
- * display area). We want the size to be the video size
- * and allow the aspectratio to handle how the surface is shown
- */
- getHolder().setFixedSize(videoWidth, videoHeight);
-
- requestLayout();
- invalidate();
- }
-
-}