Example usage for android.content ContentUris withAppendedId

List of usage examples for android.content ContentUris withAppendedId

Introduction

In this page you can find the example usage for android.content ContentUris withAppendedId.

Prototype

public static Uri withAppendedId(Uri contentUri, long id) 

Source Link

Document

Appends the given ID to the end of the path.

Usage

From source file:com.android.music.TrackBrowserFragment.java

private void removePlaylistItem(int which) {
    View v = mTrackList.getChildAt(which - mTrackList.getFirstVisiblePosition());
    if (v == null) {
        Log.d(LOGTAG, "No view when removing playlist item " + which);
        return;//ww  w  . j av  a 2 s. co m
    }
    try {
        if (MusicUtils.sService != null && which != MusicUtils.sService.getQueuePosition()) {
            mDeletedOneRow = true;
        }
    } catch (RemoteException e) {
        // Service died, so nothing playing.
        mDeletedOneRow = true;
    }
    v.setVisibility(View.GONE);
    mTrackList.invalidateViews();
    if (mTrackCursor instanceof NowPlayingCursor) {
        ((NowPlayingCursor) mTrackCursor).removeItem(which);
    } else {
        int colidx = mTrackCursor.getColumnIndexOrThrow(MediaStore.Audio.Playlists.Members._ID);
        mTrackCursor.moveToPosition(which);
        long id = mTrackCursor.getLong(colidx);
        Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", Long.valueOf(mPlaylist));
        getActivity().getContentResolver().delete(ContentUris.withAppendedId(uri, id), null, null);
    }
    v.setVisibility(View.VISIBLE);
    mTrackList.invalidateViews();
}

From source file:com.akop.bach.parser.PsnEuParser.java

@SuppressLint("DefaultLocale")
@Override/*  w w w  .  j a  v a  2  s.  c o m*/
protected void parseTrophies(PsnAccount account, long gameId) throws ParserException, IOException {
    // Find game record in local DB
    ContentResolver cr = mContext.getContentResolver();

    String gameUid = Games.getUid(mContext, gameId);

    String url = String.format(URL_TROPHIES_f, gameUid);
    String page = getResponse(url);

    int index = 0;
    long started = System.currentTimeMillis();

    Matcher trophies = PATTERN_TROPHIES.matcher(page);
    Matcher m;

    List<ContentValues> cvList = new ArrayList<ContentValues>(100);
    while (trophies.find()) {
        boolean trophyUnlocked = "true".equalsIgnoreCase(trophies.group(1));
        String trophyContent = trophies.group(2);

        String iconUrl = null;
        if ((m = PATTERN_TROPHY_ICON.matcher(trophyContent)).find())
            iconUrl = getLargeTrophyIcon(resolveImageUrl(url, m.group(1)));

        String title = mContext.getString(R.string.secret_trophy);
        String description = mContext.getString(R.string.this_is_a_secret_trophy);

        if (!(m = PATTERN_TROPHY_TITLE.matcher(trophyContent)).find())
            continue;

        int type = PSN.TROPHY_SECRET;
        boolean isSecret = false;
        String trophyType = m.group(1).toUpperCase();
        if (trophyType.equals("BRONZE"))
            type = PSN.TROPHY_BRONZE;
        else if (trophyType.equals("SILVER"))
            type = PSN.TROPHY_SILVER;
        else if (trophyType.equals("GOLD"))
            type = PSN.TROPHY_GOLD;
        else if (trophyType.equals("PLATINUM"))
            type = PSN.TROPHY_PLATINUM;
        else if (trophyType.equals("UNKNOWN"))
            isSecret = true;

        if (!isSecret) {
            title = htmlDecode(m.group(2));
            if ((m = PATTERN_TROPHY_DESCRIPTION.matcher(trophyContent)).find())
                description = htmlDecode(m.group(1));
        }

        long earned = 0;
        String earnedText = null;
        if (trophyUnlocked) {
            // No more date info
            earned = System.currentTimeMillis();
            earnedText = mContext.getString(R.string.unlocked);
        }

        ContentValues cv = new ContentValues(20);

        cv.put(Trophies.TITLE, title);
        cv.put(Trophies.DESCRIPTION, description);
        cv.put(Trophies.SORT_ORDER, index);
        cv.put(Trophies.EARNED, earned);
        cv.put(Trophies.EARNED_TEXT, earnedText);
        cv.put(Trophies.ICON_URL, iconUrl);
        cv.put(Trophies.GAME_ID, gameId);
        cv.put(Trophies.IS_SECRET, isSecret ? 1 : 0);
        cv.put(Trophies.TYPE, type);

        cvList.add(cv);
        index++;
    }

    if (App.getConfig().logToConsole())
        started = displayTimeTaken("New trophy parsing", started);

    ContentValues[] cva = new ContentValues[cvList.size()];
    cvList.toArray(cva);

    cr.delete(Trophies.CONTENT_URI, Trophies.GAME_ID + "=" + gameId, null);

    // Bulk-insert new trophies
    cr.bulkInsert(Trophies.CONTENT_URI, cva);
    cr.notifyChange(Trophies.CONTENT_URI, null);

    if (App.getConfig().logToConsole())
        started = displayTimeTaken("New trophy processing", started);

    // Update the game to remove the 'dirty' attribute
    ContentValues cv = new ContentValues(10);
    cv.put(Games.TROPHIES_DIRTY, 0);
    cr.update(Games.CONTENT_URI, cv, Games._ID + "=" + gameId, null);

    cr.notifyChange(ContentUris.withAppendedId(Games.CONTENT_URI, gameId), null);

    if (App.getConfig().logToConsole())
        displayTimeTaken("Updating Game", started);
}

