Search in sources :

Example 11 with ContentProviderOperation

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

the class MovieTools method syncMovieListsWithTrakt.

/**
     * Updates the local movie database against trakt movie watchlist and collection. Adds, updates
     * and removes movies in the database.
     *
     * <p> When syncing the first time, will upload any local movies missing from trakt collection
     * or watchlist instead of removing them locally.
     *
     * <p> Performs <b>synchronous network access</b>, make sure to run this on a background
     * thread.
     */
@SuppressLint("ApplySharedPref")
public UpdateResult syncMovieListsWithTrakt(LastActivityMore activity) {
    if (activity.collected_at == null) {
        Timber.e("syncMoviesWithTrakt: null collected_at");
        return UpdateResult.INCOMPLETE;
    }
    if (activity.watchlisted_at == null) {
        Timber.e("syncMoviesWithTrakt: null watchlisted_at");
        return UpdateResult.INCOMPLETE;
    }
    if (!TraktCredentials.get(context).hasCredentials()) {
        return UpdateResult.INCOMPLETE;
    }
    final boolean merging = !TraktSettings.hasMergedMovies(context);
    if (!merging && !TraktSettings.isMovieListsChanged(context, activity.collected_at, activity.watchlisted_at)) {
        Timber.d("syncMoviesWithTrakt: no changes");
        return UpdateResult.SUCCESS;
    }
    // download collection
    Set<Integer> collection;
    try {
        Response<List<BaseMovie>> response = traktSync.get().collectionMovies(Extended.DEFAULT_MIN).execute();
        if (response.isSuccessful()) {
            collection = buildTmdbIdSet(response.body());
        } else {
            if (SgTrakt.isUnauthorized(context, response)) {
                return UpdateResult.INCOMPLETE;
            }
            SgTrakt.trackFailedRequest(context, "get movie collection", response);
            return UpdateResult.INCOMPLETE;
        }
    } catch (IOException e) {
        SgTrakt.trackFailedRequest(context, "get movie collection", e);
        return UpdateResult.INCOMPLETE;
    }
    if (collection == null) {
        Timber.e("syncMoviesWithTrakt: null collection response");
        return UpdateResult.INCOMPLETE;
    }
    // download watchlist
    Set<Integer> watchlist;
    try {
        Response<List<BaseMovie>> response = traktSync.get().watchlistMovies(Extended.DEFAULT_MIN).execute();
        if (response.isSuccessful()) {
            watchlist = buildTmdbIdSet(response.body());
        } else {
            if (SgTrakt.isUnauthorized(context, response)) {
                return UpdateResult.INCOMPLETE;
            }
            SgTrakt.trackFailedRequest(context, "get movie watchlist", response);
            return UpdateResult.INCOMPLETE;
        }
    } catch (IOException e) {
        SgTrakt.trackFailedRequest(context, "get movie watchlist", e);
        return UpdateResult.INCOMPLETE;
    }
    if (watchlist == null) {
        Timber.e("syncMoviesWithTrakt: null watchlist response");
        return UpdateResult.INCOMPLETE;
    }
    // build updates
    // loop through all local movies
    Set<Integer> moviesNotOnTraktCollection = new HashSet<>();
    Set<Integer> moviesNotOnTraktWatchlist = new HashSet<>();
    ArrayList<ContentProviderOperation> batch = new ArrayList<>();
    HashSet<Integer> localMovies = getMovieTmdbIdsAsSet(context);
    if (localMovies == null) {
        Timber.e("syncMoviesWithTrakt: querying local movies failed");
        return UpdateResult.INCOMPLETE;
    }
    for (Integer tmdbId : localMovies) {
        // is local movie in trakt collection or watchlist?
        boolean inCollection = collection.remove(tmdbId);
        boolean inWatchlist = watchlist.remove(tmdbId);
        if (merging) {
            // upload movie if missing from trakt collection or watchlist
            if (!inCollection) {
                moviesNotOnTraktCollection.add(tmdbId);
            }
            if (!inWatchlist) {
                moviesNotOnTraktWatchlist.add(tmdbId);
            }
            // add to local collection or watchlist, but do NOT remove
            if (inCollection || inWatchlist) {
                ContentProviderOperation.Builder builder = ContentProviderOperation.newUpdate(SeriesGuideContract.Movies.buildMovieUri(tmdbId));
                if (inCollection) {
                    builder.withValue(SeriesGuideContract.Movies.IN_COLLECTION, true);
                }
                if (inWatchlist) {
                    builder.withValue(SeriesGuideContract.Movies.IN_WATCHLIST, true);
                }
                batch.add(builder.build());
            }
        } else {
            // mirror trakt collection and watchlist flag
            // will take care of removing unneeded (not watched or in any list) movies
            // in later sync step
            ContentProviderOperation op = ContentProviderOperation.newUpdate(SeriesGuideContract.Movies.buildMovieUri(tmdbId)).withValue(SeriesGuideContract.Movies.IN_COLLECTION, inCollection).withValue(SeriesGuideContract.Movies.IN_WATCHLIST, inWatchlist).build();
            batch.add(op);
        }
    }
    // apply collection and watchlist updates to existing movies
    try {
        DBUtils.applyInSmallBatches(context, batch);
        Timber.d("syncMoviesWithTrakt: updated %s", batch.size());
    } catch (OperationApplicationException e) {
        Timber.e(e, "syncMoviesWithTrakt: database updates failed");
        return UpdateResult.INCOMPLETE;
    }
    batch.clear();
    // merge on first run
    if (merging) {
        // upload movies not in trakt collection or watchlist
        if (toTrakt(moviesNotOnTraktCollection, moviesNotOnTraktWatchlist) != UpdateResult.SUCCESS) {
            return UpdateResult.INCOMPLETE;
        } else {
            // set merge successful
            PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean(TraktSettings.KEY_HAS_MERGED_MOVIES, true).commit();
        }
    }
    // add movies from trakt missing locally
    // all local movies were removed from trakt collection and watchlist,
    // so they only contain movies missing locally
    UpdateResult result = addMovies(collection, watchlist);
    if (result == UpdateResult.SUCCESS) {
        // store last activity timestamps
        TraktSettings.storeLastMoviesChangedAt(context, activity.collected_at, activity.watchlisted_at);
        // ensure all movie ratings and watched flags are downloaded next
        if (collection.size() > 0 || watchlist.size() > 0) {
            TraktSettings.resetMoviesLastActivity(context);
        }
    }
    return result;
}
Also used : ContentProviderOperation(android.content.ContentProviderOperation) ArrayList(java.util.ArrayList) IOException(java.io.IOException) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) MovieList(com.uwetrottmann.seriesguide.backend.movies.model.MovieList) OperationApplicationException(android.content.OperationApplicationException) UpdateResult(com.battlelancer.seriesguide.sync.SgSyncAdapter.UpdateResult) HashSet(java.util.HashSet) SuppressLint(android.annotation.SuppressLint)

