RetrieveTransactionpublic class RetrieveTransaction extends Transaction implements RunnableThe 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.String | getContentLocation(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 int | getType()
return RETRIEVE_TRANSACTION;
| private static boolean | isDuplicateMessage(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 void | process()
new Thread(this).start();
| public void | run()
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 void | sendAcknowledgeInd(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 void | updateContentLocation(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);
|
|