From source file:com.tct.emailcommon.utility.AttachmentUtilities.java

public static void saveAttachmentToExternal(Context context, Attachment attachment, String path) {
    final Uri uri = ContentUris.withAppendedId(Attachment.CONTENT_URI, attachment.mId);
    final ContentValues cv = new ContentValues();
    final long attachmentId = attachment.mId;
    final long accountId = attachment.mAccountKey;
    //TS: wenggangjin 2014-12-11 EMAIL BUGFIX_868520 MOD_S
    String contentUri = null;/*w ww  .  ja v a2  s  .  c om*/
    //TS: wenggangjin 2014-12-11 EMAIL BUGFIX_868520 MOD_S
    final long size;
    InputStream in = null;
    OutputStream out = null;
    try {
        ContentResolver resolver = context.getContentResolver();
        if (Utility.isExternalStorageMounted()) {
            if (TextUtils.isEmpty(attachment.mFileName)) {
                // TODO: This will prevent a crash but does not surface the underlying problem
                // to the user correctly.
                LogUtils.w(Logging.LOG_TAG, "Trying to save an attachment with no name: %d", attachmentId);
                throw new IOException("Can't save an attachment with no name");
            }
            // TS: Gantao 2015-07-29 EMAIL BUGFIX-1055568 MOD_S
            try {
                String cachedFileUri = attachment.getCachedFileUri();
                if (TextUtils.isEmpty(cachedFileUri)) {
                    throw new IOException();
                }
                in = resolver.openInputStream(Uri.parse(cachedFileUri));
            } catch (IOException e) {
                String contentUriForOpen = attachment.getContentUri();
                if (TextUtils.isEmpty(contentUriForOpen)) {
                    throw new IOException();
                }
                in = resolver.openInputStream(Uri.parse(contentUriForOpen));
                //TS: junwei-xu 2016-03-31 EMAIL BUGFIX-1886442 ADD_S
            } catch (IllegalArgumentException e) {
                String contentUriForOpen = attachment.getContentUri();
                if (TextUtils.isEmpty(contentUriForOpen)) {
                    throw new IOException();
                }
                in = resolver.openInputStream(Uri.parse(contentUriForOpen));
            }
            //TS: junwei-xu 2016-03-31 EMAIL BUGFIX-1886442 ADD_E
            //TS: jian.xu 2016-01-20 EMAIL FEATURE-1477377 MOD_S
            //Note: we support save attachment at user designated location.
            File downloads;
            if (path != null) {
                downloads = new File(path);
            } else {
                downloads = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
            }
            //TS: jian.xu 2016-01-20 EMAIL FEATURE-1477377 MOD_E
            downloads.mkdirs();
            File file = Utility.createUniqueFile(downloads, attachment.mFileName);
            out = new FileOutputStream(file);
            size = copyFile(in, out);
            String absolutePath = file.getAbsolutePath();
            // Although the download manager can scan media files, scanning only happens
            // after the user clicks on the item in the Downloads app. So, we run the
            // attachment through the media scanner ourselves so it gets added to
            // gallery / music immediately.
            MediaScannerConnection.scanFile(context, new String[] { absolutePath }, null, null);
            final String mimeType = TextUtils.isEmpty(attachment.mMimeType) ? "application/octet-stream"
                    : attachment.mMimeType;
            try {
                DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
                //TS: junwei-xu 2016-02-04 EMAIL BUGFIX-1531245 MOD_S
                //Note: should use media scanner, it will allow update the
                //media provider uri column in download manager's database.
                long id = dm.addCompletedDownload(attachment.mFileName, attachment.mFileName,
                        true /* use media scanner */, mimeType, absolutePath, size,
                        true /* show notification */);
                //TS: junwei-xu 2016-02-04 EMAIL BUGFIX-1531245 MOD_E
                contentUri = dm.getUriForDownloadedFile(id).toString();
            } catch (final IllegalArgumentException e) {
                LogUtils.d(LogUtils.TAG, e, "IAE from DownloadManager while saving attachment");
                throw new IOException(e);
            }
        } else {
            LogUtils.w(Logging.LOG_TAG, "Trying to save an attachment without external storage?");
            throw new IOException();
        }
        // Update the attachment
        cv.put(AttachmentColumns.SIZE, size);
        cv.put(AttachmentColumns.UI_STATE, UIProvider.UIPROVIDER_ATTACHMENTSTATE_SAVED);
        // TS: Gantao 2015-06-30 EMAIL BUGFIX-1031608 ADD_S
        //Note:we have saved the attachment to sd card,so should update the attachment destination external
        cv.put(AttachmentColumns.UI_DESTINATION, UIProvider.UIPROVIDER_ATTACHMENTDESTINATION_EXTERNAL);
        // TS: Gantao 2015-06-30 EMAIL BUGFIX-1031608 ADD_E
    } catch (IOException e) {
        // Handle failures here...
        LogUtils.e(Logging.LOG_TAG, "IOException while save an attachment to external storage");
    } finally {
        try {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        } catch (IOException e) {
            LogUtils.e(Logging.LOG_TAG, "ioexception while close the stream");
        }
    }
    // TS: Gantao 2015-07-29 EMAIL BUGFIX-1055568 MOD_E
    //TS: wenggangjin 2014-12-10 EMAIL BUGFIX_871936 MOD_S
    //        context.getContentResolver().update(uri, cv, null, null);
    if (cv.size() > 0) {
        context.getContentResolver().update(uri, cv, null, null);
    }
    //TS: wenggangjin 2014-12-10 EMAIL BUGFIX_871936 MOD_E
    //TS: wenggangjin 2014-12-11 EMAIL BUGFIX_868520 MOD_S
    if (contentUri != null && attachment.mContentId != null && attachment.mContentId.length() > 0) {
        Body body = Body.restoreBodyWithMessageId(context, attachment.mMessageKey);
        if (body != null && body.mHtmlContent != null) {
            cv.clear();
            String html = body.mHtmlContent;
            String contentIdRe = "\\s+(?i)src=\"cid(?-i):\\Q" + attachment.mContentId + "\\E\"";
            String srcContentUri = " src=\"" + contentUri + "\"";
            //TS: zhaotianyong 2015-04-15 EMAIL BUGFIX_976967 MOD_S
            try {
                html = html.replaceAll(contentIdRe, srcContentUri);
            } catch (PatternSyntaxException e) {
                LogUtils.w(Logging.LOG_TAG, "Unrecognized backslash escape sequence in pattern");
            }
            //TS: zhaotianyong 2015-04-15 EMAIL BUGFIX_976967 MOD_E
            cv.put(BodyColumns.HTML_CONTENT, html);
            Body.updateBodyWithMessageId(context, attachment.mMessageKey, cv);
            Body.restoreBodyHtmlWithMessageId(context, attachment.mMessageKey);
        }
    }
    //TS: wenggangjin 2014-12-11 EMAIL BUGFIX_868520 MOD_E
}