Example 12 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 13 with ContentProviderOperation

use of android.content.ContentProviderOperation in project qksms by moezbhatti.

the class ContactOperations method insertContact.

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void insertContact(VCard vcard) throws RemoteException, OperationApplicationException {
    // TODO handle Raw properties - Raw properties include various extension which start with "X-" like X-ASSISTANT, X-AIM, X-SPOUSE
    List<NonEmptyContentValues> contentValues = new ArrayList<>();
    contentValues.add(account);
    convertName(contentValues, vcard);
    convertNickname(contentValues, vcard);
    convertPhones(contentValues, vcard);
    convertEmails(contentValues, vcard);
    convertAddresses(contentValues, vcard);
    convertIms(contentValues, vcard);
    // handle Android Custom fields..This is only valid for Android generated Vcards. As the Android would
    // generate NickName, ContactEvents other than Birthday and RelationShip with this "X-ANDROID-CUSTOM" name
    convertCustomFields(contentValues, vcard);
    // handle Iphone kinda of group properties. which are grouped together.
    convertGroupedProperties(contentValues, vcard);
    convertBirthdays(contentValues, vcard);
    convertWebsites(contentValues, vcard);
    convertNotes(contentValues, vcard);
    convertPhotos(contentValues, vcard);
    convertOrganization(contentValues, vcard);
    ArrayList<ContentProviderOperation> operations = new ArrayList<>(contentValues.size());
    for (NonEmptyContentValues values : contentValues) {
        ContentValues cv = values.getContentValues();
        if (cv.size() == 0) {
            continue;
        }
        //@formatter:off
        ContentProviderOperation operation = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactID).withValues(cv).build();
        //@formatter:on
        operations.add(operation);
    }
    // Executing all the insert operations as a single database transaction
    context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, operations);
}
Also used : ContentValues(android.content.ContentValues) ContentProviderOperation(android.content.ContentProviderOperation) ArrayList(java.util.ArrayList) TargetApi(android.annotation.TargetApi)

