private Integer syncToSeriesGuide(ServiceManager manager, String username) { mResult = ""; List<TvShow> shows; try { // get watched episodes from trakt shows = manager.userService().libraryShowsWatched(username).extended(ExtendedParam.Min).fire(); } catch (TraktException e) { fireTrackerEventToSeriesGuide(e.getMessage()); Log.w(TAG, e); return FAILED_API; } catch (ApiException e) { fireTrackerEventToSeriesGuide(e.getMessage()); Log.w(TAG, e); return FAILED_API; } // get show ids in local database Cursor showTvdbIds = mContext .getContentResolver() .query(Shows.CONTENT_URI, new String[] {Shows._ID}, null, null, null); // assume we have a local list of which shows to sync (later...) while (showTvdbIds.moveToNext()) { String tvdbId = showTvdbIds.getString(0); for (TvShow tvShow : shows) { if (tvdbId.equalsIgnoreCase(tvShow.tvdbId)) { if (mResult.length() != 0) { mResult += ", "; } if (mIsSyncingUnseen) { ContentValues values = new ContentValues(); values.put(Episodes.WATCHED, false); mContext .getContentResolver() .update(Episodes.buildEpisodesOfShowUri(tvdbId), values, null, null); } final ArrayList<ContentProviderOperation> batch = Lists.newArrayList(); // go through watched seasons, try to match them with local // season List<TvShowSeason> seasons = tvShow.seasons; for (TvShowSeason season : seasons) { Cursor seasonMatch = mContext .getContentResolver() .query( Seasons.buildSeasonsOfShowUri(tvdbId), new String[] {Seasons._ID}, Seasons.COMBINED + "=?", new String[] {season.season.toString()}, null); // if we found a season, go on with its episodes if (seasonMatch.moveToFirst()) { String seasonId = seasonMatch.getString(0); // build episodes update query to mark seen episodes for (Integer episode : season.episodes.numbers) { batch.add( ContentProviderOperation.newUpdate(Episodes.buildEpisodesOfSeasonUri(seasonId)) .withSelection(Episodes.NUMBER + "=?", new String[] {episode.toString()}) .withValue(Episodes.WATCHED, true) .build()); } } seasonMatch.close(); } // last chance to abort before doing work if (isCancelled()) { showTvdbIds.close(); return null; } try { mContext.getContentResolver().applyBatch(SeriesContract.CONTENT_AUTHORITY, batch); } catch (RemoteException e) { // Failed binder transactions aren't recoverable fireTrackerEventToSeriesGuide(e.getMessage()); throw new RuntimeException("Problem applying batch operation", e); } catch (OperationApplicationException e) { // Failures like constraint violation aren't // recoverable fireTrackerEventToSeriesGuide(e.getMessage()); throw new RuntimeException("Problem applying batch operation", e); } mResult += tvShow.title; // remove synced show shows.remove(tvShow); break; } } } showTvdbIds.close(); if (mResult.length() != 0) { return SUCCESS_WORK; } else { return SUCCESS_NOWORK; } }
/** * Adds a show and its episodes. If it already exists updates them. This uses two consequent * connections. The first one downloads the base series record, to check if the show is already in * the database. The second downloads all episode information. This allows for a smaller download, * if a show already exists in your database. * * @param showId * @param seenShows * @return true if show and its episodes were added, false if it already exists * @throws IOException * @throws SAXException */ public static boolean addShow(String showId, List<TvShow> seenShows, Context context) throws SAXException { String language = getTheTVDBLanguage(context); Series show = fetchShow(showId, language, context); boolean isShowExists = DBUtils.isShowExists(showId, context); final ArrayList<ContentProviderOperation> batch = Lists.newArrayList(); batch.add(DBUtils.buildShowOp(show, context, !isShowExists)); batch.addAll(importShowEpisodes(showId, show.getAirsTime(), language, context)); try { context.getContentResolver().applyBatch(SeriesContract.CONTENT_AUTHORITY, batch); } catch (RemoteException e) { // Failed binder transactions aren't recoverable throw new RuntimeException("Problem applying batch operation", e); } catch (OperationApplicationException e) { // Failures like constraint violation aren't recoverable throw new RuntimeException("Problem applying batch operation", e); } // try to find seen episodes from trakt for (TvShow tvShow : seenShows) { if (showId.equals(tvShow.tvdbId)) { batch.clear(); // try to find matching seasons final List<TvShowSeason> seasons = tvShow.seasons; for (TvShowSeason season : seasons) { final Cursor seasonMatch = context .getContentResolver() .query( Seasons.buildSeasonsOfShowUri(showId), new String[] {Seasons._ID}, Seasons.COMBINED + "=?", new String[] {season.season.toString()}, null); // add ops to mark episodes as watched if (seasonMatch.moveToFirst()) { final String seasonId = seasonMatch.getString(0); for (Integer episode : season.episodes.numbers) { batch.add( ContentProviderOperation.newUpdate(Episodes.buildEpisodesOfSeasonUri(seasonId)) .withSelection(Episodes.NUMBER + "=?", new String[] {episode.toString()}) .withValue(Episodes.WATCHED, true) .build()); } } seasonMatch.close(); } try { context.getContentResolver().applyBatch(SeriesContract.CONTENT_AUTHORITY, batch); } catch (RemoteException e) { // Failed binder transactions aren't recoverable throw new RuntimeException("Problem applying batch operation", e); } catch (OperationApplicationException e) { // Failures like constraint violation aren't // recoverable throw new RuntimeException("Problem applying batch operation", e); } break; } } DBUtils.updateLatestEpisode(context, showId); return !isShowExists; }