|
Android example source code file (PduPersister.java)
The PduPersister.java Android example source code
/*
* Copyright (C) 2007-2008 Esmertec AG.
* Copyright (C) 2007-2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.mms.pdu;
import com.google.android.mms.ContentType;
import com.google.android.mms.InvalidHeaderValueException;
import com.google.android.mms.MmsException;
import com.google.android.mms.util.PduCache;
import com.google.android.mms.util.PduCacheEntry;
import com.google.android.mms.util.SqliteWrapper;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.net.Uri;
import android.provider.Telephony;
import android.provider.Telephony.Mms;
import android.provider.Telephony.MmsSms;
import android.provider.Telephony.Threads;
import android.provider.Telephony.Mms.Addr;
import android.provider.Telephony.Mms.Part;
import android.provider.Telephony.MmsSms.PendingMessages;
import android.text.TextUtils;
import android.util.Config;
import android.util.Log;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import com.google.android.mms.pdu.EncodedStringValue;
/**
* This class is the high-level manager of PDU storage.
*/
public class PduPersister {
private static final String TAG = "PduPersister";
private static final boolean DEBUG = false;
private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
private static final long DUMMY_THREAD_ID = Long.MAX_VALUE;
/**
* The uri of temporary drm objects.
*/
public static final String TEMPORARY_DRM_OBJECT_URI =
"content://mms/" + Long.MAX_VALUE + "/part";
/**
* Indicate that we transiently failed to process a MM.
*/
public static final int PROC_STATUS_TRANSIENT_FAILURE = 1;
/**
* Indicate that we permanently failed to process a MM.
*/
public static final int PROC_STATUS_PERMANENTLY_FAILURE = 2;
/**
* Indicate that we have successfully processed a MM.
*/
public static final int PROC_STATUS_COMPLETED = 3;
private static PduPersister sPersister;
private static final PduCache PDU_CACHE_INSTANCE;
private static final int[] ADDRESS_FIELDS = new int[] {
PduHeaders.BCC,
PduHeaders.CC,
PduHeaders.FROM,
PduHeaders.TO
};
private static final String[] PDU_PROJECTION = new String[] {
Mms._ID,
Mms.MESSAGE_BOX,
Mms.THREAD_ID,
Mms.RETRIEVE_TEXT,
Mms.SUBJECT,
Mms.CONTENT_LOCATION,
Mms.CONTENT_TYPE,
Mms.MESSAGE_CLASS,
Mms.MESSAGE_ID,
Mms.RESPONSE_TEXT,
Mms.TRANSACTION_ID,
Mms.CONTENT_CLASS,
Mms.DELIVERY_REPORT,
Mms.MESSAGE_TYPE,
Mms.MMS_VERSION,
Mms.PRIORITY,
Mms.READ_REPORT,
Mms.READ_STATUS,
Mms.REPORT_ALLOWED,
Mms.RETRIEVE_STATUS,
Mms.STATUS,
Mms.DATE,
Mms.DELIVERY_TIME,
Mms.EXPIRY,
Mms.MESSAGE_SIZE,
Mms.SUBJECT_CHARSET,
Mms.RETRIEVE_TEXT_CHARSET,
};
private static final int PDU_COLUMN_ID = 0;
private static final int PDU_COLUMN_MESSAGE_BOX = 1;
private static final int PDU_COLUMN_THREAD_ID = 2;
private static final int PDU_COLUMN_RETRIEVE_TEXT = 3;
private static final int PDU_COLUMN_SUBJECT = 4;
private static final int PDU_COLUMN_CONTENT_LOCATION = 5;
private static final int PDU_COLUMN_CONTENT_TYPE = 6;
private static final int PDU_COLUMN_MESSAGE_CLASS = 7;
private static final int PDU_COLUMN_MESSAGE_ID = 8;
private static final int PDU_COLUMN_RESPONSE_TEXT = 9;
private static final int PDU_COLUMN_TRANSACTION_ID = 10;
private static final int PDU_COLUMN_CONTENT_CLASS = 11;
private static final int PDU_COLUMN_DELIVERY_REPORT = 12;
private static final int PDU_COLUMN_MESSAGE_TYPE = 13;
private static final int PDU_COLUMN_MMS_VERSION = 14;
private static final int PDU_COLUMN_PRIORITY = 15;
private static final int PDU_COLUMN_READ_REPORT = 16;
private static final int PDU_COLUMN_READ_STATUS = 17;
private static final int PDU_COLUMN_REPORT_ALLOWED = 18;
private static final int PDU_COLUMN_RETRIEVE_STATUS = 19;
private static final int PDU_COLUMN_STATUS = 20;
private static final int PDU_COLUMN_DATE = 21;
private static final int PDU_COLUMN_DELIVERY_TIME = 22;
private static final int PDU_COLUMN_EXPIRY = 23;
private static final int PDU_COLUMN_MESSAGE_SIZE = 24;
private static final int PDU_COLUMN_SUBJECT_CHARSET = 25;
private static final int PDU_COLUMN_RETRIEVE_TEXT_CHARSET = 26;
private static final String[] PART_PROJECTION = new String[] {
Part._ID,
Part.CHARSET,
Part.CONTENT_DISPOSITION,
Part.CONTENT_ID,
Part.CONTENT_LOCATION,
Part.CONTENT_TYPE,
Part.FILENAME,
Part.NAME,
Part.TEXT
};
private static final int PART_COLUMN_ID = 0;
private static final int PART_COLUMN_CHARSET = 1;
private static final int PART_COLUMN_CONTENT_DISPOSITION = 2;
private static final int PART_COLUMN_CONTENT_ID = 3;
private static final int PART_COLUMN_CONTENT_LOCATION = 4;
private static final int PART_COLUMN_CONTENT_TYPE = 5;
private static final int PART_COLUMN_FILENAME = 6;
private static final int PART_COLUMN_NAME = 7;
private static final int PART_COLUMN_TEXT = 8;
private static final HashMap<Uri, Integer> MESSAGE_BOX_MAP;
// These map are used for convenience in persist() and load().
private static final HashMap<Integer, Integer> CHARSET_COLUMN_INDEX_MAP;
private static final HashMap<Integer, Integer> ENCODED_STRING_COLUMN_INDEX_MAP;
private static final HashMap<Integer, Integer> TEXT_STRING_COLUMN_INDEX_MAP;
private static final HashMap<Integer, Integer> OCTET_COLUMN_INDEX_MAP;
private static final HashMap<Integer, Integer> LONG_COLUMN_INDEX_MAP;
private static final HashMap<Integer, String> CHARSET_COLUMN_NAME_MAP;
private static final HashMap<Integer, String> ENCODED_STRING_COLUMN_NAME_MAP;
private static final HashMap<Integer, String> TEXT_STRING_COLUMN_NAME_MAP;
private static final HashMap<Integer, String> OCTET_COLUMN_NAME_MAP;
private static final HashMap<Integer, String> LONG_COLUMN_NAME_MAP;
static {
MESSAGE_BOX_MAP = new HashMap<Uri, Integer>();
MESSAGE_BOX_MAP.put(Mms.Inbox.CONTENT_URI, Mms.MESSAGE_BOX_INBOX);
MESSAGE_BOX_MAP.put(Mms.Sent.CONTENT_URI, Mms.MESSAGE_BOX_SENT);
MESSAGE_BOX_MAP.put(Mms.Draft.CONTENT_URI, Mms.MESSAGE_BOX_DRAFTS);
MESSAGE_BOX_MAP.put(Mms.Outbox.CONTENT_URI, Mms.MESSAGE_BOX_OUTBOX);
CHARSET_COLUMN_INDEX_MAP = new HashMap<Integer, Integer>();
CHARSET_COLUMN_INDEX_MAP.put(PduHeaders.SUBJECT, PDU_COLUMN_SUBJECT_CHARSET);
CHARSET_COLUMN_INDEX_MAP.put(PduHeaders.RETRIEVE_TEXT, PDU_COLUMN_RETRIEVE_TEXT_CHARSET);
CHARSET_COLUMN_NAME_MAP = new HashMap<Integer, String>();
CHARSET_COLUMN_NAME_MAP.put(PduHeaders.SUBJECT, Mms.SUBJECT_CHARSET);
CHARSET_COLUMN_NAME_MAP.put(PduHeaders.RETRIEVE_TEXT, Mms.RETRIEVE_TEXT_CHARSET);
// Encoded string field code -> column index/name map.
ENCODED_STRING_COLUMN_INDEX_MAP = new HashMap<Integer, Integer>();
ENCODED_STRING_COLUMN_INDEX_MAP.put(PduHeaders.RETRIEVE_TEXT, PDU_COLUMN_RETRIEVE_TEXT);
ENCODED_STRING_COLUMN_INDEX_MAP.put(PduHeaders.SUBJECT, PDU_COLUMN_SUBJECT);
ENCODED_STRING_COLUMN_NAME_MAP = new HashMap<Integer, String>();
ENCODED_STRING_COLUMN_NAME_MAP.put(PduHeaders.RETRIEVE_TEXT, Mms.RETRIEVE_TEXT);
ENCODED_STRING_COLUMN_NAME_MAP.put(PduHeaders.SUBJECT, Mms.SUBJECT);
// Text string field code -> column index/name map.
TEXT_STRING_COLUMN_INDEX_MAP = new HashMap<Integer, Integer>();
TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.CONTENT_LOCATION, PDU_COLUMN_CONTENT_LOCATION);
TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.CONTENT_TYPE, PDU_COLUMN_CONTENT_TYPE);
TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.MESSAGE_CLASS, PDU_COLUMN_MESSAGE_CLASS);
TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.MESSAGE_ID, PDU_COLUMN_MESSAGE_ID);
TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.RESPONSE_TEXT, PDU_COLUMN_RESPONSE_TEXT);
TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.TRANSACTION_ID, PDU_COLUMN_TRANSACTION_ID);
TEXT_STRING_COLUMN_NAME_MAP = new HashMap<Integer, String>();
TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.CONTENT_LOCATION, Mms.CONTENT_LOCATION);
TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.CONTENT_TYPE, Mms.CONTENT_TYPE);
TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.MESSAGE_CLASS, Mms.MESSAGE_CLASS);
TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.MESSAGE_ID, Mms.MESSAGE_ID);
TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.RESPONSE_TEXT, Mms.RESPONSE_TEXT);
TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.TRANSACTION_ID, Mms.TRANSACTION_ID);
// Octet field code -> column index/name map.
OCTET_COLUMN_INDEX_MAP = new HashMap<Integer, Integer>();
OCTET_COLUMN_INDEX_MAP.put(PduHeaders.CONTENT_CLASS, PDU_COLUMN_CONTENT_CLASS);
OCTET_COLUMN_INDEX_MAP.put(PduHeaders.DELIVERY_REPORT, PDU_COLUMN_DELIVERY_REPORT);
OCTET_COLUMN_INDEX_MAP.put(PduHeaders.MESSAGE_TYPE, PDU_COLUMN_MESSAGE_TYPE);
OCTET_COLUMN_INDEX_MAP.put(PduHeaders.MMS_VERSION, PDU_COLUMN_MMS_VERSION);
OCTET_COLUMN_INDEX_MAP.put(PduHeaders.PRIORITY, PDU_COLUMN_PRIORITY);
OCTET_COLUMN_INDEX_MAP.put(PduHeaders.READ_REPORT, PDU_COLUMN_READ_REPORT);
OCTET_COLUMN_INDEX_MAP.put(PduHeaders.READ_STATUS, PDU_COLUMN_READ_STATUS);
OCTET_COLUMN_INDEX_MAP.put(PduHeaders.REPORT_ALLOWED, PDU_COLUMN_REPORT_ALLOWED);
OCTET_COLUMN_INDEX_MAP.put(PduHeaders.RETRIEVE_STATUS, PDU_COLUMN_RETRIEVE_STATUS);
OCTET_COLUMN_INDEX_MAP.put(PduHeaders.STATUS, PDU_COLUMN_STATUS);
OCTET_COLUMN_NAME_MAP = new HashMap<Integer, String>();
OCTET_COLUMN_NAME_MAP.put(PduHeaders.CONTENT_CLASS, Mms.CONTENT_CLASS);
OCTET_COLUMN_NAME_MAP.put(PduHeaders.DELIVERY_REPORT, Mms.DELIVERY_REPORT);
OCTET_COLUMN_NAME_MAP.put(PduHeaders.MESSAGE_TYPE, Mms.MESSAGE_TYPE);
OCTET_COLUMN_NAME_MAP.put(PduHeaders.MMS_VERSION, Mms.MMS_VERSION);
OCTET_COLUMN_NAME_MAP.put(PduHeaders.PRIORITY, Mms.PRIORITY);
OCTET_COLUMN_NAME_MAP.put(PduHeaders.READ_REPORT, Mms.READ_REPORT);
OCTET_COLUMN_NAME_MAP.put(PduHeaders.READ_STATUS, Mms.READ_STATUS);
OCTET_COLUMN_NAME_MAP.put(PduHeaders.REPORT_ALLOWED, Mms.REPORT_ALLOWED);
OCTET_COLUMN_NAME_MAP.put(PduHeaders.RETRIEVE_STATUS, Mms.RETRIEVE_STATUS);
OCTET_COLUMN_NAME_MAP.put(PduHeaders.STATUS, Mms.STATUS);
// Long field code -> column index/name map.
LONG_COLUMN_INDEX_MAP = new HashMap<Integer, Integer>();
LONG_COLUMN_INDEX_MAP.put(PduHeaders.DATE, PDU_COLUMN_DATE);
LONG_COLUMN_INDEX_MAP.put(PduHeaders.DELIVERY_TIME, PDU_COLUMN_DELIVERY_TIME);
LONG_COLUMN_INDEX_MAP.put(PduHeaders.EXPIRY, PDU_COLUMN_EXPIRY);
LONG_COLUMN_INDEX_MAP.put(PduHeaders.MESSAGE_SIZE, PDU_COLUMN_MESSAGE_SIZE);
LONG_COLUMN_NAME_MAP = new HashMap<Integer, String>();
LONG_COLUMN_NAME_MAP.put(PduHeaders.DATE, Mms.DATE);
LONG_COLUMN_NAME_MAP.put(PduHeaders.DELIVERY_TIME, Mms.DELIVERY_TIME);
LONG_COLUMN_NAME_MAP.put(PduHeaders.EXPIRY, Mms.EXPIRY);
LONG_COLUMN_NAME_MAP.put(PduHeaders.MESSAGE_SIZE, Mms.MESSAGE_SIZE);
PDU_CACHE_INSTANCE = PduCache.getInstance();
}
private final Context mContext;
private final ContentResolver mContentResolver;
private PduPersister(Context context) {
mContext = context;
mContentResolver = context.getContentResolver();
}
/** Get(or create if not exist) an instance of PduPersister */
public static PduPersister getPduPersister(Context context) {
if ((sPersister == null) || !context.equals(sPersister.mContext)) {
sPersister = new PduPersister(context);
}
return sPersister;
}
private void setEncodedStringValueToHeaders(
Cursor c, int columnIndex,
PduHeaders headers, int mapColumn) {
String s = c.getString(columnIndex);
if ((s != null) && (s.length() > 0)) {
int charsetColumnIndex = CHARSET_COLUMN_INDEX_MAP.get(mapColumn);
int charset = c.getInt(charsetColumnIndex);
EncodedStringValue value = new EncodedStringValue(
charset, getBytes(s));
headers.setEncodedStringValue(value, mapColumn);
}
}
private void setTextStringToHeaders(
Cursor c, int columnIndex,
PduHeaders headers, int mapColumn) {
String s = c.getString(columnIndex);
if (s != null) {
headers.setTextString(getBytes(s), mapColumn);
}
}
private void setOctetToHeaders(
Cursor c, int columnIndex,
PduHeaders headers, int mapColumn) throws InvalidHeaderValueException {
if (!c.isNull(columnIndex)) {
int b = c.getInt(columnIndex);
headers.setOctet(b, mapColumn);
}
}
private void setLongToHeaders(
Cursor c, int columnIndex,
PduHeaders headers, int mapColumn) {
if (!c.isNull(columnIndex)) {
long l = c.getLong(columnIndex);
headers.setLongInteger(l, mapColumn);
}
}
private Integer getIntegerFromPartColumn(Cursor c, int columnIndex) {
if (!c.isNull(columnIndex)) {
return c.getInt(columnIndex);
}
return null;
}
private byte[] getByteArrayFromPartColumn(Cursor c, int columnIndex) {
if (!c.isNull(columnIndex)) {
return getBytes(c.getString(columnIndex));
}
return null;
}
private PduPart[] loadParts(long msgId) throws MmsException {
Cursor c = SqliteWrapper.query(mContext, mContentResolver,
Uri.parse("content://mms/" + msgId + "/part"),
PART_PROJECTION, null, null, null);
PduPart[] parts = null;
try {
if ((c == null) || (c.getCount() == 0)) {
if (LOCAL_LOGV) {
Log.v(TAG, "loadParts(" + msgId + "): no part to load.");
}
return null;
}
int partCount = c.getCount();
int partIdx = 0;
parts = new PduPart[partCount];
while (c.moveToNext()) {
PduPart part = new PduPart();
Integer charset = getIntegerFromPartColumn(
c, PART_COLUMN_CHARSET);
if (charset != null) {
part.setCharset(charset);
}
byte[] contentDisposition = getByteArrayFromPartColumn(
c, PART_COLUMN_CONTENT_DISPOSITION);
if (contentDisposition != null) {
part.setContentDisposition(contentDisposition);
}
byte[] contentId = getByteArrayFromPartColumn(
c, PART_COLUMN_CONTENT_ID);
if (contentId != null) {
part.setContentId(contentId);
}
byte[] contentLocation = getByteArrayFromPartColumn(
c, PART_COLUMN_CONTENT_LOCATION);
if (contentLocation != null) {
part.setContentLocation(contentLocation);
}
byte[] contentType = getByteArrayFromPartColumn(
c, PART_COLUMN_CONTENT_TYPE);
if (contentType != null) {
part.setContentType(contentType);
} else {
throw new MmsException("Content-Type must be set.");
}
byte[] fileName = getByteArrayFromPartColumn(
c, PART_COLUMN_FILENAME);
if (fileName != null) {
part.setFilename(fileName);
}
byte[] name = getByteArrayFromPartColumn(
c, PART_COLUMN_NAME);
if (name != null) {
part.setName(name);
}
// Construct a Uri for this part.
long partId = c.getLong(PART_COLUMN_ID);
Uri partURI = Uri.parse("content://mms/part/" + partId);
part.setDataUri(partURI);
// For images/audio/video, we won't keep their data in Part
// because their renderer accept Uri as source.
String type = toIsoString(contentType);
if (!ContentType.isImageType(type)
&& !ContentType.isAudioType(type)
&& !ContentType.isVideoType(type)) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = null;
// Store simple string values directly in the database instead of an
// external file. This makes the text searchable and retrieval slightly
// faster.
if ("text/plain".equals(type) || "application/smil".equals(type)) {
String text = c.getString(PART_COLUMN_TEXT);
byte [] blob = new EncodedStringValue(text != null ? text : "")
.getTextString();
baos.write(blob, 0, blob.length);
} else {
try {
is = mContentResolver.openInputStream(partURI);
byte[] buffer = new byte[256];
int len = is.read(buffer);
while (len >= 0) {
baos.write(buffer, 0, len);
len = is.read(buffer);
}
} catch (IOException e) {
Log.e(TAG, "Failed to load part data", e);
c.close();
throw new MmsException(e);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
Log.e(TAG, "Failed to close stream", e);
} // Ignore
}
}
}
part.setData(baos.toByteArray());
}
parts[partIdx++] = part;
}
} finally {
if (c != null) {
c.close();
}
}
return parts;
}
private void loadAddress(long msgId, PduHeaders headers) {
Cursor c = SqliteWrapper.query(mContext, mContentResolver,
Uri.parse("content://mms/" + msgId + "/addr"),
new String[] { Addr.ADDRESS, Addr.CHARSET, Addr.TYPE },
null, null, null);
if (c != null) {
try {
while (c.moveToNext()) {
String addr = c.getString(0);
if (!TextUtils.isEmpty(addr)) {
int addrType = c.getInt(2);
switch (addrType) {
case PduHeaders.FROM:
headers.setEncodedStringValue(
new EncodedStringValue(c.getInt(1), getBytes(addr)),
addrType);
break;
case PduHeaders.TO:
case PduHeaders.CC:
case PduHeaders.BCC:
headers.appendEncodedStringValue(
new EncodedStringValue(c.getInt(1), getBytes(addr)),
addrType);
break;
default:
Log.e(TAG, "Unknown address type: " + addrType);
break;
}
}
}
} finally {
c.close();
}
}
}
/**
* Load a PDU from storage by given Uri.
*
* @param uri The Uri of the PDU to be loaded.
* @return A generic PDU object, it may be cast to dedicated PDU.
* @throws MmsException Failed to load some fields of a PDU.
*/
public GenericPdu load(Uri uri) throws MmsException {
PduCacheEntry cacheEntry = PDU_CACHE_INSTANCE.get(uri);
if (cacheEntry != null) {
return cacheEntry.getPdu();
}
Cursor c = SqliteWrapper.query(mContext, mContentResolver, uri,
PDU_PROJECTION, null, null, null);
PduHeaders headers = new PduHeaders();
Set<Entry
Other Android examples (source code examples)Here is a short list of links related to this Android PduPersister.java source code file: |
Other websites by Alvin Alexander:
Life/living in Alaska (OneMansAlaska.com)
How I Sold My Business (HowISoldMyBusiness.com)
Copyright 1998-2011 Alvin Alexander, devdaily.com
All Rights Reserved.