From source file:com.android.exchange.ExchangeService.java

/**
 * Return a list of all Accounts in EmailProvider.  Because the result of this call may be used
 * in account reconciliation, an exception is thrown if the result cannot be guaranteed accurate
 * @param context the caller's context//from  w  w w  . ja  v a  2  s .c om
 * @param accounts a list that Accounts will be added into
 * @return the list of Accounts
 * @throws ProviderUnavailableException if the list of Accounts cannot be guaranteed valid
 */
private static AccountList collectEasAccounts(Context context, AccountList accounts) {
    ContentResolver resolver = context.getContentResolver();
    Cursor c = resolver.query(Account.CONTENT_URI, Account.CONTENT_PROJECTION, null, null, null);
    // We must throw here; callers might use the information we provide for reconciliation, etc.
    if (c == null)
        throw new ProviderUnavailableException();
    try {
        ContentValues cv = new ContentValues();
        while (c.moveToNext()) {
            long hostAuthId = c.getLong(Account.CONTENT_HOST_AUTH_KEY_RECV_COLUMN);
            if (hostAuthId > 0) {
                HostAuth ha = HostAuth.restoreHostAuthWithId(context, hostAuthId);
                if (ha != null && ha.mProtocol.equals("eas")) {
                    Account account = new Account();
                    account.restore(c);
                    // Cache the HostAuth
                    account.mHostAuthRecv = ha;
                    accounts.add(account);
                    // Fixup flags for inbox (should accept moved mail)
                    Mailbox inbox = Mailbox.restoreMailboxOfType(context, account.mId, Mailbox.TYPE_INBOX);
                    if (inbox != null && ((inbox.mFlags & Mailbox.FLAG_ACCEPTS_MOVED_MAIL) == 0)) {
                        cv.put(MailboxColumns.FLAGS, inbox.mFlags | Mailbox.FLAG_ACCEPTS_MOVED_MAIL);
                        resolver.update(ContentUris.withAppendedId(Mailbox.CONTENT_URI, inbox.mId), cv, null,
                                null);
                    }
                }
            }
        }
    } finally {
        c.close();
    }
    return accounts;
}

