DeliveryReportActivity.java revision 72735c62aba8fd2a9420a0f9f83d22543e3c164f
1/* 2 * Copyright (C) 2008 Esmertec AG. 3 * Copyright (C) 2008 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package com.android.mms.ui; 19 20import com.android.mms.R; 21import com.android.mms.ui.RecipientList.Recipient; 22import com.google.android.mms.pdu.PduHeaders; 23import com.google.android.mms.util.SqliteWrapper; 24 25import android.app.ListActivity; 26import android.content.Intent; 27import android.database.Cursor; 28import android.net.Uri; 29import android.os.Bundle; 30import android.provider.Telephony.Mms; 31import android.provider.Telephony.Sms; 32import android.telephony.PhoneNumberUtils; 33import android.text.TextUtils; 34import android.util.Log; 35import android.view.LayoutInflater; 36import android.view.View; 37import android.view.Window; 38import android.widget.ListView; 39 40import java.util.ArrayList; 41import java.util.HashMap; 42import java.util.Iterator; 43import java.util.List; 44import java.util.Map; 45import java.util.Set; 46 47/** 48 * This is the UI for displaying a delivery report: 49 * 50 * This activity can handle the following parameters from the intent 51 * by which it is launched: 52 * 53 * thread_id long The id of the conversation from which to get the recipients 54 * for the report. 55 * message_id long The id of the message about which a report should be displayed. 56 * message_type String The type of message (Sms or Mms). This is used in 57 * conjunction with the message id to retrive the particular message that 58 * the report will be about. 59 */ 60public class DeliveryReportActivity extends ListActivity { 61 private static final String LOG_TAG = "DeliveryReportActivity"; 62 63 static final String[] MMS_REPORT_REQUEST_PROJECTION = new String[] { 64 Mms.Addr.ADDRESS, //0 65 Mms.DELIVERY_REPORT, //1 66 Mms.READ_REPORT //2 67 }; 68 69 static final String[] MMS_REPORT_STATUS_PROJECTION = new String[] { 70 Mms.Addr.ADDRESS, //0 71 "delivery_status", //1 72 "read_status" //2 73 }; 74 75 static final String[] SMS_REPORT_STATUS_PROJECTION = new String[] { 76 Sms.ADDRESS, //0 77 Sms.STATUS //1 78 }; 79 80 // These indices must sync up with the projections above. 81 static final int COLUMN_RECIPIENT = 0; 82 static final int COLUMN_DELIVERY_REPORT = 1; 83 static final int COLUMN_READ_REPORT = 2; 84 static final int COLUMN_DELIVERY_STATUS = 1; 85 static final int COLUMN_READ_STATUS = 2; 86 87 private long mMessageId; 88 private String mMessageType; 89 90 @Override 91 protected void onCreate(Bundle icicle) { 92 super.onCreate(icicle); 93 requestWindowFeature(Window.FEATURE_NO_TITLE); 94 setContentView(R.layout.delivery_report_activity); 95 96 Intent intent = getIntent(); 97 mMessageId = getMessageId(icicle, intent); 98 mMessageType = getMessageType(icicle, intent); 99 100 initListView(); 101 initListAdapter(); 102 } 103 104 private void initListView() { 105 // Add the header for the list view. 106 LayoutInflater inflater = getLayoutInflater(); 107 View header = inflater.inflate(R.layout.delivery_report_header, null); 108 getListView().addHeaderView(header, null, true); 109 } 110 111 private void initListAdapter() { 112 List<DeliveryReportItem> items = getReportItems(); 113 if (items == null) { 114 items = new ArrayList<DeliveryReportItem>(1); 115 items.add(new DeliveryReportItem("", getString(R.string.status_none))); 116 Log.w(LOG_TAG, "cursor == null"); 117 } 118 setListAdapter(new DeliveryReportAdapter(this, items)); 119 } 120 121 @Override 122 public void onResume() { 123 super.onResume(); 124 refreshDeliveryReport(); 125 } 126 127 private void refreshDeliveryReport() { 128 ListView list = getListView(); 129 list.invalidateViews(); 130 list.requestFocus(); 131 } 132 133 private long getMessageId(Bundle icicle, Intent intent) { 134 long msgId = 0L; 135 136 if (icicle != null) { 137 msgId = icicle.getLong("message_id"); 138 } 139 140 if (msgId == 0L) { 141 msgId = intent.getLongExtra("message_id", 0L); 142 } 143 144 return msgId; 145 } 146 147 private String getMessageType(Bundle icicle, Intent intent) { 148 String msgType = null; 149 150 if (icicle != null) { 151 msgType = icicle.getString("message_type"); 152 } 153 154 if (msgType == null) { 155 msgType = intent.getStringExtra("message_type"); 156 } 157 158 return msgType; 159 } 160 161 private List<DeliveryReportItem> getReportItems() { 162 if (mMessageType.equals("sms")) { 163 return getSmsReportItems(); 164 } else { 165 return getMmsReportItems(); 166 } 167 } 168 169 private List<DeliveryReportItem> getSmsReportItems() { 170 String selection = "_id = " + mMessageId; 171 Cursor c = SqliteWrapper.query(this, getContentResolver(), Sms.CONTENT_URI, 172 SMS_REPORT_STATUS_PROJECTION, selection, null, null); 173 if (c == null) { 174 return null; 175 } 176 177 try { 178 if (c.getCount() <= 0) { 179 return null; 180 } 181 182 List<DeliveryReportItem> items = new ArrayList<DeliveryReportItem>(); 183 while (c.moveToNext()) { 184 items.add(new DeliveryReportItem( 185 getString(R.string.recipient_label) + c.getString(COLUMN_RECIPIENT), 186 getString(R.string.status_label) + 187 getSmsStatusText(c.getInt(COLUMN_DELIVERY_STATUS)))); 188 } 189 return items; 190 } finally { 191 c.close(); 192 } 193 } 194 195 private String getMmsReportStatusText( 196 MmsReportRequest request, 197 Map<String, MmsReportStatus> reportStatus) { 198 if (reportStatus == null) { 199 // haven't received any reports. 200 return getString(R.string.status_pending); 201 } 202 203 String recipient = request.getRecipient(); 204 recipient = (Mms.isEmailAddress(recipient))? 205 Mms.extractAddrSpec(recipient): Recipient.filterPhoneNumber(recipient); 206 MmsReportStatus status = queryStatusByRecipient(reportStatus, recipient); 207 if (status == null) { 208 // haven't received any reports. 209 return getString(R.string.status_pending); 210 } 211 212 if (request.isReadReportRequested()) { 213 if (status.readStatus != 0) { 214 switch (status.readStatus) { 215 case PduHeaders.READ_STATUS_READ: 216 return getString(R.string.status_read); 217 case PduHeaders.READ_STATUS__DELETED_WITHOUT_BEING_READ: 218 return getString(R.string.status_unread); 219 } 220 } 221 } 222 223 switch (status.deliveryStatus) { 224 case 0: // No delivery report received so far. 225 return getString(R.string.status_pending); 226 case PduHeaders.STATUS_FORWARDED: 227 case PduHeaders.STATUS_RETRIEVED: 228 return getString(R.string.status_received); 229 case PduHeaders.STATUS_REJECTED: 230 return getString(R.string.status_rejected); 231 default: 232 return getString(R.string.status_failed); 233 } 234 } 235 236 private static MmsReportStatus queryStatusByRecipient( 237 Map<String, MmsReportStatus> status, String recipient) { 238 Set<String> recipientSet = status.keySet(); 239 Iterator<String> iterator = recipientSet.iterator(); 240 while (iterator.hasNext()) { 241 String r = iterator.next(); 242 if (Mms.isEmailAddress(recipient)) { 243 if (TextUtils.equals(r, recipient)) { 244 return status.get(r); 245 } 246 } 247 else if (PhoneNumberUtils.compare(r, recipient)) { 248 return status.get(r); 249 } 250 } 251 return null; 252 } 253 254 private List<DeliveryReportItem> getMmsReportItems() { 255 List<MmsReportRequest> reportReqs = getMmsReportRequests(); 256 if (null == reportReqs) { 257 return null; 258 } 259 260 if (reportReqs.size() == 0) { 261 return null; 262 } 263 264 Map<String, MmsReportStatus> reportStatus = getMmsReportStatus(); 265 List<DeliveryReportItem> items = new ArrayList<DeliveryReportItem>(); 266 for (MmsReportRequest reportReq : reportReqs) { 267 String statusText = getString(R.string.status_label) + 268 getMmsReportStatusText(reportReq, reportStatus); 269 items.add(new DeliveryReportItem(getString(R.string.recipient_label) + 270 reportReq.getRecipient(), statusText)); 271 } 272 return items; 273 } 274 275 private Map<String, MmsReportStatus> getMmsReportStatus() { 276 Uri uri = Uri.withAppendedPath(Mms.REPORT_STATUS_URI, 277 String.valueOf(mMessageId)); 278 Cursor c = SqliteWrapper.query(this, getContentResolver(), uri, 279 MMS_REPORT_STATUS_PROJECTION, null, null, null); 280 281 if (c == null) { 282 return null; 283 } 284 285 try { 286 Map<String, MmsReportStatus> statusMap = 287 new HashMap<String, MmsReportStatus>(); 288 289 while (c.moveToNext()) { 290 String recipient = c.getString(COLUMN_RECIPIENT); 291 recipient = (Mms.isEmailAddress(recipient))? 292 Mms.extractAddrSpec(recipient): 293 Recipient.filterPhoneNumber(recipient); 294 MmsReportStatus status = new MmsReportStatus( 295 c.getInt(COLUMN_DELIVERY_STATUS), 296 c.getInt(COLUMN_READ_STATUS)); 297 statusMap.put(recipient, status); 298 } 299 return statusMap; 300 } finally { 301 c.close(); 302 } 303 } 304 305 private List<MmsReportRequest> getMmsReportRequests() { 306 Uri uri = Uri.withAppendedPath(Mms.REPORT_REQUEST_URI, 307 String.valueOf(mMessageId)); 308 Cursor c = SqliteWrapper.query(this, getContentResolver(), uri, 309 MMS_REPORT_REQUEST_PROJECTION, null, null, null); 310 311 if (c == null) { 312 return null; 313 } 314 315 try { 316 if (c.getCount() <= 0) { 317 return null; 318 } 319 320 List<MmsReportRequest> reqList = new ArrayList<MmsReportRequest>(); 321 while (c.moveToNext()) { 322 reqList.add(new MmsReportRequest( 323 c.getString(COLUMN_RECIPIENT), 324 c.getInt(COLUMN_DELIVERY_REPORT), 325 c.getInt(COLUMN_READ_REPORT))); 326 } 327 return reqList; 328 } finally { 329 c.close(); 330 } 331 } 332 333 private String getSmsStatusText(int status) { 334 if (status == Sms.STATUS_NONE) { 335 // No delivery report requested 336 return getString(R.string.status_none); 337 } else if (status >= Sms.STATUS_FAILED) { 338 // Failure 339 return getString(R.string.status_failed); 340 } else if (status >= Sms.STATUS_PENDING) { 341 // Pending 342 return getString(R.string.status_pending); 343 } else { 344 // Success 345 return getString(R.string.status_received); 346 } 347 } 348 349 private static final class MmsReportStatus { 350 final int deliveryStatus; 351 final int readStatus; 352 353 public MmsReportStatus(int drStatus, int rrStatus) { 354 deliveryStatus = drStatus; 355 readStatus = rrStatus; 356 } 357 } 358 359 private static final class MmsReportRequest { 360 private final String mRecipient; 361 private final boolean mIsDeliveryReportRequsted; 362 private final boolean mIsReadReportRequested; 363 364 public MmsReportRequest(String recipient, int drValue, int rrValue) { 365 mRecipient = recipient; 366 mIsDeliveryReportRequsted = drValue == PduHeaders.VALUE_YES; 367 mIsReadReportRequested = rrValue == PduHeaders.VALUE_YES; 368 } 369 370 public String getRecipient() { 371 return mRecipient; 372 } 373 374 public boolean isDeliveryReportRequested() { 375 return mIsDeliveryReportRequsted; 376 } 377 378 public boolean isReadReportRequested() { 379 return mIsReadReportRequested; 380 } 381 } 382} 383