Example usage for android.content ContentUris parseId

List of usage examples for android.content ContentUris parseId

Introduction

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

Prototype

public static long parseId(Uri contentUri) 

Source Link

Document

Converts the last path segment to a long.

Usage

From source file:com.android.providers.contacts.ContactsSyncAdapter.java

protected static void updateProviderWithContactEntry(String account, Long syncLocalId, ContactEntry entry,
        ContentProvider provider) throws ParseException {
    final String name = entry.getTitle();
    final String notes = entry.getContent();
    final String yomiName = entry.getYomiName();
    final String personSyncId = lastItemFromUri(entry.getId());
    final String personSyncVersion = lastItemFromUri(entry.getEditUri());

    // Store the info about the person
    ContentValues values = new ContentValues();
    values.put(People.NAME, name);//from   w  w  w. j  a va 2 s . c  o m
    values.put(People.NOTES, notes);
    values.put(People.PHONETIC_NAME, yomiName);
    values.put(SyncConstValue._SYNC_ACCOUNT, account);
    values.put(SyncConstValue._SYNC_ID, personSyncId);
    values.put(SyncConstValue._SYNC_DIRTY, "0");
    values.put(SyncConstValue._SYNC_LOCAL_ID, syncLocalId);
    values.put(SyncConstValue._SYNC_TIME, personSyncVersion);
    values.put(SyncConstValue._SYNC_VERSION, personSyncVersion);
    Uri personUri = provider.insert(People.CONTENT_URI, values);

    // Store the photo information
    final boolean photoExistsOnServer = !TextUtils.isEmpty(entry.getLinkPhotoHref());
    final String photoVersion = lastItemFromUri(entry.getLinkEditPhotoHref());
    values.clear();
    values.put(Photos.PERSON_ID, ContentUris.parseId(personUri));
    values.put(Photos.EXISTS_ON_SERVER, photoExistsOnServer ? 1 : 0);
    values.put(SyncConstValue._SYNC_ACCOUNT, account);
    values.put(SyncConstValue._SYNC_ID, personSyncId);
    values.put(SyncConstValue._SYNC_DIRTY, 0);
    values.put(SyncConstValue._SYNC_LOCAL_ID, syncLocalId);
    values.put(SyncConstValue._SYNC_TIME, photoVersion);
    values.put(SyncConstValue._SYNC_VERSION, photoVersion);
    if (provider.insert(Photos.CONTENT_URI, values) == null) {
        Log.e(TAG, "error inserting photo row, " + values);
    }

    // Store each email address
    for (Object object : entry.getEmailAddresses()) {
        EmailAddress email = (EmailAddress) object;
        values.clear();
        contactsElementToValues(values, email, ENTRY_TYPE_TO_PROVIDER_EMAIL);
        values.put(ContactMethods.DATA, email.getAddress());
        values.put(ContactMethods.KIND, Contacts.KIND_EMAIL);
        Uri uri = Uri.withAppendedPath(personUri, People.ContactMethods.CONTENT_DIRECTORY);
        provider.insert(uri, values);
    }

    // Store each postal address
    for (Object object : entry.getPostalAddresses()) {
        PostalAddress address = (PostalAddress) object;
        values.clear();
        contactsElementToValues(values, address, ENTRY_TYPE_TO_PROVIDER_POSTAL);
        values.put(ContactMethods.DATA, address.getValue());
        values.put(ContactMethods.KIND, Contacts.KIND_POSTAL);
        Uri uri = Uri.withAppendedPath(personUri, People.ContactMethods.CONTENT_DIRECTORY);
        provider.insert(uri, values);
    }

    // Store each im address
    for (Object object : entry.getImAddresses()) {
        ImAddress address = (ImAddress) object;
        values.clear();
        contactsElementToValues(values, address, ENTRY_TYPE_TO_PROVIDER_IM);
        values.put(ContactMethods.DATA, address.getAddress());
        values.put(ContactMethods.KIND, Contacts.KIND_IM);
        final byte protocolType = address.getProtocolPredefined();
        if (protocolType == ImAddress.PROTOCOL_NONE) {
            // don't add anything
        } else if (protocolType == ImAddress.PROTOCOL_CUSTOM) {
            values.put(ContactMethods.AUX_DATA,
                    ContactMethods.encodeCustomImProtocol(address.getProtocolCustom()));
        } else {
            Integer providerProtocolType = ENTRY_IM_PROTOCOL_TO_PROVIDER_PROTOCOL.get(protocolType);
            if (providerProtocolType == null) {
                throw new IllegalArgumentException("unknown protocol type, " + protocolType);
            }
            values.put(ContactMethods.AUX_DATA,
                    ContactMethods.encodePredefinedImProtocol(providerProtocolType));
        }
        Uri uri = Uri.withAppendedPath(personUri, People.ContactMethods.CONTENT_DIRECTORY);
        provider.insert(uri, values);
    }

    // Store each organization
    for (Object object : entry.getOrganizations()) {
        Organization organization = (Organization) object;
        values.clear();
        contactsElementToValues(values, organization, ENTRY_TYPE_TO_PROVIDER_ORGANIZATION);
        values.put(Organizations.COMPANY, organization.getName());
        values.put(Organizations.TITLE, organization.getTitle());
        values.put(Organizations.COMPANY, organization.getName());
        Uri uri = Uri.withAppendedPath(personUri, Organizations.CONTENT_DIRECTORY);
        provider.insert(uri, values);
    }

    // Store each group
    for (Object object : entry.getGroups()) {
        GroupMembershipInfo groupMembershipInfo = (GroupMembershipInfo) object;
        if (groupMembershipInfo.isDeleted()) {
            continue;
        }
        values.clear();
        values.put(GroupMembership.GROUP_SYNC_ACCOUNT, account);
        values.put(GroupMembership.GROUP_SYNC_ID, lastItemFromUri(groupMembershipInfo.getGroup()));
        Uri uri = Uri.withAppendedPath(personUri, GroupMembership.CONTENT_DIRECTORY);
        provider.insert(uri, values);
    }

    // Store each phone number
    for (Object object : entry.getPhoneNumbers()) {
        PhoneNumber phone = (PhoneNumber) object;
        values.clear();
        contactsElementToValues(values, phone, ENTRY_TYPE_TO_PROVIDER_PHONE);
        values.put(People.Phones.NUMBER, phone.getPhoneNumber());
        values.put(People.Phones.LABEL, phone.getLabel());
        Uri uri = Uri.withAppendedPath(personUri, People.Phones.CONTENT_DIRECTORY);
        provider.insert(uri, values);
    }

    // Store the extended properties
    for (Object object : entry.getExtendedProperties()) {
        ExtendedProperty extendedProperty = (ExtendedProperty) object;
        if (!"android".equals(extendedProperty.getName())) {
            continue;
        }
        JSONObject jsonObject = null;
        try {
            jsonObject = new JSONObject(extendedProperty.getXmlBlob());
        } catch (JSONException e) {
            Log.w(TAG, "error parsing the android extended property, dropping, entry is " + entry.toString());
            continue;
        }
        Iterator jsonIterator = jsonObject.keys();
        while (jsonIterator.hasNext()) {
            String key = (String) jsonIterator.next();
            values.clear();
            values.put(Extensions.NAME, key);
            try {
                values.put(Extensions.VALUE, jsonObject.getString(key));
            } catch (JSONException e) {
                // this should never happen, since we just got the key from the iterator
            }
            Uri uri = Uri.withAppendedPath(personUri, People.Extensions.CONTENT_DIRECTORY);
            if (null == provider.insert(uri, values)) {
                Log.e(TAG, "Error inserting extension into provider, uri " + uri + ", values " + values);
            }
        }
        break;
    }
}

