Search in sources :

Example 1 with DownloadStatus

use of de.danoeh.antennapod.core.service.download.DownloadStatus in project AntennaPod by AntennaPod.

the class FeedParserTask method call.

@Override
public FeedHandlerResult call() {
    Feed feed = new Feed(request.getSource(), request.getLastModified());
    feed.setFile_url(request.getDestination());
    feed.setId(request.getFeedfileId());
    feed.setDownloaded(true);
    feed.setPreferences(new FeedPreferences(0, true, FeedPreferences.AutoDeleteAction.GLOBAL, VolumeAdaptionSetting.OFF, request.getUsername(), request.getPassword()));
    feed.setPageNr(request.getArguments().getInt(DownloadRequest.REQUEST_ARG_PAGE_NR, 0));
    DownloadError reason = null;
    String reasonDetailed = null;
    FeedHandler feedHandler = new FeedHandler();
    FeedHandlerResult result = null;
    try {
        result = feedHandler.parseFeed(feed);
        Log.d(TAG, feed.getTitle() + " parsed");
        checkFeedData(feed);
    } catch (SAXException | IOException | 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;
        if ("html".equalsIgnoreCase(e.getRootElement())) {
            reason = DownloadError.ERROR_UNSUPPORTED_TYPE_HTML;
        }
        reasonDetailed = e.getMessage();
    } catch (InvalidFeedException e) {
        e.printStackTrace();
        successful = false;
        reason = DownloadError.ERROR_PARSER_EXCEPTION;
        reasonDetailed = e.getMessage();
    } finally {
        File feedFile = new File(request.getDestination());
        if (feedFile.exists()) {
            boolean deleted = feedFile.delete();
            Log.d(TAG, "Deletion of file '" + feedFile.getAbsolutePath() + "' " + (deleted ? "successful" : "FAILED"));
        }
    }
    if (successful) {
        downloadStatus = new DownloadStatus(feed, feed.getHumanReadableIdentifier(), DownloadError.SUCCESS, successful, reasonDetailed, request.isInitiatedByUser());
        return result;
    } else {
        downloadStatus = new DownloadStatus(feed, feed.getTitle(), reason, successful, reasonDetailed, request.isInitiatedByUser());
        return null;
    }
}
Also used : FeedPreferences(de.danoeh.antennapod.model.feed.FeedPreferences) InvalidFeedException(de.danoeh.antennapod.core.util.InvalidFeedException) UnsupportedFeedtypeException(de.danoeh.antennapod.parser.feed.UnsupportedFeedtypeException) FeedHandlerResult(de.danoeh.antennapod.parser.feed.FeedHandlerResult) IOException(java.io.IOException) SAXException(org.xml.sax.SAXException) DownloadError(de.danoeh.antennapod.core.util.DownloadError) FeedHandler(de.danoeh.antennapod.parser.feed.FeedHandler) DownloadStatus(de.danoeh.antennapod.core.service.download.DownloadStatus) ParserConfigurationException(javax.xml.parsers.ParserConfigurationException) File(java.io.File) Feed(de.danoeh.antennapod.model.feed.Feed)

Example 2 with DownloadStatus

use of de.danoeh.antennapod.core.service.download.DownloadStatus in project AntennaPod by AntennaPod.

the class DBReader method getDownloadLog.

/**
 * Loads the download log from the database.
 *
 * @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() {
    Log.d(TAG, "getDownloadLog() called");
    PodDBAdapter adapter = PodDBAdapter.getInstance();
    adapter.open();
    try (Cursor cursor = adapter.getDownloadLogCursor(DOWNLOAD_LOG_SIZE)) {
        List<DownloadStatus> downloadLog = new ArrayList<>(cursor.getCount());
        while (cursor.moveToNext()) {
            downloadLog.add(DownloadStatus.fromCursor(cursor));
        }
        Collections.sort(downloadLog, new DownloadStatusComparator());
        return downloadLog;
    } finally {
        adapter.close();
    }
}
Also used : DownloadStatus(de.danoeh.antennapod.core.service.download.DownloadStatus) ArrayList(java.util.ArrayList) Cursor(android.database.Cursor) DownloadStatusComparator(de.danoeh.antennapod.core.util.comparator.DownloadStatusComparator)

Example 3 with DownloadStatus

use of de.danoeh.antennapod.core.service.download.DownloadStatus in project AntennaPod by AntennaPod.

the class DBTasks method updateFeed.

/**
 * 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 with the exception of the most recent FeedItem.
 * <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 newFeed The new Feed object.
 * @param removeUnlistedItems The item list in the new Feed object is considered to be exhaustive.
 *                            I.e. items are removed from the database if they are not in this item list.
 * @return The updated Feed from the database if it already existed, or the new Feed from the parameters otherwise.
 */
