Search in sources :

Example 21 with ContentProviderOperation

use of android.content.ContentProviderOperation in project Signal-Android by WhisperSystems.

the class ContactsDatabase method setRegisteredUsers.

@NonNull
public synchronized List<String> setRegisteredUsers(@NonNull Account account, @NonNull String localNumber, @NonNull List<ContactTokenDetails> registeredContacts, boolean remove) throws RemoteException, OperationApplicationException {
    Map<String, ContactTokenDetails> registeredNumbers = new HashMap<>();
    List<String> addedNumbers = new LinkedList<>();
    ArrayList<ContentProviderOperation> operations = new ArrayList<>();
    Map<String, SignalContact> currentContacts = getSignalRawContacts(account, localNumber);
    for (ContactTokenDetails registeredContact : registeredContacts) {
        String registeredNumber = registeredContact.getNumber();
        registeredNumbers.put(registeredNumber, registeredContact);
        if (!currentContacts.containsKey(registeredNumber)) {
            Optional<SystemContactInfo> systemContactInfo = getSystemContactInfo(registeredNumber, localNumber);
            if (systemContactInfo.isPresent()) {
                Log.w(TAG, "Adding number: " + registeredNumber);
                addedNumbers.add(registeredNumber);
                addTextSecureRawContact(operations, account, systemContactInfo.get().number, systemContactInfo.get().name, systemContactInfo.get().id, true);
            }
        }
    }
    for (Map.Entry<String, SignalContact> currentContactEntry : currentContacts.entrySet()) {
        ContactTokenDetails tokenDetails = registeredNumbers.get(currentContactEntry.getKey());
        if (tokenDetails == null) {
            if (remove) {
                Log.w(TAG, "Removing number: " + currentContactEntry.getKey());
                removeTextSecureRawContact(operations, account, currentContactEntry.getValue().getId());
            }
        } else if (!currentContactEntry.getValue().isVoiceSupported()) {
            Log.w(TAG, "Adding voice support: " + currentContactEntry.getKey());
            addContactVoiceSupport(operations, currentContactEntry.getKey(), currentContactEntry.getValue().getId());
        } else if (!Util.isStringEquals(currentContactEntry.getValue().getRawDisplayName(), currentContactEntry.getValue().getAggregateDisplayName())) {
            Log.w(TAG, "Updating display name: " + currentContactEntry.getKey());
            updateDisplayName(operations, currentContactEntry.getValue().getAggregateDisplayName(), currentContactEntry.getValue().getId(), currentContactEntry.getValue().getDisplayNameSource());
        }
    }
    if (!operations.isEmpty()) {
        context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, operations);
    }
    return addedNumbers;
}
Also used : ContentProviderOperation(android.content.ContentProviderOperation) HashMap(java.util.HashMap) ContactTokenDetails(org.whispersystems.signalservice.api.push.ContactTokenDetails) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) HashMap(java.util.HashMap) Map(java.util.Map) NonNull(android.support.annotation.NonNull)

Example 22 with ContentProviderOperation

use of android.content.ContentProviderOperation in project SeriesGuide by UweTrottmann.

the class TvdbTools method addShow.

/**
     * Adds a show and its episodes to the database. If the show already exists, does nothing.
     *
     * <p> If signed in to Hexagon, gets show properties and episode flags.
     *
     * <p> If connected to trakt, but not signed in to Hexagon, gets episode flags from trakt
     * instead.
     *
     * @return True, if the show and its episodes were added to the database.
     */
public boolean addShow(int showTvdbId, @Nullable String language, @Nullable HashMap<Integer, BaseShow> traktCollection, @Nullable HashMap<Integer, BaseShow> traktWatched) throws TvdbException {
    boolean isShowExists = DBUtils.isShowExists(app, showTvdbId);
    if (isShowExists) {
        return false;
    }
    // get show and determine the language to use
    Show show = getShowDetailsWithHexagon(showTvdbId, language);
    language = show.language;
    // get episodes and store everything to the database
    final ArrayList<ContentProviderOperation> batch = new ArrayList<>();
    batch.add(DBUtils.buildShowOp(app, show, true));
    getEpisodesAndUpdateDatabase(batch, show, language);
    // restore episode flags...
    if (HexagonSettings.isEnabled(app)) {
        // ...from Hexagon
        boolean success = EpisodeTools.Download.flagsFromHexagon(app, showTvdbId);
        if (!success) {
            // failed to download episode flags
            // flag show as needing an episode merge
            ContentValues values = new ContentValues();
            values.put(Shows.HEXAGON_MERGE_COMPLETE, false);
            app.getContentResolver().update(Shows.buildShowUri(showTvdbId), values, null, null);
        }
        // flag show to be auto-added (again), send (new) language to Hexagon
        app.getShowTools().sendIsAdded(showTvdbId, language);
    } else {
        // ...from trakt
        TraktTools traktTools = app.getTraktTools();
        if (!traktTools.storeEpisodeFlags(traktWatched, showTvdbId, TraktTools.Flag.WATCHED)) {
            throw new TvdbDataException("addShow: storing trakt watched episodes failed.");
        }
        if (!traktTools.storeEpisodeFlags(traktCollection, showTvdbId, TraktTools.Flag.COLLECTED)) {
            throw new TvdbDataException("addShow: storing trakt collected episodes failed.");
        }
    }
    // calculate next episode
    DBUtils.updateLatestEpisode(app, showTvdbId);
    return true;
}
Also used : ContentValues(android.content.ContentValues) ContentProviderOperation(android.content.ContentProviderOperation) ArrayList(java.util.ArrayList) BaseShow(com.uwetrottmann.trakt5.entities.BaseShow) Show(com.battlelancer.seriesguide.dataliberation.model.Show) TraktTools(com.battlelancer.seriesguide.util.TraktTools)