From source file:edu.mit.mobile.android.locast.net.NetworkClient.java

/**
 * Uploads the content, displaying a notification in the system tray. The notification will show
 * a progress bar as the upload goes on and will show a message when finished indicating whether
 * or not it was successful./*from   w w w  . j a v  a  2 s  .c om*/
 *
 * @param context
 * @param cast
 *            cast item
 * @param serverPath
 *            the path on which
 * @param localFile
 * @param contentType
 * @param uploadType
 * @throws NetworkProtocolException
 * @throws IOException
 * @throws JSONException
 */
public JSONObject uploadContentWithNotification(Context context, Uri cast, String serverPath, Uri localFile,
        String contentType, UploadType uploadType) throws NetworkProtocolException, IOException, JSONException {
    String castTitle = Cast.getTitle(context, cast);
    if (castTitle == null) {
        castTitle = "untitled (cast #" + cast.getLastPathSegment() + ")";
    }
    JSONObject updatedCastMedia;
    final ProgressNotification notification = new ProgressNotification(context,
            context.getString(R.string.sync_uploading_cast, castTitle), ProgressNotification.TYPE_UPLOAD,
            PendingIntent.getActivity(context, 0,
                    new Intent(Intent.ACTION_VIEW, cast).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0),
            true);

    // assume fail: when successful, all will be reset.
    notification.successful = false;
    notification.doneTitle = context.getString(R.string.sync_upload_fail);
    notification.doneText = context.getString(R.string.sync_upload_fail_message, castTitle);

    notification.doneIntent = PendingIntent.getActivity(context, 0,
            new Intent(Intent.ACTION_VIEW, cast).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0);

    final NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    final NotificationProgressListener tpl = new NotificationProgressListener(nm, notification, 0,
            (int) ContentUris.parseId(cast));

    try {
        final AssetFileDescriptor afd = context.getContentResolver().openAssetFileDescriptor(localFile, "r");
        final long max = afd.getLength();

        tpl.setSize(max);

        switch (uploadType) {
        case RAW_PUT:
            updatedCastMedia = uploadContent(context, tpl, serverPath, localFile, contentType);
            break;
        case FORM_POST:
            updatedCastMedia = uploadContentUsingForm(context, tpl, serverPath, localFile, contentType);
            break;

        default:
            throw new IllegalArgumentException("unhandled upload type: " + uploadType);
        }

        notification.doneTitle = context.getString(R.string.sync_upload_success);
        notification.doneText = context.getString(R.string.sync_upload_success_message, castTitle);
        notification.successful = true;

    } catch (final NetworkProtocolException e) {
        notification.setUnsuccessful(e.getLocalizedMessage());
        throw e;
    } catch (final IOException e) {
        notification.setUnsuccessful(e.getLocalizedMessage());
        throw e;
    } finally {
        tpl.done();
    }
    return updatedCastMedia;
}

