private void buildSpeaker( boolean isInsert, Speaker speaker, ArrayList<ContentProviderOperation> list) { Uri allSpeakersUri = ScheduleContractHelper.setUriAsCalledFromSyncAdapter(ScheduleContract.Speakers.CONTENT_URI); Uri thisSpeakerUri = ScheduleContractHelper.setUriAsCalledFromSyncAdapter( ScheduleContract.Speakers.buildSpeakerUri(speaker.id)); ContentProviderOperation.Builder builder; if (isInsert) { builder = ContentProviderOperation.newInsert(allSpeakersUri); } else { builder = ContentProviderOperation.newUpdate(thisSpeakerUri); } list.add( builder .withValue(ScheduleContract.SyncColumns.UPDATED, System.currentTimeMillis()) .withValue(ScheduleContract.Speakers.SPEAKER_ID, speaker.id) .withValue(ScheduleContract.Speakers.SPEAKER_NAME, speaker.name) .withValue(ScheduleContract.Speakers.SPEAKER_ABSTRACT, speaker.bio) .withValue(ScheduleContract.Speakers.SPEAKER_COMPANY, speaker.company) .withValue(ScheduleContract.Speakers.SPEAKER_IMAGE_URL, speaker.thumbnailUrl) .withValue(ScheduleContract.Speakers.SPEAKER_PLUSONE_URL, speaker.plusoneUrl) .withValue(ScheduleContract.Speakers.SPEAKER_TWITTER_URL, speaker.twitterUrl) .withValue( ScheduleContract.Speakers.SPEAKER_IMPORT_HASHCODE, speaker.getImportHashcode()) .build()); }
private HashMap<String, String> loadSpeakerHashcodes() { Uri uri = ScheduleContractHelper.setUriAsCalledFromSyncAdapter(ScheduleContract.Speakers.CONTENT_URI); Cursor cursor = null; try { cursor = mContext .getContentResolver() .query(uri, SpeakerHashcodeQuery.PROJECTION, null, null, null); if (cursor == null) { LOGE(TAG, "Error querying speaker hashcodes (got null cursor)"); return null; } if (cursor.getCount() < 1) { LOGE(TAG, "Error querying speaker hashcodes (no records returned)"); return null; } HashMap<String, String> result = new HashMap<String, String>(); if (cursor.moveToFirst()) { do { String speakerId = cursor.getString(SpeakerHashcodeQuery.SPEAKER_ID); String hashcode = cursor.getString(SpeakerHashcodeQuery.SPEAKER_IMPORT_HASHCODE); result.put(speakerId, hashcode == null ? "" : hashcode); } while (cursor.moveToNext()); } return result; } finally { if (cursor != null) { cursor.close(); } } }
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()); }
@Override public void makeContentProviderOperations(ArrayList<ContentProviderOperation> list) { Uri uri = ScheduleContractHelper.setUriAsCalledFromSyncAdapter(ScheduleContract.Speakers.CONTENT_URI); HashMap<String, String> speakerHashcodes = loadSpeakerHashcodes(); HashSet<String> speakersToKeep = new HashSet<String>(); boolean isIncrementalUpdate = speakerHashcodes != null && speakerHashcodes.size() > 0; if (isIncrementalUpdate) { LOGD(TAG, "Doing incremental update for speakers."); } else { LOGD(TAG, "Doing FULL (non incremental) update for speakers."); list.add(ContentProviderOperation.newDelete(uri).build()); } int updatedSpeakers = 0; for (Speaker speaker : mSpeakers.values()) { String hashCode = speaker.getImportHashcode(); speakersToKeep.add(speaker.id); // add speaker, if necessary if (!isIncrementalUpdate || !speakerHashcodes.containsKey(speaker.id) || !speakerHashcodes.get(speaker.id).equals(hashCode)) { ++updatedSpeakers; boolean isNew = !isIncrementalUpdate || !speakerHashcodes.containsKey(speaker.id); buildSpeaker(isNew, speaker, list); } } int deletedSpeakers = 0; if (isIncrementalUpdate) { for (String speakerId : speakerHashcodes.keySet()) { if (!speakersToKeep.contains(speakerId)) { buildDeleteOperation(speakerId, list); ++deletedSpeakers; } } } LOGD( TAG, "Speakers: " + (isIncrementalUpdate ? "INCREMENTAL" : "FULL") + " update. " + updatedSpeakers + " to update, " + deletedSpeakers + " to delete. New total: " + mSpeakers.size()); }
@Override public void makeContentProviderOperations(ArrayList<ContentProviderOperation> list) { Uri uri = ScheduleContractHelper.setUriAsCalledFromSyncAdapter(ScheduleContract.Videos.CONTENT_URI); HashMap<String, String> videoHashcodes = loadVideoHashcodes(); HashSet<String> videosToKeep = new HashSet<String>(); boolean isIncrementalUpdate = videoHashcodes != null && videoHashcodes.size() > 0; if (isIncrementalUpdate) { LOGD(TAG, "Doing incremental update for videos."); } else { LOGD(TAG, "Doing FULL (non incremental) update for videos."); list.add(ContentProviderOperation.newDelete(uri).build()); } int updatedVideos = 0; for (Video video : mVideos.values()) { String hashCode = video.getImportHashcode(); videosToKeep.add(video.id); // add video, if necessary if (!isIncrementalUpdate || !videoHashcodes.containsKey(video.id) || !videoHashcodes.get(video.id).equals(hashCode)) { ++updatedVideos; boolean isNew = !isIncrementalUpdate || !videoHashcodes.containsKey(video.id); buildVideo(isNew, video, list); } } int deletedVideos = 0; if (isIncrementalUpdate) { for (String videoId : videoHashcodes.keySet()) { if (!videosToKeep.contains(videoId)) { buildDeleteOperation(videoId, list); ++deletedVideos; } } } LOGD( TAG, "Videos: " + (isIncrementalUpdate ? "INCREMENTAL" : "FULL") + " update. " + updatedVideos + " to update, " + deletedVideos + " to delete. New total: " + mVideos.size()); }
private void buildDeleteOperation(String speakerId, ArrayList<ContentProviderOperation> list) { Uri speakerUri = ScheduleContractHelper.setUriAsCalledFromSyncAdapter( ScheduleContract.Speakers.buildSpeakerUri(speakerId)); list.add(ContentProviderOperation.newDelete(speakerUri).build()); }
private void buildDeleteOperation(String videoId, ArrayList<ContentProviderOperation> list) { Uri videoUri = ScheduleContractHelper.setUriAsCalledFromSyncAdapter( ScheduleContract.Videos.buildVideoUri(videoId)); list.add(ContentProviderOperation.newDelete(videoUri).build()); }