public static synchronized Feed updateFeed(Context context, Feed newFeed, boolean removeUnlistedItems) {
    Feed resultFeed;
    List<FeedItem> unlistedItems = new ArrayList<>();
    PodDBAdapter adapter = PodDBAdapter.getInstance();
    adapter.open();
    // Look up feed in the feedslist
    final Feed savedFeed = searchFeedByIdentifyingValueOrID(adapter, newFeed);
    if (savedFeed == null) {
        Log.d(TAG, "Found no existing Feed with title " + newFeed.getTitle() + ". Adding as new one.");
        // Add a new Feed
        // all new feeds will have the most recent item marked as unplayed
        FeedItem mostRecent = newFeed.getMostRecentItem();
        if (mostRecent != null) {
            mostRecent.setNew();
        }
        resultFeed = newFeed;
    } else {
        Log.d(TAG, "Feed with title " + newFeed.getTitle() + " already exists. Syncing new with existing one.");
        Collections.sort(newFeed.getItems(), new FeedItemPubdateComparator());
        if (newFeed.getPageNr() == savedFeed.getPageNr()) {
            if (savedFeed.compareWithOther(newFeed)) {
                Log.d(TAG, "Feed has updated attribute values. Updating old feed's attributes");
                savedFeed.updateFromOther(newFeed);
            }
        } else {
            Log.d(TAG, "New feed has a higher page number.");
            savedFeed.setNextPageLink(newFeed.getNextPageLink());
        }
        if (savedFeed.getPreferences().compareWithOther(newFeed.getPreferences())) {
            Log.d(TAG, "Feed has updated preferences. Updating old feed's preferences");
            savedFeed.getPreferences().updateFromOther(newFeed.getPreferences());
        }
        // get the most recent date now, before we start changing the list
        FeedItem priorMostRecent = savedFeed.getMostRecentItem();
        Date priorMostRecentDate = null;
        if (priorMostRecent != null) {
            priorMostRecentDate = priorMostRecent.getPubDate();
        }
        // Look for new or updated Items
        for (int idx = 0; idx < newFeed.getItems().size(); idx++) {
            final FeedItem item = newFeed.getItems().get(idx);
            FeedItem possibleDuplicate = searchFeedItemGuessDuplicate(newFeed.getItems(), item);
            if (!newFeed.isLocalFeed() && possibleDuplicate != null && item != possibleDuplicate) {
                // Canonical episode is the first one returned (usually oldest)
                DBWriter.addDownloadStatus(new DownloadStatus(savedFeed, item.getTitle(), DownloadError.ERROR_PARSER_EXCEPTION_DUPLICATE, false, "The podcast host appears to have added the same episode twice. " + "AntennaPod still refreshed the feed and attempted to repair it." + "\n\nOriginal episode:\n" + duplicateEpisodeDetails(item) + "\n\nSecond episode that is also in the feed:\n" + duplicateEpisodeDetails(possibleDuplicate), false));
                continue;
            }
            FeedItem oldItem = searchFeedItemByIdentifyingValue(savedFeed.getItems(), item);
            if (!newFeed.isLocalFeed() && oldItem == null) {
                oldItem = searchFeedItemGuessDuplicate(savedFeed.getItems(), item);
                if (oldItem != null) {
                    Log.d(TAG, "Repaired duplicate: " + oldItem + ", " + item);
                    DBWriter.addDownloadStatus(new DownloadStatus(savedFeed, item.getTitle(), DownloadError.ERROR_PARSER_EXCEPTION_DUPLICATE, false, "The podcast host changed the ID of an existing episode instead of just " + "updating the episode itself. AntennaPod still refreshed the feed and " + "attempted to repair it." + "\n\nOriginal episode:\n" + duplicateEpisodeDetails(oldItem) + "\n\nNow the feed contains:\n" + duplicateEpisodeDetails(item), false));
                    oldItem.setItemIdentifier(item.getItemIdentifier());
                    if (oldItem.isPlayed() && oldItem.getMedia() != null) {
                        EpisodeAction action = new EpisodeAction.Builder(oldItem, EpisodeAction.PLAY).currentTimestamp().started(oldItem.getMedia().getDuration() / 1000).position(oldItem.getMedia().getDuration() / 1000).total(oldItem.getMedia().getDuration() / 1000).build();
                        SynchronizationQueueSink.enqueueEpisodeActionIfSynchronizationIsActive(context, action);
                    }
                }
            }
            if (oldItem != null) {
                oldItem.updateFromOther(item);
            } else {
                // item is new
                item.setFeed(savedFeed);
                if (idx >= savedFeed.getItems().size()) {
                    savedFeed.getItems().add(item);
                } else {
                    savedFeed.getItems().add(idx, item);
                }
                // New items that do not have a pubDate set are always marked as new
                if (item.getPubDate() == null || priorMostRecentDate == null || priorMostRecentDate.before(item.getPubDate()) || priorMostRecentDate.equals(item.getPubDate())) {
                    Log.d(TAG, "Marking item published on " + item.getPubDate() + " new, prior most recent date = " + priorMostRecentDate);
                    item.setNew();
                }
            }
        }
        // identify items to be removed
        if (removeUnlistedItems) {
            Iterator<FeedItem> it = savedFeed.getItems().iterator();
            while (it.hasNext()) {
                FeedItem feedItem = it.next();
                if (searchFeedItemByIdentifyingValue(newFeed.getItems(), feedItem) == null) {
                    unlistedItems.add(feedItem);
                    it.remove();
                }
            }
        }
        // update attributes
        savedFeed.setLastUpdate(newFeed.getLastUpdate());
        savedFeed.setType(newFeed.getType());
        savedFeed.setLastUpdateFailed(false);
        resultFeed = savedFeed;
    }
    try {
        if (savedFeed == null) {
            DBWriter.addNewFeed(context, newFeed).get();
            // Update with default values that are set in database
            resultFeed = searchFeedByIdentifyingValueOrID(adapter, newFeed);
        } else {
            DBWriter.setCompleteFeed(savedFeed).get();
        }
        if (removeUnlistedItems) {
            DBWriter.deleteFeedItems(context, unlistedItems).get();
        }
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
    adapter.close();
    if (savedFeed != null) {
        EventBus.getDefault().post(new FeedListUpdateEvent(savedFeed));
    } else {
        EventBus.getDefault().post(new FeedListUpdateEvent(Collections.emptyList()));
    }
    return resultFeed;
}
Also used : ArrayList(java.util.ArrayList) Date(java.util.Date) EpisodeAction(de.danoeh.antennapod.net.sync.model.EpisodeAction) FeedItemPubdateComparator(de.danoeh.antennapod.core.util.comparator.FeedItemPubdateComparator) FeedItem(de.danoeh.antennapod.model.feed.FeedItem) DownloadStatus(de.danoeh.antennapod.core.service.download.DownloadStatus) ExecutionException(java.util.concurrent.ExecutionException) FeedListUpdateEvent(de.danoeh.antennapod.event.FeedListUpdateEvent) Feed(de.danoeh.antennapod.model.feed.Feed)

Example 4 with DownloadStatus

use of de.danoeh.antennapod.core.service.download.DownloadStatus in project AntennaPod by AntennaPod.

the class HttpDownloaderTest method download.

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, null, false);
    Downloader downloader = new HttpDownloader(request);
    downloader.call();
    DownloadStatus status = downloader.getResult();
    assertNotNull(status);
    assertEquals(expectedResult, status.isSuccessful());
    assertTrue(status.isDone());
    // the file should not exist if the download has failed and deleteExisting was true
    assertTrue(!deleteExisting || new File(feedFile.getFile_url()).exists() == expectedResult);
    return downloader;
}
Also used : HttpDownloader(de.danoeh.antennapod.core.service.download.HttpDownloader) DownloadStatus(de.danoeh.antennapod.core.service.download.DownloadStatus) FeedFile(de.danoeh.antennapod.model.feed.FeedFile) DownloadRequest(de.danoeh.antennapod.core.service.download.DownloadRequest) Downloader(de.danoeh.antennapod.core.service.download.Downloader) HttpDownloader(de.danoeh.antennapod.core.service.download.HttpDownloader) File(java.io.File) FeedFile(de.danoeh.antennapod.model.feed.FeedFile)