From source file:org.kontalk.ui.AbstractComposeFragment.java

protected void loadConversationMetadata(Uri uri) {
    threadId = ContentUris.parseId(uri);
    mConversation = Conversation.loadFromId(getActivity(), threadId);
    if (mConversation == null) {
        Log.w(TAG, "conversation for thread " + threadId + " not found!");
        startActivity(new Intent(getActivity(), ConversationsActivity.class));
        getActivity().finish();//ww  w .  jav a  2 s  . com
    }
}

From source file:com.android.tv.MainActivity.java

private void startTv(Uri channelUri) {
    if (DEBUG)/*from   w  w  w  .  j a  va  2s  . com*/
        Log.d(TAG, "startTv Uri=" + channelUri);
    if ((channelUri == null || !TvContract.isChannelUriForPassthroughInput(channelUri))
            && mChannelTuner.isCurrentChannelPassthrough()) {
        // For passthrough TV input, channelUri is always given. If TV app is launched
        // by TV app icon in a launcher, channelUri is null. So if passthrough TV input
        // is playing, we stop the passthrough TV input.
        stopTv();
    }
    SoftPreconditions.checkState(
            TvContract.isChannelUriForPassthroughInput(channelUri) || mChannelTuner.areAllChannelsLoaded(), TAG,
            "startTV assumes that ChannelDataManager is already loaded.");
    if (mTvView.isPlaying()) {
        // TV has already started.
        if (channelUri == null) {
            // Simply adjust the volume without tune.
            setVolumeByAudioFocusStatus();
            return;
        }
        if (channelUri.equals(mChannelTuner.getCurrentChannelUri())) {
            // The requested channel is already tuned.
            setVolumeByAudioFocusStatus();
            return;
        }
        stopTv();
    }
    if (mChannelTuner.getCurrentChannel() != null) {
        Log.w(TAG, "The current channel should be reset before");
        mChannelTuner.resetCurrentChannel();
    }
    if (channelUri == null) {
        // If any initial channel id is not given, remember the last channel the user watched.
        long channelId = Utils.getLastWatchedChannelId(this);
        if (channelId != Channel.INVALID_ID) {
            channelUri = TvContract.buildChannelUri(channelId);
        }
    }

    if (channelUri == null) {
        mChannelTuner.moveToChannel(mChannelTuner.findNearestBrowsableChannel(0));
    } else {
        if (TvContract.isChannelUriForPassthroughInput(channelUri)) {
            Channel channel = Channel.createPassthroughChannel(channelUri);
            mChannelTuner.moveToChannel(channel);
        } else {
            long channelId = ContentUris.parseId(channelUri);
            Channel channel = mChannelDataManager.getChannel(channelId);
            if (channel == null || !mChannelTuner.moveToChannel(channel)) {
                mChannelTuner.moveToChannel(mChannelTuner.findNearestBrowsableChannel(0));
                Log.w(TAG, "The requested channel (id=" + channelId + ") doesn't exist. "
                        + "The first channel will be tuned to.");
            }
        }
    }

    mTvView.start(mTvInputManagerHelper);
    setVolumeByAudioFocusStatus();
    if (mRecordingUri != null) {
        playRecording(mRecordingUri);
        mRecordingUri = null;
    } else {
        tune();
    }
}