From source file:com.jefftharris.passwdsafe.sync.MainActivity.java

/** Update the UI when the Dropbox account is changed */
private void updateDropboxAccount(Cursor cursor) {
    boolean haveCursor = (cursor != null);
    GuiUtils.setVisible(findViewById(R.id.dropbox_container), haveCursor);
    GuiUtils.setVisible(findViewById(R.id.dropbox_separator), haveCursor);
    if (haveCursor) {
        long id = cursor.getLong(PasswdSafeContract.Providers.PROJECTION_IDX_ID);
        String acct = PasswdSafeContract.Providers.getDisplayName(cursor);
        int freqVal = cursor.getInt(PasswdSafeContract.Providers.PROJECTION_IDX_SYNC_FREQ);
        ProviderSyncFreqPref freq = ProviderSyncFreqPref.freqValueOf(freqVal);
        itsDropboxUri = ContentUris.withAppendedId(PasswdSafeContract.Providers.CONTENT_URI, id);
        boolean authorized = getDbxProvider().isAccountAuthorized();

        TextView acctView = (TextView) findViewById(R.id.dropbox_acct);
        assert acctView != null;
        acctView.setText(acct);//  w  ww. jav  a2 s.c  o m
        View chooseFilesBtn = findViewById(R.id.dropbox_choose_files);
        assert chooseFilesBtn != null;
        chooseFilesBtn.setEnabled(authorized);

        View freqSpinLabel = findViewById(R.id.dropbox_interval_label);
        assert freqSpinLabel != null;
        Spinner freqSpin = (Spinner) findViewById(R.id.dropbox_interval);
        assert freqSpin != null;
        freqSpin.setSelection(freq.getDisplayIdx());
        freqSpin.setEnabled(true);
        freqSpinLabel.setEnabled(true);

        GuiUtils.setVisible(findViewById(R.id.dropbox_acct_unlink), !authorized);
    } else {
        itsDropboxUri = null;
    }
}

