SmsManager.java revision a2091571054b8fcf38ed112dfaac6240b6ade301
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 SmsManager associated with the default subId. The instance will always be 453 * associated with the default subId, even if the default subId is changed. 454 * 455 * @return the SmsManager associated with the default subId 456 */ 457 public static SmsManager getDefault() { 458 return sInstance; 459 } 460 461 /** 462 * Get the the instance of the SmsManager associated with a particular subId 463 * 464 * @param subId a SMS subscription id, typically accessed using 465 * {@link android.telephony.SubscriptionManager} 466 * @return the instance of the SmsManager associated with subId 467 */ 468 public static SmsManager getSmsManagerUsingSubId(long subId) { 469 // TODO(shri): Add javadoc link once SubscriptionManager is made public api 470 synchronized(sLockObject) { 471 SmsManager smsManager = sSubInstances.get(subId); 472 if (smsManager == null) { 473 smsManager = new SmsManager(subId); 474 sSubInstances.put(subId, smsManager); 475 } 476 return smsManager; 477 } 478 } 479 480 private SmsManager(long subId) { 481 mSubId = subId; 482 } 483 484 /** 485 * Get the associated subId. If the instance was returned by {@link #getDefault()}, then this 486 * method may return different values at different points in time (if the user changes the 487 * default subId). It will return {@link android.telephony.SubscriptionManager#INVALID_SUB_ID} 488 * if the default subId cannot be determined. 489 * 490 * @return associated subId 491 */ 492 public long getSubId() { 493 if (mSubId == DEFAULT_SUB_ID) { 494 return getDefaultSmsSubId(); 495 } 496 return mSubId; 497 } 498 499 /** 500 * Returns the ISms service, or throws an UnsupportedOperationException if 501 * the service does not exist. 502 */ 503 private static ISms getISmsServiceOrThrow() { 504 ISms iccISms = getISmsService(); 505 if (iccISms == null) { 506 throw new UnsupportedOperationException("Sms is not supported"); 507 } 508 return iccISms; 509 } 510 511 private static ISms getISmsService() { 512 return ISms.Stub.asInterface(ServiceManager.getService("isms")); 513 } 514 515 /** 516 * Copy a raw SMS PDU to the ICC. 517 * ICC (Integrated Circuit Card) is the card of the device. 518 * For example, this can be the SIM or USIM for GSM. 519 * 520 * @param smsc the SMSC for this message, or NULL for the default SMSC 521 * @param pdu the raw PDU to store 522 * @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD, 523 * STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT) 524 * @return true for success 525 * 526 * @throws IllegalArgumentException if pdu is NULL 527 * {@hide} 528 */ 529 public boolean copyMessageToIcc(byte[] smsc, byte[] pdu,int status) { 530 boolean success = false; 531 532 if (null == pdu) { 533 throw new IllegalArgumentException("pdu is NULL"); 534 } 535 try { 536 ISms iccISms = getISmsService(); 537 if (iccISms != null) { 538 success = iccISms.copyMessageToIccEf(ActivityThread.currentPackageName(), 539 status, pdu, smsc); 540 } 541 } catch (RemoteException ex) { 542 // ignore it 543 } 544 545 return success; 546 } 547 548 /** 549 * Delete the specified message from the ICC. 550 * ICC (Integrated Circuit Card) is the card of the device. 551 * For example, this can be the SIM or USIM for GSM. 552 * 553 * @param messageIndex is the record index of the message on ICC 554 * @return true for success 555 * 556 * {@hide} 557 */ 558 public boolean 559 deleteMessageFromIcc(int messageIndex) { 560 boolean success = false; 561 byte[] pdu = new byte[IccConstants.SMS_RECORD_LENGTH-1]; 562 Arrays.fill(pdu, (byte)0xff); 563 564 try { 565 ISms iccISms = getISmsService(); 566 if (iccISms != null) { 567 success = iccISms.updateMessageOnIccEf(ActivityThread.currentPackageName(), 568 messageIndex, STATUS_ON_ICC_FREE, pdu); 569 } 570 } catch (RemoteException ex) { 571 // ignore it 572 } 573 574 return success; 575 } 576 577 /** 578 * Update the specified message on the ICC. 579 * ICC (Integrated Circuit Card) is the card of the device. 580 * For example, this can be the SIM or USIM for GSM. 581 * 582 * @param messageIndex record index of message to update 583 * @param newStatus new message status (STATUS_ON_ICC_READ, 584 * STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT, 585 * STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE) 586 * @param pdu the raw PDU to store 587 * @return true for success 588 * 589 * {@hide} 590 */ 591 public boolean updateMessageOnIcc(int messageIndex, int newStatus, byte[] pdu) { 592 boolean success = false; 593 594 try { 595 ISms iccISms = getISmsService(); 596 if (iccISms != null) { 597 success = iccISms.updateMessageOnIccEf(ActivityThread.currentPackageName(), 598 messageIndex, newStatus, pdu); 599 } 600 } catch (RemoteException ex) { 601 // ignore it 602 } 603 604 return success; 605 } 606 607 /** 608 * Retrieves all messages currently stored on ICC. 609 * ICC (Integrated Circuit Card) is the card of the device. 610 * For example, this can be the SIM or USIM for GSM. 611 * 612 * @return <code>ArrayList</code> of <code>SmsMessage</code> objects 613 * 614 * {@hide} 615 */ 616 public static ArrayList<SmsMessage> getAllMessagesFromIcc() { 617 List<SmsRawData> records = null; 618 619 try { 620 ISms iccISms = getISmsService(); 621 if (iccISms != null) { 622 records = iccISms.getAllMessagesFromIccEf(ActivityThread.currentPackageName()); 623 } 624 } catch (RemoteException ex) { 625 // ignore it 626 } 627 628 return createMessageListFromRawRecords(records); 629 } 630 631 /** 632 * Enable reception of cell broadcast (SMS-CB) messages with the given 633 * message identifier. Note that if two different clients enable the same 634 * message identifier, they must both disable it for the device to stop 635 * receiving those messages. All received messages will be broadcast in an 636 * intent with the action "android.provider.Telephony.SMS_CB_RECEIVED". 637 * Note: This call is blocking, callers may want to avoid calling it from 638 * the main thread of an application. 639 * 640 * @param messageIdentifier Message identifier as specified in TS 23.041 (3GPP) 641 * or C.R1001-G (3GPP2) 642 * @return true if successful, false otherwise 643 * @see #disableCellBroadcast(int) 644 * 645 * {@hide} 646 */ 647 public boolean enableCellBroadcast(int messageIdentifier) { 648 boolean success = false; 649 650 try { 651 ISms iccISms = getISmsService(); 652 if (iccISms != null) { 653 success = iccISms.enableCellBroadcast(messageIdentifier); 654 } 655 } catch (RemoteException ex) { 656 // ignore it 657 } 658 659 return success; 660 } 661 662 /** 663 * Disable reception of cell broadcast (SMS-CB) messages with the given 664 * message identifier. Note that if two different clients enable the same 665 * message identifier, they must both disable it for the device to stop 666 * receiving those messages. 667 * Note: This call is blocking, callers may want to avoid calling it from 668 * the main thread of an application. 669 * 670 * @param messageIdentifier Message identifier as specified in TS 23.041 (3GPP) 671 * or C.R1001-G (3GPP2) 672 * @return true if successful, false otherwise 673 * 674 * @see #enableCellBroadcast(int) 675 * 676 * {@hide} 677 */ 678 public boolean disableCellBroadcast(int messageIdentifier) { 679 boolean success = false; 680 681 try { 682 ISms iccISms = getISmsService(); 683 if (iccISms != null) { 684 success = iccISms.disableCellBroadcast(messageIdentifier); 685 } 686 } catch (RemoteException ex) { 687 // ignore it 688 } 689 690 return success; 691 } 692 693 /** 694 * Enable reception of cell broadcast (SMS-CB) messages with the given 695 * message identifier range. Note that if two different clients enable the same 696 * message identifier, they must both disable it for the device to stop 697 * receiving those messages. All received messages will be broadcast in an 698 * intent with the action "android.provider.Telephony.SMS_CB_RECEIVED". 699 * Note: This call is blocking, callers may want to avoid calling it from 700 * the main thread of an application. 701 * 702 * @param startMessageId first message identifier as specified in TS 23.041 (3GPP) 703 * or C.R1001-G (3GPP2) 704 * @param endMessageId last message identifier as specified in TS 23.041 (3GPP) 705 * or C.R1001-G (3GPP2) 706 * @return true if successful, false otherwise 707 * @see #disableCellBroadcastRange(int, int) 708 * 709 * @throws IllegalArgumentException if endMessageId < startMessageId 710 * {@hide} 711 */ 712 public boolean enableCellBroadcastRange(int startMessageId, int endMessageId) { 713 boolean success = false; 714 715 if (endMessageId < startMessageId) { 716 throw new IllegalArgumentException("endMessageId < startMessageId"); 717 } 718 try { 719 ISms iccISms = getISmsService(); 720 if (iccISms != null) { 721 success = iccISms.enableCellBroadcastRange(startMessageId, endMessageId); 722 } 723 } catch (RemoteException ex) { 724 // ignore it 725 } 726 727 return success; 728 } 729 730 /** 731 * Disable reception of cell broadcast (SMS-CB) messages with the given 732 * message identifier range. Note that if two different clients enable the same 733 * message identifier, they must both disable it for the device to stop 734 * receiving those messages. 735 * Note: This call is blocking, callers may want to avoid calling it from 736 * the main thread of an application. 737 * 738 * @param startMessageId first message identifier as specified in TS 23.041 (3GPP) 739 * or C.R1001-G (3GPP2) 740 * @param endMessageId last message identifier as specified in TS 23.041 (3GPP) 741 * or C.R1001-G (3GPP2) 742 * @return true if successful, false otherwise 743 * 744 * @see #enableCellBroadcastRange(int, int) 745 * 746 * @throws IllegalArgumentException if endMessageId < startMessageId 747 * {@hide} 748 */ 749 public boolean disableCellBroadcastRange(int startMessageId, int endMessageId) { 750 boolean success = false; 751 752 if (endMessageId < startMessageId) { 753 throw new IllegalArgumentException("endMessageId < startMessageId"); 754 } 755 try { 756 ISms iccISms = getISmsService(); 757 if (iccISms != null) { 758 success = iccISms.disableCellBroadcastRange(startMessageId, endMessageId); 759 } 760 } catch (RemoteException ex) { 761 // ignore it 762 } 763 764 return success; 765 } 766 767 /** 768 * Create a list of <code>SmsMessage</code>s from a list of RawSmsData 769 * records returned by <code>getAllMessagesFromIcc()</code> 770 * 771 * @param records SMS EF records, returned by 772 * <code>getAllMessagesFromIcc</code> 773 * @return <code>ArrayList</code> of <code>SmsMessage</code> objects. 774 */ 775 private static ArrayList<SmsMessage> createMessageListFromRawRecords(List<SmsRawData> records) { 776 ArrayList<SmsMessage> messages = new ArrayList<SmsMessage>(); 777 if (records != null) { 778 int count = records.size(); 779 for (int i = 0; i < count; i++) { 780 SmsRawData data = records.get(i); 781 // List contains all records, including "free" records (null) 782 if (data != null) { 783 SmsMessage sms = SmsMessage.createFromEfRecord(i+1, data.getBytes()); 784 if (sms != null) { 785 messages.add(sms); 786 } 787 } 788 } 789 } 790 return messages; 791 } 792 793 /** 794 * SMS over IMS is supported if IMS is registered and SMS is supported 795 * on IMS. 796 * 797 * @return true if SMS over IMS is supported, false otherwise 798 * 799 * @see #getImsSmsFormat() 800 * 801 * @hide 802 */ 803 boolean isImsSmsSupported() { 804 boolean boSupported = false; 805 try { 806 ISms iccISms = getISmsService(); 807 if (iccISms != null) { 808 boSupported = iccISms.isImsSmsSupported(); 809 } 810 } catch (RemoteException ex) { 811 // ignore it 812 } 813 return boSupported; 814 } 815 816 /** 817 * Gets SMS format supported on IMS. SMS over IMS format is 818 * either 3GPP or 3GPP2. 819 * 820 * @return SmsMessage.FORMAT_3GPP, 821 * SmsMessage.FORMAT_3GPP2 822 * or SmsMessage.FORMAT_UNKNOWN 823 * 824 * @see #isImsSmsSupported() 825 * 826 * @hide 827 */ 828 String getImsSmsFormat() { 829 String format = com.android.internal.telephony.SmsConstants.FORMAT_UNKNOWN; 830 try { 831 ISms iccISms = getISmsService(); 832 if (iccISms != null) { 833 format = iccISms.getImsSmsFormat(); 834 } 835 } catch (RemoteException ex) { 836 // ignore it 837 } 838 return format; 839 } 840 841 /** 842 * Get default sms subId 843 * 844 * @return the default SubId 845 * @hide 846 */ 847 public static long getDefaultSmsSubId() { 848 return SubscriptionManager.getDefaultSmsSubId(); 849 } 850 851 /** 852 * Get SMS prompt property, enabled or not 853 * 854 * @return true if enabled, false otherwise 855 * @hide 856 */ 857 public boolean isSMSPromptEnabled() { 858 ISms iccISms = null; 859 try { 860 iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); 861 return iccISms.isSMSPromptEnabled(); 862 } catch (RemoteException ex) { 863 return false; 864 } catch (NullPointerException ex) { 865 return false; 866 } 867 } 868 869 // see SmsMessage.getStatusOnIcc 870 871 /** Free space (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 872 static public final int STATUS_ON_ICC_FREE = 0; 873 874 /** Received and read (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 875 static public final int STATUS_ON_ICC_READ = 1; 876 877 /** Received and unread (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 878 static public final int STATUS_ON_ICC_UNREAD = 3; 879 880 /** Stored and sent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 881 static public final int STATUS_ON_ICC_SENT = 5; 882 883 /** Stored and unsent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 884 static public final int STATUS_ON_ICC_UNSENT = 7; 885 886 // SMS send failure result codes 887 888 /** Generic failure cause */ 889 static public final int RESULT_ERROR_GENERIC_FAILURE = 1; 890 /** Failed because radio was explicitly turned off */ 891 static public final int RESULT_ERROR_RADIO_OFF = 2; 892 /** Failed because no pdu provided */ 893 static public final int RESULT_ERROR_NULL_PDU = 3; 894 /** Failed because service is currently unavailable */ 895 static public final int RESULT_ERROR_NO_SERVICE = 4; 896 /** Failed because we reached the sending queue limit. {@hide} */ 897 static public final int RESULT_ERROR_LIMIT_EXCEEDED = 5; 898 /** Failed because FDN is enabled. {@hide} */ 899 static public final int RESULT_ERROR_FDN_CHECK_FAILURE = 6; 900 901 /** 902 * Send an MMS message 903 * 904 * @param contentUri the content Uri from which the message pdu will be read 905 * @param locationUrl the optional location url where message should be sent to 906 * @param configOverrides the carrier-specific messaging configuration values to override for 907 * sending the message. 908 * @param sentIntent if not NULL this <code>PendingIntent</code> is 909 * broadcast when the message is successfully sent, or failed 910 * @throws IllegalArgumentException if contentUri is empty 911 */ 912 public void sendMultimediaMessage(Uri contentUri, String locationUrl, 913 Bundle configOverrides, PendingIntent sentIntent) { 914 if (contentUri == null) { 915 throw new IllegalArgumentException("Uri contentUri null"); 916 } 917 try { 918 final IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 919 if (iMms == null) { 920 return; 921 } 922 iMms.sendMessage(getSubId(), ActivityThread.currentPackageName(), contentUri, 923 locationUrl, configOverrides, sentIntent); 924 } catch (RemoteException e) { 925 // Ignore it 926 } 927 } 928 929 /** 930 * Download an MMS message from carrier by a given location URL 931 * 932 * @param locationUrl the location URL of the MMS message to be downloaded, usually obtained 933 * from the MMS WAP push notification 934 * @param contentUri the content uri to which the downloaded pdu will be written 935 * @param configOverrides the carrier-specific messaging configuration values to override for 936 * downloading the message. 937 * @param downloadedIntent if not NULL this <code>PendingIntent</code> is 938 * broadcast when the message is downloaded, or the download is failed 939 * @throws IllegalArgumentException if locationUrl or contentUri is empty 940 */ 941 public void downloadMultimediaMessage(String locationUrl, Uri contentUri, 942 Bundle configOverrides, PendingIntent downloadedIntent) { 943 if (TextUtils.isEmpty(locationUrl)) { 944 throw new IllegalArgumentException("Empty MMS location URL"); 945 } 946 if (contentUri == null) { 947 throw new IllegalArgumentException("Uri contentUri null"); 948 } 949 try { 950 final IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 951 if (iMms == null) { 952 return; 953 } 954 iMms.downloadMessage(getSubId(), ActivityThread.currentPackageName(), locationUrl, 955 contentUri, configOverrides, downloadedIntent); 956 } catch (RemoteException e) { 957 // Ignore it 958 } 959 } 960 961 // MMS send/download failure result codes 962 public static final int MMS_ERROR_UNSPECIFIED = 1; 963 public static final int MMS_ERROR_INVALID_APN = 2; 964 public static final int MMS_ERROR_UNABLE_CONNECT_MMS = 3; 965 public static final int MMS_ERROR_HTTP_FAILURE = 4; 966 public static final int MMS_ERROR_IO_ERROR = 5; 967 968 // Intent extra name for result data 969 public static final String EXTRA_MMS_DATA = "android.telephony.extra.MMS_DATA"; 970 971 /** 972 * Update the status of a pending (send-by-IP) MMS message handled by the carrier app. 973 * If the carrier app fails to send this message, it would be resent via carrier network. 974 * 975 * The caller should have carrier privileges. 976 * @see android.telephony.TelephonyManager.hasCarrierPrivileges 977 * 978 * @param messageRef the reference number of the MMS message. 979 * @param success True if and only if the message was sent successfully. If its value is 980 * false, this message should be resent via carrier network 981 */ 982 public void updateMmsSendStatus(int messageRef, boolean success) { 983 try { 984 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 985 if (iMms == null) { 986 return; 987 } 988 iMms.updateMmsSendStatus(messageRef, success); 989 } catch (RemoteException ex) { 990 // ignore it 991 } 992 } 993 994 /** 995 * Update the status of a pending (download-by-IP) MMS message handled by the carrier app. 996 * If the carrier app fails to download this message, it would be re-downloaded via carrier 997 * network. 998 * 999 * The caller should have carrier privileges. 1000 * @see android.telephony.TelephonyManager.hasCarrierPrivileges 1001 * 1002 * @param messageRef the reference number of the MMS message. 1003 * @param pdu non-empty if downloaded successfully, otherwise, it is empty and the message 1004 * will be downloaded via carrier network 1005 */ 1006 public void updateMmsDownloadStatus(int messageRef, byte[] pdu) { 1007 try { 1008 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1009 if (iMms == null) { 1010 return; 1011 } 1012 iMms.updateMmsDownloadStatus(messageRef, pdu); 1013 } catch (RemoteException ex) { 1014 // ignore it 1015 } 1016 } 1017 1018 /** 1019 * Import a text message into system's SMS store 1020 * 1021 * Only default SMS apps can import SMS 1022 * 1023 * @param address the destination(source) address of the sent(received) message 1024 * @param type the type of the message 1025 * @param text the message text 1026 * @param timestampMillis the message timestamp in milliseconds 1027 * @param seen if the message is seen 1028 * @param read if the message is read 1029 * @return the message URI, null if failed 1030 * @hide 1031 */ 1032 public Uri importTextMessage(String address, int type, String text, long timestampMillis, 1033 boolean seen, boolean read) { 1034 try { 1035 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1036 if (iMms != null) { 1037 return iMms.importTextMessage(ActivityThread.currentPackageName(), 1038 address, type, text, timestampMillis, seen, read); 1039 } 1040 } catch (RemoteException ex) { 1041 // ignore it 1042 } 1043 return null; 1044 } 1045 1046 /** Represents the received SMS message for importing {@hide} */ 1047 public static final int SMS_TYPE_INCOMING = 0; 1048 /** Represents the sent SMS message for importing {@hide} */ 1049 public static final int SMS_TYPE_OUTGOING = 1; 1050 1051 /** 1052 * Import a multimedia message into system's MMS store. Only the following PDU type is 1053 * supported: Retrieve.conf, Send.req, Notification.ind, Delivery.ind, Read-Orig.ind 1054 * 1055 * Only default SMS apps can import MMS 1056 * 1057 * @param contentUri the content uri from which to read the PDU of the message to import 1058 * @param messageId the optional message id. Use null if not specifying 1059 * @param timestampSecs the optional message timestamp. Use -1 if not specifying 1060 * @param seen if the message is seen 1061 * @param read if the message is read 1062 * @return the message URI, null if failed 1063 * @throws IllegalArgumentException if pdu is empty 1064 * {@hide} 1065 */ 1066 public Uri importMultimediaMessage(Uri contentUri, String messageId, long timestampSecs, 1067 boolean seen, boolean read) { 1068 if (contentUri == null) { 1069 throw new IllegalArgumentException("Uri contentUri null"); 1070 } 1071 try { 1072 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1073 if (iMms != null) { 1074 return iMms.importMultimediaMessage(ActivityThread.currentPackageName(), 1075 contentUri, messageId, timestampSecs, seen, read); 1076 } 1077 } catch (RemoteException ex) { 1078 // ignore it 1079 } 1080 return null; 1081 } 1082 1083 /** 1084 * Delete a system stored SMS or MMS message 1085 * 1086 * Only default SMS apps can delete system stored SMS and MMS messages 1087 * 1088 * @param messageUri the URI of the stored message 1089 * @return true if deletion is successful, false otherwise 1090 * @throws IllegalArgumentException if messageUri is empty 1091 * {@hide} 1092 */ 1093 public boolean deleteStoredMessage(Uri messageUri) { 1094 if (messageUri == null) { 1095 throw new IllegalArgumentException("Empty message URI"); 1096 } 1097 try { 1098 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1099 if (iMms != null) { 1100 return iMms.deleteStoredMessage(ActivityThread.currentPackageName(), messageUri); 1101 } 1102 } catch (RemoteException ex) { 1103 // ignore it 1104 } 1105 return false; 1106 } 1107 1108 /** 1109 * Delete a system stored SMS or MMS thread 1110 * 1111 * Only default SMS apps can delete system stored SMS and MMS conversations 1112 * 1113 * @param conversationId the ID of the message conversation 1114 * @return true if deletion is successful, false otherwise 1115 * {@hide} 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 * {@hide} 1139 */ 1140 public boolean updateStoredMessageStatus(Uri messageUri, ContentValues statusValues) { 1141 if (messageUri == null) { 1142 throw new IllegalArgumentException("Empty message URI"); 1143 } 1144 try { 1145 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1146 if (iMms != null) { 1147 return iMms.updateStoredMessageStatus(ActivityThread.currentPackageName(), 1148 messageUri, statusValues); 1149 } 1150 } catch (RemoteException ex) { 1151 // ignore it 1152 } 1153 return false; 1154 } 1155 1156 /** Message status property: whether the message has been seen. 1 means seen, 0 not {@hide} */ 1157 public static final String MESSAGE_STATUS_SEEN = "seen"; 1158 /** Message status property: whether the message has been read. 1 means read, 0 not {@hide} */ 1159 public static final String MESSAGE_STATUS_READ = "read"; 1160 1161 /** 1162 * Archive or unarchive a stored conversation 1163 * 1164 * @param conversationId the ID of the message conversation 1165 * @param archived true to archive the conversation, false to unarchive 1166 * @return true if update is successful, false otherwise 1167 * {@hide} 1168 */ 1169 public boolean archiveStoredConversation(long conversationId, boolean archived) { 1170 try { 1171 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1172 if (iMms != null) { 1173 return iMms.archiveStoredConversation(ActivityThread.currentPackageName(), 1174 conversationId, archived); 1175 } 1176 } catch (RemoteException ex) { 1177 // ignore it 1178 } 1179 return false; 1180 } 1181 1182 /** 1183 * Add a text message draft to system SMS store 1184 * 1185 * Only default SMS apps can add SMS draft 1186 * 1187 * @param address the destination address of message 1188 * @param text the body of the message to send 1189 * @return the URI of the stored draft message 1190 * {@hide} 1191 */ 1192 public Uri addTextMessageDraft(String address, String text) { 1193 try { 1194 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1195 if (iMms != null) { 1196 return iMms.addTextMessageDraft(ActivityThread.currentPackageName(), address, text); 1197 } 1198 } catch (RemoteException ex) { 1199 // ignore it 1200 } 1201 return null; 1202 } 1203 1204 /** 1205 * Add a multimedia message draft to system MMS store 1206 * 1207 * Only default SMS apps can add MMS draft 1208 * 1209 * @param contentUri the content uri from which to read the PDU data of the draft MMS 1210 * @return the URI of the stored draft message 1211 * @throws IllegalArgumentException if pdu is empty 1212 * {@hide} 1213 */ 1214 public Uri addMultimediaMessageDraft(Uri contentUri) { 1215 if (contentUri == null) { 1216 throw new IllegalArgumentException("Uri contentUri null"); 1217 } 1218 try { 1219 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1220 if (iMms != null) { 1221 return iMms.addMultimediaMessageDraft(ActivityThread.currentPackageName(), 1222 contentUri); 1223 } 1224 } catch (RemoteException ex) { 1225 // ignore it 1226 } 1227 return null; 1228 } 1229 1230 /** 1231 * Send a system stored text message. 1232 * 1233 * You can only send a failed text message or a draft text message. 1234 * 1235 * @param messageUri the URI of the stored message 1236 * @param scAddress is the service center address or null to use the current default SMSC 1237 * @param sentIntent if not NULL this <code>PendingIntent</code> is 1238 * broadcast when the message is successfully sent, or failed. 1239 * The result code will be <code>Activity.RESULT_OK</code> for success, 1240 * or one of these errors:<br> 1241 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 1242 * <code>RESULT_ERROR_RADIO_OFF</code><br> 1243 * <code>RESULT_ERROR_NULL_PDU</code><br> 1244 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 1245 * the extra "errorCode" containing a radio technology specific value, 1246 * generally only useful for troubleshooting.<br> 1247 * The per-application based SMS control checks sentIntent. If sentIntent 1248 * is NULL the caller will be checked against all unknown applications, 1249 * which cause smaller number of SMS to be sent in checking period. 1250 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 1251 * broadcast when the message is delivered to the recipient. The 1252 * raw pdu of the status report is in the extended data ("pdu"). 1253 * 1254 * @throws IllegalArgumentException if messageUri is empty 1255 * {@hide} 1256 */ 1257 public void sendStoredTextMessage(Uri messageUri, String scAddress, PendingIntent sentIntent, 1258 PendingIntent deliveryIntent) { 1259 if (messageUri == null) { 1260 throw new IllegalArgumentException("Empty message URI"); 1261 } 1262 try { 1263 ISms iccISms = getISmsServiceOrThrow(); 1264 iccISms.sendStoredText(getSubId(), ActivityThread.currentPackageName(), messageUri, 1265 scAddress, sentIntent, deliveryIntent); 1266 } catch (RemoteException ex) { 1267 // ignore it 1268 } 1269 } 1270 1271 /** 1272 * Send a system stored multi-part text message. 1273 * 1274 * You can only send a failed text message or a draft text message. 1275 * The provided <code>PendingIntent</code> lists should match the part number of the 1276 * divided text of the stored message by using <code>divideMessage</code> 1277 * 1278 * @param messageUri the URI of the stored message 1279 * @param scAddress is the service center address or null to use 1280 * the current default SMSC 1281 * @param sentIntents if not null, an <code>ArrayList</code> of 1282 * <code>PendingIntent</code>s (one for each message part) that is 1283 * broadcast when the corresponding message part has been sent. 1284 * The result code will be <code>Activity.RESULT_OK</code> for success, 1285 * or one of these errors:<br> 1286 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 1287 * <code>RESULT_ERROR_RADIO_OFF</code><br> 1288 * <code>RESULT_ERROR_NULL_PDU</code><br> 1289 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> each sentIntent may include 1290 * the extra "errorCode" containing a radio technology specific value, 1291 * generally only useful for troubleshooting.<br> 1292 * The per-application based SMS control checks sentIntent. If sentIntent 1293 * is NULL the caller will be checked against all unknown applications, 1294 * which cause smaller number of SMS to be sent in checking period. 1295 * @param deliveryIntents if not null, an <code>ArrayList</code> of 1296 * <code>PendingIntent</code>s (one for each message part) that is 1297 * broadcast when the corresponding message part has been delivered 1298 * to the recipient. The raw pdu of the status report is in the 1299 * extended data ("pdu"). 1300 * 1301 * @throws IllegalArgumentException if messageUri is empty 1302 * {@hide} 1303 */ 1304 public void sendStoredMultipartTextMessage(Uri messageUri, String scAddress, 1305 ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) { 1306 if (messageUri == null) { 1307 throw new IllegalArgumentException("Empty message URI"); 1308 } 1309 try { 1310 ISms iccISms = getISmsServiceOrThrow(); 1311 iccISms.sendStoredMultipartText(getSubId(), ActivityThread.currentPackageName(), messageUri, 1312 scAddress, sentIntents, deliveryIntents); 1313 } catch (RemoteException ex) { 1314 // ignore it 1315 } 1316 } 1317 1318 /** 1319 * Send a system stored MMS message 1320 * 1321 * This is used for sending a previously sent, but failed-to-send, message or 1322 * for sending a text message that has been stored as a draft. 1323 * 1324 * @param messageUri the URI of the stored message 1325 * @param configOverrides the carrier-specific messaging configuration values to override for 1326 * sending the message. 1327 * @param sentIntent if not NULL this <code>PendingIntent</code> is 1328 * broadcast when the message is successfully sent, or failed 1329 * @throws IllegalArgumentException if messageUri is empty 1330 * {@hide} 1331 */ 1332 public void sendStoredMultimediaMessage(Uri messageUri, Bundle configOverrides, 1333 PendingIntent sentIntent) { 1334 if (messageUri == null) { 1335 throw new IllegalArgumentException("Empty message URI"); 1336 } 1337 try { 1338 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1339 if (iMms != null) { 1340 iMms.sendStoredMessage(getSubId(), ActivityThread.currentPackageName(), messageUri, 1341 configOverrides, sentIntent); 1342 } 1343 } catch (RemoteException ex) { 1344 // ignore it 1345 } 1346 } 1347 1348 /** 1349 * Turns on/off the flag to automatically write sent/received SMS/MMS messages into system 1350 * 1351 * When this flag is on, all SMS/MMS sent/received are stored by system automatically 1352 * When this flag is off, only SMS/MMS sent by non-default SMS apps are stored by system 1353 * automatically 1354 * 1355 * This flag can only be changed by default SMS apps 1356 * 1357 * @param enabled Whether to enable message auto persisting 1358 * {@hide} 1359 */ 1360 public void setAutoPersisting(boolean enabled) { 1361 try { 1362 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1363 if (iMms != null) { 1364 iMms.setAutoPersisting(ActivityThread.currentPackageName(), enabled); 1365 } 1366 } catch (RemoteException ex) { 1367 // ignore it 1368 } 1369 } 1370 1371 /** 1372 * Get the value of the flag to automatically write sent/received SMS/MMS messages into system 1373 * 1374 * When this flag is on, all SMS/MMS sent/received are stored by system automatically 1375 * When this flag is off, only SMS/MMS sent by non-default SMS apps are stored by system 1376 * automatically 1377 * 1378 * @return the current value of the auto persist flag 1379 * {@hide} 1380 */ 1381 public boolean getAutoPersisting() { 1382 try { 1383 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1384 if (iMms != null) { 1385 return iMms.getAutoPersisting(); 1386 } 1387 } catch (RemoteException ex) { 1388 // ignore it 1389 } 1390 return false; 1391 } 1392 1393 /** 1394 * Get carrier-dependent configuration values. 1395 * 1396 * @return bundle key/values pairs of configuration values 1397 */ 1398 public Bundle getCarrierConfigValues() { 1399 try { 1400 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1401 if (iMms != null) { 1402 return iMms.getCarrierConfigValues(getSubId()); 1403 } 1404 } catch (RemoteException ex) { 1405 // ignore it 1406 } 1407 return null; 1408 } 1409 1410} 1411