From source file:com.android.messaging.mmslib.pdu.PduPersister.java

/**
 * Update headers of a SendReq./*from w  w  w  .j  av a 2  s . c  om*/
 *
 * @param uri The PDU which need to be updated.
 * @param pdu New headers.
 * @throws MmsException Bad URI or updating failed.
 */
public void updateHeaders(final Uri uri, final SendReq sendReq) {
    synchronized (PDU_CACHE_INSTANCE) {
        // If the cache item is getting updated, wait until it's done updating before
        // purging it.
        if (PDU_CACHE_INSTANCE.isUpdating(uri)) {
            if (LOCAL_LOGV) {
                LogUtil.v(TAG, "updateHeaders: " + uri + " blocked by isUpdating()");
            }
            try {
                PDU_CACHE_INSTANCE.wait();
            } catch (final InterruptedException e) {
                Log.e(TAG, "updateHeaders: ", e);
            }
        }
    }
    PDU_CACHE_INSTANCE.purge(uri);

    final ContentValues values = new ContentValues(10);
    final byte[] contentType = sendReq.getContentType();
    if (contentType != null) {
        values.put(Mms.CONTENT_TYPE, toIsoString(contentType));
    }

    final long date = sendReq.getDate();
    if (date != -1) {
        values.put(Mms.DATE, date);
    }

    final int deliveryReport = sendReq.getDeliveryReport();
    if (deliveryReport != 0) {
        values.put(Mms.DELIVERY_REPORT, deliveryReport);
    }

    final long expiry = sendReq.getExpiry();
    if (expiry != -1) {
        values.put(Mms.EXPIRY, expiry);
    }

    final byte[] msgClass = sendReq.getMessageClass();
    if (msgClass != null) {
        values.put(Mms.MESSAGE_CLASS, toIsoString(msgClass));
    }

    final int priority = sendReq.getPriority();
    if (priority != 0) {
        values.put(Mms.PRIORITY, priority);
    }

    final int readReport = sendReq.getReadReport();
    if (readReport != 0) {
        values.put(Mms.READ_REPORT, readReport);
    }

    final byte[] transId = sendReq.getTransactionId();
    if (transId != null) {
        values.put(Mms.TRANSACTION_ID, toIsoString(transId));
    }

    final EncodedStringValue subject = sendReq.getSubject();
    if (subject != null) {
        values.put(Mms.SUBJECT, toIsoString(subject.getTextString()));
        values.put(Mms.SUBJECT_CHARSET, subject.getCharacterSet());
    } else {
        values.put(Mms.SUBJECT, "");
    }

    final long messageSize = sendReq.getMessageSize();
    if (messageSize > 0) {
        values.put(Mms.MESSAGE_SIZE, messageSize);
    }

    final PduHeaders headers = sendReq.getPduHeaders();
    final HashSet<String> recipients = new HashSet<String>();
    for (final int addrType : ADDRESS_FIELDS) {
        EncodedStringValue[] array = null;
        if (addrType == PduHeaders.FROM) {
            final EncodedStringValue v = headers.getEncodedStringValue(addrType);
            if (v != null) {
                array = new EncodedStringValue[1];
                array[0] = v;
            }
        } else {
            array = headers.getEncodedStringValues(addrType);
        }

        if (array != null) {
            final long msgId = ContentUris.parseId(uri);
            updateAddress(msgId, addrType, array);
            if (addrType == PduHeaders.TO) {
                for (final EncodedStringValue v : array) {
                    if (v != null) {
                        recipients.add(v.getString());
                    }
                }
            }
        }
    }
    if (!recipients.isEmpty()) {
        final long threadId = MmsSmsUtils.Threads.getOrCreateThreadId(mContext, recipients);
        values.put(Mms.THREAD_ID, threadId);
    }

    SqliteWrapper.update(mContext, mContentResolver, uri, values, null, null);
}