Example 14 with ContentProviderOperation

use of android.content.ContentProviderOperation in project android by owncloud.

the class FileDataStorageManager method updateSharedFiles.

public void updateSharedFiles(Collection<OCFile> sharedFiles) {
    resetShareFlagsInAllFiles();
    if (sharedFiles != null) {
        ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(sharedFiles.size());
        // prepare operations to insert or update files to save in the given folder
        for (OCFile file : sharedFiles) {
            ContentValues cv = new ContentValues();
            cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
            cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, file.getModificationTimestampAtLastSyncForData());
            cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
            cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
            cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
            cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
            cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
            cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
            if (!file.isFolder()) {
                cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
            }
            cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
            cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
            cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
            cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.getAvailableOfflineStatus().getValue());
            cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
            cv.put(ProviderTableMeta.FILE_TREE_ETAG, file.getTreeEtag());
            cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, file.isSharedViaLink() ? 1 : 0);
            cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, file.isSharedWithSharee() ? 1 : 0);
            cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
            cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
            cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
            cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.needsUpdateThumbnail() ? 1 : 0);
            cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading() ? 1 : 0);
            cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict());
            boolean existsByPath = fileExists(file.getRemotePath());
            if (existsByPath || fileExists(file.getFileId())) {
                // updating an existing file
                operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).withValues(cv).withSelection(ProviderTableMeta._ID + "=?", new String[] { String.valueOf(file.getFileId()) }).build());
            } else {
                // adding a new file
                setInitialAvailableOfflineStatus(file, cv);
                operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).withValues(cv).build());
            }
        }
        // apply operations in batch
        if (operations.size() > 0) {
            @SuppressWarnings("unused") ContentProviderResult[] results = null;
            Log_OC.d(TAG, "Sending " + operations.size() + " operations to FileContentProvider");
            try {
                if (getContentResolver() != null) {
                    results = getContentResolver().applyBatch(MainApp.getAuthority(), operations);
                } else {
                    results = getContentProviderClient().applyBatch(operations);
                }
            } catch (OperationApplicationException e) {
                Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
            } catch (RemoteException e) {
                Log_OC.e(TAG, "Exception in batch of operations  " + e.getMessage());
            }
        }
    }
}
Also used : ContentValues(android.content.ContentValues) ContentProviderResult(android.content.ContentProviderResult) ContentProviderOperation(android.content.ContentProviderOperation) ArrayList(java.util.ArrayList) RemoteException(android.os.RemoteException) OperationApplicationException(android.content.OperationApplicationException)

Example 15 with ContentProviderOperation

use of android.content.ContentProviderOperation in project android by owncloud.

the class FileDataStorageManager method moveLocalFile.

/**
     * Updates database and file system for a file or folder that was moved to a different location.
     *
     * TODO explore better (faster) implementations
     * TODO throw exceptions up !
     */