Example 23 with ContentProviderOperation

use of android.content.ContentProviderOperation in project SeriesGuide by UweTrottmann.

the class TvdbTools method updateShow.

/**
     * Updates a show. Adds new, updates changed and removes orphaned episodes.
     */
public void updateShow(int showTvdbId) throws TvdbException {
    // determine which translation to get
    String language = getShowLanguage(app, showTvdbId);
    if (language == null) {
        return;
    }
    final ArrayList<ContentProviderOperation> batch = new ArrayList<>();
    Show show = getShowDetails(showTvdbId, language);
    batch.add(DBUtils.buildShowOp(app, show, false));
    // get episodes in the language as returned in the TVDB show entry
    // the show might not be available in the desired language
    getEpisodesAndUpdateDatabase(batch, show, show.language);
}
Also used : ContentProviderOperation(android.content.ContentProviderOperation) ArrayList(java.util.ArrayList) BaseShow(com.uwetrottmann.trakt5.entities.BaseShow) Show(com.battlelancer.seriesguide.dataliberation.model.Show)

Example 24 with ContentProviderOperation

use of android.content.ContentProviderOperation in project SeriesGuide by UweTrottmann.

the class DBUtils method updateLatestEpisode.

/**
     * Update next episode field and unwatched episode count for the given show. If no show id is
     * passed, will update next episodes for all shows.
     *
     * @return If only one show was passed, the TVDb id of the new next episode. Otherwise -1.
     */