From source file:com.android.contacts.quickcontact.QuickContactActivity.java

private void processIntent(Intent intent) {
    if (intent == null) {
        finish();/*from  ww w . j  ava 2 s.c o  m*/
        return;
    }
    Uri lookupUri = intent.getData();

    // Check to see whether it comes from the old version.
    if (lookupUri != null && LEGACY_AUTHORITY.equals(lookupUri.getAuthority())) {
        final long rawContactId = ContentUris.parseId(lookupUri);
        lookupUri = RawContacts.getContactLookupUri(getContentResolver(),
                ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId));
    }
    mExtraMode = getIntent().getIntExtra(QuickContact.EXTRA_MODE, QuickContact.MODE_LARGE);
    mExtraPrioritizedMimeType = getIntent().getStringExtra(QuickContact.EXTRA_PRIORITIZED_MIMETYPE);
    final Uri oldLookupUri = mLookupUri;

    if (lookupUri == null) {
        finish();
        return;
    }
    mLookupUri = lookupUri;
    mExcludeMimes = intent.getStringArrayExtra(QuickContact.EXTRA_EXCLUDE_MIMES);
    if (oldLookupUri == null) {
        mContactLoader = (ContactLoader) getLoaderManager().initLoader(LOADER_CONTACT_ID, null,
                mLoaderContactCallbacks);
    } else if (oldLookupUri != mLookupUri) {
        // After copying a directory contact, the contact URI changes. Therefore,
        // we need to reload the new contact.
        destroyInteractionLoaders();
        mContactLoader = (ContactLoader) (Loader<?>) getLoaderManager().getLoader(LOADER_CONTACT_ID);
        mContactLoader.setLookupUri(mLookupUri);
        mCachedCp2DataCardModel = null;
    }
    mContactLoader.forceLoad();

    NfcHandler.register(this, mLookupUri);
}

From source file:org.kontalk.ui.ComposeMessageFragment.java

private void loadConversationMetadata(Uri uri) {
    threadId = ContentUris.parseId(uri);
    mConversation = Conversation.loadFromId(getActivity(), threadId);
    if (mConversation == null) {
        Log.w(TAG, "conversation for thread " + threadId + " not found!");
        startActivity(new Intent(getActivity(), ConversationsActivity.class));
        getActivity().finish();//from  w w  w .j  av a 2s  .co m
        return;
    }

    mUserJID = mConversation.getRecipient();
    Contact contact = mConversation.getContact();
    if (contact != null) {
        mUserName = contact.getName();
        mUserPhone = contact.getNumber();
    } else {
        mUserName = mUserJID;
    }
}

From source file:com.android.messaging.mmslib.pdu.PduPersister.java

/**
 * Update all parts of a PDU.//from w w  w  . ja  va 2  s  . c o m
 *
 * @param uri            The PDU which need to be updated.
 * @param body           New message body of the PDU.
 * @param preOpenedFiles if not null, a map of preopened InputStreams for the parts.
 * @throws MmsException Bad URI or updating failed.
 */