public void moveLocalFile(OCFile file, String targetPath, String targetParentPath) {
    if (file != null && file.fileExists() && !OCFile.ROOT_PATH.equals(file.getFileName())) {
        OCFile targetParent = getFileByPath(targetParentPath);
        if (targetParent == null) {
            throw new IllegalStateException("Parent folder of the target path does not exist!!");
        }
        /// 1. get all the descendants of the moved element in a single QUERY
        Cursor c = null;
        if (getContentProviderClient() != null) {
            try {
                c = getContentProviderClient().query(ProviderTableMeta.CONTENT_URI, null, ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ? ", new String[] { mAccount.name, file.getRemotePath() + "%" }, ProviderTableMeta.FILE_PATH + " ASC ");
            } catch (RemoteException e) {
                Log_OC.e(TAG, e.getMessage());
            }
        } else {
            c = getContentResolver().query(ProviderTableMeta.CONTENT_URI, null, ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ? ", new String[] { mAccount.name, file.getRemotePath() + "%" }, ProviderTableMeta.FILE_PATH + " ASC ");
        }
        List<String> originalPathsToTriggerMediaScan = new ArrayList<>();
        List<String> newPathsToTriggerMediaScan = new ArrayList<>();
        String defaultSavePath = FileStorageUtils.getSavePath(mAccount.name);
        /// 2. prepare a batch of update operations to change all the descendants
        if (c != null) {
            ArrayList<ContentProviderOperation> operations = new ArrayList<>(c.getCount());
            if (c.moveToFirst()) {
                int lengthOfOldPath = file.getRemotePath().length();
                int lengthOfOldStoragePath = defaultSavePath.length() + lengthOfOldPath;
                do {
                    // keep construction in the loop
                    ContentValues cv = new ContentValues();
                    OCFile child = createFileInstance(c);
                    cv.put(ProviderTableMeta.FILE_PATH, targetPath + child.getRemotePath().substring(lengthOfOldPath));
                    if (child.getStoragePath() != null && child.getStoragePath().startsWith(defaultSavePath)) {
                        // update link to downloaded content - but local move is not done here!
                        String targetLocalPath = defaultSavePath + targetPath + child.getStoragePath().substring(lengthOfOldStoragePath);
                        cv.put(ProviderTableMeta.FILE_STORAGE_PATH, targetLocalPath);
                        originalPathsToTriggerMediaScan.add(child.getStoragePath());
                        newPathsToTriggerMediaScan.add(targetLocalPath);
                    }
                    if (targetParent.getAvailableOfflineStatus() != OCFile.AvailableOfflineStatus.NOT_AVAILABLE_OFFLINE) {
                        // moving to an available offline subfolder
                        cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, OCFile.AvailableOfflineStatus.AVAILABLE_OFFLINE_PARENT.getValue());
                    } else {
                        // moving to a not available offline subfolder - with care
                        if (file.getAvailableOfflineStatus() == OCFile.AvailableOfflineStatus.AVAILABLE_OFFLINE_PARENT) {
                            cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, OCFile.AvailableOfflineStatus.NOT_AVAILABLE_OFFLINE.getValue());
                        }
                    }
                    if (child.getRemotePath().equals(file.getRemotePath())) {
                        cv.put(ProviderTableMeta.FILE_PARENT, targetParent.getFileId());
                    }
                    operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).withValues(cv).withSelection(ProviderTableMeta._ID + "=?", new String[] { String.valueOf(child.getFileId()) }).build());
                } while (c.moveToNext());
            }
            c.close();
            /// 3. apply updates in batch
            try {
                if (getContentResolver() != null) {
                    getContentResolver().applyBatch(MainApp.getAuthority(), operations);
                } else {
                    getContentProviderClient().applyBatch(operations);
                }
            } catch (Exception e) {
                Log_OC.e(TAG, "Fail to update " + file.getFileId() + " and descendants in database", e);
            }
        }
        /// 4. move in local file system
        String originalLocalPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, file);
        String targetLocalPath = defaultSavePath + targetPath;
        File localFile = new File(originalLocalPath);
        boolean renamed = false;
        if (localFile.exists()) {
            File targetFile = new File(targetLocalPath);
            File targetFolder = targetFile.getParentFile();
            if (!targetFolder.exists()) {
                targetFolder.mkdirs();
            }
            renamed = localFile.renameTo(targetFile);
        }
        if (renamed) {
            Iterator<String> it = originalPathsToTriggerMediaScan.iterator();
            while (it.hasNext()) {
                // Notify MediaScanner about removed file
                deleteFileInMediaScan(it.next());
            }
            it = newPathsToTriggerMediaScan.iterator();
            while (it.hasNext()) {
                // Notify MediaScanner about new file/folder
                triggerMediaScan(it.next());
            }
        }
    }
}
Also used : ContentValues(android.content.ContentValues) ContentProviderOperation(android.content.ContentProviderOperation) ArrayList(java.util.ArrayList) Cursor(android.database.Cursor) RemoteException(android.os.RemoteException) IOException(java.io.IOException) OperationApplicationException(android.content.OperationApplicationException) RemoteException(android.os.RemoteException) File(java.io.File)

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