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