public static long updateLatestEpisode(Context context, Integer showTvdbIdToUpdate) {
    // get a list of shows and their last watched episodes
    Cursor shows;
    try {
        shows = context.getContentResolver().query(Shows.CONTENT_URI_WITH_LAST_EPISODE, LastWatchedEpisodeQuery.PROJECTION, showTvdbIdToUpdate != null ? Qualified.SHOWS_ID + "=" + showTvdbIdToUpdate : null, null, null);
    } catch (SQLiteException e) {
        shows = null;
        Timber.e(e, "updateLatestEpisode: show query failed.");
        postDatabaseError(e);
    }
    if (shows == null) {
        // abort completely on query failure
        Timber.e("Failed to update next episode values");
        return -1;
    }
    final List<String[]> showsLastEpisodes = new ArrayList<>();
    while (shows.moveToNext()) {
        showsLastEpisodes.add(new String[] { // 0
        shows.getString(LastWatchedEpisodeQuery.SHOW_TVDB_ID), // 1
        shows.getString(LastWatchedEpisodeQuery.LAST_EPISODE_TVDB_ID), // 2
        shows.getString(LastWatchedEpisodeQuery.LAST_EPISODE_SEASON), // 3
        shows.getString(LastWatchedEpisodeQuery.LAST_EPISODE_NUMBER), shows.getString(LastWatchedEpisodeQuery.LAST_EPISODE_FIRST_RELEASE_MS) });
    }
    shows.close();
    // pre-build next episode selection
    final boolean isNoReleasedEpisodes = DisplaySettings.isNoReleasedEpisodes(context);
    final String nextEpisodeSelection = buildNextEpisodeSelection(DisplaySettings.isHidingSpecials(context), isNoReleasedEpisodes);
    // build updated next episode values for each show
    int nextEpisodeTvdbId = -1;
    final ContentValues newShowValues = new ContentValues();
    final ArrayList<ContentProviderOperation> batch = new ArrayList<>();
    final String currentTime = String.valueOf(TimeTools.getCurrentTime(context));
    final boolean displayExactDate = DisplaySettings.isDisplayExactDate(context);
    DisplaySettings.preventSpoilers(context);
    for (String[] show : showsLastEpisodes) {
        // STEP 1: get last watched episode details
        final String showTvdbId = show[0];
        final String lastEpisodeTvdbId = show[1];
        String season = show[2];
        String number = show[3];
        String releaseTime = show[4];
        if (TextUtils.isEmpty(lastEpisodeTvdbId) || season == null || number == null || releaseTime == null) {
            // by default: no watched episodes, include all starting with special 0
            season = "-1";
            number = "-1";
            releaseTime = String.valueOf(Long.MIN_VALUE);
        }
        // STEP 2: get episode released closest afterwards; or at the same time,
        // but with a higher number
        final String[] selectionArgs;
        if (isNoReleasedEpisodes) {
            // restrict to episodes with future release date
            selectionArgs = new String[] { releaseTime, number, season, releaseTime, currentTime };
        } else {
            // restrict to episodes with any valid air date
            selectionArgs = new String[] { releaseTime, number, season, releaseTime };
        }
        Cursor next;
        try {
            next = context.getContentResolver().query(Episodes.buildEpisodesOfShowUri(showTvdbId), NextEpisodesQuery.PROJECTION, nextEpisodeSelection, selectionArgs, NextEpisodesQuery.SORTORDER);
        } catch (SQLiteException e) {
            next = null;
            Timber.e(e, "updateLatestEpisode: next episode query failed.");
            postDatabaseError(e);
        }
        if (next == null) {
            // abort completely on query failure
            Timber.e("Failed to update next episode values");
            return -1;
        }
        // STEP 3: build updated next episode values
        if (next.moveToFirst()) {
            final String nextEpisodeString;
            int seasonNumber = next.getInt(NextEpisodesQuery.SEASON);
            int episodeNumber = next.getInt(NextEpisodesQuery.NUMBER);
            if (DisplaySettings.preventSpoilers(context)) {
                // just the number, like '0x12'
                nextEpisodeString = TextTools.getEpisodeNumber(context, seasonNumber, episodeNumber);
            } else {
                // next episode text, like '0x12 Episode Name'
                nextEpisodeString = TextTools.getNextEpisodeString(context, seasonNumber, episodeNumber, next.getString(NextEpisodesQuery.TITLE));
            }
            // next release date text, e.g. "in 15 mins (Fri)"
            long releaseTimeNext = next.getLong(NextEpisodesQuery.FIRST_RELEASE_MS);
            Date actualRelease = TimeTools.applyUserOffset(context, releaseTimeNext);
            String dateTime = displayExactDate ? TimeTools.formatToLocalDateShort(context, actualRelease) : TimeTools.formatToLocalRelativeTime(context, actualRelease);
            final String nextReleaseDateString = context.getString(R.string.release_date_and_day, dateTime, TimeTools.formatToLocalDay(actualRelease));
            nextEpisodeTvdbId = next.getInt(NextEpisodesQuery.ID);
            newShowValues.put(Shows.NEXTEPISODE, nextEpisodeTvdbId);
            newShowValues.put(Shows.NEXTAIRDATEMS, releaseTimeNext);
            newShowValues.put(Shows.NEXTTEXT, nextEpisodeString);
            newShowValues.put(Shows.NEXTAIRDATETEXT, nextReleaseDateString);
        } else {
            // no next episode, set empty values
            nextEpisodeTvdbId = 0;
            newShowValues.put(Shows.NEXTEPISODE, "");
            newShowValues.put(Shows.NEXTAIRDATEMS, UNKNOWN_NEXT_RELEASE_DATE);
            newShowValues.put(Shows.NEXTTEXT, "");
            newShowValues.put(Shows.NEXTAIRDATETEXT, "");
        }
        next.close();
        // STEP 4: get remaining episodes count
        int unwatchedEpisodesCount = getUnwatchedEpisodesOfShow(context, showTvdbId);
        newShowValues.put(Shows.UNWATCHED_COUNT, unwatchedEpisodesCount);
        // update the show with the new next episode values
        batch.add(ContentProviderOperation.newUpdate(Shows.buildShowUri(showTvdbId)).withValues(newShowValues).build());
        newShowValues.clear();
    }
    try {
        DBUtils.applyInSmallBatches(context, batch);
    } catch (OperationApplicationException e) {
        Timber.e(e, "Failed to update next episode values");
        return -1;
    }
    return nextEpisodeTvdbId;
}
Also used : ContentValues(android.content.ContentValues) ContentProviderOperation(android.content.ContentProviderOperation) ArrayList(java.util.ArrayList) Cursor(android.database.Cursor) SQLiteException(android.database.sqlite.SQLiteException) Date(java.util.Date) OperationApplicationException(android.content.OperationApplicationException)

Example 25 with ContentProviderOperation

use of android.content.ContentProviderOperation in project SeriesGuide by UweTrottmann.

the class TraktTools method downloadShowRatings.

