use of android.content.ContentProviderOperation in project SeriesGuide by UweTrottmann.
the class SeriesGuideProvider method applyBatch.
/**
* Apply the given set of {@link ContentProviderOperation}, executing inside a {@link
* SQLiteDatabase} transaction. All changes will be rolled back if any single one fails.
*/
@NonNull
@Override
public ContentProviderResult[] applyBatch(@NonNull ArrayList<ContentProviderOperation> operations) throws OperationApplicationException {
final int numOperations = operations.size();
if (numOperations == 0) {
return new ContentProviderResult[0];
}
mDb = mDbHelper.getWritableDatabase();
mDb.beginTransaction();
try {
mApplyingBatch.set(true);
final ContentProviderResult[] results = new ContentProviderResult[numOperations];
for (int i = 0; i < numOperations; i++) {
final ContentProviderOperation operation = operations.get(i);
if (i > 0 && operation.isYieldAllowed()) {
mDb.yieldIfContendedSafely();
}
results[i] = operation.apply(this, results, i);
}
mDb.setTransactionSuccessful();
return results;
} finally {
mApplyingBatch.set(false);
mDb.endTransaction();
}
}
use of android.content.ContentProviderOperation in project SeriesGuide by UweTrottmann.
the class DBUtils method buildSeasonOp.
/**
* Creates a {@link ContentProviderOperation} for insert if isNew, or update instead for with
* the given season values.
*/
public static ContentProviderOperation buildSeasonOp(ContentValues values, boolean isNew) {
ContentProviderOperation op;
final String seasonId = values.getAsString(Seasons.REF_SEASON_ID);
final ContentValues seasonValues = new ContentValues();
seasonValues.put(Seasons.COMBINED, values.getAsString(Episodes.SEASON));
if (isNew) {
seasonValues.put(Seasons._ID, seasonId);
seasonValues.put(Shows.REF_SHOW_ID, values.getAsString(Shows.REF_SHOW_ID));
op = ContentProviderOperation.newInsert(Seasons.CONTENT_URI).withValues(seasonValues).build();
} else {
op = ContentProviderOperation.newUpdate(Seasons.buildSeasonUri(seasonId)).withValues(seasonValues).build();
}
return op;
}
use of android.content.ContentProviderOperation in project SeriesGuide by UweTrottmann.
the class ListsTools method removeListsRemovedOnHexagon.
public static boolean removeListsRemovedOnHexagon(SgApp app) {
Timber.d("removeListsRemovedOnHexagon");
HashSet<String> localListIds = getListIds(app);
if (localListIds == null) {
// query failed
return false;
}
if (localListIds.size() <= 1) {
// one or no list, can not remove any list
return true;
}
// get list of ids of lists on hexagon
List<String> hexagonListIds = new ArrayList<>(localListIds.size());
String cursor = null;
do {
try {
Lists listsService = app.getHexagonTools().getListsService();
if (listsService == null) {
// no longer signed in
return false;
}
Lists.GetIds request = listsService.getIds();
if (!TextUtils.isEmpty(cursor)) {
request.setCursor(cursor);
}
SgListIds response = request.execute();
if (response == null) {
Timber.d("removeListsRemovedOnHexagon: failed, response is null.");
return false;
}
List<String> listIds = response.getListIds();
if (listIds == null || listIds.size() == 0) {
// empty response, assume we got all ids
break;
}
hexagonListIds.addAll(listIds);
cursor = response.getCursor();
} catch (IOException e) {
HexagonTools.trackFailedRequest(app, "get list ids", e);
return false;
}
} while (// fetch next batch
!TextUtils.isEmpty(cursor));
if (hexagonListIds.size() <= 1) {
// one or no list on hexagon, can not remove any list
return true;
}
// exclude any lists that are on hexagon
for (String listId : hexagonListIds) {
localListIds.remove(listId);
}
// remove any list not on hexagon
if (localListIds.size() > 0) {
ArrayList<ContentProviderOperation> batch = new ArrayList<>();
for (String listId : localListIds) {
batch.add(ContentProviderOperation.newDelete(SeriesGuideContract.Lists.buildListUri(listId)).build());
}
try {
DBUtils.applyInSmallBatches(app, batch);
} catch (OperationApplicationException e) {
Timber.e(e, "removeListsRemovedOnHexagon: deleting lists failed.");
return false;
}
}
return true;
}
use of android.content.ContentProviderOperation in project SeriesGuide by UweTrottmann.
the class ActivityTools method populateShowsLastWatchedTime.
/**
* Get latest activity for each show and update last watched time if newer.
*/
public static void populateShowsLastWatchedTime(Context context) {
Cursor query = context.getContentResolver().query(Activity.CONTENT_URI, new String[] { Activity.TIMESTAMP_MS, Activity.SHOW_TVDB_ID }, null, null, Activity.SORT_LATEST);
if (query == null) {
Timber.e("populateShowsLastWatchedTime: query is null.");
return;
}
ArrayList<ContentProviderOperation> batch = new ArrayList<>();
HashSet<Integer> handledShows = new HashSet<>();
while (query.moveToNext()) {
int showTvdbId = query.getInt(1);
if (!handledShows.contains(showTvdbId)) {
handledShows.add(showTvdbId);
long lastWatchedMs = query.getLong(0);
ShowTools.addLastWatchedUpdateOpIfNewer(context, batch, showTvdbId, lastWatchedMs);
}
}
query.close();
}
use of android.content.ContentProviderOperation in project SeriesGuide by UweTrottmann.
the class TraktTools method processTraktEpisodes.
private boolean processTraktEpisodes(boolean isInitialSync, String seasonId, BaseSeason traktSeason, List<SyncSeason> syncSeasons, Flag flag) {
HashSet<Integer> traktEpisodes = buildTraktEpisodesMap(traktSeason.episodes);
Cursor localEpisodesQuery = context.getContentResolver().query(SeriesGuideContract.Episodes.buildEpisodesOfSeasonUri(seasonId), new String[] { SeriesGuideContract.Episodes._ID, SeriesGuideContract.Episodes.NUMBER, flag.databaseColumn }, null, null, null);
if (localEpisodesQuery == null) {
return false;
}
ArrayList<ContentProviderOperation> batch = new ArrayList<>();
List<SyncEpisode> syncEpisodes = new ArrayList<>();
int episodesAddFlagCount = 0;
int episodesRemoveFlagCount = 0;
while (localEpisodesQuery.moveToNext()) {
int episodeId = localEpisodesQuery.getInt(0);
int episodeNumber = localEpisodesQuery.getInt(1);
int flagValue = localEpisodesQuery.getInt(2);
boolean isFlagged = flag == Flag.WATCHED ? EpisodeTools.isWatched(flagValue) : EpisodeTools.isCollected(flagValue);
if (traktEpisodes.contains(episodeNumber)) {
// episode watched/collected on trakt
if (!isFlagged) {
// set as watched/collected
batch.add(ContentProviderOperation.newUpdate(SeriesGuideContract.Episodes.buildEpisodeUri(episodeId)).withValue(flag.databaseColumn, flag.flaggedValue).build());
episodesAddFlagCount++;
}
} else {
// episode not watched/collected on trakt
if (isFlagged) {
if (isInitialSync) {
// upload to trakt
syncEpisodes.add(new SyncEpisode().number(episodeNumber));
} else {
// set as not watched/collected if it is currently watched/collected
boolean isSkipped = flag == Flag.WATCHED && EpisodeTools.isSkipped(flagValue);
if (!isSkipped) {
batch.add(ContentProviderOperation.newUpdate(SeriesGuideContract.Episodes.buildEpisodeUri(episodeId)).withValue(flag.databaseColumn, flag.notFlaggedValue).build());
episodesRemoveFlagCount++;
}
}
}
}
}
int localEpisodeCount = localEpisodesQuery.getCount();
boolean addFlagToWholeSeason = episodesAddFlagCount == localEpisodeCount;
boolean removeFlagFromWholeSeason = episodesRemoveFlagCount == localEpisodeCount;
localEpisodesQuery.close();
// if setting the whole season as (not) watched/collected, replace with single db op
if (addFlagToWholeSeason || removeFlagFromWholeSeason) {
batch.clear();
batch.add(ContentProviderOperation.newUpdate(SeriesGuideContract.Episodes.buildEpisodesOfSeasonUri(seasonId)).withValue(flag.databaseColumn, addFlagToWholeSeason ? flag.flaggedValue : flag.notFlaggedValue).build());
}
try {
DBUtils.applyInSmallBatches(context, batch);
} catch (OperationApplicationException e) {
Timber.e(e, "Episodes watched/collected values database update failed.");
}
if (syncEpisodes.size() > 0) {
syncSeasons.add(new SyncSeason().number(traktSeason.number).episodes(syncEpisodes));
}
return true;
}
Aggregations