List of usage examples for android.util SparseArray SparseArray
public SparseArray(int initialCapacity)
From source file:com.tct.mail.ui.AnimatedAdapter.java
public AnimatedAdapter(Context context, ConversationCursor cursor, ConversationSelectionSet batch, ControllableActivity activity, SwipeableListView listView, final List<ConversationSpecialItemView> specialViews) { super(context, -1, cursor, UIProvider.CONVERSATION_PROJECTION, null, 0); mContext = context;//from ww w. j ava2s . co m mBatchConversations = batch; setAccount(mAccountListener.initialize(activity.getAccountController())); mActivity = activity; mShowFooter = false; mListView = listView; /// M: add search params @{ ActivityController controller = (ActivityController) mActivity.getAccountController(); mListContext = controller.getCurrentListContext(); /// @} mSendersImagesCache = mActivity.getSenderImageCache(); mContactResolver = mActivity.getContactResolver(mContext.getContentResolver(), mSendersImagesCache); mHandler = new Handler(); if (sDismissAllShortDelay == -1) { final Resources r = context.getResources(); sDismissAllShortDelay = r.getInteger(R.integer.dismiss_all_leavebehinds_short_delay); sDismissAllLongDelay = r.getInteger(R.integer.dismiss_all_leavebehinds_long_delay); } if (specialViews != null) { mFleetingViews = new ArrayList<ConversationSpecialItemView>(specialViews); } else { mFleetingViews = new ArrayList<ConversationSpecialItemView>(0); } /** Total number of special views */ final int size = mFleetingViews.size(); mSpecialViews = new SparseArray<ConversationSpecialItemView>(size); mColumnViews = new SparseArray<ConversationTimeColumnView>(size); //TS: zheng.zou 2015-09-01 EMAIL BUGFIX_539892 ADD // Set the adapter in teaser views. for (final ConversationSpecialItemView view : mFleetingViews) { view.setAdapter(this); } updateSpecialViews(); }
From source file:android.support.transition.Transition.java
/** * This method, essentially a wrapper around all calls to createAnimator for all * possible target views, is called with the entire set of start/end * values. The implementation in Transition iterates through these lists * and calls {@link #createAnimator(android.view.ViewGroup, android.support.transition.TransitionValues, android.support.transition.TransitionValues)} * with each set of start/end values on this transition. The * TransitionSet subclass overrides this method and delegates it to * each of its children in succession.//w w w . j a va2 s . c o m * * @hide */ protected void createAnimators(ViewGroup sceneRoot, TransitionValuesMaps startValues, TransitionValuesMaps endValues) { if (DBG) { Log.d(LOG_TAG, "createAnimators() for " + this); } ArrayMap<View, TransitionValues> endCopy = new ArrayMap<View, TransitionValues>(endValues.viewValues); SparseArray<TransitionValues> endIdCopy = new SparseArray<TransitionValues>(endValues.idValues.size()); for (int i = 0; i < endValues.idValues.size(); ++i) { int id = endValues.idValues.keyAt(i); endIdCopy.put(id, endValues.idValues.valueAt(i)); } LongSparseArray<TransitionValues> endItemIdCopy = new LongSparseArray<TransitionValues>( endValues.itemIdValues.size()); for (int i = 0; i < endValues.itemIdValues.size(); ++i) { long id = endValues.itemIdValues.keyAt(i); endItemIdCopy.put(id, endValues.itemIdValues.valueAt(i)); } // Walk through the start values, playing everything we find // Remove from the end set as we go ArrayList<TransitionValues> startValuesList = new ArrayList<TransitionValues>(); ArrayList<TransitionValues> endValuesList = new ArrayList<TransitionValues>(); for (View view : startValues.viewValues.keySet()) { TransitionValues start = null; TransitionValues end = null; boolean isInListView = false; if (view.getParent() instanceof ListView) { isInListView = true; } if (!isInListView) { int id = view.getId(); start = startValues.viewValues.get(view) != null ? startValues.viewValues.get(view) : startValues.idValues.get(id); if (endValues.viewValues.get(view) != null) { end = endValues.viewValues.get(view); endCopy.remove(view); } else if (id != View.NO_ID) { end = endValues.idValues.get(id); View removeView = null; for (View viewToRemove : endCopy.keySet()) { if (viewToRemove.getId() == id) { removeView = viewToRemove; } } if (removeView != null) { endCopy.remove(removeView); } } endIdCopy.remove(id); if (isValidTarget(view, id)) { startValuesList.add(start); endValuesList.add(end); } } else { ListView parent = (ListView) view.getParent(); if (parent.getAdapter().hasStableIds()) { int position = parent.getPositionForView(view); long itemId = parent.getItemIdAtPosition(position); start = startValues.itemIdValues.get(itemId); endItemIdCopy.remove(itemId); // TODO: deal with targetIDs for itemIDs for ListView items startValuesList.add(start); endValuesList.add(end); } } } int startItemIdCopySize = startValues.itemIdValues.size(); for (int i = 0; i < startItemIdCopySize; ++i) { long id = startValues.itemIdValues.keyAt(i); if (isValidTarget(null, id)) { TransitionValues start = startValues.itemIdValues.get(id); TransitionValues end = endValues.itemIdValues.get(id); endItemIdCopy.remove(id); startValuesList.add(start); endValuesList.add(end); } } // Now walk through the remains of the end set for (View view : endCopy.keySet()) { int id = view.getId(); if (isValidTarget(view, id)) { TransitionValues start = startValues.viewValues.get(view) != null ? startValues.viewValues.get(view) : startValues.idValues.get(id); TransitionValues end = endCopy.get(view); endIdCopy.remove(id); startValuesList.add(start); endValuesList.add(end); } } int endIdCopySize = endIdCopy.size(); for (int i = 0; i < endIdCopySize; ++i) { int id = endIdCopy.keyAt(i); if (isValidTarget(null, id)) { TransitionValues start = startValues.idValues.get(id); TransitionValues end = endIdCopy.get(id); startValuesList.add(start); endValuesList.add(end); } } int endItemIdCopySize = endItemIdCopy.size(); for (int i = 0; i < endItemIdCopySize; ++i) { long id = endItemIdCopy.keyAt(i); // TODO: Deal with targetIDs and itemIDs TransitionValues start = startValues.itemIdValues.get(id); TransitionValues end = endItemIdCopy.get(id); startValuesList.add(start); endValuesList.add(end); } ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators(); for (int i = 0; i < startValuesList.size(); ++i) { TransitionValues start = startValuesList.get(i); TransitionValues end = endValuesList.get(i); // Only bother trying to animate with values that differ between start/end if (start != null || end != null) { if (start == null || !start.equals(end)) { if (DBG) { View view = (end != null) ? end.view : start.view; Log.d(LOG_TAG, " differing start/end values for view " + view); if (start == null || end == null) { Log.d(LOG_TAG, " " + ((start == null) ? "start null, end non-null" : "start non-null, end null")); } else { for (String key : start.values.keySet()) { Object startValue = start.values.get(key); Object endValue = end.values.get(key); if (startValue != endValue && !startValue.equals(endValue)) { Log.d(LOG_TAG, " " + key + ": start(" + startValue + "), end(" + endValue + ")"); } } } } // TODO: what to do about targetIds and itemIds? Animator animator = createAnimator(sceneRoot, start, end); if (animator != null) { // Save animation info for future cancellation purposes View view = null; TransitionValues infoValues = null; if (end != null) { view = end.view; String[] properties = getTransitionProperties(); if (view != null && properties != null && properties.length > 0) { infoValues = new TransitionValues(); infoValues.view = view; TransitionValues newValues = endValues.viewValues.get(view); if (newValues != null) { for (int j = 0; j < properties.length; ++j) { infoValues.values.put(properties[j], newValues.values.get(properties[j])); } } int numExistingAnims = runningAnimators.size(); for (int j = 0; j < numExistingAnims; ++j) { Animator anim = runningAnimators.keyAt(j); AnimationInfo info = runningAnimators.get(anim); if (info.values != null && info.view == view && ((info.name == null && getName() == null) || info.name.equals(getName()))) { if (info.values.equals(infoValues)) { // Favor the old animator animator = null; break; } } } } } else { view = (start != null) ? start.view : null; } if (animator != null) { AnimationInfo info = new AnimationInfo(view, getName(), infoValues); runningAnimators.put(animator, info); mAnimators.add(animator); } } } } } }
From source file:com.twistedequations.rotor.MediaMetadataCompat.java
@TargetApi(Build.VERSION_CODES.KITKAT) private static void fillEditorTypeMapping() { EDITOR_KEYS_TYPE = new SparseArray<Integer>(26); EDITOR_KEYS_TYPE.put(MediaMetadataEditor.BITMAP_KEY_ARTWORK, METADATA_TYPE_BITMAP); EDITOR_KEYS_TYPE.put(MediaMetadataEditor.RATING_KEY_BY_OTHERS, METADATA_TYPE_RATING); EDITOR_KEYS_TYPE.put(MediaMetadataEditor.RATING_KEY_BY_USER, METADATA_TYPE_RATING); EDITOR_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_ALBUM, METADATA_TYPE_TEXT); EDITOR_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST, METADATA_TYPE_TEXT); EDITOR_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_ARTIST, METADATA_TYPE_TEXT); EDITOR_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_AUTHOR, METADATA_TYPE_TEXT); EDITOR_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER, METADATA_TYPE_LONG); EDITOR_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_COMPOSER, METADATA_TYPE_TEXT); EDITOR_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_COMPILATION, METADATA_TYPE_TEXT); EDITOR_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_DATE, METADATA_TYPE_TEXT); EDITOR_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_DISC_NUMBER, METADATA_TYPE_LONG); EDITOR_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_DURATION, METADATA_TYPE_LONG); EDITOR_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_YEAR, METADATA_TYPE_LONG); EDITOR_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_GENRE, METADATA_TYPE_TEXT); EDITOR_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_TITLE, METADATA_TYPE_TEXT); EDITOR_KEYS_TYPE.put(MediaMetadataRetriever.METADATA_KEY_WRITER, METADATA_TYPE_TEXT); }
From source file:com.blestep.sportsbracelet.view.TimelineChartViewSleep.java
private void processData() { if (mCursor != null && !mCursor.isClosed() && mCursor.moveToFirst()) { // Load the cursor to memory double max = 0d; final SparseArray<Object[]> data = new SparseArray<>(mCursor.getCount()); do {//from w w w. j a va2 s. co m int position = mCursor.getInt(0); String label = mCursor.getString(1); String start = mCursor.getString(2); String end = mCursor.getString(3); double deep = mCursor.getDouble(4); double light = mCursor.getDouble(5); double awake = mCursor.getDouble(6); double asleep = mCursor.getDouble(7); if (asleep > max) { max = asleep; } Object[] values = new Object[] { label, start, end, deep, light, awake, asleep }; data.put(position, values); } while (mCursor.moveToNext()); // Calculate the max available offset int size = data.size() - 1; float maxOffset = mBarWidth * size; //swap data synchronized (mLock) { mData = data; mMaxValue = max; mMaxOffset = maxOffset; mLastOffset = -1.f; mCurrentPosition = size; mCurrentOffset = computeOffsetForPosition(mCurrentPosition); setupTickLabels(); } } }
From source file:com.blestep.sportsbracelet.view.TimelineChartView.java
private void processData() { if (mCursor != null && !mCursor.isClosed() && mCursor.moveToFirst()) { // Load the cursor to memory double max = 0d; final SparseArray<Object[]> data = new SparseArray<>(mCursor.getCount()); do {/*from www. j a v a 2s .co m*/ int position = mCursor.getInt(0); String label = mCursor.getString(1); double stepCount = mCursor.getDouble(2); double stepDuration = mCursor.getDouble(3); double stepDistance = mCursor.getDouble(4); double stepCalorie = mCursor.getDouble(5); if (stepCount > max) { max = stepCount; } Object[] values = new Object[] { label, stepCount, stepDuration, stepDistance, stepCalorie }; data.put(position, values); } while (mCursor.moveToNext()); // Calculate the max available offset int size = data.size() - 1; float maxOffset = mBarWidth * size; //swap data synchronized (mLock) { mData = data; mMaxValue = max; mMaxOffset = maxOffset; mLastOffset = -1.f; mCurrentPosition = size; mCurrentOffset = computeOffsetForPosition(mCurrentPosition); setupTickLabels(); } } }
From source file:com.staggeredgrid.library.StaggeredGridView.java
/*** * Our mColumnTops and mColumnBottoms need to be re-built up to the * mSyncPosition - the following layout request will then * layout the that position and then fillUp and fillDown appropriately. *///from ww w .ja va2 s. c om private void onColumnSync() { // re-calc tops for new column count! int syncPosition = Math.min(mSyncPosition, getCount() - 1); SparseArray<Double> positionHeightRatios = new SparseArray<Double>(syncPosition); for (int pos = 0; pos < syncPosition; pos++) { // check for weirdness final GridItemRecord rec = mPositionData.get(pos); if (rec == null) break; Log.d(TAG, "onColumnSync:" + pos + " ratio:" + rec.heightRatio); positionHeightRatios.append(pos, rec.heightRatio); } mPositionData.clear(); // re-calc our relative position while at the same time // rebuilding our GridItemRecord collection if (DBG) Log.d(TAG, "onColumnSync column width:" + mColumnWidth); for (int pos = 0; pos < syncPosition; pos++) { //Check for weirdness again final Double heightRatio = positionHeightRatios.get(pos); if (heightRatio == null) { break; } final GridItemRecord rec = getOrCreateRecord(pos); final int height = (int) (mColumnWidth * heightRatio); rec.heightRatio = heightRatio; int top; int bottom; // check for headers if (isHeaderOrFooter(pos)) { // the next top is the bottom for that column top = getLowestPositionedBottom(); bottom = top + height; for (int i = 0; i < mColumnCount; i++) { mColumnTops[i] = top; mColumnBottoms[i] = bottom; } } else { // what's the next column down ? final int column = getHighestPositionedBottomColumn(); // the next top is the bottom for that column top = mColumnBottoms[column]; bottom = top + height + getChildTopMargin(pos) + getChildBottomMargin(); mColumnTops[column] = top; mColumnBottoms[column] = bottom; rec.column = column; } if (DBG) Log.d(TAG, "onColumnSync position:" + pos + " top:" + top + " bottom:" + bottom + " height:" + height + " heightRatio:" + heightRatio); } // our sync position will be displayed in this column final int syncColumn = getHighestPositionedBottomColumn(); setPositionColumn(syncPosition, syncColumn); // we want to offset from height of the sync position // minus the offset int syncToBottom = mColumnBottoms[syncColumn]; int offset = -syncToBottom + mSpecificTop; // offset all columns by offsetAllColumnsTopAndBottom(offset); // sync the distance to top mDistanceToTop = -syncToBottom; // stash our bottoms in our tops - though these will be copied back to the bottoms System.arraycopy(mColumnBottoms, 0, mColumnTops, 0, mColumnCount); }
From source file:android.app.Activity.java
/** * Restore the state of any saved managed dialogs. * * @param savedInstanceState The bundle to restore from. *///from w w w . j a v a2s . c o m private void restoreManagedDialogs(Bundle savedInstanceState) { final Bundle b = savedInstanceState.getBundle(SAVED_DIALOGS_TAG); if (b == null) { return; } final int[] ids = b.getIntArray(SAVED_DIALOG_IDS_KEY); final int numDialogs = ids.length; mManagedDialogs = new SparseArray<ManagedDialog>(numDialogs); for (int i = 0; i < numDialogs; i++) { final Integer dialogId = ids[i]; Bundle dialogState = b.getBundle(savedDialogKeyFor(dialogId)); if (dialogState != null) { // Calling onRestoreInstanceState() below will invoke dispatchOnCreate // so tell createDialog() not to do it, otherwise we get an exception final ManagedDialog md = new ManagedDialog(); md.mArgs = b.getBundle(savedDialogArgsKeyFor(dialogId)); md.mDialog = createDialog(dialogId, dialogState, md.mArgs); if (md.mDialog != null) { mManagedDialogs.put(dialogId, md); onPrepareDialog(dialogId, md.mDialog, md.mArgs); md.mDialog.onRestoreInstanceState(dialogState); } } } }
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 . j a va 2 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; }