Example 5 with DownloadStatus

use of de.danoeh.antennapod.core.service.download.DownloadStatus in project AntennaPod by AntennaPod.

the class DownloadLogAdapter method getView.

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    DownloadLogItemViewHolder holder;
    if (convertView == null) {
        holder = new DownloadLogItemViewHolder(context, parent);
        holder.itemView.setTag(holder);
    } else {
        holder = (DownloadLogItemViewHolder) convertView.getTag();
    }
    Object item = getItem(position);
    if (item instanceof DownloadStatus) {
        bind(holder, (DownloadStatus) item, position);
    } else if (item instanceof Downloader) {
        bind(holder, (Downloader) item, position);
    }
    return holder.itemView;
}
Also used : DownloadLogItemViewHolder(de.danoeh.antennapod.view.viewholder.DownloadLogItemViewHolder) DownloadStatus(de.danoeh.antennapod.core.service.download.DownloadStatus) Downloader(de.danoeh.antennapod.core.service.download.Downloader)

Aggregations

DownloadStatus (de.danoeh.antennapod.core.service.download.DownloadStatus)14 ArrayList (java.util.ArrayList)6 Downloader (de.danoeh.antennapod.core.service.download.Downloader)5 DownloadRequest (de.danoeh.antennapod.core.service.download.DownloadRequest)4 Feed (de.danoeh.antennapod.model.feed.Feed)4 File (java.io.File)4 Cursor (android.database.Cursor)3 DownloadStatusComparator (de.danoeh.antennapod.core.util.comparator.DownloadStatusComparator)3 FeedItem (de.danoeh.antennapod.model.feed.FeedItem)3 FeedMedia (de.danoeh.antennapod.model.feed.FeedMedia)3 Log (android.util.Log)2 View (android.view.View)2 ListFragment (androidx.fragment.app.ListFragment)2 R (de.danoeh.antennapod.R)2 MainActivity (de.danoeh.antennapod.activity.MainActivity)2 DownloadService (de.danoeh.antennapod.core.service.download.DownloadService)2 DBReader (de.danoeh.antennapod.core.storage.DBReader)2 List (java.util.List)2 Activity (android.app.Activity)1 Dialog (android.app.Dialog)1