List of usage examples for android.content ContentProviderOperation newInsert
public static Builder newInsert(Uri uri)
From source file:com.weimed.app.sync.SyncAdapter.java
/** * Read JSON from an input stream, storing it into the content provider. * * <p>This is where incoming data is persisted, committing the results of a sync. In order to * minimize (expensive) disk operations, we compare incoming data with what's already in our * database, and compute a merge. Only changes (insert/update/delete) will result in a database * write./*ww w .jav a 2 s . co m*/ * * <p>As an additional optimization, we use a batch operation to perform all database writes at * once. * * <p>Merge strategy: * 1. Get cursor to all items in feed<br/> * 2. For each item, check if it's in the incoming data.<br/> * a. YES: Remove from "incoming" list. Check if data has mutated, if so, perform * database UPDATE.<br/> * b. NO: Schedule DELETE from database.<br/> * (At this point, incoming database only contains missing items.)<br/> * 3. For any items remaining in incoming list, ADD to database. */ public void updateLocalJSONData(final InputStream stream, final SyncResult syncResult) throws IOException, JSONException, RemoteException, OperationApplicationException, ParseException { final JSONParser JSONParser = new JSONParser(); final ContentResolver contentResolver = getContext().getContentResolver(); Log.i(TAG, "Parsing stream as JSON Array"); final JSONObject json = JSONParser.parseJSONObject(stream); Log.i(TAG, "Parsing complete. Found " + json.getInt("total_rows") + " entries"); ArrayList<ContentProviderOperation> batch = new ArrayList<ContentProviderOperation>(); // Build hash table of incoming entries HashMap<String, JSONObject> entryMap = new HashMap<String, JSONObject>(); final JSONArray entries = json.getJSONArray("rows"); for (int i = 0; i < json.getInt("total_rows"); i++) { JSONObject e = entries.getJSONObject(i).getJSONObject("value"); entryMap.put(e.getString("_id"), e); } // Get list of all items Log.i(TAG, "Fetching local entries for merge"); Uri uri = NewsContract.Entry.CONTENT_URI; // Get all entries Cursor c = contentResolver.query(uri, PROJECTION, null, null, null); assert c != null; Log.i(TAG, "Found " + c.getCount() + " local entries. Computing merge solution..."); // Find stale data int id; String entryId; String title; String content; String publisher; String picurl; String originalurl; String createdat; String updatedat; String publishedat; while (c.moveToNext()) { syncResult.stats.numEntries++; id = c.getInt(COLUMN_ID); entryId = c.getString(COLUMN_ENTRY_ID); title = c.getString(COLUMN_TITLE); content = c.getString(COLUMN_CONTENT); publisher = c.getString(COLUMN_PUBLISHER); picurl = c.getString(COLUMN_PICURL); originalurl = c.getString(COLUMN_ORIGINALURL); createdat = c.getString(COLUMN_CREATEDAT); updatedat = c.getString(COLUMN_UPDATEDAT); publishedat = c.getString(COLUMN_PUBLISHEDAT); JSONObject match = entryMap.get(entryId); // if (match != null) { // Entry exists. Remove from entry map to prevent insert later. // entryMap.remove(entryId); // Check to see if the entry needs to be updated // How to know update local or remote? updatedAt! which is newer, update another. // Uri existingUri = NewsContract.Entry.CONTENT_URI.buildUpon() // .appendPath(Integer.toString(id)).build(); // if ((match.getString("title") != null && !match.getString("title").equals(title)) || // (match.getString("content") != null && !match.getString("content").equals(content)) || // (match.getString("publisher") != null && !match.getString("publisher").equals(publisher)) || // (match.getString("picurl") != null && !match.getString("picurl").equals(picurl)) || // (match.getString("originalurl") != null && !match.getString("originalurl").equals(originalurl)) || // (match.getString("createdat") != null && !match.getString("createdat").equals(createdat)) || // (match.getString("updatedat") != null && !match.getString("updatedat").equals(updatedat)) || // (match.getString("publishedat") != null && !match.getString("publishedat").equals(publishedat)) // ) { // // Update existing record // Log.i(TAG, "Scheduling update: " + existingUri); // batch.add(ContentProviderOperation.newUpdate(existingUri) // .withValue(NewsContract.Entry.COLUMN_TITLE, title) // .withValue(NewsContract.Entry.COLUMN_CONTENT, content) // .withValue(NewsContract.Entry.COLUMN_PUBLISHER, publisher) // .withValue(NewsContract.Entry.COLUMN_PICURL, picurl) // .withValue(NewsContract.Entry.COLUMN_ORIGINALURL, originalurl) // .withValue(NewsContract.Entry.COLUMN_CREATEDAT, createdat) // .withValue(NewsContract.Entry.COLUMN_UPDATEDAT, updatedat) // .withValue(NewsContract.Entry.COLUMN_PUBLISHEDAT, publishedat) // .build()); // syncResult.stats.numUpdates++; // } else { // Log.i(TAG, "No action: " + existingUri); // } // } else { // Entry doesn't exist. Remove it from the database. Uri deleteUri = NewsContract.Entry.CONTENT_URI.buildUpon().appendPath(Integer.toString(id)).build(); Log.i(TAG, "Scheduling delete: " + deleteUri); batch.add(ContentProviderOperation.newDelete(deleteUri).build()); syncResult.stats.numDeletes++; // } } c.close(); // Add new items for (JSONObject e : entryMap.values()) { Log.i(TAG, "Scheduling insert: entry_id=" + e.getString("_id")); batch.add(ContentProviderOperation.newInsert(NewsContract.Entry.CONTENT_URI) .withValue(NewsContract.Entry.COLUMN_ENTRY_ID, e.getString("_id")) .withValue(NewsContract.Entry.COLUMN_TITLE, e.getString("title")) .withValue(NewsContract.Entry.COLUMN_CONTENT, fetchTextFileToString(NEWS_URL_BASE + '/' + e.getString("_id") + "/content.md")) .withValue(NewsContract.Entry.COLUMN_PUBLISHER, e.getString("publisher")) .withValue(NewsContract.Entry.COLUMN_PICURL, e.has("pic_link") ? e.getString("pic_link") : null) .withValue(NewsContract.Entry.COLUMN_ORIGINALURL, e.getString("origin_link")) .withValue(NewsContract.Entry.COLUMN_CREATEDAT, e.getString("created_at")) .withValue(NewsContract.Entry.COLUMN_UPDATEDAT, e.getString("updated_at")) .withValue(NewsContract.Entry.COLUMN_PUBLISHEDAT, e.getString("publish_at")).build()); syncResult.stats.numInserts++; } Log.i(TAG, "Merge solution ready. Applying batch update"); mContentResolver.applyBatch(NewsContract.CONTENT_AUTHORITY, batch); mContentResolver.notifyChange(NewsContract.Entry.CONTENT_URI, // URI where data was modified null, // No local observer false); // IMPORTANT: Do not sync to network // This sample doesn't support uploads, but if *your* code does, make sure you set // syncToNetwork=false in the line above to prevent duplicate syncs. }
From source file:at.bitfire.ical4android.AndroidEvent.java
protected int add(BatchOperation batch) { Builder builder = ContentProviderOperation.newInsert(calendar.syncAdapterURI(eventsSyncURI())); final int idxEvent = batch.nextBackrefIdx(); buildEvent(null, builder);/* w ww. j a va 2 s. c om*/ batch.enqueue(builder.build()); // add reminders for (VAlarm alarm : event.getAlarms()) insertReminder(batch, idxEvent, alarm); // add attendees for (Attendee attendee : event.getAttendees()) insertAttendee(batch, idxEvent, attendee); // add exceptions for (Event exception : event.getExceptions()) { /* I guess exceptions should be inserted using Events.CONTENT_EXCEPTION_URI so that we could benefit from some provider logic (for recurring exceptions e.g.). However, this method has some caveats: - For instance, only Events.SYNC_DATA1, SYNC_DATA3 and SYNC_DATA7 can be used in exception events (that's hardcoded in the CalendarProvider, don't ask me why). - Also, CONTENT_EXCEPTIONS_URI doesn't deal with exceptions for recurring events defined by RDATE (it checks for RRULE and aborts if no RRULE is found). So I have chosen the method of inserting the exception event manually. It's also noteworthy that the link between the "master event" and the exception is not between ID and ORIGINAL_ID (as one could assume), but between _SYNC_ID and ORIGINAL_SYNC_ID. So, if you don't set _SYNC_ID in the master event and ORIGINAL_SYNC_ID in the exception, the exception will appear additionally (and not *instead* of the instance). */ builder = ContentProviderOperation.newInsert(calendar.syncAdapterURI(eventsSyncURI())); buildEvent(exception, builder); Date date = exception.recurrenceId.getDate(); if (event.isAllDay() && date instanceof DateTime) { // correct VALUE=DATE-TIME RECURRENCE-IDs to VALUE=DATE for all-day events final DateFormat dateFormatDate = new SimpleDateFormat("yyyyMMdd", Locale.US); final String dateString = dateFormatDate.format(exception.recurrenceId.getDate()); try { date = new Date(dateString); } catch (ParseException e) { Log.e(TAG, "Couldn't parse DATE part of DATE-TIME RECURRENCE-ID", e); } } builder.withValueBackReference(Events.ORIGINAL_ID, idxEvent) .withValue(Events.ORIGINAL_ALL_DAY, event.isAllDay() ? 1 : 0) .withValue(Events.ORIGINAL_INSTANCE_TIME, date.getTime()); int idxException = batch.nextBackrefIdx(); batch.enqueue(builder.build()); // add exception reminders for (VAlarm alarm : exception.getAlarms()) insertReminder(batch, idxException, alarm); // add exception attendees for (Attendee attendee : exception.getAttendees()) insertAttendee(batch, idxException, attendee); } return idxEvent; }
From source file:com.google.samples.apps.iosched.io.SessionsHandler.java
private void buildTagsMapping(Session session, ArrayList<ContentProviderOperation> list) { final Uri uri = ScheduleContractHelper .setUriAsCalledFromSyncAdapter(ScheduleContract.Sessions.buildTagsDirUri(session.id)); // delete any existing mappings list.add(ContentProviderOperation.newDelete(uri).build()); // add a mapping (a session+tag tuple) for each tag in the session if (session.tags != null) { for (String tag : session.tags) { list.add(ContentProviderOperation.newInsert(uri) .withValue(ScheduleDatabase.SessionsTags.SESSION_ID, session.id) .withValue(ScheduleDatabase.SessionsTags.TAG_ID, tag).build()); }/*ww w .j a v a 2s .c o m*/ } }
From source file:pl.epodreczniki.service.MetadataService.java
private ContentProviderOperation toInsertOperation(JSONBook book) { if (book == null) { return null; }/* w w w. j a va 2 s . c o m*/ int longerEdge = Util.getLongerEdge(this); StringBuilder authorsStringBuilder = new StringBuilder(); String mainAuthor = null; if (book.getMdAuthors() != null) { final JSONAuthor.JSONAuthorComparator cmp = new JSONAuthor.JSONAuthorComparator(); Map<String, List<JSONAuthor>> byRoles = authorsByRoles(book.getMdAuthors()); for (Map.Entry<String, List<JSONAuthor>> entry : byRoles.entrySet()) { final String roleName = entry.getKey(); if (!roleName.equals(KEY_ROLELESS)) { authorsStringBuilder.append("<b>").append(roleName).append("</b><br />"); } else { authorsStringBuilder.append("<b>").append("Autorzy").append("</b><br />"); } Collections.sort(entry.getValue(), cmp); for (JSONAuthor auth : entry.getValue()) { final String fullName = TextUtils.isEmpty(auth.getMdFullName()) ? auth.getFullName() : auth.getMdFullName(); if (!TextUtils.isEmpty(fullName)) { authorsStringBuilder.append(fullName); authorsStringBuilder.append(", "); if (mainAuthor == null) { mainAuthor = fullName; } } } if (authorsStringBuilder.toString().endsWith(", ")) { authorsStringBuilder.replace(authorsStringBuilder.length() - 2, authorsStringBuilder.length(), "<br />"); } } } String educationLevel = null; Integer epClass = null; if (book.getMdSchool() != null) { educationLevel = book.getMdSchool().getMdEducationLevel(); epClass = book.getMdSchool().getEpClass(); } String subject = null; if (book.getMdSubject() != null) { subject = book.getMdSubject().getMdName(); } String zip = null; Long extractedSize = null; if (book.getFormats() != null) { Map<Integer, UrlAndSize> resolutions = new TreeMap<Integer, UrlAndSize>(); for (JSONFormat format : book.getFormats()) { final String formatStr = format.getFormat(); if (!TextUtils.isEmpty(formatStr)) { if (formatStr.matches(Constants.RE_ZIP)) { final int resolution = Integer.parseInt(formatStr.split("-")[1]); final String url = format.getUrl(); final Long size = format.getSize(); resolutions.put(resolution, new UrlAndSize(url, size)); } } } int chosen = 0; for (Map.Entry<Integer, UrlAndSize> entry : resolutions.entrySet()) { chosen = chosen == 0 ? entry.getKey() : (entry.getKey() <= longerEdge ? entry.getKey() : chosen); } final UrlAndSize choice = resolutions.get(chosen); zip = choice.url; extractedSize = choice.size; } String cover = null; if (book.getCovers() != null) { Map<Integer, String> resolutions = new TreeMap<Integer, String>(); for (JSONFormat cvr : book.getCovers()) { final String formatStr = cvr.getFormat(); if (!TextUtils.isEmpty(formatStr)) { if (formatStr.matches(Constants.RE_COVER)) { final int resolution = Integer.parseInt(formatStr.split("-")[1]); final String url = cvr.getUrl(); resolutions.put(resolution, url); } } } int chosen = 0; for (Map.Entry<Integer, String> entry : resolutions.entrySet()) { chosen = chosen == 0 ? entry.getKey() : (entry.getKey() <= longerEdge ? entry.getKey() : chosen); } Log.e("MDS", "chosen cover resolution: " + chosen); cover = resolutions.get(chosen); } ContentProviderOperation.Builder res = ContentProviderOperation.newInsert(BooksProvider.BOOKS_URI) .withValue(BooksTable.C_MD_CONTENT_ID, book.getMdContentId()) .withValue(BooksTable.C_MD_TITLE, book.getMdTitle()) .withValue(BooksTable.C_MD_ABSTRACT, book.getMdAbstract()) .withValue(BooksTable.C_MD_PUBLISHED, book.getMdPublished() == null ? 0 : book.getMdPublished() ? 1 : 0) .withValue(BooksTable.C_MD_VERSION, book.getMdVersion()) .withValue(BooksTable.C_MD_LANGUAGE, book.getMdLanguage()) .withValue(BooksTable.C_MD_LICENSE, book.getMdLicense()) .withValue(BooksTable.C_MD_CREATED, book.getMdCreated()) .withValue(BooksTable.C_MD_REVISED, book.getMdRevised()).withValue(BooksTable.C_COVER, cover) .withValue(BooksTable.C_LINK, book.getLink()) .withValue(BooksTable.C_MD_SUBTITLE, book.getMdSubtitle()) .withValue(BooksTable.C_AUTHORS, authorsStringBuilder.toString()) .withValue(BooksTable.C_MAIN_AUTHOR, mainAuthor) .withValue(BooksTable.C_EDUCATION_LEVEL, educationLevel).withValue(BooksTable.C_CLASS, epClass) .withValue(BooksTable.C_SUBJECT, subject).withValue(BooksTable.C_ZIP, zip) .withValue(BooksTable.C_EXTRACTED_SIZE, extractedSize); if (book.getAppVersion() != null) { return res.withValue(BooksTable.C_APP_VERSION, book.getAppVersion()).build(); } else { return res.build(); } }
From source file:com.rukman.emde.smsgroups.syncadapter.SyncAdapter.java
/** * We know that the group exists locally, so we can use the data in the JSON group as gold * @param group//from www.j av a2s . c o m * @param provider * @param authToken * @param account * @param syncResult * @throws JSONException * @throws RemoteException * @throws OperationApplicationException */ private void optimisticallyAddContactsToExistingGroup(JSONObject group, ContentProviderClient provider, String authToken, Account account, SyncResult syncResult) throws JSONException, RemoteException { if (!group.has(JSONKeys.KEY_MEMBERS)) { return; } String groupCloudId = group.getString(JSONKeys.KEY_ID); Cursor groupCursor = provider.query(GMSGroups.CONTENT_URI, new String[] { GMSGroup._ID, GMSGroup.CLOUD_ID }, GMSGroup.CLOUD_ID + "=?", new String[] { groupCloudId }, null); try { if (groupCursor == null || 1 != groupCursor.getCount() || !groupCursor.moveToFirst()) { syncResult.databaseError = true; return; } long groupId = groupCursor.getLong(0); if (groupId < 0L) { syncResult.databaseError = true; return; } // Optimistically add the contacts JSONArray membersArray = group.getJSONArray(JSONKeys.KEY_MEMBERS); for (int j = 0; j < membersArray.length(); ++j) { JSONObject member = membersArray.getJSONObject(j); ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>(); // If the first operation asserts it means the contact exists already // Operation 0 ContentProviderOperation op = ContentProviderOperation.newAssertQuery(GMSContacts.CONTENT_URI) .withSelection(GMSContact.CLOUD_ID + "=? AND " + GMSContact.GROUP_ID + "=?", new String[] { member.getString(JSONKeys.KEY_ID), String.valueOf(groupId) }) .withExpectedCount(0).build(); ops.add(op); op = ContentProviderOperation.newInsert(GMSContacts.CONTENT_URI) .withValues(GMSApplication.getMemberValues(member)).withValue(GMSContact.GROUP_ID, groupId) .withValue(GMSContact.STATUS, GMSContact.STATUS_SYNCED).build(); ops.add(op); try { @SuppressWarnings("unused") ContentProviderResult[] results = provider.applyBatch(ops); } catch (OperationApplicationException e) { // The contact already exists, so we'll optionally update it, based on its version Cursor contactCursor = null; try { contactCursor = provider.query(GMSContacts.CONTENT_URI, new String[] { GMSContact._ID, GMSContact.CLOUD_ID, GMSContact.GROUP_ID }, GMSContact.CLOUD_ID + "=? AND " + GMSContact.GROUP_ID + "=?", new String[] { member.getString(JSONKeys.KEY_ID), String.valueOf(groupId) }, null); if (contactCursor == null || !contactCursor.moveToFirst()) { syncResult.databaseError = true; return; } // The member already exists, so optinally update it ops = new ArrayList<ContentProviderOperation>(); // Operation 0 - we know it exists. If its the right version, we don't need to do the update // So we assert that we'll find zero records with the current version and if that's right, we'll update our // record, including the version with the new record data op = ContentProviderOperation .newAssertQuery(ContentUris.withAppendedId(GMSContacts.CONTENT_URI, contactCursor.getLong(0))) .withSelection(GMSContact.VERSION + "=?", new String[] { member.getString(JSONKeys.KEY_VERSION) }) .withExpectedCount(0).build(); ops.add(op); op = ContentProviderOperation .newUpdate(ContentUris.withAppendedId(GMSContacts.CONTENT_URI, contactCursor.getLong(0))) .withValues(GMSApplication.getMemberValues(member)) .withValue(GMSContact.STATUS, GMSContact.STATUS_SYNCED).withExpectedCount(1) .build(); ops.add(op); provider.applyBatch(ops); } catch (OperationApplicationException l) { ops = new ArrayList<ContentProviderOperation>(); // Operation 0 - we know it exists and is of the current version, so no update of attributes is needed // We still have to update the status to SYNCED so we don't blow it away later. op = ContentProviderOperation .newUpdate(ContentUris.withAppendedId(GMSContacts.CONTENT_URI, contactCursor.getLong(0))) .withValue(GMSContact.STATUS, GMSContact.STATUS_SYNCED).withExpectedCount(1) .build(); ops.add(op); try { provider.applyBatch(ops); } catch (OperationApplicationException e1) { syncResult.stats.numSkippedEntries++; e1.printStackTrace(); } } finally { if (contactCursor != null) { contactCursor.close(); } } } } } finally { if (groupCursor != null) { groupCursor.close(); } } }
From source file:net.smartpager.android.activity.MainActivity.java
private void insertQuickResponsesDefaults() { String[] strArray = getResources().getStringArray(R.array.quick_resp_defaults); List<String> defaultsList = Arrays.asList(strArray); ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(); Uri uri = SmartPagerContentProvider.CONTENT_QUICK_RESPONSE_URI; for (String item : defaultsList) { Builder builder = ContentProviderOperation.newInsert(uri); builder.withValue(QuickResponseTable.messageText.name(), item); operations.add(builder.build()); }/* ww w . j a v a 2s .c o m*/ try { getContentResolver().applyBatch(SmartPagerContentProvider.AUTHORITY, operations); } catch (RemoteException e) { e.printStackTrace(); } catch (OperationApplicationException e) { e.printStackTrace(); } }
From source file:ch.berta.fabio.popularmovies.data.repositories.MovieRepositoryImpl.java
private void addMovieReviewsOps(@NonNull MovieDetails movieDetails, long movieRowId, @NonNull ArrayList<ContentProviderOperation> ops) { ops.add(ContentProviderOperation.newDelete(MovieContract.Review.buildReviewsFromMovieUri(movieRowId)) .build());/*from w w w. j a va 2 s . c o m*/ List<Review> reviews = movieDetails.getReviewsPage().getReviews(); if (!reviews.isEmpty()) { for (Review review : reviews) { ops.add(ContentProviderOperation.newInsert(MovieContract.Review.CONTENT_URI) .withValue(MovieContract.Review.COLUMN_MOVIE_ID, movieRowId) .withValues(review.getContentValuesEntry()).build()); } } }
From source file:com.trellmor.berrymotes.sync.SubredditEmoteDownloader.java
public void updateEmotes(List<EmoteImage> emotes) throws RemoteException, OperationApplicationException, InterruptedException { checkInterrupted();/*from w w w .j a v a2 s. c o m*/ Log.debug("Updating emote database"); // Build map of entries HashMap<String, EmoteImage> emoteHash = new HashMap<String, EmoteImage>(); for (EmoteImage emote : emotes) { emoteHash.put(emote.getHash(), emote); } checkInterrupted(); Cursor c = mContentResolver.query(EmotesContract.Emote.CONTENT_URI_DISTINCT, new String[] { EmotesContract.Emote._ID, EmotesContract.Emote.COLUMN_NAME, EmotesContract.Emote.COLUMN_HASH }, EmotesContract.Emote.COLUMN_SUBREDDIT + "=?", new String[] { mSubreddit }, null); if (c != null) { ArrayList<ContentProviderOperation> batch = new ArrayList<ContentProviderOperation>(); if (c.moveToFirst()) { final int POS_ID = c.getColumnIndex(EmotesContract.Emote._ID); final int POS_NAME = c.getColumnIndex(EmotesContract.Emote.COLUMN_NAME); final int POS_HASH = c.getColumnIndex(EmotesContract.Emote.COLUMN_HASH); do { String hash = c.getString(POS_HASH); String name = c.getString(POS_NAME); EmoteImage emote = emoteHash.get(hash); if (emote != null) { if (emote.getNames().contains(name)) { emote.getNames().remove(name); if (emote.getNames().size() == 0) { // Already in db, no need to insert emoteHash.remove(hash); emotes.remove(emote); } } else { Log.debug("Removing " + name + " (" + hash + ") from DB"); Uri deleteUri = EmotesContract.Emote.CONTENT_URI.buildUpon() .appendPath(Integer.toString(c.getInt(POS_ID))).build(); batch.add(ContentProviderOperation.newDelete(deleteUri).build()); } } } while (c.moveToNext()); } c.close(); // Delete all emotes that no longer exist Log.debug("Removing emotes names from DB"); checkInterrupted(); applyBatch(batch); mSyncResult.stats.numDeletes += batch.size(); Log.info("Removed " + Integer.toString(batch.size()) + " emotes names from DB"); } // Generate batch insert checkInterrupted(); ArrayList<ContentProviderOperation> batch = new ArrayList<ContentProviderOperation>(); String baseDir = mBaseDir.getAbsolutePath() + File.separator; for (EmoteImage emote : emotes) { for (String name : emote.getNames()) { Log.debug("Adding " + name + " to DB"); batch.add(ContentProviderOperation.newInsert(EmotesContract.Emote.CONTENT_URI) .withValue(EmotesContract.Emote.COLUMN_NAME, name) .withValue(EmotesContract.Emote.COLUMN_NSFW, (emote.isNsfw() ? 1 : 0)) .withValue(EmotesContract.Emote.COLUMN_APNG, (emote.isApng() ? 1 : 0)) .withValue(EmotesContract.Emote.COLUMN_IMAGE, baseDir + emote.getImage()) .withValue(EmotesContract.Emote.COLUMN_HASH, emote.getHash()) .withValue(EmotesContract.Emote.COLUMN_INDEX, emote.getIndex()) .withValue(EmotesContract.Emote.COLUMN_DELAY, emote.getDelay()) .withValue(EmotesContract.Emote.COLUMN_SUBREDDIT, emote.getSubreddit()).build()); } } Log.debug("Adding emotes names to DB"); checkInterrupted(); applyBatch(batch); mSyncResult.stats.numInserts += batch.size(); Log.info("Added " + Integer.toString(batch.size()) + " emotes names to DB"); }
From source file:com.owncloud.android.datamodel.FileDataStorageManager.java
/** * Inserts or updates the list of files contained in a given folder. * <p/>/* ww w . j av a 2s . c o m*/ * CALLER IS THE RESPONSIBLE FOR GRANTING RIGHT UPDATE OF INFORMATION, NOT THIS METHOD. * HERE ONLY DATA CONSISTENCY SHOULD BE GRANTED * * @param folder * @param updatedFiles * @param filesToRemove */ public void saveFolder(OCFile folder, Collection<OCFile> updatedFiles, Collection<OCFile> filesToRemove) { Log_OC.d(TAG, "Saving folder " + folder.getRemotePath() + " with " + updatedFiles.size() + " children and " + filesToRemove.size() + " files to remove"); ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>( updatedFiles.size()); // prepare operations to insert or update files to save in the given folder for (OCFile file : updatedFiles) { 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, folder.getFileId()); 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_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_PERMISSIONS, file.getPermissions()); cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId()); cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.needsUpdateThumbnail()); cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading()); cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict()); cv.put(ProviderTableMeta.FILE_PRIVATE_LINK, file.getPrivateLink()); 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()); } } // prepare operations to remove files in the given folder String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?"; String[] whereArgs = null; for (OCFile file : filesToRemove) { if (file.getParentId() == folder.getFileId()) { whereArgs = new String[] { mAccount.name, file.getRemotePath() }; if (file.isFolder()) { operations.add(ContentProviderOperation .newDelete( ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, file.getFileId())) .withSelection(where, whereArgs).build()); File localFolder = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file)); if (localFolder.exists()) { removeLocalFolder(localFolder); } } else { operations.add(ContentProviderOperation.newDelete( ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, file.getFileId())) .withSelection(where, whereArgs).build()); if (file.isDown()) { String path = file.getStoragePath(); new File(path).delete(); triggerMediaScan(path); // notify MediaScanner about removed file } } } } // update metadata of folder ContentValues cv = new ContentValues(); cv.put(ProviderTableMeta.FILE_MODIFIED, folder.getModificationTimestamp()); cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, folder.getModificationTimestampAtLastSyncForData()); cv.put(ProviderTableMeta.FILE_CREATION, folder.getCreationTimestamp()); cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, folder.getFileLength()); cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, folder.getMimetype()); cv.put(ProviderTableMeta.FILE_NAME, folder.getFileName()); cv.put(ProviderTableMeta.FILE_PARENT, folder.getParentId()); cv.put(ProviderTableMeta.FILE_PATH, folder.getRemotePath()); cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name); cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, folder.getLastSyncDateForProperties()); cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, folder.getLastSyncDateForData()); cv.put(ProviderTableMeta.FILE_ETAG, folder.getEtag()); cv.put(ProviderTableMeta.FILE_TREE_ETAG, folder.getTreeEtag()); cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, folder.isSharedViaLink() ? 1 : 0); cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, folder.isSharedWithSharee() ? 1 : 0); cv.put(ProviderTableMeta.FILE_PERMISSIONS, folder.getPermissions()); cv.put(ProviderTableMeta.FILE_REMOTE_ID, folder.getRemoteId()); cv.put(ProviderTableMeta.FILE_PRIVATE_LINK, folder.getPrivateLink()); operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).withValues(cv) .withSelection(ProviderTableMeta._ID + "=?", new String[] { String.valueOf(folder.getFileId()) }) .build()); // apply operations in batch 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()); } // update new id in file objects for insertions if (results != null) { long newId; Iterator<OCFile> filesIt = updatedFiles.iterator(); OCFile file = null; for (int i = 0; i < results.length; i++) { if (filesIt.hasNext()) { file = filesIt.next(); } else { file = null; } if (results[i].uri != null) { newId = Long.parseLong(results[i].uri.getPathSegments().get(1)); //updatedFiles.get(i).setFileId(newId); if (file != null) { file.setFileId(newId); } } } } }
From source file:org.pixmob.droidlink.sync.SyncAdapter.java
private void doPerformSync(NetworkClient client, SharedPreferences prefs, ContentProviderClient provider, SyncResult syncResult, boolean fullSync) { // Prepare the query. final String selection = DEVICE_ID + "=? AND " + STATE + "=? OR " + STATE + "=?"; final String[] selectionArgs = { client.getDeviceId(), String.valueOf(EventsContract.PENDING_UPLOAD_STATE), String.valueOf(EventsContract.PENDING_DELETE_STATE) }; // Get local data to sync. final Map<String, JSONObject> eventsToUpload = new HashMap<String, JSONObject>(8); final Set<String> eventsToDelete = new HashSet<String>(4); Cursor c = null;//from www . j av a2s .c o m try { c = provider.query(EventsContract.CONTENT_URI, PROJECTION, selection, selectionArgs, null); final int idIdx = c.getColumnIndexOrThrow(_ID); final int typeIdx = c.getColumnIndexOrThrow(TYPE); final int createdIdx = c.getColumnIndexOrThrow(CREATED); final int numberIdx = c.getColumnIndexOrThrow(NUMBER); final int nameIdx = c.getColumnIndexOrThrow(NAME); final int messageIdx = c.getColumnIndexOrThrow(MESSAGE); final int stateIdx = c.getColumnIndexOrThrow(STATE); while (c.moveToNext()) { final String eventId = c.getString(idIdx); final int eventState = c.getInt(stateIdx); if (EventsContract.PENDING_UPLOAD_STATE == eventState) { // This is a newly created event. final JSONObject event = new JSONObject(); try { event.put("deviceId", client.getDeviceId()); event.put("created", c.getLong(createdIdx)); event.put("type", c.getInt(typeIdx)); event.put("number", c.getString(numberIdx)); event.put("name", c.getString(nameIdx)); event.put("message", c.getString(messageIdx)); } catch (JSONException e) { Log.w(TAG, "Invalid event " + eventId + ": cannot sync", e); syncResult.stats.numSkippedEntries++; continue; } eventsToUpload.put(eventId, event); } else if (EventsContract.PENDING_DELETE_STATE == eventState) { // The user wants this event to be deleted. eventsToDelete.add(eventId); } } } catch (RemoteException e) { Log.e(TAG, "Failed to get events: cannot sync", e); syncResult.stats.numIoExceptions++; } finally { if (c != null) { c.close(); c = null; } } final ArrayList<ContentProviderOperation> batch = new ArrayList<ContentProviderOperation>(32); final ContentValues values = new ContentValues(8); if (eventsToDelete.isEmpty()) { Log.i(TAG, "No events to delete"); } else { Log.i(TAG, "Found " + eventsToDelete.size() + " event(s) to delete"); } // Delete events on the remote server. for (final String eventId : eventsToDelete) { if (DEVELOPER_MODE) { Log.d(TAG, "Deleting event: " + eventId); } try { client.delete("/events/" + eventId); if (DEVELOPER_MODE) { Log.d(TAG, "Deleting event in local database: " + eventId); } batch.add(ContentProviderOperation .newDelete(Uri.withAppendedPath(EventsContract.CONTENT_URI, eventId)).build()); syncResult.stats.numDeletes++; } catch (IOException e) { Log.e(TAG, "Event deletion error: cannot sync", e); syncResult.stats.numIoExceptions++; return; } catch (AppEngineAuthenticationException e) { Log.e(TAG, "Authentication error: cannot sync", e); syncResult.stats.numAuthExceptions++; return; } } try { provider.applyBatch(batch); } catch (Exception e) { Log.w(TAG, "Database error: cannot sync", e); syncResult.stats.numIoExceptions++; return; } batch.clear(); if (fullSync) { // Get all events from the remote server. final JSONArray events; if (DEVELOPER_MODE) { Log.d(TAG, "Fetching events from the remote server"); } try { events = client.getAsArray("/events"); } catch (IOException e) { Log.e(TAG, "Event listing error: cannot sync", e); syncResult.stats.numIoExceptions++; return; } catch (AppEngineAuthenticationException e) { Log.e(TAG, "Authentication error: cannot sync", e); syncResult.stats.numAuthExceptions++; return; } final int eventsLen = events != null ? events.length() : 0; if (eventsLen == 0) { Log.i(TAG, "No events from the remote server"); } else { Log.i(TAG, "Found " + eventsLen + " event(s) from the remote server"); } // Build a collection with local event identifiers. // This collection will be used to identify which events have // been deleted on the remote server. final Set<String> localEventIds; try { c = provider.query(EventsContract.CONTENT_URI, PROJECTION_ID, STATE + "=?", new String[] { String.valueOf(EventsContract.UPLOADED_STATE) }, null); localEventIds = new HashSet<String>(c.getCount()); final int idIdx = c.getColumnIndexOrThrow(_ID); while (c.moveToNext()) { final String eventId = c.getString(idIdx); localEventIds.add(eventId); } } catch (RemoteException e) { Log.e(TAG, "Failed to get events from local database", e); syncResult.stats.numIoExceptions++; return; } finally { if (c != null) { c.close(); c = null; } } String newEventId = null; int newEventCount = 0; // Reconcile remote events with local events. for (int i = 0; i < eventsLen; ++i) { String eventId = null; try { final JSONObject event = events.getJSONObject(i); eventId = event.getString("id"); // Check if this event exists in the local database. if (localEventIds.contains(eventId)) { // Found the event: update it. values.clear(); values.put(NUMBER, trimToNull(event.getString("number"))); values.put(NAME, trimToNull(event.getString("name"))); values.put(MESSAGE, trimToNull(event.getString("message"))); if (DEVELOPER_MODE) { Log.d(TAG, "Updating event in local database: " + eventId); } batch.add(ContentProviderOperation .newUpdate(Uri.withAppendedPath(EventsContract.CONTENT_URI, eventId)) .withExpectedCount(1).withValues(values).build()); syncResult.stats.numUpdates++; } else { // The event was not found: insert it. values.clear(); values.put(_ID, eventId); values.put(DEVICE_ID, event.getString("deviceId")); values.put(CREATED, event.getLong("created")); values.put(TYPE, event.getInt("type")); values.put(NUMBER, trimToNull(event.getString("number"))); values.put(NAME, trimToNull(event.getString("name"))); values.put(MESSAGE, trimToNull(event.getString("message"))); values.put(STATE, EventsContract.UPLOADED_STATE); if (DEVELOPER_MODE) { Log.d(TAG, "Adding event to local database: " + eventId); } batch.add(ContentProviderOperation .newInsert(Uri.withAppendedPath(EventsContract.CONTENT_URI, eventId)) .withValues(values).build()); syncResult.stats.numInserts++; ++newEventCount; if (newEventId == null) { newEventId = eventId; } } // This event now exists in the local database: // remove its identifier from this collection as we // don't want to delete it. localEventIds.remove(eventId); } catch (JSONException e) { Log.w(TAG, "Invalid event at index " + i + ": cannot sync", e); syncResult.stats.numSkippedEntries++; continue; } } // The remaining event identifiers was removed on the remote // server: there are still present in the local database. These // events are now being deleted. for (final String eventId : localEventIds) { if (DEVELOPER_MODE) { Log.d(TAG, "Deleting event in local database: " + eventId); } batch.add(ContentProviderOperation .newDelete(Uri.withAppendedPath(EventsContract.CONTENT_URI, eventId)).build()); syncResult.stats.numDeletes++; } try { provider.applyBatch(batch); } catch (Exception e) { Log.e(TAG, "Database error: cannot sync", e); syncResult.stats.numIoExceptions++; return; } batch.clear(); if (newEventCount > 1) { newEventId = null; } if (newEventCount != 0) { startSyncNotificationService(newEventCount, newEventId); } } final int numEventsToUpload = eventsToUpload.size(); if (numEventsToUpload == 0) { Log.i(TAG, "No events to upload"); } else { Log.i(TAG, "Found " + numEventsToUpload + " event(s) to upload"); } // Send local events to the remote server. for (final Map.Entry<String, JSONObject> entry : eventsToUpload.entrySet()) { final String eventId = entry.getKey(); if (DEVELOPER_MODE) { Log.d(TAG, "Uploading event: " + eventId); } final JSONObject event = entry.getValue(); try { client.put("/events/" + eventId, event); if (DEVELOPER_MODE) { Log.d(TAG, "Updating event state to UPLOADED: " + eventId); } values.clear(); values.put(STATE, EventsContract.UPLOADED_STATE); batch.add(ContentProviderOperation .newUpdate(Uri.withAppendedPath(EventsContract.CONTENT_URI, eventId)).withValues(values) .withExpectedCount(1).build()); syncResult.stats.numUpdates++; Log.i(TAG, "Event upload successful: " + eventId); } catch (NetworkClientException e) { if (e.getStatusCode() == 404) { Log.e(TAG, "Device not found: cannot sync", e); registerDevice(); } else { Log.e(TAG, "Network error: cannot sync", e); } syncResult.stats.numIoExceptions++; return; } catch (IOException e) { Log.e(TAG, "Event upload error: cannot sync", e); syncResult.stats.numIoExceptions++; return; } catch (AppEngineAuthenticationException e) { Log.e(TAG, "Authentication error: cannot sync", e); syncResult.stats.numAuthExceptions++; return; } } try { provider.applyBatch(batch); } catch (Exception e) { Log.w(TAG, "Database error: cannot sync", e); syncResult.stats.numIoExceptions++; return; } batch.clear(); final SharedPreferences.Editor prefsEditor = prefs.edit(); final boolean syncRequired = !eventsToDelete.isEmpty() || !eventsToUpload.isEmpty(); if (syncRequired) { // Generate an unique sync token: the server will send this token to // every devices. If this token is received on this device, the sync // will not start. final String syncToken = UUID.randomUUID().toString(); prefsEditor.putString(SP_KEY_SYNC_TOKEN, syncToken); Features.getFeature(SharedPreferencesSaverFeature.class).save(prefsEditor); // Sync user devices. try { final JSONObject data = new JSONObject(); data.put("token", syncToken); client.post("/devices/" + client.getDeviceId() + "/sync", data); } catch (NetworkClientException e) { if (e.getStatusCode() == 404) { registerDevice(); } } catch (IOException e) { Log.e(TAG, "Device sync error: cannot sync", e); syncResult.stats.numIoExceptions++; return; } catch (AppEngineAuthenticationException e) { Log.e(TAG, "Authentication error: cannot sync", e); syncResult.stats.numAuthExceptions++; return; } catch (JSONException e) { Log.w(TAG, "Invalid sync token " + syncToken + ": cannot sync", e); syncResult.stats.numIoExceptions++; return; } } // Store sync time. prefsEditor.putLong(SP_KEY_LAST_SYNC, System.currentTimeMillis()); Features.getFeature(SharedPreferencesSaverFeature.class).save(prefsEditor); }