/*
* Copyright (C) 2008 Esmertec AG.
* Copyright (C) 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.android.mms.ui;
import com.android.mms.R;
import com.google.android.mms.MmsException;
import android.content.Context;
import android.database.Cursor;
import android.os.Handler;
import android.provider.BaseColumns;
import android.provider.Telephony.Mms;
import android.provider.Telephony.MmsSms;
import android.provider.Telephony.Sms;
import android.provider.Telephony.MmsSms.PendingMessages;
import android.provider.Telephony.Sms.Conversations;
import android.util.Config;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.ListView;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* The back-end data adapter of a message list.
*/
public class MessageListAdapter extends CursorAdapter {
private static final String TAG = "MessageListAdapter";
private static final boolean DEBUG = false;
private static final boolean LOCAL_LOGV = Config.LOGV && DEBUG;
static final String[] PROJECTION = new String[] {
// TODO: should move this symbol into android.provider.Telephony.
MmsSms.TYPE_DISCRIMINATOR_COLUMN,
BaseColumns._ID,
Conversations.THREAD_ID,
// For SMS
Sms.ADDRESS,
Sms.BODY,
Sms.DATE,
Sms.READ,
Sms.TYPE,
Sms.STATUS,
// For MMS
Mms.SUBJECT,
Mms.SUBJECT_CHARSET,
Mms.DATE,
Mms.READ,
Mms.MESSAGE_TYPE,
Mms.MESSAGE_BOX,
Mms.DELIVERY_REPORT,
Mms.READ_REPORT,
PendingMessages.ERROR_TYPE
};
// The indexes of the default columns which must be consistent
// with above PROJECTION.
static final int COLUMN_MSG_TYPE = 0;
static final int COLUMN_ID = 1;
static final int COLUMN_THREAD_ID = 2;
static final int COLUMN_SMS_ADDRESS = 3;
static final int COLUMN_SMS_BODY = 4;
static final int COLUMN_SMS_DATE = 5;
static final int COLUMN_SMS_READ = 6;
static final int COLUMN_SMS_TYPE = 7;
static final int COLUMN_SMS_STATUS = 8;
static final int COLUMN_MMS_SUBJECT = 9;
static final int COLUMN_MMS_SUBJECT_CHARSET = 10;
static final int COLUMN_MMS_DATE = 11;
static final int COLUMN_MMS_READ = 12;
static final int COLUMN_MMS_MESSAGE_TYPE = 13;
static final int COLUMN_MMS_MESSAGE_BOX = 14;
static final int COLUMN_MMS_DELIVERY_REPORT = 15;
static final int COLUMN_MMS_READ_REPORT = 16;
static final int COLUMN_MMS_ERROR_TYPE = 17;
private static final int CACHE_SIZE = 50;
protected LayoutInflater mInflater;
private final ListView mListView;
private final LinkedHashMap<Long, MessageItem> mMessageItemCache;
private final ColumnsMap mColumnsMap;
private OnDataSetChangedListener mOnDataSetChangedListener;
private final int mThreadType;
private Handler mMsgListItemHandler;
public MessageListAdapter(
Context context, Cursor c, ListView listView,
boolean useDefaultColumnsMap, int threadType) {
super(context, c);
mThreadType = threadType;
mInflater = (LayoutInflater) context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
mListView = listView;
mMessageItemCache = new LinkedHashMap<Long, MessageItem>(
10, 1.0f, true) {
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > CACHE_SIZE;
}
};
if (useDefaultColumnsMap) {
mColumnsMap = new ColumnsMap();
} else {
mColumnsMap = new ColumnsMap(c);
}
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
if (view instanceof MessageListItem) {
String type = cursor.getString(mColumnsMap.mColumnMsgType);
long msgId = cursor.getLong(mColumnsMap.mColumnMsgId);
MessageItem msgItem = getCachedMessageItem(type, msgId, cursor);
if (msgItem != null) {
((MessageListItem) view).bind(msgItem);
((MessageListItem) view).setMsgListItemHandler(mMsgListItemHandler);
}
}
}
public interface OnDataSetChangedListener {
void onDataSetChanged(MessageListAdapter adapter);
}
public void setOnDataSetChangedListener(OnDataSetChangedListener l) {
mOnDataSetChangedListener = l;
}
public void setMsgListItemHandler(Handler handler) {
mMsgListItemHandler = handler;
}
@Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
if (LOCAL_LOGV) {
Log.v(TAG, "MessageListAdapter.notifyDataSetChanged().");
}
mListView.setSelection(mListView.getCount());
mMessageItemCache.clear();
if (mOnDataSetChangedListener != null) {
mOnDataSetChangedListener.onDataSetChanged(this);
}
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return mInflater.inflate(R.layout.message_list_item, parent, false);
}
public MessageItem getCachedMessageItem(String type, long msgId, Cursor c) {
MessageItem item = mMessageItemCache.get(getKey(type, msgId));
if (item == null) {
try {
item = new MessageItem(mContext, type, c, mColumnsMap, mThreadType);
mMessageItemCache.put(getKey(item.mType, item.mMsgId), item);
} catch (MmsException e) {
Log.e(TAG, e.getMessage());
}
}
return item;
}
private static long getKey(String type, long id) {
if (type.equals("mms")) {
return -id;
} else {
return id;
}
}
final class ColumnsMap {
int mColumnMsgType;
int mColumnMsgId;
int mColumnSmsAddress;
int mColumnSmsBody;
int mColumnSmsDate;
int mColumnSmsRead;
int mColumnSmsType;
int mColumnSmsStatus;
int mColumnMmsSubject;
int mColumnMmsSubjectCharset;
int mColumnMmsDate;
int mColumnMmsRead;
int mColumnMmsMessageType;
int mColumnMmsMessageBox;
int mColumnMmsDeliveryReport;
int mColumnMmsReadReport;
int mColumnMmsErrorType;
ColumnsMap() {
mColumnMsgType = COLUMN_MSG_TYPE;
mColumnMsgId = COLUMN_ID;
mColumnSmsAddress = COLUMN_SMS_ADDRESS;
mColumnSmsBody = COLUMN_SMS_BODY;
mColumnSmsDate = COLUMN_SMS_DATE;
mColumnSmsRead = COLUMN_SMS_READ;
mColumnSmsType = COLUMN_SMS_TYPE;
mColumnSmsStatus = COLUMN_SMS_STATUS;
mColumnMmsSubject = COLUMN_MMS_SUBJECT;
mColumnMmsSubjectCharset = COLUMN_MMS_SUBJECT_CHARSET;
mColumnMmsDate = COLUMN_MMS_DATE;
mColumnMmsRead = COLUMN_MMS_READ;
mColumnMmsMessageType = COLUMN_MMS_MESSAGE_TYPE;
mColumnMmsMessageBox = COLUMN_MMS_MESSAGE_BOX;
mColumnMmsDeliveryReport = COLUMN_MMS_DELIVERY_REPORT;
mColumnMmsReadReport = COLUMN_MMS_READ_REPORT;
mColumnMmsErrorType = COLUMN_MMS_ERROR_TYPE;
}
ColumnsMap(Cursor cursor) {
// Ignore all 'not found' exceptions since the custom columns
// may be just a subset of the default columns.
try {
mColumnMsgType = cursor.getColumnIndexOrThrow(
MmsSms.TYPE_DISCRIMINATOR_COLUMN);
} catch (IllegalArgumentException e) {
Log.w("colsMap", e.getMessage());
}
try {
mColumnMsgId = cursor.getColumnIndexOrThrow(BaseColumns._ID);
} catch (IllegalArgumentException e) {
Log.w("colsMap", e.getMessage());
}
try {
mColumnSmsAddress = cursor.getColumnIndexOrThrow(Sms.ADDRESS);
} catch (IllegalArgumentException e) {
Log.w("colsMap", e.getMessage());
}
try {
mColumnSmsBody = cursor.getColumnIndexOrThrow(Sms.BODY);
} catch (IllegalArgumentException e) {
Log.w("colsMap", e.getMessage());
}
try {
mColumnSmsDate = cursor.getColumnIndexOrThrow(Sms.DATE);
} catch (IllegalArgumentException e) {
Log.w("colsMap", e.getMessage());
}
try {
mColumnSmsRead = cursor.getColumnIndexOrThrow(Sms.READ);
} catch (IllegalArgumentException e) {
Log.w("colsMap", e.getMessage());
}
try {
mColumnSmsType = cursor.getColumnIndexOrThrow(Sms.TYPE);
} catch (IllegalArgumentException e) {
Log.w("colsMap", e.getMessage());
}
try {
mColumnSmsStatus = cursor.getColumnIndexOrThrow(Sms.STATUS);
} catch (IllegalArgumentException e) {
Log.w("colsMap", e.getMessage());
}
try {
mColumnMmsSubject = cursor.getColumnIndexOrThrow(Mms.SUBJECT);
} catch (IllegalArgumentException e) {
Log.w("colsMap", e.getMessage());
}
try {
mColumnMmsSubjectCharset = cursor.getColumnIndexOrThrow(Mms.SUBJECT_CHARSET);
} catch (IllegalArgumentException e) {
Log.w("colsMap", e.getMessage());
}
try {
mColumnMmsDate = cursor.getColumnIndexOrThrow(Mms.DATE);
} catch (IllegalArgumentException e) {
Log.w("colsMap", e.getMessage());
}
try {
mColumnMmsRead = cursor.getColumnIndexOrThrow(Mms.READ);
} catch (IllegalArgumentException e) {
Log.w("colsMap", e.getMessage());
}
try {
mColumnMmsMessageType = cursor.getColumnIndexOrThrow(Mms.MESSAGE_TYPE);
} catch (IllegalArgumentException e) {
Log.w("colsMap", e.getMessage());
}
try {
mColumnMmsMessageBox = cursor.getColumnIndexOrThrow(Mms.MESSAGE_BOX);
} catch (IllegalArgumentException e) {
Log.w("colsMap", e.getMessage());
}
try {
mColumnMmsDeliveryReport = cursor.getColumnIndexOrThrow(Mms.DELIVERY_REPORT);
} catch (IllegalArgumentException e) {
Log.w("colsMap", e.getMessage());
}
try {
mColumnMmsReadReport = cursor.getColumnIndexOrThrow(Mms.READ_REPORT);
} catch (IllegalArgumentException e) {
Log.w("colsMap", e.getMessage());
}
try {
mColumnMmsErrorType = cursor.getColumnIndexOrThrow(PendingMessages.ERROR_TYPE);
} catch (IllegalArgumentException e) {
Log.w("colsMap", e.getMessage());
}
}
}
}
|