public void updateParts(final Uri uri, final PduBody body, final Map<Uri, InputStream> preOpenedFiles)
        throws MmsException {
    try {
        PduCacheEntry cacheEntry;
        synchronized (PDU_CACHE_INSTANCE) {
            if (PDU_CACHE_INSTANCE.isUpdating(uri)) {
                if (LOCAL_LOGV) {
                    LogUtil.v(TAG, "updateParts: " + uri + " blocked by isUpdating()");
                }
                try {
                    PDU_CACHE_INSTANCE.wait();
                } catch (final InterruptedException e) {
                    Log.e(TAG, "updateParts: ", e);
                }
                cacheEntry = PDU_CACHE_INSTANCE.get(uri);
                if (cacheEntry != null) {
                    ((MultimediaMessagePdu) cacheEntry.getPdu()).setBody(body);
                }
            }
            // Tell the cache to indicate to other callers that this item
            // is currently being updated.
            PDU_CACHE_INSTANCE.setUpdating(uri, true);
        }

        final ArrayList<PduPart> toBeCreated = new ArrayList<PduPart>();
        final ArrayMap<Uri, PduPart> toBeUpdated = new ArrayMap<Uri, PduPart>();

        final int partsNum = body.getPartsNum();
        final StringBuilder filter = new StringBuilder().append('(');
        for (int i = 0; i < partsNum; i++) {
            final PduPart part = body.getPart(i);
            final Uri partUri = part.getDataUri();
            if ((partUri == null) || !partUri.getAuthority().startsWith("mms")) {
                toBeCreated.add(part);
            } else {
                toBeUpdated.put(partUri, part);

                // Don't use 'i > 0' to determine whether we should append
                // 'AND' since 'i = 0' may be skipped in another branch.
                if (filter.length() > 1) {
                    filter.append(" AND ");
                }

                filter.append(Part._ID);
                filter.append("!=");
                DatabaseUtils.appendEscapedSQLString(filter, partUri.getLastPathSegment());
            }
        }
        filter.append(')');

        final long msgId = ContentUris.parseId(uri);

        // Remove the parts which doesn't exist anymore.
        SqliteWrapper.delete(mContext, mContentResolver, Uri.parse(Mms.CONTENT_URI + "/" + msgId + "/part"),
                filter.length() > 2 ? filter.toString() : null, null);

        // Create new parts which didn't exist before.
        for (final PduPart part : toBeCreated) {
            persistPart(part, msgId, preOpenedFiles);
        }

        // Update the modified parts.
        for (final Map.Entry<Uri, PduPart> e : toBeUpdated.entrySet()) {
            updatePart(e.getKey(), e.getValue(), preOpenedFiles);
        }
    } finally {
        synchronized (PDU_CACHE_INSTANCE) {
            PDU_CACHE_INSTANCE.setUpdating(uri, false);
            PDU_CACHE_INSTANCE.notifyAll();
        }
    }
}

From source file:com.android.messaging.mmslib.pdu.PduPersister.java

/**
 * Persist a PDU object to specific location in the storage.
 *
 * @param pdu             The PDU object to be stored.
 * @param uri             Where to store the given PDU object.
 * @param subId           Subscription id associated with this message.
 * @param subPhoneNumber TODO/*from w  w  w  .  java2 s .  c o  m*/
 * @param preOpenedFiles  if not null, a map of preopened InputStreams for the parts.
 * @return A Uri which can be used to access the stored PDU.
 */
