mirror of
https://github.com/AntennaPod/AntennaPod.git
synced 2025-01-27 09:01:22 +01:00
Squashed commit of the following:
commit 7d0e6d5c2dc75f8f1e54f4a1279c6b0cffa7b8cc Author: daniel oeh <daniel.oeh@gmail.com> Date: Mon Nov 10 21:00:58 2014 +0100 Made tests compile commit 05c57df87dd469d8f64835700eefe2e3c87e04e4 Author: daniel oeh <daniel.oeh@gmail.com> Date: Mon Nov 10 20:56:58 2014 +0100 Removed unused code commit 0a1fbc9e6d9648646140e30dec0ec8389fb8d37f Author: daniel oeh <daniel.oeh@gmail.com> Date: Thu Nov 6 15:48:24 2014 +0100 Added UI controls to download more feed pages closes #245 commit 6486fb40f1d03887e264df95946f91f0a9cdac9b Author: daniel oeh <daniel.oeh@gmail.com> Date: Thu Nov 6 14:49:43 2014 +0100 Added support for downloading feed pages commit e1faa06908bfd50f2aa0c28ee5118772c4281557 Author: daniel oeh <daniel.oeh@gmail.com> Date: Wed Nov 5 21:27:03 2014 +0100 Added "paged" and "loadAllPages" attributes
This commit is contained in:
parent
6035e8fee9
commit
ad04a80ae7
@ -65,7 +65,7 @@ public class HttpDownloaderTest extends InstrumentationTestCase {
|
||||
|
||||
private Downloader download(String url, String title, boolean expectedResult, boolean deleteExisting, String username, String password, boolean deleteOnFail) {
|
||||
FeedFile feedFile = setupFeedFile(url, title, deleteExisting);
|
||||
DownloadRequest request = new DownloadRequest(feedFile.getFile_url(), url, title, 0, feedFile.getTypeAsInt(), username, password, deleteOnFail);
|
||||
DownloadRequest request = new DownloadRequest(feedFile.getFile_url(), url, title, 0, feedFile.getTypeAsInt(), username, password, deleteOnFail, null);
|
||||
Downloader downloader = new HttpDownloader(request);
|
||||
downloader.call();
|
||||
DownloadStatus status = downloader.getResult();
|
||||
|
@ -43,7 +43,7 @@ public class DBReaderTest extends InstrumentationTestCase {
|
||||
private void expiredFeedListTestHelper(long lastUpdate, long expirationTime, boolean shouldReturn) {
|
||||
final Context context = getInstrumentation().getTargetContext();
|
||||
Feed feed = new Feed(0, new Date(lastUpdate), "feed", "link", "descr", null,
|
||||
null, null, null, "feed", null, null, "url", false, new FlattrStatus());
|
||||
null, null, null, "feed", null, null, "url", false, new FlattrStatus(), false, null);
|
||||
feed.setItems(new ArrayList<FeedItem>());
|
||||
PodDBAdapter adapter = new PodDBAdapter(context);
|
||||
adapter.open();
|
||||
|
@ -296,7 +296,7 @@ public class DBTasksTest extends InstrumentationTestCase {
|
||||
final Context context = getInstrumentation().getTargetContext();
|
||||
UserPreferences.setUpdateInterval(context, expirationTime);
|
||||
Feed feed = new Feed(0, new Date(lastUpdate), "feed", "link", "descr", null,
|
||||
null, null, null, "feed", null, null, "url", false, new FlattrStatus());
|
||||
null, null, null, "feed", null, null, "url", false, new FlattrStatus(), false, null);
|
||||
feed.setItems(new ArrayList<FeedItem>());
|
||||
PodDBAdapter adapter = new PodDBAdapter(context);
|
||||
adapter.open();
|
||||
|
@ -32,7 +32,7 @@ public class DBTestUtils {
|
||||
adapter.open();
|
||||
for (int i = 0; i < numFeeds; i++) {
|
||||
Feed f = new Feed(0, new Date(), "feed " + i, "link" + i, "descr", null, null,
|
||||
null, null, "id" + i, null, null, "url" + i, false, new FlattrStatus());
|
||||
null, null, "id" + i, null, null, "url" + i, false, new FlattrStatus(), false, null);
|
||||
f.setItems(new ArrayList<FeedItem>());
|
||||
for (int j = 0; j < numItems; j++) {
|
||||
FeedItem item = new FeedItem(0, "item " + j, "id" + j, "link" + j, new Date(),
|
||||
|
@ -183,14 +183,14 @@ public abstract class OnlineFeedViewActivity extends ActionBarActivity {
|
||||
url = URLChecker.prepareURL(url);
|
||||
feed = new Feed(url, new Date());
|
||||
if (username != null && password != null) {
|
||||
feed.setPreferences(new FeedPreferences(0, true, username, password));
|
||||
feed.setPreferences(new FeedPreferences(0, false, 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);
|
||||
feed.getDownload_url(), "OnlineFeed", 0, Feed.FEEDFILETYPE_FEED, username, password, true, null);
|
||||
downloader = new HttpDownloader(
|
||||
request);
|
||||
new Thread() {
|
||||
|
@ -13,7 +13,7 @@ public class StorageCallbacksImpl implements StorageCallbacks {
|
||||
|
||||
@Override
|
||||
public int getDatabaseVersion() {
|
||||
return 12;
|
||||
return 13;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -103,5 +103,11 @@ public class StorageCallbacksImpl implements StorageCallbacks {
|
||||
+ " ADD COLUMN " + PodDBAdapter.KEY_IMAGE
|
||||
+ " INTEGER");
|
||||
}
|
||||
if (oldVersion <= 12) {
|
||||
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
|
||||
+ " ADD COLUMN " + PodDBAdapter.KEY_IS_PAGED + " INTEGER DEFAULT 0");
|
||||
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
|
||||
+ " ADD COLUMN " + PodDBAdapter.KEY_NEXT_PAGE_LINK + " TEXT");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ 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;
|
||||
@ -44,9 +43,11 @@ import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.service.download.DownloadService;
|
||||
import de.danoeh.antennapod.core.service.download.Downloader;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.DBTasks;
|
||||
import de.danoeh.antennapod.core.storage.DownloadRequestException;
|
||||
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
||||
import de.danoeh.antennapod.core.util.QueueAccess;
|
||||
import de.danoeh.antennapod.core.util.gui.MoreContentListFooterUtil;
|
||||
import de.danoeh.antennapod.dialog.FeedItemDialog;
|
||||
import de.danoeh.antennapod.menuhandler.FeedMenuHandler;
|
||||
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
|
||||
@ -82,6 +83,8 @@ public class ItemlistFragment extends ListFragment {
|
||||
private FeedItemDialog feedItemDialog;
|
||||
private FeedItemDialog.FeedItemDialogSavedInstance feedItemDialogSavedInstance;
|
||||
|
||||
private MoreContentListFooterUtil listFooter;
|
||||
|
||||
private boolean isUpdatingFeed;
|
||||
|
||||
/**
|
||||
@ -293,12 +296,17 @@ public class ItemlistFragment extends ListFragment {
|
||||
if (isUpdatingFeed != updateRefreshMenuItemChecker.isRefreshing()) {
|
||||
getActivity().supportInvalidateOptionsMenu();
|
||||
}
|
||||
if (listFooter != null) {
|
||||
listFooter.setLoadingState(DownloadRequester.getInstance().isDownloadingFeeds());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void onFragmentLoaded() {
|
||||
if (adapter == null) {
|
||||
getListView().setAdapter(null);
|
||||
setupHeaderView();
|
||||
setupFooterView();
|
||||
adapter = new FeedItemlistAdapter(getActivity(), itemAccess, new DefaultActionButtonCallback(getActivity()), false);
|
||||
setListAdapter(adapter);
|
||||
downloadObserver = new DownloadObserver(getActivity(), new Handler(), downloadObserverCallback);
|
||||
@ -313,6 +321,11 @@ public class ItemlistFragment extends ListFragment {
|
||||
feedItemDialog = FeedItemDialog.newInstance(getActivity(), feedItemDialogSavedInstance);
|
||||
}
|
||||
getActivity().supportInvalidateOptionsMenu();
|
||||
|
||||
if (feed != null && feed.getNextPageLink() == null && listFooter != null) {
|
||||
getListView().removeFooterView(listFooter.getRoot());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private DownloadObserver.Callback downloadObserverCallback = new DownloadObserver.Callback() {
|
||||
@ -372,6 +385,34 @@ public class ItemlistFragment extends ListFragment {
|
||||
});
|
||||
}
|
||||
|
||||
private void setupFooterView() {
|
||||
if (getListView() == null || feed == null) {
|
||||
Log.e(TAG, "Unable to setup listview: listView = null or feed = null");
|
||||
return;
|
||||
}
|
||||
if (feed.isPaged() && feed.getNextPageLink() != null) {
|
||||
ListView lv = getListView();
|
||||
LayoutInflater inflater = (LayoutInflater)
|
||||
getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
View header = inflater.inflate(R.layout.more_content_list_footer, lv, false);
|
||||
lv.addFooterView(header);
|
||||
listFooter = new MoreContentListFooterUtil(header);
|
||||
listFooter.setClickListener(new MoreContentListFooterUtil.Listener() {
|
||||
@Override
|
||||
public void onClick() {
|
||||
if (feed != null) {
|
||||
try {
|
||||
DBTasks.loadNextPageOfFeed(getActivity(), feed, false);
|
||||
} catch (DownloadRequestException e) {
|
||||
e.printStackTrace();
|
||||
DownloadRequestErrorDialogCreator.newRequestErrorDialog(getActivity(), e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private FeedItemlistAdapter.ItemAccess itemAccess = new FeedItemlistAdapter.ItemAccess() {
|
||||
|
||||
@Override
|
||||
|
@ -41,6 +41,8 @@ public class FeedMenuHandler {
|
||||
else
|
||||
menu.findItem(R.id.support_item).setVisible(false);
|
||||
|
||||
menu.findItem(R.id.refresh_complete_item).setVisible(selectedFeed.isPaged());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -55,6 +57,9 @@ public class FeedMenuHandler {
|
||||
case R.id.refresh_item:
|
||||
DBTasks.refreshFeed(context, selectedFeed);
|
||||
break;
|
||||
case R.id.refresh_complete_item:
|
||||
DBTasks.refreshCompleteFeed(context, selectedFeed);
|
||||
break;
|
||||
case R.id.mark_all_read_item:
|
||||
DBWriter.markFeedRead(context, selectedFeed.getId());
|
||||
break;
|
||||
|
@ -6,29 +6,35 @@
|
||||
android:id="@+id/refresh_item"
|
||||
android:icon="?attr/navigation_refresh"
|
||||
android:menuCategory="container"
|
||||
custom:showAsAction="ifRoom"
|
||||
android:title="@string/refresh_label">
|
||||
android:title="@string/refresh_label"
|
||||
custom:showAsAction="ifRoom">
|
||||
</item>
|
||||
<item
|
||||
android:id="@+id/refresh_complete_item"
|
||||
android:menuCategory="container"
|
||||
android:title="@string/load_complete_feed"
|
||||
custom:showAsAction="collapseActionView">
|
||||
</item>
|
||||
<item
|
||||
android:id="@+id/mark_all_read_item"
|
||||
android:menuCategory="container"
|
||||
custom:showAsAction="collapseActionView"
|
||||
android:title="@string/mark_all_read_label">
|
||||
android:title="@string/mark_all_read_label"
|
||||
custom:showAsAction="collapseActionView">
|
||||
</item>
|
||||
<item
|
||||
android:id="@+id/support_item"
|
||||
android:menuCategory="container"
|
||||
custom:showAsAction="collapseActionView"
|
||||
android:title="@string/support_label"
|
||||
android:visible="false">
|
||||
android:visible="false"
|
||||
custom:showAsAction="collapseActionView">
|
||||
</item>
|
||||
<item
|
||||
android:id="@+id/remove_item"
|
||||
android:menuCategory="container"
|
||||
android:icon="?attr/content_discard"
|
||||
custom:showAsAction="collapseActionView"
|
||||
android:menuCategory="container"
|
||||
android:title="@string/remove_feed_label"
|
||||
android:visible="true">
|
||||
android:visible="true"
|
||||
custom:showAsAction="collapseActionView">
|
||||
</item>
|
||||
|
||||
</menu>
|
@ -3,6 +3,12 @@ package de.danoeh.antennapod.core.feed;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import de.danoeh.antennapod.core.asynctask.PicassoImageResource;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
@ -10,10 +16,6 @@ import de.danoeh.antennapod.core.util.EpisodeFilter;
|
||||
import de.danoeh.antennapod.core.util.flattr.FlattrStatus;
|
||||
import de.danoeh.antennapod.core.util.flattr.FlattrThing;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Data Object for a whole feed
|
||||
*
|
||||
@ -58,12 +60,33 @@ public class Feed extends FeedFile implements FlattrThing, PicassoImageResource
|
||||
*/
|
||||
private FeedPreferences preferences;
|
||||
|
||||
/**
|
||||
* The page number that this feed is on. Only feeds with page number "0" should be stored in the
|
||||
* database, feed objects with a higher page number only exist temporarily and should be merged
|
||||
* into feeds with page number "0".
|
||||
* <p/>
|
||||
* This attribute's value is not saved in the database
|
||||
*/
|
||||
private int pageNr;
|
||||
|
||||
/**
|
||||
* True if this is a "paged feed", i.e. there exist other feed files that belong to the same
|
||||
* logical feed.
|
||||
*/
|
||||
private boolean paged;
|
||||
|
||||
/**
|
||||
* Link to the next page of this feed. If this feed object represents a logical feed (i.e. a feed
|
||||
* that is saved in the database) this might be null while still being a paged feed.
|
||||
*/
|
||||
private String nextPageLink;
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
String downloadUrl, boolean downloaded, FlattrStatus status, boolean paged, String nextPageLink) {
|
||||
super(fileUrl, downloadUrl, downloaded);
|
||||
this.id = id;
|
||||
this.title = title;
|
||||
@ -81,6 +104,8 @@ public class Feed extends FeedFile implements FlattrThing, PicassoImageResource
|
||||
this.feedIdentifier = feedIdentifier;
|
||||
this.image = image;
|
||||
this.flattrStatus = status;
|
||||
this.paged = paged;
|
||||
this.nextPageLink = nextPageLink;
|
||||
|
||||
items = new ArrayList<FeedItem>();
|
||||
}
|
||||
@ -92,7 +117,7 @@ public class Feed extends FeedFile implements FlattrThing, PicassoImageResource
|
||||
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());
|
||||
fileUrl, downloadUrl, downloaded, new FlattrStatus(), false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -270,6 +295,12 @@ public class Feed extends FeedFile implements FlattrThing, PicassoImageResource
|
||||
if (other.flattrStatus != null) {
|
||||
flattrStatus = other.flattrStatus;
|
||||
}
|
||||
// this feed's nextPage might already point to a higher page, so we only update the nextPage value
|
||||
// if this feed is not paged and the other feed is.
|
||||
if (!this.paged && other.paged) {
|
||||
this.paged = other.paged;
|
||||
this.nextPageLink = other.nextPageLink;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean compareWithOther(Feed other) {
|
||||
@ -310,6 +341,12 @@ public class Feed extends FeedFile implements FlattrThing, PicassoImageResource
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (other.isPaged() && !this.isPaged()) {
|
||||
return true;
|
||||
}
|
||||
if (!StringUtils.equals(other.getNextPageLink(), this.getNextPageLink())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -374,13 +411,13 @@ public class Feed extends FeedFile implements FlattrThing, PicassoImageResource
|
||||
this.feedIdentifier = feedIdentifier;
|
||||
}
|
||||
|
||||
public void setFlattrStatus(FlattrStatus status) {
|
||||
this.flattrStatus = status;
|
||||
}
|
||||
public void setFlattrStatus(FlattrStatus status) {
|
||||
this.flattrStatus = status;
|
||||
}
|
||||
|
||||
public FlattrStatus getFlattrStatus() {
|
||||
return flattrStatus;
|
||||
}
|
||||
public FlattrStatus getFlattrStatus() {
|
||||
return flattrStatus;
|
||||
}
|
||||
|
||||
public String getPaymentLink() {
|
||||
return paymentLink;
|
||||
@ -442,4 +479,28 @@ public class Feed extends FeedFile implements FlattrThing, PicassoImageResource
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public int getPageNr() {
|
||||
return pageNr;
|
||||
}
|
||||
|
||||
public void setPageNr(int pageNr) {
|
||||
this.pageNr = pageNr;
|
||||
}
|
||||
|
||||
public boolean isPaged() {
|
||||
return paged;
|
||||
}
|
||||
|
||||
public void setPaged(boolean paged) {
|
||||
this.paged = paged;
|
||||
}
|
||||
|
||||
public String getNextPageLink() {
|
||||
return nextPageLink;
|
||||
}
|
||||
|
||||
public void setNextPageLink(String nextPageLink) {
|
||||
this.nextPageLink = nextPageLink;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package de.danoeh.antennapod.core.service.download;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
@ -15,6 +16,7 @@ public class DownloadRequest implements Parcelable {
|
||||
private boolean deleteOnFailure;
|
||||
private final long feedfileId;
|
||||
private final int feedfileType;
|
||||
private final Bundle arguments;
|
||||
|
||||
protected int progressPercent;
|
||||
protected long soFar;
|
||||
@ -22,7 +24,7 @@ public class DownloadRequest implements Parcelable {
|
||||
protected int statusMsg;
|
||||
|
||||
public DownloadRequest(String destination, String source, String title,
|
||||
long feedfileId, int feedfileType, String username, String password, boolean deleteOnFailure) {
|
||||
long feedfileId, int feedfileType, String username, String password, boolean deleteOnFailure, Bundle arguments) {
|
||||
Validate.notNull(destination);
|
||||
Validate.notNull(source);
|
||||
Validate.notNull(title);
|
||||
@ -35,11 +37,12 @@ public class DownloadRequest implements Parcelable {
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.deleteOnFailure = deleteOnFailure;
|
||||
this.arguments = (arguments != null) ? arguments : new Bundle();
|
||||
}
|
||||
|
||||
public DownloadRequest(String destination, String source, String title,
|
||||
long feedfileId, int feedfileType) {
|
||||
this(destination, source, title, feedfileId, feedfileType, null, null, true);
|
||||
this(destination, source, title, feedfileId, feedfileType, null, null, true, null);
|
||||
}
|
||||
|
||||
private DownloadRequest(Parcel in) {
|
||||
@ -49,6 +52,7 @@ public class DownloadRequest implements Parcelable {
|
||||
feedfileId = in.readLong();
|
||||
feedfileType = in.readInt();
|
||||
deleteOnFailure = (in.readByte() > 0);
|
||||
arguments = in.readBundle();
|
||||
if (in.dataAvail() > 0) {
|
||||
username = in.readString();
|
||||
} else {
|
||||
@ -74,6 +78,7 @@ public class DownloadRequest implements Parcelable {
|
||||
dest.writeLong(feedfileId);
|
||||
dest.writeInt(feedfileType);
|
||||
dest.writeByte((deleteOnFailure) ? (byte) 1 : 0);
|
||||
dest.writeBundle(arguments);
|
||||
if (username != null) {
|
||||
dest.writeString(username);
|
||||
}
|
||||
@ -92,6 +97,7 @@ public class DownloadRequest implements Parcelable {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
@ -106,11 +112,11 @@ public class DownloadRequest implements Parcelable {
|
||||
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 (!arguments.equals(that.arguments)) return false;
|
||||
if (!destination.equals(that.destination)) 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 (!source.equals(that.source)) 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;
|
||||
@ -120,14 +126,15 @@ public class DownloadRequest implements Parcelable {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = destination != null ? destination.hashCode() : 0;
|
||||
result = 31 * result + (source != null ? source.hashCode() : 0);
|
||||
int result = destination.hashCode();
|
||||
result = 31 * result + source.hashCode();
|
||||
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 + arguments.hashCode();
|
||||
result = 31 * result + progressPercent;
|
||||
result = 31 * result + (int) (soFar ^ (soFar >>> 32));
|
||||
result = 31 * result + (int) (size ^ (size >>> 32));
|
||||
@ -206,4 +213,8 @@ public class DownloadRequest implements Parcelable {
|
||||
public boolean isDeleteOnFailure() {
|
||||
return deleteOnFailure;
|
||||
}
|
||||
|
||||
public Bundle getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.util.Pair;
|
||||
import android.util.Log;
|
||||
import android.webkit.URLUtil;
|
||||
|
||||
@ -66,6 +67,7 @@ import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
import de.danoeh.antennapod.core.storage.DownloadRequestException;
|
||||
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
||||
import de.danoeh.antennapod.core.syndication.handler.FeedHandler;
|
||||
import de.danoeh.antennapod.core.syndication.handler.FeedHandlerResult;
|
||||
import de.danoeh.antennapod.core.syndication.handler.UnsupportedFeedtypeException;
|
||||
import de.danoeh.antennapod.core.util.ChapterUtils;
|
||||
import de.danoeh.antennapod.core.util.DownloadError;
|
||||
@ -669,7 +671,7 @@ public class DownloadService extends Service {
|
||||
private static final String TAG = "FeedSyncThread";
|
||||
|
||||
private BlockingQueue<DownloadRequest> completedRequests = new LinkedBlockingDeque<DownloadRequest>();
|
||||
private CompletionService<Feed> parserService = new ExecutorCompletionService<Feed>(Executors.newSingleThreadExecutor());
|
||||
private CompletionService<Pair<DownloadRequest, FeedHandlerResult>> parserService = new ExecutorCompletionService<Pair<DownloadRequest, FeedHandlerResult>>(Executors.newSingleThreadExecutor());
|
||||
private ExecutorService dbService = Executors.newSingleThreadExecutor();
|
||||
private Future<?> dbUpdateFuture;
|
||||
private volatile boolean isActive = true;
|
||||
@ -684,8 +686,8 @@ public class DownloadService extends Service {
|
||||
*
|
||||
* @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>();
|
||||
private List<Pair<DownloadRequest, FeedHandlerResult>> collectCompletedRequests() {
|
||||
List<Pair<DownloadRequest, FeedHandlerResult>> results = new LinkedList<Pair<DownloadRequest, FeedHandlerResult>>();
|
||||
DownloadRequester requester = DownloadRequester.getInstance();
|
||||
int tasks = 0;
|
||||
|
||||
@ -727,9 +729,9 @@ public class DownloadService extends Service {
|
||||
|
||||
for (int i = 0; i < tasks; i++) {
|
||||
try {
|
||||
Feed f = parserService.take().get();
|
||||
if (f != null) {
|
||||
results.add(f);
|
||||
Pair<DownloadRequest, FeedHandlerResult> result = parserService.take().get();
|
||||
if (result != null) {
|
||||
results.add(result);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
@ -754,16 +756,16 @@ public class DownloadService extends Service {
|
||||
@Override
|
||||
public void run() {
|
||||
while (isActive) {
|
||||
final List<Feed> feeds = collectCompletedRequests();
|
||||
final List<Pair<DownloadRequest, FeedHandlerResult>> results = collectCompletedRequests();
|
||||
|
||||
if (feeds == null) {
|
||||
if (results == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (BuildConfig.DEBUG) Log.d(TAG, "Bundling " + feeds.size() + " feeds");
|
||||
if (BuildConfig.DEBUG) Log.d(TAG, "Bundling " + results.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.
|
||||
for (Pair<DownloadRequest, FeedHandlerResult> result : results) {
|
||||
removeDuplicateImages(result.second.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
|
||||
@ -780,9 +782,10 @@ public class DownloadService extends Service {
|
||||
dbUpdateFuture = dbService.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Feed[] savedFeeds = DBTasks.updateFeed(DownloadService.this, feeds.toArray(new Feed[feeds.size()]));
|
||||
Feed[] savedFeeds = DBTasks.updateFeed(DownloadService.this, getFeeds(results));
|
||||
|
||||
for (Feed savedFeed : savedFeeds) {
|
||||
for (int i = 0; i < savedFeeds.length; i++) {
|
||||
Feed savedFeed = savedFeeds[i];
|
||||
// Download Feed Image if provided and not downloaded
|
||||
if (savedFeed.getImage() != null
|
||||
&& savedFeed.getImage().isDownloaded() == false) {
|
||||
@ -816,6 +819,19 @@ public class DownloadService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
// If loadAllPages=true, check if another page is available and queue it for download
|
||||
|
||||
final boolean loadAllPages = results.get(i).first.getArguments().getBoolean(DownloadRequester.REQUEST_ARG_LOAD_ALL_PAGES);
|
||||
final Feed feed = results.get(i).second.feed;
|
||||
if (loadAllPages && feed.getNextPageLink() != null) {
|
||||
try {
|
||||
feed.setId(savedFeed.getId());
|
||||
DBTasks.loadNextPageOfFeed(DownloadService.this, savedFeed, true);
|
||||
} catch (DownloadRequestException e) {
|
||||
Log.e(TAG, "Error trying to load next page", e);
|
||||
}
|
||||
}
|
||||
|
||||
ClientConfig.downloadServiceCallbacks.onFeedParsed(DownloadService.this,
|
||||
savedFeed);
|
||||
|
||||
@ -840,12 +856,22 @@ public class DownloadService extends Service {
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (BuildConfig.DEBUG) Log.d(TAG, "Shutting down");
|
||||
|
||||
}
|
||||
|
||||
private class FeedParserTask implements Callable<Feed> {
|
||||
/**
|
||||
* Helper method
|
||||
*/
|
||||
private Feed[] getFeeds(List<Pair<DownloadRequest, FeedHandlerResult>> results) {
|
||||
Feed[] feeds = new Feed[results.size()];
|
||||
for (int i = 0; i < results.size(); i++) {
|
||||
feeds[i] = results.get(i).second.feed;
|
||||
}
|
||||
return feeds;
|
||||
}
|
||||
|
||||
private class FeedParserTask implements Callable<Pair<DownloadRequest, FeedHandlerResult>> {
|
||||
|
||||
private DownloadRequest request;
|
||||
|
||||
@ -854,27 +880,28 @@ public class DownloadService extends Service {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Feed call() throws Exception {
|
||||
public Pair<DownloadRequest, FeedHandlerResult> call() throws Exception {
|
||||
return parseFeed(request);
|
||||
}
|
||||
}
|
||||
|
||||
private Feed parseFeed(DownloadRequest request) {
|
||||
Feed savedFeed = null;
|
||||
|
||||
private Pair<DownloadRequest, FeedHandlerResult> parseFeed(DownloadRequest request) {
|
||||
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()));
|
||||
feed.setPreferences(new FeedPreferences(0, true,
|
||||
request.getUsername(), request.getPassword()));
|
||||
feed.setPageNr(request.getArguments().getInt(DownloadRequester.REQUEST_ARG_PAGE_NR, 0));
|
||||
|
||||
DownloadError reason = null;
|
||||
String reasonDetailed = null;
|
||||
boolean successful = true;
|
||||
FeedHandler feedHandler = new FeedHandler();
|
||||
|
||||
FeedHandlerResult result = null;
|
||||
try {
|
||||
feed = feedHandler.parseFeed(feed).feed;
|
||||
result = feedHandler.parseFeed(feed);
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(TAG, feed.getTitle() + " parsed");
|
||||
if (checkFeedData(feed) == false) {
|
||||
@ -909,17 +936,14 @@ public class DownloadService extends Service {
|
||||
}
|
||||
|
||||
// cleanup();
|
||||
if (savedFeed == null) {
|
||||
savedFeed = feed;
|
||||
}
|
||||
|
||||
|
||||
if (successful) {
|
||||
return savedFeed;
|
||||
return Pair.create(request, result);
|
||||
} else {
|
||||
numberOfDownloads.decrementAndGet();
|
||||
saveDownloadStatus(new DownloadStatus(savedFeed,
|
||||
savedFeed.getHumanReadableIdentifier(), reason, successful,
|
||||
saveDownloadStatus(new DownloadStatus(feed,
|
||||
feed.getHumanReadableIdentifier(), reason, successful,
|
||||
reasonDetailed));
|
||||
return null;
|
||||
}
|
||||
|
@ -350,7 +350,9 @@ public final class DBReader {
|
||||
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)));
|
||||
new FlattrStatus(cursor.getLong(PodDBAdapter.IDX_FEED_SEL_STD_FLATTR_STATUS)),
|
||||
cursor.getInt(PodDBAdapter.IDX_FEED_SEL_STD_IS_PAGED) > 0,
|
||||
cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_NEXT_PAGE_LINK));
|
||||
|
||||
if (image != null) {
|
||||
image.setOwner(feed);
|
||||
|
@ -4,11 +4,32 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import de.danoeh.antennapod.core.BuildConfig;
|
||||
import de.danoeh.antennapod.core.ClientConfig;
|
||||
import de.danoeh.antennapod.core.asynctask.FlattrClickWorker;
|
||||
import de.danoeh.antennapod.core.asynctask.FlattrStatusFetcher;
|
||||
import de.danoeh.antennapod.core.feed.*;
|
||||
import de.danoeh.antennapod.core.feed.EventDistributor;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedImage;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.service.GpodnetSyncService;
|
||||
import de.danoeh.antennapod.core.service.download.DownloadStatus;
|
||||
@ -20,10 +41,6 @@ import de.danoeh.antennapod.core.util.comparator.FeedItemPubdateComparator;
|
||||
import de.danoeh.antennapod.core.util.exception.MediaFileNotFoundException;
|
||||
import de.danoeh.antennapod.core.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.
|
||||
*/
|
||||
@ -239,6 +256,49 @@ public final class DBTasks {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads all pages of the given feed.
|
||||
*
|
||||
* @param context Used for requesting the download.
|
||||
* @param feed The Feed object.
|
||||
*/
|
||||
public static void refreshCompleteFeed(final Context context, final Feed feed) {
|
||||
try {
|
||||
refreshFeed(context, feed, true);
|
||||
} catch (DownloadRequestException e) {
|
||||
e.printStackTrace();
|
||||
DBWriter.addDownloadStatus(
|
||||
context,
|
||||
new DownloadStatus(feed, feed
|
||||
.getHumanReadableIdentifier(),
|
||||
DownloadError.ERROR_REQUEST_ERROR, false, e
|
||||
.getMessage()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues the next page of this Feed for download. The given Feed has to be a paged
|
||||
* Feed (isPaged()=true) and must contain a nextPageLink.
|
||||
*
|
||||
* @param context Used for requesting the download.
|
||||
* @param feed The feed whose next page should be loaded.
|
||||
* @param loadAllPages True if any subsequent pages should also be loaded, false otherwise.
|
||||
*/
|
||||
public static void loadNextPageOfFeed(final Context context, Feed feed, boolean loadAllPages) throws DownloadRequestException {
|
||||
if (feed.isPaged() && feed.getNextPageLink() != null) {
|
||||
int pageNr = feed.getPageNr() + 1;
|
||||
Feed nextFeed = new Feed(feed.getNextPageLink(), new Date(), feed.getTitle() + "(" + pageNr + ")");
|
||||
nextFeed.setPageNr(pageNr);
|
||||
nextFeed.setPaged(true);
|
||||
nextFeed.setId(feed.getId());
|
||||
DownloadRequester.getInstance().downloadFeed(context, nextFeed, loadAllPages);
|
||||
} else {
|
||||
Log.e(TAG, "loadNextPageOfFeed: Feed was either not paged or contained no nextPageLink");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a specific Feed.
|
||||
*
|
||||
@ -247,6 +307,10 @@ public final class DBTasks {
|
||||
*/
|
||||
public static void refreshFeed(Context context, Feed feed)
|
||||
throws DownloadRequestException {
|
||||
refreshFeed(context, feed, false);
|
||||
}
|
||||
|
||||
private static void refreshFeed(Context context, Feed feed, boolean loadAllPages) throws DownloadRequestException {
|
||||
Feed f;
|
||||
if (feed.getPreferences() == null) {
|
||||
f = new Feed(feed.getDownload_url(), new Date(), feed.getTitle());
|
||||
@ -255,7 +319,7 @@ public final class DBTasks {
|
||||
feed.getPreferences().getUsername(), feed.getPreferences().getPassword());
|
||||
}
|
||||
f.setId(feed.getId());
|
||||
DownloadRequester.getInstance().downloadFeed(context, f);
|
||||
DownloadRequester.getInstance().downloadFeed(context, f, loadAllPages);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -388,7 +452,7 @@ public final class DBTasks {
|
||||
* 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 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.
|
||||
@ -687,11 +751,21 @@ public final class DBTasks {
|
||||
+ " already exists. Syncing new with existing one.");
|
||||
|
||||
Collections.sort(newFeed.getItems(), new FeedItemPubdateComparator());
|
||||
if (savedFeed.compareWithOther(newFeed)) {
|
||||
|
||||
final boolean markNewItemsAsUnread;
|
||||
if (newFeed.getPageNr() == savedFeed.getPageNr()) {
|
||||
if (savedFeed.compareWithOther(newFeed)) {
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(TAG,
|
||||
"Feed has updated attribute values. Updating old feed's attributes");
|
||||
savedFeed.updateFromOther(newFeed);
|
||||
}
|
||||
markNewItemsAsUnread = true;
|
||||
} else {
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(TAG,
|
||||
"Feed has updated attribute values. Updating old feed's attributes");
|
||||
savedFeed.updateFromOther(newFeed);
|
||||
Log.d(TAG, "New feed has a higher page number. Merging without marking as unread");
|
||||
markNewItemsAsUnread = false;
|
||||
savedFeed.setNextPageLink(newFeed.getNextPageLink());
|
||||
}
|
||||
if (savedFeed.getPreferences().compareWithOther(newFeed.getPreferences())) {
|
||||
if (BuildConfig.DEBUG)
|
||||
@ -708,7 +782,9 @@ public final class DBTasks {
|
||||
final int i = idx;
|
||||
item.setFeed(savedFeed);
|
||||
savedFeed.getItems().add(i, item);
|
||||
item.setRead(false);
|
||||
if (markNewItemsAsUnread) {
|
||||
item.setRead(false);
|
||||
}
|
||||
} else {
|
||||
oldItem.updateFromOther(item);
|
||||
}
|
||||
|
@ -2,15 +2,10 @@ package de.danoeh.antennapod.core.storage;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.webkit.URLUtil;
|
||||
import de.danoeh.antennapod.core.BuildConfig;
|
||||
import de.danoeh.antennapod.core.feed.*;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.service.download.DownloadRequest;
|
||||
import de.danoeh.antennapod.core.service.download.DownloadService;
|
||||
import de.danoeh.antennapod.core.util.FileNameGenerator;
|
||||
import de.danoeh.antennapod.core.util.URLChecker;
|
||||
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
@ -19,6 +14,18 @@ import java.io.File;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import de.danoeh.antennapod.core.BuildConfig;
|
||||
import de.danoeh.antennapod.core.feed.EventDistributor;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedFile;
|
||||
import de.danoeh.antennapod.core.feed.FeedImage;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.service.download.DownloadRequest;
|
||||
import de.danoeh.antennapod.core.service.download.DownloadService;
|
||||
import de.danoeh.antennapod.core.util.FileNameGenerator;
|
||||
import de.danoeh.antennapod.core.util.URLChecker;
|
||||
|
||||
|
||||
/**
|
||||
* Sends download requests to the DownloadService. This class should always be used for starting downloads,
|
||||
@ -31,6 +38,16 @@ public class DownloadRequester {
|
||||
public static final String FEED_DOWNLOADPATH = "cache/";
|
||||
public static final String MEDIA_DOWNLOADPATH = "media/";
|
||||
|
||||
/**
|
||||
* Denotes the page of the feed that is contained in the DownloadRequest sent by the DownloadRequester.
|
||||
*/
|
||||
public static final String REQUEST_ARG_PAGE_NR = "page";
|
||||
|
||||
/**
|
||||
* True if all pages after the feed that is contained in this DownloadRequest should be downloaded.
|
||||
*/
|
||||
public static final String REQUEST_ARG_LOAD_ALL_PAGES = "loadAllPages";
|
||||
|
||||
private static DownloadRequester downloader;
|
||||
|
||||
private Map<String, DownloadRequest> downloads;
|
||||
@ -74,7 +91,7 @@ public class DownloadRequester {
|
||||
}
|
||||
|
||||
private void download(Context context, FeedFile item, File dest,
|
||||
boolean overwriteIfExists, String username, String password, boolean deleteOnFailure) {
|
||||
boolean overwriteIfExists, String username, String password, boolean deleteOnFailure, Bundle arguments) {
|
||||
if (!isDownloadingFile(item)) {
|
||||
if (!isFilenameAvailable(dest.toString()) || (deleteOnFailure && dest.exists())) {
|
||||
if (BuildConfig.DEBUG)
|
||||
@ -116,7 +133,7 @@ public class DownloadRequester {
|
||||
|
||||
DownloadRequest request = new DownloadRequest(dest.toString(),
|
||||
URLChecker.prepareURL(item.getDownload_url()), item.getHumanReadableIdentifier(),
|
||||
item.getId(), item.getTypeAsInt(), username, password, deleteOnFailure);
|
||||
item.getId(), item.getTypeAsInt(), username, password, deleteOnFailure, arguments);
|
||||
|
||||
download(context, request);
|
||||
} else {
|
||||
@ -144,22 +161,30 @@ public class DownloadRequester {
|
||||
return true;
|
||||
}
|
||||
|
||||
public synchronized void downloadFeed(Context context, Feed feed)
|
||||
public synchronized void downloadFeed(Context context, Feed feed, boolean loadAllPages)
|
||||
throws DownloadRequestException {
|
||||
if (feedFileValid(feed)) {
|
||||
String username = (feed.getPreferences() != null) ? feed.getPreferences().getUsername() : null;
|
||||
String password = (feed.getPreferences() != null) ? feed.getPreferences().getPassword() : null;
|
||||
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(REQUEST_ARG_PAGE_NR, feed.getPageNr());
|
||||
args.putBoolean(REQUEST_ARG_LOAD_ALL_PAGES, loadAllPages);
|
||||
|
||||
download(context, feed, new File(getFeedfilePath(context),
|
||||
getFeedfileName(feed)), true, username, password, true);
|
||||
getFeedfileName(feed)), true, username, password, true, args);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void downloadFeed(Context context, Feed feed) throws DownloadRequestException {
|
||||
downloadFeed(context, feed, false);
|
||||
}
|
||||
|
||||
public synchronized void downloadImage(Context context, FeedImage image)
|
||||
throws DownloadRequestException {
|
||||
if (feedFileValid(image)) {
|
||||
download(context, image, new File(getImagefilePath(context),
|
||||
getImagefileName(image)), false, null, null, false);
|
||||
getImagefileName(image)), false, null, null, false, null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -185,8 +210,7 @@ public class DownloadRequester {
|
||||
getMediafilename(feedmedia));
|
||||
}
|
||||
download(context, feedmedia,
|
||||
dest, false, username, password, false
|
||||
);
|
||||
dest, false, username, password, false, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,9 @@ public class PodDBAdapter {
|
||||
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;
|
||||
public static final int KEY_IS_PAGED_INDEX = 17;
|
||||
public static final int KEY_LOAD_ALL_PAGES_INDEX = 18;
|
||||
public static final int KEY_NEXT_PAGE_LINK_INDEX = 19;
|
||||
// ----------- FeedItem indices
|
||||
public static final int KEY_CONTENT_ENCODED_INDEX = 2;
|
||||
public static final int KEY_PUBDATE_INDEX = 3;
|
||||
@ -144,6 +147,8 @@ public class PodDBAdapter {
|
||||
public static final String KEY_PLAYED_DURATION = "played_duration";
|
||||
public static final String KEY_USERNAME = "username";
|
||||
public static final String KEY_PASSWORD = "password";
|
||||
public static final String KEY_IS_PAGED = "is_paged";
|
||||
public static final String KEY_NEXT_PAGE_LINK = "next_page_link";
|
||||
|
||||
// Table names
|
||||
public static final String TABLE_NAME_FEEDS = "Feeds";
|
||||
@ -168,7 +173,10 @@ public class PodDBAdapter {
|
||||
+ KEY_FEED_IDENTIFIER + " TEXT," + KEY_AUTO_DOWNLOAD + " INTEGER DEFAULT 1,"
|
||||
+ KEY_FLATTR_STATUS + " INTEGER,"
|
||||
+ KEY_USERNAME + " TEXT,"
|
||||
+ KEY_PASSWORD + " TEXT)";
|
||||
+ KEY_PASSWORD + " TEXT,"
|
||||
+ KEY_IS_PAGED + " INTEGER DEFAULT 0,"
|
||||
+ KEY_NEXT_PAGE_LINK + " TEXT)";
|
||||
|
||||
|
||||
public static final String CREATE_TABLE_FEED_ITEMS = "CREATE TABLE "
|
||||
+ TABLE_NAME_FEED_ITEMS + " (" + TABLE_PRIMARY_KEY + KEY_TITLE
|
||||
@ -234,8 +242,10 @@ public class PodDBAdapter {
|
||||
TABLE_NAME_FEEDS + "." + KEY_FEED_IDENTIFIER,
|
||||
TABLE_NAME_FEEDS + "." + KEY_AUTO_DOWNLOAD,
|
||||
TABLE_NAME_FEEDS + "." + KEY_FLATTR_STATUS,
|
||||
TABLE_NAME_FEEDS + "." + KEY_IS_PAGED,
|
||||
TABLE_NAME_FEEDS + "." + KEY_NEXT_PAGE_LINK,
|
||||
TABLE_NAME_FEEDS + "." + KEY_USERNAME,
|
||||
TABLE_NAME_FEEDS + "." + KEY_PASSWORD
|
||||
TABLE_NAME_FEEDS + "." + KEY_PASSWORD,
|
||||
};
|
||||
|
||||
// column indices for FEED_SEL_STD
|
||||
@ -255,8 +265,10 @@ public class PodDBAdapter {
|
||||
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;
|
||||
public static final int IDX_FEED_SEL_STD_IS_PAGED = 16;
|
||||
public static final int IDX_FEED_SEL_STD_NEXT_PAGE_LINK = 17;
|
||||
public static final int IDX_FEED_SEL_PREFERENCES_USERNAME = 18;
|
||||
public static final int IDX_FEED_SEL_PREFERENCES_PASSWORD = 19;
|
||||
|
||||
|
||||
/**
|
||||
@ -386,6 +398,8 @@ public class PodDBAdapter {
|
||||
Log.d(TAG, "Setting feed with flattr status " + feed.getTitle() + ": " + feed.getFlattrStatus().toLong());
|
||||
|
||||
values.put(KEY_FLATTR_STATUS, feed.getFlattrStatus().toLong());
|
||||
values.put(KEY_IS_PAGED, feed.isPaged());
|
||||
values.put(KEY_NEXT_PAGE_LINK, feed.getNextPageLink());
|
||||
if (feed.getId() == 0) {
|
||||
// Create new entry
|
||||
if (BuildConfig.DEBUG)
|
||||
|
@ -1,9 +1,9 @@
|
||||
package de.danoeh.antennapod.core.syndication.handler;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
|
||||
/**
|
||||
* Container for results returned by the Feed parser
|
||||
*/
|
||||
|
@ -1,6 +1,9 @@
|
||||
package de.danoeh.antennapod.core.syndication.namespace.atom;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
|
||||
import de.danoeh.antennapod.core.BuildConfig;
|
||||
import de.danoeh.antennapod.core.feed.FeedImage;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
@ -12,7 +15,6 @@ import de.danoeh.antennapod.core.syndication.namespace.Namespace;
|
||||
import de.danoeh.antennapod.core.syndication.namespace.SyndElement;
|
||||
import de.danoeh.antennapod.core.syndication.util.SyndDateUtils;
|
||||
import de.danoeh.antennapod.core.syndication.util.SyndTypeUtils;
|
||||
import org.xml.sax.Attributes;
|
||||
|
||||
public class NSAtom extends Namespace {
|
||||
private static final String TAG = "NSAtom";
|
||||
@ -44,6 +46,7 @@ public class NSAtom extends Namespace {
|
||||
private static final String LINK_REL_PAYMENT = "payment";
|
||||
private static final String LINK_REL_RELATED = "related";
|
||||
private static final String LINK_REL_SELF = "self";
|
||||
private static final String LINK_REL_NEXT = "next";
|
||||
// type-values
|
||||
private static final String LINK_TYPE_ATOM = "application/atom+xml";
|
||||
private static final String LINK_TYPE_HTML = "text/html";
|
||||
@ -120,6 +123,9 @@ public class NSAtom extends Namespace {
|
||||
}
|
||||
} else if (rel.equals(LINK_REL_PAYMENT)) {
|
||||
state.getFeed().setPaymentLink(href);
|
||||
} else if (rel.equals(LINK_REL_NEXT)) {
|
||||
state.getFeed().setPaged(true);
|
||||
state.getFeed().setNextPageLink(href);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,56 @@
|
||||
package de.danoeh.antennapod.core.util.gui;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import de.danoeh.antennapod.core.R;
|
||||
|
||||
/**
|
||||
* Utility methods for the more_content_list_footer layout.
|
||||
*/
|
||||
public class MoreContentListFooterUtil {
|
||||
|
||||
private final View root;
|
||||
|
||||
private boolean loading;
|
||||
|
||||
private Listener listener;
|
||||
|
||||
public MoreContentListFooterUtil(View root) {
|
||||
this.root = root;
|
||||
root.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (listener != null && !loading) {
|
||||
listener.onClick();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setLoadingState(boolean newState) {
|
||||
final ImageView imageView = (ImageView) root.findViewById(R.id.imgExpand);
|
||||
final ProgressBar progressBar = (ProgressBar) root.findViewById(R.id.progBar);
|
||||
if (newState) {
|
||||
imageView.setVisibility(View.GONE);
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
imageView.setVisibility(View.VISIBLE);
|
||||
progressBar.setVisibility(View.GONE);
|
||||
}
|
||||
loading = newState;
|
||||
}
|
||||
|
||||
public void setClickListener(Listener l) {
|
||||
listener = l;
|
||||
}
|
||||
|
||||
public static interface Listener {
|
||||
public void onClick();
|
||||
}
|
||||
|
||||
public View getRoot() {
|
||||
return root;
|
||||
}
|
||||
}
|
26
core/src/main/res/layout/more_content_list_footer.xml
Normal file
26
core/src/main/res/layout/more_content_list_footer.xml
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/selectableItemBackground">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgExpand"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_margin="16dp"
|
||||
android:contentDescription="@string/load_next_page_label"
|
||||
android:src="?attr/navigation_expand" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_margin="16dp"
|
||||
android:indeterminateOnly="true"
|
||||
android:visibility="gone" />
|
||||
|
||||
</FrameLayout>
|
@ -85,6 +85,7 @@
|
||||
<string name="share_source_label">Share feed link</string>
|
||||
<string name="feed_delete_confirmation_msg">Please confirm that you want to delete this feed and ALL episodes of this feed that you have downloaded.</string>
|
||||
<string name="feed_remover_msg">Removing feed</string>
|
||||
<string name="load_complete_feed">Load complete feed</string>
|
||||
|
||||
<!-- actions on feeditems -->
|
||||
<string name="download_label">Download</string>
|
||||
@ -369,6 +370,7 @@
|
||||
<string name="new_episodes_count_label">Number of new episodes</string>
|
||||
<string name="in_progress_episodes_count_label">Number of episodes you have started listening to</string>
|
||||
<string name="drag_handle_content_description">Drag to change the position of this item</string>
|
||||
<string name="load_next_page_label">Load next page</string>
|
||||
|
||||
<!-- Feed information screen -->
|
||||
<string name="authentication_label">Authentication</string>
|
||||
|
Loading…
Reference in New Issue
Block a user