From source file:com.bangz.smartmute.LocationsMapFragment.java

@Override
public void onInfoWindowClick(Marker marker) {

    MarkerExInfo mei = markerManager.getExtraInfo(marker);
    LatLng latlng = marker.getPosition();

    Uri uri = null;//from w ww  .  j  av  a  2  s. c  o m
    Intent intent = new Intent(getActivity(), LocationRuleEditActivity.class);
    switch (mei.getCollectionID()) {
    case MC_DATABASE:
        uri = ContentUris.withAppendedId(RulesColumns.CONTENT_URI, mei.getDatabaseId());
        intent.setData(uri);
        intent.putExtra(Constants.INTENT_EDITORNEW, Constants.INTENT_EDIT);
        startActivity(intent);
        break;
    case MC_CURRPLACE:
    case MC_NEWPLACE:
        intent.putExtra(Constants.INTENT_EDITORNEW, Constants.INTENT_NEW);
        intent.putExtra(Constants.INTENT_LATLNG, latlng);
        startActivityForResult(intent, ADD_PLACE_REQUEST);
        break;
    }

}

From source file:com.android.contacts.common.model.ContactLoader.java

/**
 * Extracts Contact level columns from the cursor.
 */// w w w  .  ja v  a 2s. com
private Contact loadContactHeaderData(final Cursor cursor, Uri contactUri) {
    final String directoryParameter = contactUri.getQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY);
    final long directoryId = directoryParameter == null ? Directory.DEFAULT
            : Long.parseLong(directoryParameter);
    final long contactId = cursor.getLong(ContactQuery.CONTACT_ID);
    final String lookupKey = cursor.getString(ContactQuery.LOOKUP_KEY);
    final long nameRawContactId = cursor.getLong(ContactQuery.NAME_RAW_CONTACT_ID);
    final int displayNameSource = cursor.getInt(ContactQuery.DISPLAY_NAME_SOURCE);
    final String displayName = cursor.getString(ContactQuery.DISPLAY_NAME);
    final String altDisplayName = cursor.getString(ContactQuery.ALT_DISPLAY_NAME);
    final String phoneticName = cursor.getString(ContactQuery.PHONETIC_NAME);
    final long photoId = cursor.getLong(ContactQuery.PHOTO_ID);
    final String photoUri = cursor.getString(ContactQuery.PHOTO_URI);
    final boolean starred = cursor.getInt(ContactQuery.STARRED) != 0;
    final Integer presence = cursor.isNull(ContactQuery.CONTACT_PRESENCE) ? null
            : cursor.getInt(ContactQuery.CONTACT_PRESENCE);
    final boolean sendToVoicemail = cursor.getInt(ContactQuery.SEND_TO_VOICEMAIL) == 1;
    final String customRingtone = cursor.getString(ContactQuery.CUSTOM_RINGTONE);
    final boolean isUserProfile = cursor.getInt(ContactQuery.IS_USER_PROFILE) == 1;

    Uri lookupUri;
    if (directoryId == Directory.DEFAULT || directoryId == Directory.LOCAL_INVISIBLE) {
        lookupUri = ContentUris.withAppendedId(Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey),
                contactId);
    } else {
        lookupUri = contactUri;
    }

    return new Contact(mRequestedUri, contactUri, lookupUri, directoryId, lookupKey, contactId,
            nameRawContactId, displayNameSource, photoId, photoUri, displayName, altDisplayName, phoneticName,
            starred, presence, sendToVoicemail, customRingtone, isUserProfile);
}

