use of android.content.ContentProviderOperation in project Android-Developers-Samples by johnjohndoe.
the class SyncAdapter method updateLocalFeedData.
/**
* Read XML 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.
*
* <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 updateLocalFeedData(final InputStream stream, final SyncResult syncResult) throws IOException, XmlPullParserException, RemoteException, OperationApplicationException, ParseException {
final FeedParser feedParser = new FeedParser();
final ContentResolver contentResolver = getContext().getContentResolver();
Log.i(TAG, "Parsing stream as Atom feed");
final List<FeedParser.Entry> entries = feedParser.parse(stream);
Log.i(TAG, "Parsing complete. Found " + entries.size() + " entries");
ArrayList<ContentProviderOperation> batch = new ArrayList<ContentProviderOperation>();
// Build hash table of incoming entries
HashMap<String, FeedParser.Entry> entryMap = new HashMap<String, FeedParser.Entry>();
for (FeedParser.Entry e : entries) {
entryMap.put(e.id, e);
}
// Get list of all items
Log.i(TAG, "Fetching local entries for merge");
// Get all entries
Uri uri = FeedContract.Entry.CONTENT_URI;
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 link;
long published;
while (c.moveToNext()) {
syncResult.stats.numEntries++;
id = c.getInt(COLUMN_ID);
entryId = c.getString(COLUMN_ENTRY_ID);
title = c.getString(COLUMN_TITLE);
link = c.getString(COLUMN_LINK);
published = c.getLong(COLUMN_PUBLISHED);
FeedParser.Entry 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
Uri existingUri = FeedContract.Entry.CONTENT_URI.buildUpon().appendPath(Integer.toString(id)).build();
if ((match.title != null && !match.title.equals(title)) || (match.link != null && !match.link.equals(link)) || (match.published != published)) {
// Update existing record
Log.i(TAG, "Scheduling update: " + existingUri);
batch.add(ContentProviderOperation.newUpdate(existingUri).withValue(FeedContract.Entry.COLUMN_NAME_TITLE, title).withValue(FeedContract.Entry.COLUMN_NAME_LINK, link).withValue(FeedContract.Entry.COLUMN_NAME_PUBLISHED, published).build());
syncResult.stats.numUpdates++;
} else {
Log.i(TAG, "No action: " + existingUri);
}
} else {
// Entry doesn't exist. Remove it from the database.
Uri deleteUri = FeedContract.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 (FeedParser.Entry e : entryMap.values()) {
Log.i(TAG, "Scheduling insert: entry_id=" + e.id);
batch.add(ContentProviderOperation.newInsert(FeedContract.Entry.CONTENT_URI).withValue(FeedContract.Entry.COLUMN_NAME_ENTRY_ID, e.id).withValue(FeedContract.Entry.COLUMN_NAME_TITLE, e.title).withValue(FeedContract.Entry.COLUMN_NAME_LINK, e.link).withValue(FeedContract.Entry.COLUMN_NAME_PUBLISHED, e.published).build());
syncResult.stats.numInserts++;
}
Log.i(TAG, "Merge solution ready. Applying batch update");
mContentResolver.applyBatch(FeedContract.CONTENT_AUTHORITY, batch);
mContentResolver.notifyChange(// URI where data was modified
FeedContract.Entry.CONTENT_URI, // No local observer
null, // IMPORTANT: Do not sync to network
false);
// 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.
}
use of android.content.ContentProviderOperation in project PermissionsDispatcher by hotchemi.
the class ContactsFragment method insertDummyContact.
/**
* Accesses the Contacts content provider directly to insert a new contact.
* <p>
* The contact is called "__DUMMY ENTRY" and only contains a name.
*/
private void insertDummyContact() {
// Two operations are needed to insert a new contact.
ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(2);
// First, set up a new raw contact.
ContentProviderOperation.Builder op = ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI).withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null).withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null);
operations.add(op.build());
// Next, set the name for the contact.
op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0).withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE).withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, DUMMY_CONTACT_NAME);
operations.add(op.build());
// Apply the operations.
ContentResolver resolver = getActivity().getContentResolver();
try {
resolver.applyBatch(ContactsContract.AUTHORITY, operations);
} catch (RemoteException e) {
Log.d(TAG, "Could not add a new contact: " + e.getMessage());
} catch (OperationApplicationException e) {
Log.d(TAG, "Could not add a new contact: " + e.getMessage());
}
}
use of android.content.ContentProviderOperation in project iosched by google.
the class VideosHandler method buildVideo.
private void buildVideo(boolean isInsert, Video video, ArrayList<ContentProviderOperation> list) {
Uri allVideosUri = ScheduleContractHelper.setUriAsCalledFromSyncAdapter(ScheduleContract.Videos.CONTENT_URI);
Uri thisVideoUri = ScheduleContractHelper.setUriAsCalledFromSyncAdapter(ScheduleContract.Videos.buildVideoUri(video.id));
ContentProviderOperation.Builder builder;
if (isInsert) {
builder = ContentProviderOperation.newInsert(allVideosUri);
} else {
builder = ContentProviderOperation.newUpdate(thisVideoUri);
}
if (TextUtils.isEmpty(video.vid)) {
LOGW(TAG, "Ignoring video with missing video ID.");
return;
}
String thumbUrl = video.thumbnailUrl;
if (TextUtils.isEmpty(thumbUrl)) {
// Oops, missing thumbnail URL. Let's improvise.
// NOTE: this method of obtaining a thumbnail URL from the video ID
// is unofficial and might not work in the future; that's why we use
// it only as a fallback in case we don't get a thumbnail URL in the incoming data.
thumbUrl = String.format(Locale.US, Config.VIDEO_LIBRARY_FALLBACK_THUMB_URL_FMT, video.vid);
LOGW(TAG, "Video with missing thumbnail URL: " + video.vid + ". Using fallback: " + thumbUrl);
}
list.add(builder.withValue(ScheduleContract.Videos.VIDEO_ID, video.id).withValue(ScheduleContract.Videos.VIDEO_YEAR, video.year).withValue(ScheduleContract.Videos.VIDEO_TITLE, video.title.trim()).withValue(ScheduleContract.Videos.VIDEO_DESC, video.desc).withValue(ScheduleContract.Videos.VIDEO_VID, video.vid).withValue(ScheduleContract.Videos.VIDEO_TOPIC, video.topic).withValue(ScheduleContract.Videos.VIDEO_SPEAKERS, video.speakers).withValue(ScheduleContract.Videos.VIDEO_THUMBNAIL_URL, thumbUrl).withValue(ScheduleContract.Videos.VIDEO_IMPORT_HASHCODE, video.getImportHashcode()).build());
}
use of android.content.ContentProviderOperation in project iosched by google.
the class BlocksHandler method outputBlock.
private static void outputBlock(Block block, ArrayList<ContentProviderOperation> list) {
Uri uri = ScheduleContractHelper.setUriAsCalledFromSyncAdapter(ScheduleContract.Blocks.CONTENT_URI);
ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(uri);
String title = block.title != null ? block.title : "";
String meta = block.subtitle != null ? block.subtitle : "";
String type = block.type;
if (!ScheduleContract.Blocks.isValidBlockType(type)) {
LOGW(TAG, "block from " + block.start + " to " + block.end + " has unrecognized type (" + type + "). Using " + ScheduleContract.Blocks.BLOCK_TYPE_BREAK + " instead.");
type = ScheduleContract.Blocks.BLOCK_TYPE_BREAK;
}
long startTimeL = ParserUtils.parseTime(block.start);
long endTimeL = ParserUtils.parseTime(block.end);
final String blockId = ScheduleContract.Blocks.generateBlockId(startTimeL, endTimeL);
builder.withValue(ScheduleContract.Blocks.BLOCK_ID, blockId);
builder.withValue(ScheduleContract.Blocks.BLOCK_TITLE, title);
builder.withValue(ScheduleContract.Blocks.BLOCK_START, startTimeL);
builder.withValue(ScheduleContract.Blocks.BLOCK_END, endTimeL);
builder.withValue(ScheduleContract.Blocks.BLOCK_TYPE, type);
builder.withValue(ScheduleContract.Blocks.BLOCK_SUBTITLE, meta);
list.add(builder.build());
}
use of android.content.ContentProviderOperation in project iosched by google.
the class CardHandler method makeContentProviderOperations.
@Override
public void makeContentProviderOperations(ArrayList<ContentProviderOperation> list) {
LOGI(TAG, "Creating content provider operations for cards: " + mCards.size());
Uri uri = ScheduleContractHelper.setUriAsCalledFromSyncAdapter(ScheduleContract.Cards.CONTENT_URI);
// The list of cards is not large, so for simplicity we delete all of them and repopulate
list.add(ContentProviderOperation.newDelete(uri).build());
for (Card card : mCards.values()) {
ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(uri);
builder.withValue(ScheduleContract.Cards.ACTION_COLOR, card.mActionColor);
builder.withValue(ScheduleContract.Cards.ACTION_TEXT, card.mActionText);
builder.withValue(ScheduleContract.Cards.ACTION_URL, card.mActionUrl);
builder.withValue(ScheduleContract.Cards.ACTION_TYPE, card.mActionType);
builder.withValue(ScheduleContract.Cards.ACTION_EXTRA, card.mActionExtra);
builder.withValue(ScheduleContract.Cards.BACKGROUND_COLOR, card.mBackgroundColor);
builder.withValue(ScheduleContract.Cards.CARD_ID, card.mId);
try {
long startTime = Card.getEpochMillisFromTimeString(card.mValidFrom);
LOGI(TAG, "Processing card with epoch start time: " + startTime);
builder.withValue(ScheduleContract.Cards.DISPLAY_START_DATE, startTime);
} catch (IllegalArgumentException exception) {
LOGE(TAG, "Card time disabled, invalid display start date defined for card: " + card.mTitle + " " + card.mValidFrom);
builder.withValue(ScheduleContract.Cards.DISPLAY_START_DATE, Long.MAX_VALUE);
}
try {
long endTime = Card.getEpochMillisFromTimeString(card.mValidUntil);
LOGI(TAG, "Processing card with epoch end time: " + endTime);
builder.withValue(ScheduleContract.Cards.DISPLAY_END_DATE, endTime);
} catch (IllegalArgumentException exception) {
LOGE(TAG, "Card time disabled, invalid display end date defined for card: " + card.mTitle + " " + card.mValidUntil);
builder.withValue(ScheduleContract.Cards.DISPLAY_END_DATE, 0L);
}
builder.withValue(ScheduleContract.Cards.MESSAGE, card.mShortMessage);
builder.withValue(ScheduleContract.Cards.TEXT_COLOR, card.mTextColor);
builder.withValue(ScheduleContract.Cards.TITLE, card.mTitle);
list.add(builder.build());
}
}
Aggregations