| /* |
| * 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 java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import android.app.ListActivity; |
| import android.content.Intent; |
| import android.database.Cursor; |
| import android.database.sqlite.SqliteWrapper; |
| import android.net.Uri; |
| import android.os.Bundle; |
| import android.provider.Telephony.Mms; |
| import android.provider.Telephony.Sms; |
| import android.telephony.PhoneNumberUtils; |
| import android.text.TextUtils; |
| import android.util.Log; |
| import android.view.LayoutInflater; |
| import android.view.View; |
| import android.view.Window; |
| import android.widget.ListView; |
| |
| import com.android.mms.R; |
| import com.google.android.mms.pdu.PduHeaders; |
| |
| /** |
| * This is the UI for displaying a delivery report: |
| * |
| * This activity can handle the following parameters from the intent |
| * by which it is launched: |
| * |
| * thread_id long The id of the conversation from which to get the recipients |
| * for the report. |
| * message_id long The id of the message about which a report should be displayed. |
| * message_type String The type of message (Sms or Mms). This is used in |
| * conjunction with the message id to retrive the particular message that |
| * the report will be about. |
| */ |
| public class DeliveryReportActivity extends ListActivity { |
| private static final String LOG_TAG = "DeliveryReportActivity"; |
| |
| static final String[] MMS_REPORT_REQUEST_PROJECTION = new String[] { |
| Mms.Addr.ADDRESS, //0 |
| Mms.DELIVERY_REPORT, //1 |
| Mms.READ_REPORT //2 |
| }; |
| |
| static final String[] MMS_REPORT_STATUS_PROJECTION = new String[] { |
| Mms.Addr.ADDRESS, //0 |
| "delivery_status", //1 |
| "read_status" //2 |
| }; |
| |
| static final String[] SMS_REPORT_STATUS_PROJECTION = new String[] { |
| Sms.ADDRESS, //0 |
| Sms.STATUS, //1 |
| Sms.DATE_SENT, //2 |
| Sms.TYPE //3 |
| }; |
| |
| // These indices must sync up with the projections above. |
| static final int COLUMN_RECIPIENT = 0; |
| static final int COLUMN_DELIVERY_REPORT = 1; |
| static final int COLUMN_READ_REPORT = 2; |
| static final int COLUMN_DELIVERY_STATUS = 1; |
| static final int COLUMN_READ_STATUS = 2; |
| static final int COLUMN_DATE_SENT = 2; |
| static final int COLUMN_MESSAGE_TYPE = 3; |
| |
| private long mMessageId; |
| private String mMessageType; |
| |
| @Override |
| protected void onCreate(Bundle icicle) { |
| super.onCreate(icicle); |
| requestWindowFeature(Window.FEATURE_NO_TITLE); |
| setContentView(R.layout.delivery_report_activity); |
| |
| Intent intent = getIntent(); |
| mMessageId = getMessageId(icicle, intent); |
| mMessageType = getMessageType(icicle, intent); |
| |
| initListView(); |
| initListAdapter(); |
| } |
| |
| private void initListView() { |
| // Add the header for the list view. |
| LayoutInflater inflater = getLayoutInflater(); |
| View header = inflater.inflate(R.layout.delivery_report_header, null); |
| getListView().addHeaderView(header, null, true); |
| } |
| |
| private void initListAdapter() { |
| List<DeliveryReportItem> items = getReportItems(); |
| if (items == null) { |
| items = new ArrayList<DeliveryReportItem>(1); |
| items.add(new DeliveryReportItem("", getString(R.string.status_none), null)); |
| Log.w(LOG_TAG, "cursor == null"); |
| } |
| setListAdapter(new DeliveryReportAdapter(this, items)); |
| } |
| |
| @Override |
| public void onResume() { |
| super.onResume(); |
| refreshDeliveryReport(); |
| } |
| |
| private void refreshDeliveryReport() { |
| ListView list = getListView(); |
| list.invalidateViews(); |
| list.requestFocus(); |
| } |
| |
| private long getMessageId(Bundle icicle, Intent intent) { |
| long msgId = 0L; |
| |
| if (icicle != null) { |
| msgId = icicle.getLong("message_id"); |
| } |
| |
| if (msgId == 0L) { |
| msgId = intent.getLongExtra("message_id", 0L); |
| } |
| |
| return msgId; |
| } |
| |
| private String getMessageType(Bundle icicle, Intent intent) { |
| String msgType = null; |
| |
| if (icicle != null) { |
| msgType = icicle.getString("message_type"); |
| } |
| |
| if (msgType == null) { |
| msgType = intent.getStringExtra("message_type"); |
| } |
| |
| return msgType; |
| } |
| |
| private List<DeliveryReportItem> getReportItems() { |
| if (mMessageType.equals("sms")) { |
| return getSmsReportItems(); |
| } else { |
| return getMmsReportItems(); |
| } |
| } |
| |
| private List<DeliveryReportItem> getSmsReportItems() { |
| String selection = "_id = " + mMessageId; |
| Cursor c = SqliteWrapper.query(this, getContentResolver(), Sms.CONTENT_URI, |
| SMS_REPORT_STATUS_PROJECTION, selection, null, null); |
| if (c == null) { |
| return null; |
| } |
| |
| try { |
| if (c.getCount() <= 0) { |
| return null; |
| } |
| |
| List<DeliveryReportItem> items = new ArrayList<DeliveryReportItem>(); |
| while (c.moveToNext()) { |
| // For sent messages with delivery reports, we stick the delivery time in the |
| // date_sent column (see MessageStatusReceiver). |
| String deliveryDateString = null; |
| long deliveryDate = c.getLong(COLUMN_DATE_SENT); |
| int messageType = c.getInt(COLUMN_MESSAGE_TYPE); |
| if (messageType == Sms.MESSAGE_TYPE_SENT && deliveryDate > 0) { |
| deliveryDateString = getString(R.string.delivered_label) + |
| MessageUtils.formatTimeStampString(this, |
| deliveryDate, true); |
| } |
| |
| items.add(new DeliveryReportItem( |
| getString(R.string.recipient_label) + c.getString(COLUMN_RECIPIENT), |
| getString(R.string.status_label) + |
| getSmsStatusText(c.getInt(COLUMN_DELIVERY_STATUS)), |
| deliveryDateString)); |
| } |
| return items; |
| } finally { |
| c.close(); |
| } |
| } |
| |
| private String getMmsReportStatusText( |
| MmsReportRequest request, |
| Map<String, MmsReportStatus> reportStatus) { |
| if (reportStatus == null) { |
| // haven't received any reports. |
| return getString(R.string.status_pending); |
| } |
| |
| String recipient = request.getRecipient(); |
| recipient = (Mms.isEmailAddress(recipient))? |
| Mms.extractAddrSpec(recipient): PhoneNumberUtils.stripSeparators(recipient); |
| MmsReportStatus status = queryStatusByRecipient(reportStatus, recipient); |
| if (status == null) { |
| // haven't received any reports. |
| return getString(R.string.status_pending); |
| } |
| |
| if (request.isReadReportRequested()) { |
| if (status.readStatus != 0) { |
| switch (status.readStatus) { |
| case PduHeaders.READ_STATUS_READ: |
| return getString(R.string.status_read); |
| case PduHeaders.READ_STATUS__DELETED_WITHOUT_BEING_READ: |
| return getString(R.string.status_unread); |
| } |
| } |
| } |
| |
| switch (status.deliveryStatus) { |
| case 0: // No delivery report received so far. |
| return getString(R.string.status_pending); |
| case PduHeaders.STATUS_FORWARDED: |
| case PduHeaders.STATUS_RETRIEVED: |
| return getString(R.string.status_received); |
| case PduHeaders.STATUS_REJECTED: |
| return getString(R.string.status_rejected); |
| default: |
| return getString(R.string.status_failed); |
| } |
| } |
| |
| private static MmsReportStatus queryStatusByRecipient( |
| Map<String, MmsReportStatus> status, String recipient) { |
| Set<String> recipientSet = status.keySet(); |
| Iterator<String> iterator = recipientSet.iterator(); |
| while (iterator.hasNext()) { |
| String r = iterator.next(); |
| if (Mms.isEmailAddress(recipient)) { |
| if (TextUtils.equals(r, recipient)) { |
| return status.get(r); |
| } |
| } |
| else if (PhoneNumberUtils.compare(r, recipient)) { |
| return status.get(r); |
| } |
| } |
| return null; |
| } |
| |
| private List<DeliveryReportItem> getMmsReportItems() { |
| List<MmsReportRequest> reportReqs = getMmsReportRequests(); |
| if (null == reportReqs) { |
| return null; |
| } |
| |
| if (reportReqs.size() == 0) { |
| return null; |
| } |
| |
| Map<String, MmsReportStatus> reportStatus = getMmsReportStatus(); |
| List<DeliveryReportItem> items = new ArrayList<DeliveryReportItem>(); |
| for (MmsReportRequest reportReq : reportReqs) { |
| String statusText = getString(R.string.status_label) + |
| getMmsReportStatusText(reportReq, reportStatus); |
| items.add(new DeliveryReportItem(getString(R.string.recipient_label) + |
| reportReq.getRecipient(), statusText, null)); |
| } |
| return items; |
| } |
| |
| private Map<String, MmsReportStatus> getMmsReportStatus() { |
| Uri uri = Uri.withAppendedPath(Mms.REPORT_STATUS_URI, |
| String.valueOf(mMessageId)); |
| Cursor c = SqliteWrapper.query(this, getContentResolver(), uri, |
| MMS_REPORT_STATUS_PROJECTION, null, null, null); |
| |
| if (c == null) { |
| return null; |
| } |
| |
| try { |
| Map<String, MmsReportStatus> statusMap = |
| new HashMap<String, MmsReportStatus>(); |
| |
| while (c.moveToNext()) { |
| String recipient = c.getString(COLUMN_RECIPIENT); |
| recipient = (Mms.isEmailAddress(recipient))? |
| Mms.extractAddrSpec(recipient): |
| PhoneNumberUtils.stripSeparators(recipient); |
| MmsReportStatus status = new MmsReportStatus( |
| c.getInt(COLUMN_DELIVERY_STATUS), |
| c.getInt(COLUMN_READ_STATUS)); |
| statusMap.put(recipient, status); |
| } |
| return statusMap; |
| } finally { |
| c.close(); |
| } |
| } |
| |
| private List<MmsReportRequest> getMmsReportRequests() { |
| Uri uri = Uri.withAppendedPath(Mms.REPORT_REQUEST_URI, |
| String.valueOf(mMessageId)); |
| Cursor c = SqliteWrapper.query(this, getContentResolver(), uri, |
| MMS_REPORT_REQUEST_PROJECTION, null, null, null); |
| |
| if (c == null) { |
| return null; |
| } |
| |
| try { |
| if (c.getCount() <= 0) { |
| return null; |
| } |
| |
| List<MmsReportRequest> reqList = new ArrayList<MmsReportRequest>(); |
| while (c.moveToNext()) { |
| reqList.add(new MmsReportRequest( |
| c.getString(COLUMN_RECIPIENT), |
| c.getInt(COLUMN_DELIVERY_REPORT), |
| c.getInt(COLUMN_READ_REPORT))); |
| } |
| return reqList; |
| } finally { |
| c.close(); |
| } |
| } |
| |
| private String getSmsStatusText(int status) { |
| if (status == Sms.STATUS_NONE) { |
| // No delivery report requested |
| return getString(R.string.status_none); |
| } else if (status >= Sms.STATUS_FAILED) { |
| // Failure |
| return getString(R.string.status_failed); |
| } else if (status >= Sms.STATUS_PENDING) { |
| // Pending |
| return getString(R.string.status_pending); |
| } else { |
| // Success |
| return getString(R.string.status_received); |
| } |
| } |
| |
| private static final class MmsReportStatus { |
| final int deliveryStatus; |
| final int readStatus; |
| |
| public MmsReportStatus(int drStatus, int rrStatus) { |
| deliveryStatus = drStatus; |
| readStatus = rrStatus; |
| } |
| } |
| |
| private static final class MmsReportRequest { |
| private final String mRecipient; |
| private final boolean mIsDeliveryReportRequsted; |
| private final boolean mIsReadReportRequested; |
| |
| public MmsReportRequest(String recipient, int drValue, int rrValue) { |
| mRecipient = recipient; |
| mIsDeliveryReportRequsted = drValue == PduHeaders.VALUE_YES; |
| mIsReadReportRequested = rrValue == PduHeaders.VALUE_YES; |
| } |
| |
| public String getRecipient() { |
| return mRecipient; |
| } |
| |
| public boolean isDeliveryReportRequested() { |
| return mIsDeliveryReportRequsted; |
| } |
| |
| public boolean isReadReportRequested() { |
| return mIsReadReportRequested; |
| } |
| } |
| } |