From source file:com.tct.email.LegacyConversions.java

/**
 * Save the body part of a single attachment, to a file in the attachments directory.
 *//*  w w  w  .j a va 2  s  .c  om*/
public static void saveAttachmentBody(final Context context, final Part part, final Attachment localAttachment,
        long accountId) throws MessagingException, IOException {
    if (part.getBody() != null) {
        final long attachmentId = localAttachment.mId;

        final File saveIn = AttachmentUtilities.getAttachmentDirectory(context, accountId);

        if (!saveIn.isDirectory() && !saveIn.mkdirs()) {
            throw new IOException("Could not create attachment directory");
        }
        final File saveAs = AttachmentUtilities.getAttachmentFilename(context, accountId, attachmentId);

        InputStream in = null;
        FileOutputStream out = null;
        final long copySize;
        try {
            in = part.getBody().getInputStream();
            out = new FileOutputStream(saveAs);
            copySize = IOUtils.copyLarge(in, out);
            //TS: Gantao 2016-02-18 EMAIL BUGFIX_1595378 ADD_S
        } catch (MessagingException me) {
            LogUtils.e(LogUtils.TAG, "Get the attachment %d failed", attachmentId);
            deleteDirtyAttachment(context, attachmentId);
            return;
            //TS: Gantao 2016-02-18 EMAIL BUGFIX_1595378 ADD_E
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }

        // update the attachment with the extra information we now know
        final String contentUriString = AttachmentUtilities.getAttachmentUri(accountId, attachmentId)
                .toString();

        localAttachment.mSize = copySize;
        localAttachment.setContentUri(contentUriString);

        // update the attachment in the database as well
        final ContentValues cv = new ContentValues(3);
        cv.put(AttachmentColumns.SIZE, copySize);
        cv.put(AttachmentColumns.CONTENT_URI, contentUriString);
        cv.put(AttachmentColumns.UI_STATE, UIProvider.AttachmentState.SAVED);
        final Uri uri = ContentUris.withAppendedId(Attachment.CONTENT_URI, attachmentId);
        context.getContentResolver().update(uri, cv, null, null);
    }
    //TS: wenggangjin 2014-12-10 EMAIL BUGFIX_852100 MOD_S
    else {
        String contentUriString = AttachmentUtilities.getAttachmentUri(accountId, localAttachment.mId)
                .toString();
        localAttachment.setContentUri(contentUriString);
    }
    //TS: wenggangjin 2014-12-10 EMAIL BUGFIX_852100 MOD_E
}

From source file:com.rukman.emde.smsgroups.syncadapter.SyncAdapter.java

