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;
}
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;
}
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);
}
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());
}
}
}
}
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());
}
}
}
}
Aggregations