SmsManager.java revision 54fa5c2393b8f9c75a946a05dc0dfe650574b7d8
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.telephony; 18 19import android.app.ActivityThread; 20import android.app.PendingIntent; 21import android.content.ContentValues; 22import android.content.Context; 23import android.content.Intent; 24import android.net.Uri; 25import android.os.Bundle; 26import android.os.RemoteException; 27import android.os.ServiceManager; 28import android.provider.Telephony; 29import android.text.TextUtils; 30import android.util.ArrayMap; 31import android.util.Log; 32 33import com.android.internal.telephony.ISms; 34import com.android.internal.telephony.SmsRawData; 35import com.android.internal.telephony.IMms; 36import com.android.internal.telephony.uicc.IccConstants; 37 38import java.util.ArrayList; 39import java.util.Arrays; 40import java.util.List; 41import java.util.Map; 42 43/* 44 * TODO(code review): Curious question... Why are a lot of these 45 * methods not declared as static, since they do not seem to require 46 * any local object state? Presumably this cannot be changed without 47 * interfering with the API... 48 */ 49 50/** 51 * Manages SMS operations such as sending data, text, and pdu SMS messages. 52 * Get this object by calling the static method {@link #getDefault()}. 53 * 54 * <p>For information about how to behave as the default SMS app on Android 4.4 (API level 19) 55 * and higher, see {@link android.provider.Telephony}. 56 */ 57public final class SmsManager { 58 /** 59 * A psuedo-subId that represents the default subId at any given time. The actual subId it 60 * represents changes as the default subId is changed. 61 */ 62 private static final int DEFAULT_SUB_ID = -1002; 63 64 /** Singleton object constructed during class initialization. */ 65 private static final SmsManager sInstance = new SmsManager(DEFAULT_SUB_ID); 66 private static final Object sLockObject = new Object(); 67 private static final Map<Integer, SmsManager> sSubInstances = new ArrayMap<Integer, SmsManager>(); 68 /** @hide */ 69 public static final int CELL_BROADCAST_RAN_TYPE_GSM = 0; 70 /** @hide */ 71 public static final int CELL_BROADCAST_RAN_TYPE_CDMA = 1; 72 /** A concrete subId, or the pseudo DEFAULT_SUB_ID */ 73 private int mSubId; 74 75 /* 76 * Key for the various carrier-dependent configuration values. 77 * Some of the values are used by the system in processing SMS or MMS messages. Others 78 * are provided for the convenience of SMS applications. 79 */ 80 81 /** 82 * Whether to append transaction id to MMS WAP Push M-Notification.ind's content location URI 83 * when constructing the download URL of a new MMS (boolean type) 84 */ 85 public static final String MMS_CONFIG_APPEND_TRANSACTION_ID = "enabledTransID"; 86 /** 87 * Whether MMS is enabled for the current carrier (boolean type) 88 */ 89 public static final String MMS_CONFIG_MMS_ENABLED = "enabledMMS"; 90 /** 91 * Whether group MMS is enabled for the current carrier (boolean type) 92 */ 93 public static final String MMS_CONFIG_GROUP_MMS_ENABLED = "enableGroupMms"; 94 /** 95 * If this is enabled, M-NotifyResp.ind should be sent to the WAP Push content location 96 * instead of the default MMSC (boolean type) 97 */ 98 public static final String MMS_CONFIG_NOTIFY_WAP_MMSC_ENABLED = "enabledNotifyWapMMSC"; 99 /** 100 * Whether alias is enabled (boolean type) 101 */ 102 public static final String MMS_CONFIG_ALIAS_ENABLED = "aliasEnabled"; 103 /** 104 * Whether audio is allowed to be attached for MMS messages (boolean type) 105 */ 106 public static final String MMS_CONFIG_ALLOW_ATTACH_AUDIO = "allowAttachAudio"; 107 /** 108 * Whether multipart SMS is enabled (boolean type) 109 */ 110 public static final String MMS_CONFIG_MULTIPART_SMS_ENABLED = "enableMultipartSMS"; 111 /** 112 * Whether SMS delivery report is enabled (boolean type) 113 */ 114 public static final String MMS_CONFIG_SMS_DELIVERY_REPORT_ENABLED = "enableSMSDeliveryReports"; 115 /** 116 * Whether content-disposition field should be expected in an MMS PDU (boolean type) 117 */ 118 public static final String MMS_CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION = 119 "supportMmsContentDisposition"; 120 /** 121 * Whether multipart SMS should be sent as separate messages 122 */ 123 public static final String MMS_CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES = 124 "sendMultipartSmsAsSeparateMessages"; 125 /** 126 * Whether MMS read report is enabled (boolean type) 127 */ 128 public static final String MMS_CONFIG_MMS_READ_REPORT_ENABLED = "enableMMSReadReports"; 129 /** 130 * Whether MMS delivery report is enabled (boolean type) 131 */ 132 public static final String MMS_CONFIG_MMS_DELIVERY_REPORT_ENABLED = "enableMMSDeliveryReports"; 133 /** 134 * Max MMS message size in bytes (int type) 135 */ 136 public static final String MMS_CONFIG_MAX_MESSAGE_SIZE = "maxMessageSize"; 137 /** 138 * Max MMS image width (int type) 139 */ 140 public static final String MMS_CONFIG_MAX_IMAGE_WIDTH = "maxImageWidth"; 141 /** 142 * Max MMS image height (int type) 143 */ 144 public static final String MMS_CONFIG_MAX_IMAGE_HEIGHT = "maxImageHeight"; 145 /** 146 * Limit of recipients of MMS messages (int type) 147 */ 148 public static final String MMS_CONFIG_RECIPIENT_LIMIT = "recipientLimit"; 149 /** 150 * Min alias character count (int type) 151 */ 152 public static final String MMS_CONFIG_ALIAS_MIN_CHARS = "aliasMinChars"; 153 /** 154 * Max alias character count (int type) 155 */ 156 public static final String MMS_CONFIG_ALIAS_MAX_CHARS = "aliasMaxChars"; 157 /** 158 * When the number of parts of a multipart SMS reaches this threshold, it should be 159 * converted into an MMS (int type) 160 */ 161 public static final String MMS_CONFIG_SMS_TO_MMS_TEXT_THRESHOLD = "smsToMmsTextThreshold"; 162 /** 163 * Some carriers require SMS to be converted into MMS when text length reaches this threshold 164 * (int type) 165 */ 166 public static final String MMS_CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD = 167 "smsToMmsTextLengthThreshold"; 168 /** 169 * Max message text size (int type) 170 */ 171 public static final String MMS_CONFIG_MESSAGE_TEXT_MAX_SIZE = "maxMessageTextSize"; 172 /** 173 * Max message subject length (int type) 174 */ 175 public static final String MMS_CONFIG_SUBJECT_MAX_LENGTH = "maxSubjectLength"; 176 /** 177 * MMS HTTP socket timeout in milliseconds (int type) 178 */ 179 public static final String MMS_CONFIG_HTTP_SOCKET_TIMEOUT = "httpSocketTimeout"; 180 /** 181 * The name of the UA Prof URL HTTP header for MMS HTTP request (String type) 182 */ 183 public static final String MMS_CONFIG_UA_PROF_TAG_NAME = "uaProfTagName"; 184 /** 185 * The User-Agent header value for MMS HTTP request (String type) 186 */ 187 public static final String MMS_CONFIG_USER_AGENT = "userAgent"; 188 /** 189 * The UA Profile URL header value for MMS HTTP request (String type) 190 */ 191 public static final String MMS_CONFIG_UA_PROF_URL = "uaProfUrl"; 192 /** 193 * A list of HTTP headers to add to MMS HTTP request, separated by "|" (String type) 194 */ 195 public static final String MMS_CONFIG_HTTP_PARAMS = "httpParams"; 196 /** 197 * Email gateway number (String type) 198 */ 199 public static final String MMS_CONFIG_EMAIL_GATEWAY_NUMBER = "emailGatewayNumber"; 200 /** 201 * The suffix to append to the NAI header value for MMS HTTP request (String type) 202 */ 203 public static final String MMS_CONFIG_NAI_SUFFIX = "naiSuffix"; 204 /** 205 * If true, show the cell broadcast (amber alert) in the SMS settings. Some carriers 206 * don't want this shown. 207 */ 208 public static final String MMS_SHOW_CELL_BROADCAST_APP_LINKS = "config_cellBroadcastAppLinks"; 209 210 /** 211 * Send a text based SMS. 212 * 213 * <p class="note"><strong>Note:</strong> Using this method requires that your app has the 214 * {@link android.Manifest.permission#SEND_SMS} permission.</p> 215 * 216 * <p class="note"><strong>Note:</strong> Beginning with Android 4.4 (API level 19), if 217 * <em>and only if</em> an app is not selected as the default SMS app, the system automatically 218 * writes messages sent using this method to the SMS Provider (the default SMS app is always 219 * responsible for writing its sent messages to the SMS Provider). For information about 220 * how to behave as the default SMS app, see {@link android.provider.Telephony}.</p> 221 * 222 * 223 * @param destinationAddress the address to send the message to 224 * @param scAddress is the service center address or null to use 225 * the current default SMSC 226 * @param text the body of the message to send 227 * @param sentIntent if not NULL this <code>PendingIntent</code> is 228 * broadcast when the message is successfully sent, or failed. 229 * The result code will be <code>Activity.RESULT_OK</code> for success, 230 * or one of these errors:<br> 231 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 232 * <code>RESULT_ERROR_RADIO_OFF</code><br> 233 * <code>RESULT_ERROR_NULL_PDU</code><br> 234 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 235 * the extra "errorCode" containing a radio technology specific value, 236 * generally only useful for troubleshooting.<br> 237 * The per-application based SMS control checks sentIntent. If sentIntent 238 * is NULL the caller will be checked against all unknown applications, 239 * which cause smaller number of SMS to be sent in checking period. 240 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 241 * broadcast when the message is delivered to the recipient. The 242 * raw pdu of the status report is in the extended data ("pdu"). 243 * 244 * @throws IllegalArgumentException if destinationAddress or text are empty 245 */ 246 public void sendTextMessage( 247 String destinationAddress, String scAddress, String text, 248 PendingIntent sentIntent, PendingIntent deliveryIntent) { 249 if (TextUtils.isEmpty(destinationAddress)) { 250 throw new IllegalArgumentException("Invalid destinationAddress"); 251 } 252 253 if (TextUtils.isEmpty(text)) { 254 throw new IllegalArgumentException("Invalid message body"); 255 } 256 257 try { 258 ISms iccISms = getISmsServiceOrThrow(); 259 iccISms.sendTextForSubscriber(getSubId(), ActivityThread.currentPackageName(), 260 destinationAddress, 261 scAddress, text, sentIntent, deliveryIntent); 262 } catch (RemoteException ex) { 263 // ignore it 264 } 265 } 266 267 /** 268 * Inject an SMS PDU into the android application framework. 269 * 270 * The caller should have carrier privileges. 271 * @see android.telephony.TelephonyManager.hasCarrierPrivileges 272 * 273 * @param pdu is the byte array of pdu to be injected into android application framework 274 * @param format is the format of SMS pdu (3gpp or 3gpp2) 275 * @param receivedIntent if not NULL this <code>PendingIntent</code> is 276 * broadcast when the message is successfully received by the 277 * android application framework. This intent is broadcasted at 278 * the same time an SMS received from radio is acknowledged back. 279 * 280 * @throws IllegalArgumentException if format is not one of 3gpp and 3gpp2. 281 */ 282 public void injectSmsPdu(byte[] pdu, String format, PendingIntent receivedIntent) { 283 if (!format.equals(SmsMessage.FORMAT_3GPP) && !format.equals(SmsMessage.FORMAT_3GPP2)) { 284 // Format must be either 3gpp or 3gpp2. 285 throw new IllegalArgumentException( 286 "Invalid pdu format. format must be either 3gpp or 3gpp2"); 287 } 288 try { 289 ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); 290 if (iccISms != null) { 291 iccISms.injectSmsPdu(pdu, format, receivedIntent); 292 } 293 } catch (RemoteException ex) { 294 // ignore it 295 } 296 } 297 298 /** 299 * Update the status of a pending (send-by-IP) SMS message and resend by PSTN if necessary. 300 * This outbound message was handled by the carrier app. If the carrier app fails to send 301 * this message, it would be resent by PSTN. 302 * 303 * The caller should have carrier privileges. 304 * @see android.telephony.TelephonyManager.hasCarrierPrivileges 305 * 306 * @param messageRef the reference number of the SMS message. 307 * @param success True if and only if the message was sent successfully. If its value is 308 * false, this message should be resent via PSTN. 309 */ 310 public void updateSmsSendStatus(int messageRef, boolean success) { 311 try { 312 ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); 313 if (iccISms != null) { 314 iccISms.updateSmsSendStatus(messageRef, success); 315 } 316 } catch (RemoteException ex) { 317 // ignore it 318 } 319 } 320 321 /** 322 * Divide a message text into several fragments, none bigger than 323 * the maximum SMS message size. 324 * 325 * @param text the original message. Must not be null. 326 * @return an <code>ArrayList</code> of strings that, in order, 327 * comprise the original message 328 * 329 * @throws IllegalArgumentException if text is null 330 */ 331 public ArrayList<String> divideMessage(String text) { 332 if (null == text) { 333 throw new IllegalArgumentException("text is null"); 334 } 335 return SmsMessage.fragmentText(text); 336 } 337 338 /** 339 * Send a multi-part text based SMS. The callee should have already 340 * divided the message into correctly sized parts by calling 341 * <code>divideMessage</code>. 342 * 343 * <p class="note"><strong>Note:</strong> Using this method requires that your app has the 344 * {@link android.Manifest.permission#SEND_SMS} permission.</p> 345 * 346 * <p class="note"><strong>Note:</strong> Beginning with Android 4.4 (API level 19), if 347 * <em>and only if</em> an app is not selected as the default SMS app, the system automatically 348 * writes messages sent using this method to the SMS Provider (the default SMS app is always 349 * responsible for writing its sent messages to the SMS Provider). For information about 350 * how to behave as the default SMS app, see {@link android.provider.Telephony}.</p> 351 * 352 * @param destinationAddress the address to send the message to 353 * @param scAddress is the service center address or null to use 354 * the current default SMSC 355 * @param parts an <code>ArrayList</code> of strings that, in order, 356 * comprise the original message 357 * @param sentIntents if not null, an <code>ArrayList</code> of 358 * <code>PendingIntent</code>s (one for each message part) that is 359 * broadcast when the corresponding message part has been sent. 360 * The result code will be <code>Activity.RESULT_OK</code> for success, 361 * or one of these errors:<br> 362 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 363 * <code>RESULT_ERROR_RADIO_OFF</code><br> 364 * <code>RESULT_ERROR_NULL_PDU</code><br> 365 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> each sentIntent may include 366 * the extra "errorCode" containing a radio technology specific value, 367 * generally only useful for troubleshooting.<br> 368 * The per-application based SMS control checks sentIntent. If sentIntent 369 * is NULL the caller will be checked against all unknown applications, 370 * which cause smaller number of SMS to be sent in checking period. 371 * @param deliveryIntents if not null, an <code>ArrayList</code> of 372 * <code>PendingIntent</code>s (one for each message part) that is 373 * broadcast when the corresponding message part has been delivered 374 * to the recipient. The raw pdu of the status report is in the 375 * extended data ("pdu"). 376 * 377 * @throws IllegalArgumentException if destinationAddress or data are empty 378 */ 379 public void sendMultipartTextMessage( 380 String destinationAddress, String scAddress, ArrayList<String> parts, 381 ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) { 382 if (TextUtils.isEmpty(destinationAddress)) { 383 throw new IllegalArgumentException("Invalid destinationAddress"); 384 } 385 if (parts == null || parts.size() < 1) { 386 throw new IllegalArgumentException("Invalid message body"); 387 } 388 389 if (parts.size() > 1) { 390 try { 391 ISms iccISms = getISmsServiceOrThrow(); 392 iccISms.sendMultipartTextForSubscriber(getSubId(), 393 ActivityThread.currentPackageName(), 394 destinationAddress, scAddress, parts, 395 sentIntents, deliveryIntents); 396 } catch (RemoteException ex) { 397 // ignore it 398 } 399 } else { 400 PendingIntent sentIntent = null; 401 PendingIntent deliveryIntent = null; 402 if (sentIntents != null && sentIntents.size() > 0) { 403 sentIntent = sentIntents.get(0); 404 } 405 if (deliveryIntents != null && deliveryIntents.size() > 0) { 406 deliveryIntent = deliveryIntents.get(0); 407 } 408 sendTextMessage(destinationAddress, scAddress, parts.get(0), 409 sentIntent, deliveryIntent); 410 } 411 } 412 413 /** 414 * Send a data based SMS to a specific application port. 415 * 416 * <p class="note"><strong>Note:</strong> Using this method requires that your app has the 417 * {@link android.Manifest.permission#SEND_SMS} permission.</p> 418 * 419 * @param destinationAddress the address to send the message to 420 * @param scAddress is the service center address or null to use 421 * the current default SMSC 422 * @param destinationPort the port to deliver the message to 423 * @param data the body of the message to send 424 * @param sentIntent if not NULL this <code>PendingIntent</code> is 425 * broadcast when the message is successfully sent, or failed. 426 * The result code will be <code>Activity.RESULT_OK</code> for success, 427 * or one of these errors:<br> 428 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 429 * <code>RESULT_ERROR_RADIO_OFF</code><br> 430 * <code>RESULT_ERROR_NULL_PDU</code><br> 431 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 432 * the extra "errorCode" containing a radio technology specific value, 433 * generally only useful for troubleshooting.<br> 434 * The per-application based SMS control checks sentIntent. If sentIntent 435 * is NULL the caller will be checked against all unknown applications, 436 * which cause smaller number of SMS to be sent in checking period. 437 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 438 * broadcast when the message is delivered to the recipient. The 439 * raw pdu of the status report is in the extended data ("pdu"). 440 * 441 * @throws IllegalArgumentException if destinationAddress or data are empty 442 */ 443 public void sendDataMessage( 444 String destinationAddress, String scAddress, short destinationPort, 445 byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) { 446 if (TextUtils.isEmpty(destinationAddress)) { 447 throw new IllegalArgumentException("Invalid destinationAddress"); 448 } 449 450 if (data == null || data.length == 0) { 451 throw new IllegalArgumentException("Invalid message data"); 452 } 453 454 try { 455 ISms iccISms = getISmsServiceOrThrow(); 456 iccISms.sendDataForSubscriber(getSubId(), ActivityThread.currentPackageName(), 457 destinationAddress, scAddress, destinationPort & 0xFFFF, 458 data, sentIntent, deliveryIntent); 459 } catch (RemoteException ex) { 460 // ignore it 461 } 462 } 463 464 /** 465 * Get the SmsManager associated with the default subId. The instance will always be 466 * associated with the default subId, even if the default subId is changed. 467 * 468 * @return the SmsManager associated with the default subId 469 */ 470 public static SmsManager getDefault() { 471 return sInstance; 472 } 473 474 /** 475 * Get the the instance of the SmsManager associated with a particular subId 476 * 477 * @param subId a SMS subscription id, typically accessed using 478 * {@link android.telephony.SubscriptionManager} 479 * @return the instance of the SmsManager associated with subId 480 */ 481 public static SmsManager getSmsManagerForSubscriber(int subId) { 482 // TODO(shri): Add javadoc link once SubscriptionManager is made public api 483 synchronized(sLockObject) { 484 SmsManager smsManager = sSubInstances.get(subId); 485 if (smsManager == null) { 486 smsManager = new SmsManager(subId); 487 sSubInstances.put(subId, smsManager); 488 } 489 return smsManager; 490 } 491 } 492 493 private SmsManager(int subId) { 494 mSubId = subId; 495 } 496 497 /** 498 * Get the associated subId. If the instance was returned by {@link #getDefault()}, then this 499 * method may return different values at different points in time (if the user changes the 500 * default subId). It will return {@link android.telephony.SubscriptionManager#INVALID_SUB_ID} 501 * if the default subId cannot be determined. 502 * 503 * @return associated subId 504 */ 505 public int getSubId() { 506 if (mSubId == DEFAULT_SUB_ID) { 507 return getDefaultSmsSubscriptionId(); 508 } 509 return mSubId; 510 } 511 512 /** 513 * Returns the ISms service, or throws an UnsupportedOperationException if 514 * the service does not exist. 515 */ 516 private static ISms getISmsServiceOrThrow() { 517 ISms iccISms = getISmsService(); 518 if (iccISms == null) { 519 throw new UnsupportedOperationException("Sms is not supported"); 520 } 521 return iccISms; 522 } 523 524 private static ISms getISmsService() { 525 return ISms.Stub.asInterface(ServiceManager.getService("isms")); 526 } 527 528 /** 529 * Copy a raw SMS PDU to the ICC. 530 * ICC (Integrated Circuit Card) is the card of the device. 531 * For example, this can be the SIM or USIM for GSM. 532 * 533 * @param smsc the SMSC for this message, or NULL for the default SMSC 534 * @param pdu the raw PDU to store 535 * @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD, 536 * STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT) 537 * @return true for success 538 * 539 * @throws IllegalArgumentException if pdu is NULL 540 * {@hide} 541 */ 542 public boolean copyMessageToIcc(byte[] smsc, byte[] pdu,int status) { 543 boolean success = false; 544 545 if (null == pdu) { 546 throw new IllegalArgumentException("pdu is NULL"); 547 } 548 try { 549 ISms iccISms = getISmsService(); 550 if (iccISms != null) { 551 success = iccISms.copyMessageToIccEfForSubscriber(getSubId(), 552 ActivityThread.currentPackageName(), 553 status, pdu, smsc); 554 } 555 } catch (RemoteException ex) { 556 // ignore it 557 } 558 559 return success; 560 } 561 562 /** 563 * Delete the specified message from the ICC. 564 * ICC (Integrated Circuit Card) is the card of the device. 565 * For example, this can be the SIM or USIM for GSM. 566 * 567 * @param messageIndex is the record index of the message on ICC 568 * @return true for success 569 * 570 * {@hide} 571 */ 572 public boolean 573 deleteMessageFromIcc(int messageIndex) { 574 boolean success = false; 575 byte[] pdu = new byte[IccConstants.SMS_RECORD_LENGTH-1]; 576 Arrays.fill(pdu, (byte)0xff); 577 578 try { 579 ISms iccISms = getISmsService(); 580 if (iccISms != null) { 581 success = iccISms.updateMessageOnIccEfForSubscriber(getSubId(), 582 ActivityThread.currentPackageName(), 583 messageIndex, STATUS_ON_ICC_FREE, pdu); 584 } 585 } catch (RemoteException ex) { 586 // ignore it 587 } 588 589 return success; 590 } 591 592 /** 593 * Update the specified message on the ICC. 594 * ICC (Integrated Circuit Card) is the card of the device. 595 * For example, this can be the SIM or USIM for GSM. 596 * 597 * @param messageIndex record index of message to update 598 * @param newStatus new message status (STATUS_ON_ICC_READ, 599 * STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT, 600 * STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE) 601 * @param pdu the raw PDU to store 602 * @return true for success 603 * 604 * {@hide} 605 */ 606 public boolean updateMessageOnIcc(int messageIndex, int newStatus, byte[] pdu) { 607 boolean success = false; 608 609 try { 610 ISms iccISms = getISmsService(); 611 if (iccISms != null) { 612 success = iccISms.updateMessageOnIccEfForSubscriber(getSubId(), 613 ActivityThread.currentPackageName(), 614 messageIndex, newStatus, pdu); 615 } 616 } catch (RemoteException ex) { 617 // ignore it 618 } 619 620 return success; 621 } 622 623 /** 624 * Retrieves all messages currently stored on ICC. 625 * ICC (Integrated Circuit Card) is the card of the device. 626 * For example, this can be the SIM or USIM for GSM. 627 * 628 * @return <code>ArrayList</code> of <code>SmsMessage</code> objects 629 * 630 * {@hide} 631 */ 632 public static ArrayList<SmsMessage> getAllMessagesFromIcc() { 633 List<SmsRawData> records = null; 634 635 try { 636 ISms iccISms = getISmsService(); 637 if (iccISms != null) { 638 records = iccISms.getAllMessagesFromIccEfForSubscriber(getDefault().getSubId(), 639 ActivityThread.currentPackageName()); 640 } 641 } catch (RemoteException ex) { 642 // ignore it 643 } 644 645 return createMessageListFromRawRecords(records); 646 } 647 648 /** 649 * Enable reception of cell broadcast (SMS-CB) messages with the given 650 * message identifier and RAN type. The RAN type specify this message ID 651 * belong to 3GPP (GSM) or 3GPP2(CDMA).Note that if two different clients 652 * enable the same message identifier, they must both disable it for the device to stop 653 * receiving those messages. All received messages will be broadcast in an 654 * intent with the action "android.provider.Telephony.SMS_CB_RECEIVED". 655 * Note: This call is blocking, callers may want to avoid calling it from 656 * the main thread of an application. 657 * 658 * @param messageIdentifier Message identifier as specified in TS 23.041 (3GPP) 659 * or C.R1001-G (3GPP2) 660 * @param ranType as defined in class SmsManager, the value can be one of these: 661 * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM 662 * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA 663 * @return true if successful, false otherwise 664 * @see #disableCellBroadcast(int, int) 665 * 666 * {@hide} 667 */ 668 public boolean enableCellBroadcast(int messageIdentifier, int ranType) { 669 boolean success = false; 670 671 try { 672 ISms iccISms = getISmsService(); 673 if (iccISms != null) { 674 success = iccISms.enableCellBroadcastForSubscriber(getSubId(), messageIdentifier, 675 ranType); 676 } 677 } catch (RemoteException ex) { 678 // ignore it 679 } 680 681 return success; 682 } 683 684 /** 685 * Disable reception of cell broadcast (SMS-CB) messages with the given 686 * message identifier and RAN type. The RAN type specify this message ID 687 * belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different clients 688 * enable the same message identifier, they must both disable it for the 689 * device to stop receiving those messages. 690 * Note: This call is blocking, callers may want to avoid calling it from 691 * the main thread of an application. 692 * 693 * @param messageIdentifier Message identifier as specified in TS 23.041 (3GPP) 694 * or C.R1001-G (3GPP2) 695 * @param ranType as defined in class SmsManager, the value can be one of these: 696 * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM 697 * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA 698 * @return true if successful, false otherwise 699 * 700 * @see #enableCellBroadcast(int, int) 701 * 702 * {@hide} 703 */ 704 public boolean disableCellBroadcast(int messageIdentifier, int ranType) { 705 boolean success = false; 706 707 try { 708 ISms iccISms = getISmsService(); 709 if (iccISms != null) { 710 success = iccISms.disableCellBroadcastForSubscriber(getSubId(), messageIdentifier, 711 ranType); 712 } 713 } catch (RemoteException ex) { 714 // ignore it 715 } 716 717 return success; 718 } 719 720 /** 721 * Enable reception of cell broadcast (SMS-CB) messages with the given 722 * message identifier range and RAN type. The RAN type specify this message ID 723 * belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different clients enable 724 * the same message identifier, they must both disable it for the device to stop 725 * receiving those messages. All received messages will be broadcast in an 726 * intent with the action "android.provider.Telephony.SMS_CB_RECEIVED". 727 * Note: This call is blocking, callers may want to avoid calling it from 728 * the main thread of an application. 729 * 730 * @param startMessageId first message identifier as specified in TS 23.041 (3GPP) 731 * or C.R1001-G (3GPP2) 732 * @param endMessageId last message identifier as specified in TS 23.041 (3GPP) 733 * or C.R1001-G (3GPP2) 734 * @param ranType as defined in class SmsManager, the value can be one of these: 735 * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM 736 * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA 737 * @return true if successful, false otherwise 738 * @see #disableCellBroadcastRange(int, int, int) 739 * 740 * @throws IllegalArgumentException if endMessageId < startMessageId 741 * {@hide} 742 */ 743 public boolean enableCellBroadcastRange(int startMessageId, int endMessageId, int ranType) { 744 boolean success = false; 745 746 if (endMessageId < startMessageId) { 747 throw new IllegalArgumentException("endMessageId < startMessageId"); 748 } 749 try { 750 ISms iccISms = getISmsService(); 751 if (iccISms != null) { 752 success = iccISms.enableCellBroadcastRangeForSubscriber(getSubId(), 753 startMessageId, endMessageId, ranType); 754 } 755 } catch (RemoteException ex) { 756 // ignore it 757 } 758 759 return success; 760 } 761 762 /** 763 * Disable reception of cell broadcast (SMS-CB) messages with the given 764 * message identifier range and RAN type. The RAN type specify this message 765 * ID range belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different 766 * clients enable the same message identifier, they must both disable it for 767 * the device to stop receiving those messages. 768 * Note: This call is blocking, callers may want to avoid calling it from 769 * the main thread of an application. 770 * 771 * @param startMessageId first message identifier as specified in TS 23.041 (3GPP) 772 * or C.R1001-G (3GPP2) 773 * @param endMessageId last message identifier as specified in TS 23.041 (3GPP) 774 * or C.R1001-G (3GPP2) 775 * @param ranType as defined in class SmsManager, the value can be one of these: 776 * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM 777 * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA 778 * @return true if successful, false otherwise 779 * 780 * @see #enableCellBroadcastRange(int, int, int) 781 * 782 * @throws IllegalArgumentException if endMessageId < startMessageId 783 * {@hide} 784 */ 785 public boolean disableCellBroadcastRange(int startMessageId, int endMessageId, int ranType) { 786 boolean success = false; 787 788 if (endMessageId < startMessageId) { 789 throw new IllegalArgumentException("endMessageId < startMessageId"); 790 } 791 try { 792 ISms iccISms = getISmsService(); 793 if (iccISms != null) { 794 success = iccISms.disableCellBroadcastRangeForSubscriber(getSubId(), 795 startMessageId, endMessageId, ranType); 796 } 797 } catch (RemoteException ex) { 798 // ignore it 799 } 800 801 return success; 802 } 803 804 /** 805 * Create a list of <code>SmsMessage</code>s from a list of RawSmsData 806 * records returned by <code>getAllMessagesFromIcc()</code> 807 * 808 * @param records SMS EF records, returned by 809 * <code>getAllMessagesFromIcc</code> 810 * @return <code>ArrayList</code> of <code>SmsMessage</code> objects. 811 */ 812 private static ArrayList<SmsMessage> createMessageListFromRawRecords(List<SmsRawData> records) { 813 ArrayList<SmsMessage> messages = new ArrayList<SmsMessage>(); 814 if (records != null) { 815 int count = records.size(); 816 for (int i = 0; i < count; i++) { 817 SmsRawData data = records.get(i); 818 // List contains all records, including "free" records (null) 819 if (data != null) { 820 SmsMessage sms = SmsMessage.createFromEfRecord(i+1, data.getBytes()); 821 if (sms != null) { 822 messages.add(sms); 823 } 824 } 825 } 826 } 827 return messages; 828 } 829 830 /** 831 * SMS over IMS is supported if IMS is registered and SMS is supported 832 * on IMS. 833 * 834 * @return true if SMS over IMS is supported, false otherwise 835 * 836 * @see #getImsSmsFormat() 837 * 838 * @hide 839 */ 840 public boolean isImsSmsSupported() { 841 boolean boSupported = false; 842 try { 843 ISms iccISms = getISmsService(); 844 if (iccISms != null) { 845 boSupported = iccISms.isImsSmsSupportedForSubscriber(getSubId()); 846 } 847 } catch (RemoteException ex) { 848 // ignore it 849 } 850 return boSupported; 851 } 852 853 /** 854 * Gets SMS format supported on IMS. SMS over IMS format is 855 * either 3GPP or 3GPP2. 856 * 857 * @return SmsMessage.FORMAT_3GPP, 858 * SmsMessage.FORMAT_3GPP2 859 * or SmsMessage.FORMAT_UNKNOWN 860 * 861 * @see #isImsSmsSupported() 862 * 863 * @hide 864 */ 865 public String getImsSmsFormat() { 866 String format = com.android.internal.telephony.SmsConstants.FORMAT_UNKNOWN; 867 try { 868 ISms iccISms = getISmsService(); 869 if (iccISms != null) { 870 format = iccISms.getImsSmsFormatForSubscriber(getSubId()); 871 } 872 } catch (RemoteException ex) { 873 // ignore it 874 } 875 return format; 876 } 877 878 /** 879 * Get default sms subId 880 * 881 * @return the default SubId 882 */ 883 public static int getDefaultSmsSubscriptionId() { 884 ISms iccISms = null; 885 try { 886 iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); 887 return iccISms.getPreferredSmsSubscription(); 888 } catch (RemoteException ex) { 889 return SubscriptionManager.INVALID_SUB_ID; 890 } catch (NullPointerException ex) { 891 return SubscriptionManager.INVALID_SUB_ID; 892 } 893 } 894 895 /** 896 * Get SMS prompt property, enabled or not 897 * 898 * @return true if enabled, false otherwise 899 * @hide 900 */ 901 public boolean isSMSPromptEnabled() { 902 ISms iccISms = null; 903 try { 904 iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); 905 return iccISms.isSMSPromptEnabled(); 906 } catch (RemoteException ex) { 907 return false; 908 } catch (NullPointerException ex) { 909 return false; 910 } 911 } 912 913 // see SmsMessage.getStatusOnIcc 914 915 /** Free space (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 916 static public final int STATUS_ON_ICC_FREE = 0; 917 918 /** Received and read (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 919 static public final int STATUS_ON_ICC_READ = 1; 920 921 /** Received and unread (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 922 static public final int STATUS_ON_ICC_UNREAD = 3; 923 924 /** Stored and sent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 925 static public final int STATUS_ON_ICC_SENT = 5; 926 927 /** Stored and unsent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 928 static public final int STATUS_ON_ICC_UNSENT = 7; 929 930 // SMS send failure result codes 931 932 /** Generic failure cause */ 933 static public final int RESULT_ERROR_GENERIC_FAILURE = 1; 934 /** Failed because radio was explicitly turned off */ 935 static public final int RESULT_ERROR_RADIO_OFF = 2; 936 /** Failed because no pdu provided */ 937 static public final int RESULT_ERROR_NULL_PDU = 3; 938 /** Failed because service is currently unavailable */ 939 static public final int RESULT_ERROR_NO_SERVICE = 4; 940 /** Failed because we reached the sending queue limit. {@hide} */ 941 static public final int RESULT_ERROR_LIMIT_EXCEEDED = 5; 942 /** Failed because FDN is enabled. {@hide} */ 943 static public final int RESULT_ERROR_FDN_CHECK_FAILURE = 6; 944 945 static private final String PHONE_PACKAGE_NAME = "com.android.phone"; 946 947 /** 948 * Send an MMS message 949 * 950 * @param context application context 951 * @param contentUri the content Uri from which the message pdu will be read 952 * @param locationUrl the optional location url where message should be sent to 953 * @param configOverrides the carrier-specific messaging configuration values to override for 954 * sending the message. 955 * @param sentIntent if not NULL this <code>PendingIntent</code> is 956 * broadcast when the message is successfully sent, or failed 957 * @throws IllegalArgumentException if contentUri is empty 958 */ 959 public void sendMultimediaMessage(Context context, Uri contentUri, String locationUrl, 960 Bundle configOverrides, PendingIntent sentIntent) { 961 if (contentUri == null) { 962 throw new IllegalArgumentException("Uri contentUri null"); 963 } 964 try { 965 final IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 966 if (iMms == null) { 967 return; 968 } 969 context.grantUriPermission(PHONE_PACKAGE_NAME, contentUri, 970 Intent.FLAG_GRANT_READ_URI_PERMISSION); 971 grantCarrierPackageUriPermission(context, contentUri, 972 Telephony.Mms.Intents.MMS_SEND_ACTION, Intent.FLAG_GRANT_READ_URI_PERMISSION); 973 974 iMms.sendMessage(getSubId(), ActivityThread.currentPackageName(), contentUri, 975 locationUrl, configOverrides, sentIntent); 976 } catch (RemoteException e) { 977 // Ignore it 978 } 979 } 980 981 private void grantCarrierPackageUriPermission(Context context, Uri contentUri, String action, 982 int permission) { 983 Intent intent = new Intent(action); 984 TelephonyManager telephonyManager = 985 (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 986 List<String> carrierPackages = telephonyManager.getCarrierPackageNamesForIntent( 987 intent); 988 if (carrierPackages != null && carrierPackages.size() == 1) { 989 context.grantUriPermission(carrierPackages.get(0), contentUri, permission); 990 } 991 } 992 993 /** 994 * Download an MMS message from carrier by a given location URL 995 * 996 * @param context application context 997 * @param locationUrl the location URL of the MMS message to be downloaded, usually obtained 998 * from the MMS WAP push notification 999 * @param contentUri the content uri to which the downloaded pdu will be written 1000 * @param configOverrides the carrier-specific messaging configuration values to override for 1001 * downloading the message. 1002 * @param downloadedIntent if not NULL this <code>PendingIntent</code> is 1003 * broadcast when the message is downloaded, or the download is failed 1004 * @throws IllegalArgumentException if locationUrl or contentUri is empty 1005 */ 1006 public void downloadMultimediaMessage(Context context, String locationUrl, Uri contentUri, 1007 Bundle configOverrides, PendingIntent downloadedIntent) { 1008 if (TextUtils.isEmpty(locationUrl)) { 1009 throw new IllegalArgumentException("Empty MMS location URL"); 1010 } 1011 if (contentUri == null) { 1012 throw new IllegalArgumentException("Uri contentUri null"); 1013 } 1014 try { 1015 final IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1016 if (iMms == null) { 1017 return; 1018 } 1019 context.grantUriPermission(PHONE_PACKAGE_NAME, contentUri, 1020 Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 1021 1022 grantCarrierPackageUriPermission(context, contentUri, 1023 Telephony.Mms.Intents.MMS_DOWNLOAD_ACTION, 1024 Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 1025 1026 iMms.downloadMessage(getSubId(), ActivityThread.currentPackageName(), locationUrl, 1027 contentUri, configOverrides, downloadedIntent); 1028 } catch (RemoteException e) { 1029 // Ignore it 1030 } 1031 } 1032 1033 // MMS send/download failure result codes 1034 public static final int MMS_ERROR_UNSPECIFIED = 1; 1035 public static final int MMS_ERROR_INVALID_APN = 2; 1036 public static final int MMS_ERROR_UNABLE_CONNECT_MMS = 3; 1037 public static final int MMS_ERROR_HTTP_FAILURE = 4; 1038 public static final int MMS_ERROR_IO_ERROR = 5; 1039 public static final int MMS_ERROR_RETRY = 6; 1040 public static final int MMS_ERROR_CONFIGURATION_ERROR = 7; 1041 1042 // Intent extra name for MMS sending result data in byte array type 1043 public static final String EXTRA_MMS_DATA = "android.telephony.extra.MMS_DATA"; 1044 // Intent extra name for HTTP status code for MMS HTTP failure in integer type 1045 public static final String EXTRA_MMS_HTTP_STATUS = "android.telephony.extra.MMS_HTTP_STATUS"; 1046 1047 /** 1048 * Update the status of a pending (send-by-IP) MMS message handled by the carrier app. 1049 * If the carrier app fails to send this message, it may be resent via carrier network 1050 * depending on the status code. 1051 * 1052 * The caller should have carrier privileges. 1053 * @see android.telephony.TelephonyManager.hasCarrierPrivileges 1054 * 1055 * @param context application context 1056 * @param messageRef the reference number of the MMS message. 1057 * @param pdu non-empty (contains the SendConf PDU) if the message was sent successfully, 1058 * otherwise, this param should be null. 1059 * @param status send status. It can be Activity.RESULT_OK or one of the MMS error codes. 1060 * If status is Activity.RESULT_OK, the MMS was sent successfully. 1061 * If status is MMS_ERROR_RETRY, this message would be resent via carrier 1062 * network. The message will not be resent for other MMS error statuses. 1063 * @param contentUri the URI of the sent message 1064 */ 1065 public void updateMmsSendStatus(Context context, int messageRef, byte[] pdu, int status, 1066 Uri contentUri) { 1067 try { 1068 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1069 if (iMms == null) { 1070 return; 1071 } 1072 iMms.updateMmsSendStatus(messageRef, pdu, status); 1073 } catch (RemoteException ex) { 1074 // ignore it 1075 } 1076 if (contentUri != null) { 1077 context.revokeUriPermission(contentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION); 1078 } 1079 } 1080 1081 /** 1082 * Update the status of a pending (download-by-IP) MMS message handled by the carrier app. 1083 * If the carrier app fails to download this message, it may be re-downloaded via carrier 1084 * network depending on the status code. 1085 * 1086 * The caller should have carrier privileges. 1087 * @see android.telephony.TelephonyManager.hasCarrierPrivileges 1088 * 1089 * @param context application context 1090 * @param messageRef the reference number of the MMS message. 1091 * @param status download status. It can be Activity.RESULT_OK or one of the MMS error codes. 1092 * If status is Activity.RESULT_OK, the MMS was downloaded successfully. 1093 * If status is MMS_ERROR_RETRY, this message would be re-downloaded via carrier 1094 * network. The message will not be re-downloaded for other MMS error statuses. 1095 * @param contentUri the URI of the downloaded message 1096 */ 1097 public void updateMmsDownloadStatus(Context context, int messageRef, int status, 1098 Uri contentUri) { 1099 try { 1100 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1101 if (iMms == null) { 1102 return; 1103 } 1104 iMms.updateMmsDownloadStatus(messageRef, status); 1105 } catch (RemoteException ex) { 1106 // ignore it 1107 } 1108 if (contentUri != null) { 1109 context.revokeUriPermission(contentUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 1110 } 1111 } 1112 1113 /** 1114 * Import a text message into system's SMS store 1115 * 1116 * Only default SMS apps can import SMS 1117 * 1118 * @param address the destination(source) address of the sent(received) message 1119 * @param type the type of the message 1120 * @param text the message text 1121 * @param timestampMillis the message timestamp in milliseconds 1122 * @param seen if the message is seen 1123 * @param read if the message is read 1124 * @return the message URI, null if failed 1125 * @hide 1126 */ 1127 public Uri importTextMessage(String address, int type, String text, long timestampMillis, 1128 boolean seen, boolean read) { 1129 try { 1130 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1131 if (iMms != null) { 1132 return iMms.importTextMessage(ActivityThread.currentPackageName(), 1133 address, type, text, timestampMillis, seen, read); 1134 } 1135 } catch (RemoteException ex) { 1136 // ignore it 1137 } 1138 return null; 1139 } 1140 1141 /** Represents the received SMS message for importing {@hide} */ 1142 public static final int SMS_TYPE_INCOMING = 0; 1143 /** Represents the sent SMS message for importing {@hide} */ 1144 public static final int SMS_TYPE_OUTGOING = 1; 1145 1146 /** 1147 * Import a multimedia message into system's MMS store. Only the following PDU type is 1148 * supported: Retrieve.conf, Send.req, Notification.ind, Delivery.ind, Read-Orig.ind 1149 * 1150 * Only default SMS apps can import MMS 1151 * 1152 * @param contentUri the content uri from which to read the PDU of the message to import 1153 * @param messageId the optional message id. Use null if not specifying 1154 * @param timestampSecs the optional message timestamp. Use -1 if not specifying 1155 * @param seen if the message is seen 1156 * @param read if the message is read 1157 * @return the message URI, null if failed 1158 * @throws IllegalArgumentException if pdu is empty 1159 * {@hide} 1160 */ 1161 public Uri importMultimediaMessage(Uri contentUri, String messageId, long timestampSecs, 1162 boolean seen, boolean read) { 1163 if (contentUri == null) { 1164 throw new IllegalArgumentException("Uri contentUri null"); 1165 } 1166 try { 1167 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1168 if (iMms != null) { 1169 return iMms.importMultimediaMessage(ActivityThread.currentPackageName(), 1170 contentUri, messageId, timestampSecs, seen, read); 1171 } 1172 } catch (RemoteException ex) { 1173 // ignore it 1174 } 1175 return null; 1176 } 1177 1178 /** 1179 * Delete a system stored SMS or MMS message 1180 * 1181 * Only default SMS apps can delete system stored SMS and MMS messages 1182 * 1183 * @param messageUri the URI of the stored message 1184 * @return true if deletion is successful, false otherwise 1185 * @throws IllegalArgumentException if messageUri is empty 1186 * {@hide} 1187 */ 1188 public boolean deleteStoredMessage(Uri messageUri) { 1189 if (messageUri == null) { 1190 throw new IllegalArgumentException("Empty message URI"); 1191 } 1192 try { 1193 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1194 if (iMms != null) { 1195 return iMms.deleteStoredMessage(ActivityThread.currentPackageName(), messageUri); 1196 } 1197 } catch (RemoteException ex) { 1198 // ignore it 1199 } 1200 return false; 1201 } 1202 1203 /** 1204 * Delete a system stored SMS or MMS thread 1205 * 1206 * Only default SMS apps can delete system stored SMS and MMS conversations 1207 * 1208 * @param conversationId the ID of the message conversation 1209 * @return true if deletion is successful, false otherwise 1210 * {@hide} 1211 */ 1212 public boolean deleteStoredConversation(long conversationId) { 1213 try { 1214 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1215 if (iMms != null) { 1216 return iMms.deleteStoredConversation( 1217 ActivityThread.currentPackageName(), conversationId); 1218 } 1219 } catch (RemoteException ex) { 1220 // ignore it 1221 } 1222 return false; 1223 } 1224 1225 /** 1226 * Update the status properties of a system stored SMS or MMS message, e.g. 1227 * the read status of a message, etc. 1228 * 1229 * @param messageUri the URI of the stored message 1230 * @param statusValues a list of status properties in key-value pairs to update 1231 * @return true if update is successful, false otherwise 1232 * @throws IllegalArgumentException if messageUri is empty 1233 * {@hide} 1234 */ 1235 public boolean updateStoredMessageStatus(Uri messageUri, ContentValues statusValues) { 1236 if (messageUri == null) { 1237 throw new IllegalArgumentException("Empty message URI"); 1238 } 1239 try { 1240 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1241 if (iMms != null) { 1242 return iMms.updateStoredMessageStatus(ActivityThread.currentPackageName(), 1243 messageUri, statusValues); 1244 } 1245 } catch (RemoteException ex) { 1246 // ignore it 1247 } 1248 return false; 1249 } 1250 1251 /** Message status property: whether the message has been seen. 1 means seen, 0 not {@hide} */ 1252 public static final String MESSAGE_STATUS_SEEN = "seen"; 1253 /** Message status property: whether the message has been read. 1 means read, 0 not {@hide} */ 1254 public static final String MESSAGE_STATUS_READ = "read"; 1255 1256 /** 1257 * Archive or unarchive a stored conversation 1258 * 1259 * @param conversationId the ID of the message conversation 1260 * @param archived true to archive the conversation, false to unarchive 1261 * @return true if update is successful, false otherwise 1262 * {@hide} 1263 */ 1264 public boolean archiveStoredConversation(long conversationId, boolean archived) { 1265 try { 1266 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1267 if (iMms != null) { 1268 return iMms.archiveStoredConversation(ActivityThread.currentPackageName(), 1269 conversationId, archived); 1270 } 1271 } catch (RemoteException ex) { 1272 // ignore it 1273 } 1274 return false; 1275 } 1276 1277 /** 1278 * Add a text message draft to system SMS store 1279 * 1280 * Only default SMS apps can add SMS draft 1281 * 1282 * @param address the destination address of message 1283 * @param text the body of the message to send 1284 * @return the URI of the stored draft message 1285 * {@hide} 1286 */ 1287 public Uri addTextMessageDraft(String address, String text) { 1288 try { 1289 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1290 if (iMms != null) { 1291 return iMms.addTextMessageDraft(ActivityThread.currentPackageName(), address, text); 1292 } 1293 } catch (RemoteException ex) { 1294 // ignore it 1295 } 1296 return null; 1297 } 1298 1299 /** 1300 * Add a multimedia message draft to system MMS store 1301 * 1302 * Only default SMS apps can add MMS draft 1303 * 1304 * @param contentUri the content uri from which to read the PDU data of the draft MMS 1305 * @return the URI of the stored draft message 1306 * @throws IllegalArgumentException if pdu is empty 1307 * {@hide} 1308 */ 1309 public Uri addMultimediaMessageDraft(Uri contentUri) { 1310 if (contentUri == null) { 1311 throw new IllegalArgumentException("Uri contentUri null"); 1312 } 1313 try { 1314 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1315 if (iMms != null) { 1316 return iMms.addMultimediaMessageDraft(ActivityThread.currentPackageName(), 1317 contentUri); 1318 } 1319 } catch (RemoteException ex) { 1320 // ignore it 1321 } 1322 return null; 1323 } 1324 1325 /** 1326 * Send a system stored text message. 1327 * 1328 * You can only send a failed text message or a draft text message. 1329 * 1330 * @param messageUri the URI of the stored message 1331 * @param scAddress is the service center address or null to use the current default SMSC 1332 * @param sentIntent if not NULL this <code>PendingIntent</code> is 1333 * broadcast when the message is successfully sent, or failed. 1334 * The result code will be <code>Activity.RESULT_OK</code> for success, 1335 * or one of these errors:<br> 1336 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 1337 * <code>RESULT_ERROR_RADIO_OFF</code><br> 1338 * <code>RESULT_ERROR_NULL_PDU</code><br> 1339 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 1340 * the extra "errorCode" containing a radio technology specific value, 1341 * generally only useful for troubleshooting.<br> 1342 * The per-application based SMS control checks sentIntent. If sentIntent 1343 * is NULL the caller will be checked against all unknown applications, 1344 * which cause smaller number of SMS to be sent in checking period. 1345 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 1346 * broadcast when the message is delivered to the recipient. The 1347 * raw pdu of the status report is in the extended data ("pdu"). 1348 * 1349 * @throws IllegalArgumentException if messageUri is empty 1350 * {@hide} 1351 */ 1352 public void sendStoredTextMessage(Uri messageUri, String scAddress, PendingIntent sentIntent, 1353 PendingIntent deliveryIntent) { 1354 if (messageUri == null) { 1355 throw new IllegalArgumentException("Empty message URI"); 1356 } 1357 try { 1358 ISms iccISms = getISmsServiceOrThrow(); 1359 iccISms.sendStoredText(getSubId(), ActivityThread.currentPackageName(), messageUri, 1360 scAddress, sentIntent, deliveryIntent); 1361 } catch (RemoteException ex) { 1362 // ignore it 1363 } 1364 } 1365 1366 /** 1367 * Send a system stored multi-part text message. 1368 * 1369 * You can only send a failed text message or a draft text message. 1370 * The provided <code>PendingIntent</code> lists should match the part number of the 1371 * divided text of the stored message by using <code>divideMessage</code> 1372 * 1373 * @param messageUri the URI of the stored message 1374 * @param scAddress is the service center address or null to use 1375 * the current default SMSC 1376 * @param sentIntents if not null, an <code>ArrayList</code> of 1377 * <code>PendingIntent</code>s (one for each message part) that is 1378 * broadcast when the corresponding message part has been sent. 1379 * The result code will be <code>Activity.RESULT_OK</code> for success, 1380 * or one of these errors:<br> 1381 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 1382 * <code>RESULT_ERROR_RADIO_OFF</code><br> 1383 * <code>RESULT_ERROR_NULL_PDU</code><br> 1384 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> each sentIntent may include 1385 * the extra "errorCode" containing a radio technology specific value, 1386 * generally only useful for troubleshooting.<br> 1387 * The per-application based SMS control checks sentIntent. If sentIntent 1388 * is NULL the caller will be checked against all unknown applications, 1389 * which cause smaller number of SMS to be sent in checking period. 1390 * @param deliveryIntents if not null, an <code>ArrayList</code> of 1391 * <code>PendingIntent</code>s (one for each message part) that is 1392 * broadcast when the corresponding message part has been delivered 1393 * to the recipient. The raw pdu of the status report is in the 1394 * extended data ("pdu"). 1395 * 1396 * @throws IllegalArgumentException if messageUri is empty 1397 * {@hide} 1398 */ 1399 public void sendStoredMultipartTextMessage(Uri messageUri, String scAddress, 1400 ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) { 1401 if (messageUri == null) { 1402 throw new IllegalArgumentException("Empty message URI"); 1403 } 1404 try { 1405 ISms iccISms = getISmsServiceOrThrow(); 1406 iccISms.sendStoredMultipartText(getSubId(), ActivityThread.currentPackageName(), messageUri, 1407 scAddress, sentIntents, deliveryIntents); 1408 } catch (RemoteException ex) { 1409 // ignore it 1410 } 1411 } 1412 1413 /** 1414 * Send a system stored MMS message 1415 * 1416 * This is used for sending a previously sent, but failed-to-send, message or 1417 * for sending a text message that has been stored as a draft. 1418 * 1419 * @param messageUri the URI of the stored message 1420 * @param configOverrides the carrier-specific messaging configuration values to override for 1421 * sending the message. 1422 * @param sentIntent if not NULL this <code>PendingIntent</code> is 1423 * broadcast when the message is successfully sent, or failed 1424 * @throws IllegalArgumentException if messageUri is empty 1425 * {@hide} 1426 */ 1427 public void sendStoredMultimediaMessage(Uri messageUri, Bundle configOverrides, 1428 PendingIntent sentIntent) { 1429 if (messageUri == null) { 1430 throw new IllegalArgumentException("Empty message URI"); 1431 } 1432 try { 1433 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1434 if (iMms != null) { 1435 iMms.sendStoredMessage(getSubId(), ActivityThread.currentPackageName(), messageUri, 1436 configOverrides, sentIntent); 1437 } 1438 } catch (RemoteException ex) { 1439 // ignore it 1440 } 1441 } 1442 1443 /** 1444 * Turns on/off the flag to automatically write sent/received SMS/MMS messages into system 1445 * 1446 * When this flag is on, all SMS/MMS sent/received are stored by system automatically 1447 * When this flag is off, only SMS/MMS sent by non-default SMS apps are stored by system 1448 * automatically 1449 * 1450 * This flag can only be changed by default SMS apps 1451 * 1452 * @param enabled Whether to enable message auto persisting 1453 * {@hide} 1454 */ 1455 public void setAutoPersisting(boolean enabled) { 1456 try { 1457 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1458 if (iMms != null) { 1459 iMms.setAutoPersisting(ActivityThread.currentPackageName(), enabled); 1460 } 1461 } catch (RemoteException ex) { 1462 // ignore it 1463 } 1464 } 1465 1466 /** 1467 * Get the value of the flag to automatically write sent/received SMS/MMS messages into system 1468 * 1469 * When this flag is on, all SMS/MMS sent/received are stored by system automatically 1470 * When this flag is off, only SMS/MMS sent by non-default SMS apps are stored by system 1471 * automatically 1472 * 1473 * @return the current value of the auto persist flag 1474 * {@hide} 1475 */ 1476 public boolean getAutoPersisting() { 1477 try { 1478 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1479 if (iMms != null) { 1480 return iMms.getAutoPersisting(); 1481 } 1482 } catch (RemoteException ex) { 1483 // ignore it 1484 } 1485 return false; 1486 } 1487 1488 /** 1489 * Get carrier-dependent configuration values. 1490 * 1491 * @return bundle key/values pairs of configuration values 1492 */ 1493 public Bundle getCarrierConfigValues() { 1494 try { 1495 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1496 if (iMms != null) { 1497 return iMms.getCarrierConfigValues(getSubId()); 1498 } 1499 } catch (RemoteException ex) { 1500 // ignore it 1501 } 1502 return null; 1503 } 1504 1505} 1506