private void processDeletedContacts(ContentProviderClient provider, String authToken, Account account,
        SyncResult syncResult) throws IOException, JSONException, RemoteException {
    Cursor contactCursor = null;/*  w  w  w .j ava 2 s .co m*/
    try {
        contactCursor = provider.query(GMSContacts.CONTENT_URI,
                new String[] { GMSContact._ID, GMSContact.CLOUD_ID, GMSContact.STATUS, GMSContact.GROUP_ID },
                GMSContact.STATUS + "=?", new String[] { String.valueOf(GMSContact.STATUS_DELETED) }, null);
        if (contactCursor == null) {
            syncResult.databaseError = true;
            return;
        }
        while (contactCursor.moveToNext()) {
            Cursor groupCursor = null;
            try {
                groupCursor = provider.query(
                        ContentUris.withAppendedId(GMSGroups.CONTENT_URI, contactCursor.getLong(3)),
                        new String[] { GMSGroup.CLOUD_ID }, null, null, null);
                if (groupCursor == null || !groupCursor.moveToFirst()) {
                    syncResult.databaseError = true;
                    break;
                }
                if (NetworkUtilities.removeGroupContact(authToken, groupCursor.getString(0),
                        contactCursor.getString(1)) == null) {
                    syncResult.stats.numIoExceptions++;
                } else {
                    syncResult.stats.numDeletes++;
                }
            } finally {
                if (groupCursor != null) {
                    groupCursor.close();
                }
            }
        }
    } finally {
        if (contactCursor != null) {
            contactCursor.close();
        }
    }

}

From source file:com.android.contacts.ContactSaveService.java