public Uri persist(final GenericPdu pdu, final Uri uri, final int subId, final String subPhoneNumber,
        final Map<Uri, InputStream> preOpenedFiles) throws MmsException {
    if (uri == null) {
        throw new MmsException("Uri may not be null.");
    }
    long msgId = -1;
    try {
        msgId = ContentUris.parseId(uri);
    } catch (final NumberFormatException e) {
        // the uri ends with "inbox" or something else like that
    }
    final boolean existingUri = msgId != -1;

    if (!existingUri && MESSAGE_BOX_MAP.get(uri) == null) {
        throw new MmsException("Bad destination, must be one of " + "content://mms/inbox, content://mms/sent, "
                + "content://mms/drafts, content://mms/outbox, " + "content://mms/temp.");
    }
    synchronized (PDU_CACHE_INSTANCE) {
        // If the cache item is getting updated, wait until it's done updating before
        // purging it.
        if (PDU_CACHE_INSTANCE.isUpdating(uri)) {
            if (LOCAL_LOGV) {
                LogUtil.v(TAG, "persist: " + uri + " blocked by isUpdating()");
            }
            try {
                PDU_CACHE_INSTANCE.wait();
            } catch (final InterruptedException e) {
                Log.e(TAG, "persist1: ", e);
            }
        }
    }
    PDU_CACHE_INSTANCE.purge(uri);

    final PduHeaders header = pdu.getPduHeaders();
    PduBody body = null;
    ContentValues values = new ContentValues();

    // Mark new messages as seen in the telephony database so that we don't have to
    // do a global "set all messages as seen" since that occasionally seems to be
    // problematic (i.e. very slow).  See bug 18189471.
    values.put(Mms.SEEN, 1);

    //Set<Entry<Integer, String>> set;

    for (int i = ENCODED_STRING_COLUMN_NAME_MAP.size(); --i >= 0;) {
        final int field = ENCODED_STRING_COLUMN_NAME_MAP.keyAt(i);
        final EncodedStringValue encodedString = header.getEncodedStringValue(field);
        if (encodedString != null) {
            final String charsetColumn = CHARSET_COLUMN_NAME_MAP.get(field);
            values.put(ENCODED_STRING_COLUMN_NAME_MAP.valueAt(i), toIsoString(encodedString.getTextString()));
            values.put(charsetColumn, encodedString.getCharacterSet());
        }
    }

    for (int i = TEXT_STRING_COLUMN_NAME_MAP.size(); --i >= 0;) {
        final byte[] text = header.getTextString(TEXT_STRING_COLUMN_NAME_MAP.keyAt(i));
        if (text != null) {
            values.put(TEXT_STRING_COLUMN_NAME_MAP.valueAt(i), toIsoString(text));
        }
    }

    for (int i = OCTET_COLUMN_NAME_MAP.size(); --i >= 0;) {
        final int b = header.getOctet(OCTET_COLUMN_NAME_MAP.keyAt(i));
        if (b != 0) {
            values.put(OCTET_COLUMN_NAME_MAP.valueAt(i), b);
        }
    }

    for (int i = LONG_COLUMN_NAME_MAP.size(); --i >= 0;) {
        final long l = header.getLongInteger(LONG_COLUMN_NAME_MAP.keyAt(i));
        if (l != -1L) {
            values.put(LONG_COLUMN_NAME_MAP.valueAt(i), l);
        }
    }

    final SparseArray<EncodedStringValue[]> addressMap = new SparseArray<EncodedStringValue[]>(
            ADDRESS_FIELDS.length);
    // Save address information.
    for (final int addrType : ADDRESS_FIELDS) {
        EncodedStringValue[] array = null;
        if (addrType == PduHeaders.FROM) {
            final EncodedStringValue v = header.getEncodedStringValue(addrType);
            if (v != null) {
                array = new EncodedStringValue[1];
                array[0] = v;
            }
        } else {
            array = header.getEncodedStringValues(addrType);
        }
        addressMap.put(addrType, array);
    }

    final HashSet<String> recipients = new HashSet<String>();
    final int msgType = pdu.getMessageType();
    // Here we only allocate thread ID for M-Notification.ind,
    // M-Retrieve.conf and M-Send.req.
    // Some of other PDU types may be allocated a thread ID outside
    // this scope.
    if ((msgType == PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND)
            || (msgType == PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF)
            || (msgType == PduHeaders.MESSAGE_TYPE_SEND_REQ)) {
        switch (msgType) {
        case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND:
        case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF:
            loadRecipients(PduHeaders.FROM, recipients, addressMap);

            // For received messages (whether group MMS is enabled or not) we want to
            // associate this message with the thread composed of all the recipients
            // EXCLUDING our own number. This includes the person who sent the
            // message (the FROM field above) in addition to the other people the message
            // was addressed TO (or CC fields to address group messaging compatibility
            // issues with devices that place numbers in this field). Typically our own
            // number is in the TO/CC field so we have to remove it in loadRecipients.
            checkAndLoadToCcRecipients(recipients, addressMap, subPhoneNumber);
            break;
        case PduHeaders.MESSAGE_TYPE_SEND_REQ:
            loadRecipients(PduHeaders.TO, recipients, addressMap);
            break;
        }
        long threadId = -1L;
        if (!recipients.isEmpty()) {
            // Given all the recipients associated with this message, find (or create) the
            // correct thread.
            threadId = MmsSmsUtils.Threads.getOrCreateThreadId(mContext, recipients);
        } else {
            LogUtil.w(TAG, "PduPersister.persist No recipients; persisting PDU to thread: " + threadId);
        }
        values.put(Mms.THREAD_ID, threadId);
    }

    // Save parts first to avoid inconsistent message is loaded
    // while saving the parts.
    final long dummyId = System.currentTimeMillis(); // Dummy ID of the msg.

    // Figure out if this PDU is a text-only message
    boolean textOnly = true;

    // Get body if the PDU is a RetrieveConf or SendReq.
    if (pdu instanceof MultimediaMessagePdu) {
        body = ((MultimediaMessagePdu) pdu).getBody();
        // Start saving parts if necessary.
        if (body != null) {
            final int partsNum = body.getPartsNum();
            if (LOCAL_LOGV) {
                LogUtil.v(TAG, "PduPersister.persist partsNum: " + partsNum);
            }
            if (partsNum > 2) {
                // For a text-only message there will be two parts: 1-the SMIL, 2-the text.
                // Down a few lines below we're checking to make sure we've only got SMIL or
                // text. We also have to check then we don't have more than two parts.
                // Otherwise, a slideshow with two text slides would be marked as textOnly.
                textOnly = false;
            }
            for (int i = 0; i < partsNum; i++) {
                final PduPart part = body.getPart(i);
                persistPart(part, dummyId, preOpenedFiles);

                // If we've got anything besides text/plain or SMIL part, then we've got
                // an mms message with some other type of attachment.
                final String contentType = getPartContentType(part);
                if (LOCAL_LOGV) {
                    LogUtil.v(TAG, "PduPersister.persist part: " + i + " contentType: " + contentType);
                }
                if (contentType != null && !ContentType.APP_SMIL.equals(contentType)
                        && !ContentType.TEXT_PLAIN.equals(contentType)) {
                    textOnly = false;
                }
            }
        }
    }
    // Record whether this mms message is a simple plain text or not. This is a hint for the
    // UI.
    if (OsUtil.isAtLeastJB_MR1()) {
        values.put(Mms.TEXT_ONLY, textOnly ? 1 : 0);
    }

    if (OsUtil.isAtLeastL_MR1()) {
        values.put(Mms.SUBSCRIPTION_ID, subId);
    } else {
        Assert.equals(ParticipantData.DEFAULT_SELF_SUB_ID, subId);
    }

    Uri res = null;
    if (existingUri) {
        res = uri;
        SqliteWrapper.update(mContext, mContentResolver, res, values, null, null);
    } else {
        res = SqliteWrapper.insert(mContext, mContentResolver, uri, values);
        if (res == null) {
            throw new MmsException("persist() failed: return null.");
        }
        // Get the real ID of the PDU and update all parts which were
        // saved with the dummy ID.
        msgId = ContentUris.parseId(res);
    }

    values = new ContentValues(1);
    values.put(Part.MSG_ID, msgId);
    SqliteWrapper.update(mContext, mContentResolver, Uri.parse("content://mms/" + dummyId + "/part"), values,
            null, null);
    // We should return the longest URI of the persisted PDU, for
    // example, if input URI is "content://mms/inbox" and the _ID of
    // persisted PDU is '8', we should return "content://mms/inbox/8"
    // instead of "content://mms/8".
    // TODO: Should the MmsProvider be responsible for this???
    if (!existingUri) {
        res = Uri.parse(uri + "/" + msgId);
    }

    // Save address information.
    for (final int addrType : ADDRESS_FIELDS) {
        final EncodedStringValue[] array = addressMap.get(addrType);
        if (array != null) {
            persistAddress(msgId, addrType, array);
        }
    }

    return res;
}