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