/**
     * Downloads trakt show ratings and applies the latest ones to the database.
     *
     * <p> To apply all ratings, set {@link TraktSettings#KEY_LAST_SHOWS_RATED_AT} to 0.
     */
public UpdateResult downloadShowRatings(@Nullable DateTime ratedAt) {
    if (ratedAt == null) {
        Timber.e("downloadShowRatings: null rated_at");
        return UpdateResult.INCOMPLETE;
    }
    long lastRatedAt = TraktSettings.getLastShowsRatedAt(context);
    if (!ratedAt.isAfter(lastRatedAt)) {
        // not initial sync, no ratings have changed
        Timber.d("downloadShowRatings: no changes since %tF %tT", lastRatedAt, lastRatedAt);
        return UpdateResult.SUCCESS;
    }
    if (!TraktCredentials.get(context).hasCredentials()) {
        return UpdateResult.INCOMPLETE;
    }
    // download rated shows
    List<RatedShow> ratedShows;
    try {
        Response<List<RatedShow>> response = traktSync.get().ratingsShows(RatingsFilter.ALL, Extended.DEFAULT_MIN).execute();
        if (response.isSuccessful()) {
            ratedShows = response.body();
        } else {
            if (SgTrakt.isUnauthorized(context, response)) {
                return UpdateResult.INCOMPLETE;
            }
            SgTrakt.trackFailedRequest(context, "get show ratings", response);
            return UpdateResult.INCOMPLETE;
        }
    } catch (IOException e) {
        SgTrakt.trackFailedRequest(context, "get show ratings", e);
        return UpdateResult.INCOMPLETE;
    }
    if (ratedShows == null) {
        Timber.e("downloadShowRatings: null response");
        return UpdateResult.INCOMPLETE;
    }
    if (ratedShows.isEmpty()) {
        Timber.d("downloadShowRatings: no ratings on trakt");
        return UpdateResult.SUCCESS;
    }
    // trakt last activity rated_at timestamp is set after the rating timestamp
    // so include ratings that are a little older
    long ratedAtThreshold = lastRatedAt - 5 * DateUtils.MINUTE_IN_MILLIS;
    // go through ratings, latest first (trakt sends in that order)
    ArrayList<ContentProviderOperation> batch = new ArrayList<>();
    for (RatedShow show : ratedShows) {
        if (show.rating == null || show.show == null || show.show.ids == null || show.show.ids.tvdb == null) {
            // skip, can't handle
            continue;
        }
        if (show.rated_at != null && show.rated_at.isBefore(ratedAtThreshold)) {
            // no need to apply older ratings again
            break;
        }
        // if a show does not exist, this update will do nothing
        ContentProviderOperation op = ContentProviderOperation.newUpdate(SeriesGuideContract.Shows.buildShowUri(show.show.ids.tvdb)).withValue(SeriesGuideContract.Shows.RATING_USER, show.rating.value).build();
        batch.add(op);
    }
    // apply database updates
    try {
        DBUtils.applyInSmallBatches(context, batch);
    } catch (OperationApplicationException e) {
        Timber.e(e, "downloadShowRatings: database update failed");
        return UpdateResult.INCOMPLETE;
    }
    // save last rated instant
    PreferenceManager.getDefaultSharedPreferences(context).edit().putLong(TraktSettings.KEY_LAST_SHOWS_RATED_AT, ratedAt.getMillis()).commit();
    Timber.d("downloadShowRatings: success, last rated_at %tF %tT", ratedAt.getMillis(), ratedAt.getMillis());
    return UpdateResult.SUCCESS;
}
Also used : ContentProviderOperation(android.content.ContentProviderOperation) RatedShow(com.uwetrottmann.trakt5.entities.RatedShow) ArrayList(java.util.ArrayList) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) IOException(java.io.IOException) OperationApplicationException(android.content.OperationApplicationException)

Aggregations

ContentProviderOperation (android.content.ContentProviderOperation)75 ArrayList (java.util.ArrayList)53 OperationApplicationException (android.content.OperationApplicationException)34 Uri (android.net.Uri)27 ContentValues (android.content.ContentValues)25 RemoteException (android.os.RemoteException)22 Cursor (android.database.Cursor)14 ContentProviderResult (android.content.ContentProviderResult)13 ContentResolver (android.content.ContentResolver)9 LinkedList (java.util.LinkedList)8 IOException (java.io.IOException)7 JSONArray (org.json.JSONArray)6 JSONException (org.json.JSONException)6 JSONObject (org.json.JSONObject)6 Intent (android.content.Intent)5 List (java.util.List)5 SuppressLint (android.annotation.SuppressLint)4 BroadcastReceiver (android.content.BroadcastReceiver)4 Context (android.content.Context)4 IntentFilter (android.content.IntentFilter)4