FileDocCategorySizeDatePackage
RetrieveTransaction.javaAPI DocAndroid 1.5 API8518Wed May 06 22:42:46 BST 2009com.android.mms.transaction

RetrieveTransaction

public class RetrieveTransaction extends Transaction implements Runnable
The RetrieveTransaction is responsible for retrieving multimedia messages (M-Retrieve.conf) from the MMSC server. It:
  • Sends a GET request to the MMSC server.
  • Retrieves the binary M-Retrieve.conf data and parses it.
  • Persists the retrieve multimedia message.
  • Determines whether an acknowledgement is required.
  • Creates appropriate M-Acknowledge.ind and sends it to MMSC server.
  • Notifies the TransactionService about succesful completion.

Fields Summary
private static final String
TAG
private static final boolean
DEBUG
private static final boolean
LOCAL_LOGV
private final android.net.Uri
mUri
private final String
mContentLocation
Constructors Summary
public RetrieveTransaction(android.content.Context context, int serviceId, TransactionSettings connectionSettings, String uri)


        
               
              
        super(context, serviceId, connectionSettings);

        if (uri.startsWith("content://")) {
            mUri = Uri.parse(uri); // The Uri of the M-Notification.ind
            mId = mContentLocation = getContentLocation(context, mUri);
            if (LOCAL_LOGV) {
                Log.v(TAG, "X-Mms-Content-Location: " + mContentLocation);
            }
        } else {
            throw new IllegalArgumentException(
                    "Initializing from X-Mms-Content-Location is abandoned!");
        }

        // Attach the transaction to the instance of RetryScheduler.
        attach(RetryScheduler.getInstance(context));
    
Methods Summary
private static java.lang.StringgetContentLocation(android.content.Context context, android.net.Uri uri)

        Cursor cursor = SqliteWrapper.query(context, context.getContentResolver(),
                            uri, new String[] {Mms.CONTENT_LOCATION}, null, null, null);

        if (cursor != null) {
            try {
                if ((cursor.getCount() == 1) && cursor.moveToFirst()) {
                    return cursor.getString(0);
                }
            } finally {
                cursor.close();
            }
        }

        throw new MmsException("Cannot get X-Mms-Content-Location from: " + uri);
    
public intgetType()

        return RETRIEVE_TRANSACTION;
    
private static booleanisDuplicateMessage(android.content.Context context, com.google.android.mms.pdu.RetrieveConf rc)

        byte[] rawMessageId = rc.getMessageId();
        if (rawMessageId != null) {
            String messageId = new String(rawMessageId);
            String selection = "(" + Mms.MESSAGE_ID + " = ? AND "
                                   + Mms.MESSAGE_TYPE + " = ?)";
            String[] selectionArgs = new String[] { messageId,
                    String.valueOf(PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF) };
            Cursor cursor = SqliteWrapper.query(
                    context, context.getContentResolver(),
                    Mms.CONTENT_URI, new String[] { Mms._ID },
                    selection, selectionArgs, null);
            if (cursor != null) {
                try {
                    if (cursor.getCount() > 0) {
                        // We already received the same message before.
                        return true;
                    }
                } finally {
                    cursor.close();
                }
            }
        }
        return false;
    
public voidprocess()

        new Thread(this).start();
    
public voidrun()

        try {
            // Change the downloading state of the M-Notification.ind.
            DownloadManager.getInstance().markState(
                    mUri, DownloadManager.STATE_DOWNLOADING);

            // Send GET request to MMSC and retrieve the response data.
            byte[] resp = getPdu(mContentLocation);

            // Parse M-Retrieve.conf
            RetrieveConf retrieveConf = (RetrieveConf) new PduParser(resp).parse();
            if (null == retrieveConf) {
                throw new MmsException("Invalid M-Retrieve.conf PDU.");
            }

            if (isDuplicateMessage(mContext, retrieveConf)) {
                // Mark this transaction as failed to prevent duplicate
                // notification to user.
                mTransactionState.setState(TransactionState.FAILED);
                mTransactionState.setContentUri(mUri);
            } else {
                // Store M-Retrieve.conf into Inbox
                PduPersister persister = PduPersister.getPduPersister(mContext);
                Uri uri = persister.persist(retrieveConf, Inbox.CONTENT_URI);

                // The M-Retrieve.conf has been successfully downloaded.
                mTransactionState.setState(TransactionState.SUCCESS);
                mTransactionState.setContentUri(uri);
                // Remember the location the message was downloaded from.
                // Since it's not critical, it won't fail the transaction.
                updateContentLocation(mContext, uri, mContentLocation);
            }

            // Delete the corresponding M-Notification.ind.
            SqliteWrapper.delete(mContext, mContext.getContentResolver(),
                                 mUri, null, null);

            // Send ACK to the Proxy-Relay to indicate we have fetched the
            // MM successfully.
            // Don't mark the transaction as failed if we failed to send it.
            sendAcknowledgeInd(retrieveConf);
        } catch (Throwable t) {
            Log.e(TAG, Log.getStackTraceString(t));
        } finally {
            if (mTransactionState.getState() != TransactionState.SUCCESS) {
                mTransactionState.setState(TransactionState.FAILED);
                mTransactionState.setContentUri(mUri);
                Log.e(TAG, "Retrieval failed.");
            }
            notifyObservers();
        }
    
private voidsendAcknowledgeInd(com.google.android.mms.pdu.RetrieveConf rc)

        // Send M-Acknowledge.ind to MMSC if required.
        // If the Transaction-ID isn't set in the M-Retrieve.conf, it means
        // the MMS proxy-relay doesn't require an ACK.
        byte[] tranId = rc.getTransactionId();
        if (tranId != null) {
            // Create M-Acknowledge.ind
            AcknowledgeInd acknowledgeInd = new AcknowledgeInd(
                    PduHeaders.CURRENT_MMS_VERSION, tranId);

            // Pack M-Acknowledge.ind and send it
            sendPdu(new PduComposer(mContext, acknowledgeInd).make());
        }
    
private static voidupdateContentLocation(android.content.Context context, android.net.Uri uri, java.lang.String contentLocation)

        ContentValues values = new ContentValues(1);
        values.put(Mms.CONTENT_LOCATION, contentLocation);
        SqliteWrapper.update(context, context.getContentResolver(),
                             uri, values, null, null);