private void saveContact(Intent intent) {
    RawContactDeltaList state = intent.getParcelableExtra(EXTRA_CONTACT_STATE);
    boolean isProfile = intent.getBooleanExtra(EXTRA_SAVE_IS_PROFILE, false);
    Bundle updatedPhotos = intent.getParcelableExtra(EXTRA_UPDATED_PHOTOS);

    if (state == null) {
        Log.e(TAG, "Invalid arguments for saveContact request");
        return;//from www . j av  a  2  s . c  o m
    }

    int saveMode = intent.getIntExtra(EXTRA_SAVE_MODE, -1);
    // Trim any empty fields, and RawContacts, before persisting
    final AccountTypeManager accountTypes = AccountTypeManager.getInstance(this);
    RawContactModifier.trimEmpty(state, accountTypes);

    Uri lookupUri = null;

    final ContentResolver resolver = getContentResolver();

    boolean succeeded = false;

    // Keep track of the id of a newly raw-contact (if any... there can be at most one).
    long insertedRawContactId = -1;

    // Attempt to persist changes
    int tries = 0;
    while (tries++ < PERSIST_TRIES) {
        try {
            // Build operations and try applying
            final ArrayList<CPOWrapper> diffWrapper = state.buildDiffWrapper();

            final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();

            for (CPOWrapper cpoWrapper : diffWrapper) {
                diff.add(cpoWrapper.getOperation());
            }

            if (DEBUG) {
                Log.v(TAG, "Content Provider Operations:");
                for (ContentProviderOperation operation : diff) {
                    Log.v(TAG, operation.toString());
                }
            }

            int numberProcessed = 0;
            boolean batchFailed = false;
            final ContentProviderResult[] results = new ContentProviderResult[diff.size()];
            while (numberProcessed < diff.size()) {
                final int subsetCount = applyDiffSubset(diff, numberProcessed, results, resolver);
                if (subsetCount == -1) {
                    Log.w(TAG, "Resolver.applyBatch failed in saveContacts");
                    batchFailed = true;
                    break;
                } else {
                    numberProcessed += subsetCount;
                }
            }

            if (batchFailed) {
                // Retry save
                continue;
            }

            final long rawContactId = getRawContactId(state, diffWrapper, results);
            if (rawContactId == -1) {
                throw new IllegalStateException("Could not determine RawContact ID after save");
            }
            // We don't have to check to see if the value is still -1.  If we reach here,
            // the previous loop iteration didn't succeed, so any ID that we obtained is bogus.
            insertedRawContactId = getInsertedRawContactId(diffWrapper, results);
            if (isProfile) {
                // Since the profile supports local raw contacts, which may have been completely
                // removed if all information was removed, we need to do a special query to
                // get the lookup URI for the profile contact (if it still exists).
                Cursor c = resolver.query(Profile.CONTENT_URI,
                        new String[] { Contacts._ID, Contacts.LOOKUP_KEY }, null, null, null);
                if (c == null) {
                    continue;
                }
                try {
                    if (c.moveToFirst()) {
                        final long contactId = c.getLong(0);
                        final String lookupKey = c.getString(1);
                        lookupUri = Contacts.getLookupUri(contactId, lookupKey);
                    }
                } finally {
                    c.close();
                }
            } else {
                final Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
                lookupUri = RawContacts.getContactLookupUri(resolver, rawContactUri);
            }
            if (lookupUri != null && Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.v(TAG, "Saved contact. New URI: " + lookupUri);
            }

            // We can change this back to false later, if we fail to save the contact photo.
            succeeded = true;
            break;

        } catch (RemoteException e) {
            // Something went wrong, bail without success
            FeedbackHelper.sendFeedback(this, TAG, "Problem persisting user edits", e);
            break;

        } catch (IllegalArgumentException e) {
            // This is thrown by applyBatch on malformed requests
            FeedbackHelper.sendFeedback(this, TAG, "Problem persisting user edits", e);
            showToast(R.string.contactSavedErrorToast);
            break;

        } catch (OperationApplicationException e) {
            // Version consistency failed, re-parent change and try again
            Log.w(TAG, "Version consistency failed, re-parenting: " + e.toString());
            final StringBuilder sb = new StringBuilder(RawContacts._ID + " IN(");
            boolean first = true;
            final int count = state.size();
            for (int i = 0; i < count; i++) {
                Long rawContactId = state.getRawContactId(i);
                if (rawContactId != null && rawContactId != -1) {
                    if (!first) {
                        sb.append(',');
                    }
                    sb.append(rawContactId);
                    first = false;
                }
            }
            sb.append(")");

            if (first) {
                throw new IllegalStateException("Version consistency failed for a new contact", e);
            }

            final RawContactDeltaList newState = RawContactDeltaList.fromQuery(
                    isProfile ? RawContactsEntity.PROFILE_CONTENT_URI : RawContactsEntity.CONTENT_URI, resolver,
                    sb.toString(), null, null);
            state = RawContactDeltaList.mergeAfter(newState, state);

            // Update the new state to use profile URIs if appropriate.
            if (isProfile) {
                for (RawContactDelta delta : state) {
                    delta.setProfileQueryUri();
                }
            }
        }
    }

    // Now save any updated photos.  We do this at the end to ensure that
    // the ContactProvider already knows about newly-created contacts.
    if (updatedPhotos != null) {
        for (String key : updatedPhotos.keySet()) {
            Uri photoUri = updatedPhotos.getParcelable(key);
            long rawContactId = Long.parseLong(key);

            // If the raw-contact ID is negative, we are saving a new raw-contact;
            // replace the bogus ID with the new one that we actually saved the contact at.
            if (rawContactId < 0) {
                rawContactId = insertedRawContactId;
            }

            // If the save failed, insertedRawContactId will be -1
            if (rawContactId < 0 || !saveUpdatedPhoto(rawContactId, photoUri, saveMode)) {
                succeeded = false;
            }
        }
    }

    Intent callbackIntent = intent.getParcelableExtra(EXTRA_CALLBACK_INTENT);
    if (callbackIntent != null) {
        if (succeeded) {
            // Mark the intent to indicate that the save was successful (even if the lookup URI
            // is now null).  For local contacts or the local profile, it's possible that the
            // save triggered removal of the contact, so no lookup URI would exist..
            callbackIntent.putExtra(EXTRA_SAVE_SUCCEEDED, true);
        }
        callbackIntent.setData(lookupUri);
        deliverCallback(callbackIntent);
    }
}