SmsManager.java revision 70792f37a321bcd0399ae6fd00140db9c3ec9746
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 SubscriptionManager 464 * @return the instance of the SmsManager associated with subId 465 * 466 * {@hide} 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 SubscriptionManager.INVALID_SUB_ID if the default 488 * subId cannot be determined. 489 * 490 * @return associated subId 491 * 492 * {@hide} 493 */ 494 public long getSubId() { 495 // TODO(shri): Add javadoc link once SubscriptionManager is made public api 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 the default sms subId 846 * 847 * @return the default subId 848 * @hide 849 */ 850 public static long getDefaultSmsSubId() { 851 ISms iccISms = null; 852 try { 853 iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); 854 return (long) iccISms.getPreferredSmsSubscription(); 855 } catch (RemoteException ex) { 856 return DEFAULT_SUB_ID; 857 } catch (NullPointerException ex) { 858 return DEFAULT_SUB_ID; 859 } 860 } 861 862 /** 863 * Get SMS prompt property, enabled or not 864 * 865 * @return true if enabled, false otherwise 866 * @hide 867 */ 868 public boolean isSMSPromptEnabled() { 869 ISms iccISms = null; 870 try { 871 iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); 872 return iccISms.isSMSPromptEnabled(); 873 } catch (RemoteException ex) { 874 return false; 875 } catch (NullPointerException ex) { 876 return false; 877 } 878 } 879 880 // see SmsMessage.getStatusOnIcc 881 882 /** Free space (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 883 static public final int STATUS_ON_ICC_FREE = 0; 884 885 /** Received and read (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 886 static public final int STATUS_ON_ICC_READ = 1; 887 888 /** Received and unread (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 889 static public final int STATUS_ON_ICC_UNREAD = 3; 890 891 /** Stored and sent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 892 static public final int STATUS_ON_ICC_SENT = 5; 893 894 /** Stored and unsent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 895 static public final int STATUS_ON_ICC_UNSENT = 7; 896 897 // SMS send failure result codes 898 899 /** Generic failure cause */ 900 static public final int RESULT_ERROR_GENERIC_FAILURE = 1; 901 /** Failed because radio was explicitly turned off */ 902 static public final int RESULT_ERROR_RADIO_OFF = 2; 903 /** Failed because no pdu provided */ 904 static public final int RESULT_ERROR_NULL_PDU = 3; 905 /** Failed because service is currently unavailable */ 906 static public final int RESULT_ERROR_NO_SERVICE = 4; 907 /** Failed because we reached the sending queue limit. {@hide} */ 908 static public final int RESULT_ERROR_LIMIT_EXCEEDED = 5; 909 /** Failed because FDN is enabled. {@hide} */ 910 static public final int RESULT_ERROR_FDN_CHECK_FAILURE = 6; 911 912 /** 913 * Send an MMS message 914 * 915 * @param contentUri the content Uri from which the message pdu will be read 916 * @param locationUrl the optional location url where message should be sent to 917 * @param configOverrides the carrier-specific messaging configuration values to override for 918 * sending the message. 919 * @param sentIntent if not NULL this <code>PendingIntent</code> is 920 * broadcast when the message is successfully sent, or failed 921 * @throws IllegalArgumentException if contentUri is empty 922 */ 923 public void sendMultimediaMessage(Uri contentUri, String locationUrl, 924 Bundle configOverrides, PendingIntent sentIntent) { 925 if (contentUri == null) { 926 throw new IllegalArgumentException("Uri contentUri null"); 927 } 928 try { 929 final IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 930 if (iMms == null) { 931 return; 932 } 933 iMms.sendMessage(getSubId(), ActivityThread.currentPackageName(), contentUri, 934 locationUrl, configOverrides, sentIntent); 935 } catch (RemoteException e) { 936 // Ignore it 937 } 938 } 939 940 /** 941 * Download an MMS message from carrier by a given location URL 942 * 943 * @param locationUrl the location URL of the MMS message to be downloaded, usually obtained 944 * from the MMS WAP push notification 945 * @param contentUri the content uri to which the downloaded pdu will be written 946 * @param configOverrides the carrier-specific messaging configuration values to override for 947 * downloading the message. 948 * @param downloadedIntent if not NULL this <code>PendingIntent</code> is 949 * broadcast when the message is downloaded, or the download is failed 950 * @throws IllegalArgumentException if locationUrl or contentUri is empty 951 */ 952 public void downloadMultimediaMessage(String locationUrl, Uri contentUri, 953 Bundle configOverrides, PendingIntent downloadedIntent) { 954 if (TextUtils.isEmpty(locationUrl)) { 955 throw new IllegalArgumentException("Empty MMS location URL"); 956 } 957 if (contentUri == null) { 958 throw new IllegalArgumentException("Uri contentUri null"); 959 } 960 try { 961 final IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 962 if (iMms == null) { 963 return; 964 } 965 iMms.downloadMessage(getSubId(), ActivityThread.currentPackageName(), locationUrl, 966 contentUri, configOverrides, downloadedIntent); 967 } catch (RemoteException e) { 968 // Ignore it 969 } 970 } 971 972 // MMS send/download failure result codes 973 public static final int MMS_ERROR_UNSPECIFIED = 1; 974 public static final int MMS_ERROR_INVALID_APN = 2; 975 public static final int MMS_ERROR_UNABLE_CONNECT_MMS = 3; 976 public static final int MMS_ERROR_HTTP_FAILURE = 4; 977 public static final int MMS_ERROR_IO_ERROR = 5; 978 979 // Intent extra name for result data 980 public static final String EXTRA_MMS_DATA = "android.telephony.extra.MMS_DATA"; 981 982 /** 983 * Update the status of a pending (send-by-IP) MMS message handled by the carrier app. 984 * If the carrier app fails to send this message, it would be resent via carrier network. 985 * 986 * The caller should have carrier privileges. 987 * @see android.telephony.TelephonyManager.hasCarrierPrivileges 988 * 989 * @param messageRef the reference number of the MMS message. 990 * @param success True if and only if the message was sent successfully. If its value is 991 * false, this message should be resent via carrier network 992 */ 993 public void updateMmsSendStatus(int messageRef, boolean success) { 994 try { 995 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 996 if (iMms == null) { 997 return; 998 } 999 iMms.updateMmsSendStatus(messageRef, success); 1000 } catch (RemoteException ex) { 1001 // ignore it 1002 } 1003 } 1004 1005 /** 1006 * Update the status of a pending (download-by-IP) MMS message handled by the carrier app. 1007 * If the carrier app fails to download this message, it would be re-downloaded via carrier 1008 * network. 1009 * 1010 * The caller should have carrier privileges. 1011 * @see android.telephony.TelephonyManager.hasCarrierPrivileges 1012 * 1013 * @param messageRef the reference number of the MMS message. 1014 * @param pdu non-empty if downloaded successfully, otherwise, it is empty and the message 1015 * will be downloaded via carrier network 1016 */ 1017 public void updateMmsDownloadStatus(int messageRef, byte[] pdu) { 1018 try { 1019 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1020 if (iMms == null) { 1021 return; 1022 } 1023 iMms.updateMmsDownloadStatus(messageRef, pdu); 1024 } catch (RemoteException ex) { 1025 // ignore it 1026 } 1027 } 1028 1029 /** 1030 * Import a text message into system's SMS store 1031 * 1032 * Only default SMS apps can import SMS 1033 * 1034 * @param address the destination(source) address of the sent(received) message 1035 * @param type the type of the message 1036 * @param text the message text 1037 * @param timestampMillis the message timestamp in milliseconds 1038 * @param seen if the message is seen 1039 * @param read if the message is read 1040 * @return the message URI, null if failed 1041 * @hide 1042 */ 1043 public Uri importTextMessage(String address, int type, String text, long timestampMillis, 1044 boolean seen, boolean read) { 1045 try { 1046 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1047 if (iMms != null) { 1048 return iMms.importTextMessage(ActivityThread.currentPackageName(), 1049 address, type, text, timestampMillis, seen, read); 1050 } 1051 } catch (RemoteException ex) { 1052 // ignore it 1053 } 1054 return null; 1055 } 1056 1057 /** Represents the received SMS message for importing {@hide} */ 1058 public static final int SMS_TYPE_INCOMING = 0; 1059 /** Represents the sent SMS message for importing {@hide} */ 1060 public static final int SMS_TYPE_OUTGOING = 1; 1061 1062 /** 1063 * Import a multimedia message into system's MMS store. Only the following PDU type is 1064 * supported: Retrieve.conf, Send.req, Notification.ind, Delivery.ind, Read-Orig.ind 1065 * 1066 * Only default SMS apps can import MMS 1067 * 1068 * @param contentUri the content uri from which to read the PDU of the message to import 1069 * @param messageId the optional message id. Use null if not specifying 1070 * @param timestampSecs the optional message timestamp. Use -1 if not specifying 1071 * @param seen if the message is seen 1072 * @param read if the message is read 1073 * @return the message URI, null if failed 1074 * @throws IllegalArgumentException if pdu is empty 1075 * {@hide} 1076 */ 1077 public Uri importMultimediaMessage(Uri contentUri, String messageId, long timestampSecs, 1078 boolean seen, boolean read) { 1079 if (contentUri == null) { 1080 throw new IllegalArgumentException("Uri contentUri null"); 1081 } 1082 try { 1083 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1084 if (iMms != null) { 1085 return iMms.importMultimediaMessage(ActivityThread.currentPackageName(), 1086 contentUri, messageId, timestampSecs, seen, read); 1087 } 1088 } catch (RemoteException ex) { 1089 // ignore it 1090 } 1091 return null; 1092 } 1093 1094 /** 1095 * Delete a system stored SMS or MMS message 1096 * 1097 * Only default SMS apps can delete system stored SMS and MMS messages 1098 * 1099 * @param messageUri the URI of the stored message 1100 * @return true if deletion is successful, false otherwise 1101 * @throws IllegalArgumentException if messageUri is empty 1102 * {@hide} 1103 */ 1104 public boolean deleteStoredMessage(Uri messageUri) { 1105 if (messageUri == null) { 1106 throw new IllegalArgumentException("Empty message URI"); 1107 } 1108 try { 1109 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1110 if (iMms != null) { 1111 return iMms.deleteStoredMessage(ActivityThread.currentPackageName(), messageUri); 1112 } 1113 } catch (RemoteException ex) { 1114 // ignore it 1115 } 1116 return false; 1117 } 1118 1119 /** 1120 * Delete a system stored SMS or MMS thread 1121 * 1122 * Only default SMS apps can delete system stored SMS and MMS conversations 1123 * 1124 * @param conversationId the ID of the message conversation 1125 * @return true if deletion is successful, false otherwise 1126 * {@hide} 1127 */ 1128 public boolean deleteStoredConversation(long conversationId) { 1129 try { 1130 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1131 if (iMms != null) { 1132 return iMms.deleteStoredConversation( 1133 ActivityThread.currentPackageName(), conversationId); 1134 } 1135 } catch (RemoteException ex) { 1136 // ignore it 1137 } 1138 return false; 1139 } 1140 1141 /** 1142 * Update the status properties of a system stored SMS or MMS message, e.g. 1143 * the read status of a message, etc. 1144 * 1145 * @param messageUri the URI of the stored message 1146 * @param statusValues a list of status properties in key-value pairs to update 1147 * @return true if update is successful, false otherwise 1148 * @throws IllegalArgumentException if messageUri is empty 1149 * {@hide} 1150 */ 1151 public boolean updateStoredMessageStatus(Uri messageUri, ContentValues statusValues) { 1152 if (messageUri == null) { 1153 throw new IllegalArgumentException("Empty message URI"); 1154 } 1155 try { 1156 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1157 if (iMms != null) { 1158 return iMms.updateStoredMessageStatus(ActivityThread.currentPackageName(), 1159 messageUri, statusValues); 1160 } 1161 } catch (RemoteException ex) { 1162 // ignore it 1163 } 1164 return false; 1165 } 1166 1167 /** Message status property: whether the message has been seen. 1 means seen, 0 not {@hide} */ 1168 public static final String MESSAGE_STATUS_SEEN = "seen"; 1169 /** Message status property: whether the message has been read. 1 means read, 0 not {@hide} */ 1170 public static final String MESSAGE_STATUS_READ = "read"; 1171 1172 /** 1173 * Archive or unarchive a stored conversation 1174 * 1175 * @param conversationId the ID of the message conversation 1176 * @param archived true to archive the conversation, false to unarchive 1177 * @return true if update is successful, false otherwise 1178 * {@hide} 1179 */ 1180 public boolean archiveStoredConversation(long conversationId, boolean archived) { 1181 try { 1182 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1183 if (iMms != null) { 1184 return iMms.archiveStoredConversation(ActivityThread.currentPackageName(), 1185 conversationId, archived); 1186 } 1187 } catch (RemoteException ex) { 1188 // ignore it 1189 } 1190 return false; 1191 } 1192 1193 /** 1194 * Add a text message draft to system SMS store 1195 * 1196 * Only default SMS apps can add SMS draft 1197 * 1198 * @param address the destination address of message 1199 * @param text the body of the message to send 1200 * @return the URI of the stored draft message 1201 * {@hide} 1202 */ 1203 public Uri addTextMessageDraft(String address, String text) { 1204 try { 1205 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1206 if (iMms != null) { 1207 return iMms.addTextMessageDraft(ActivityThread.currentPackageName(), address, text); 1208 } 1209 } catch (RemoteException ex) { 1210 // ignore it 1211 } 1212 return null; 1213 } 1214 1215 /** 1216 * Add a multimedia message draft to system MMS store 1217 * 1218 * Only default SMS apps can add MMS draft 1219 * 1220 * @param contentUri the content uri from which to read the PDU data of the draft MMS 1221 * @return the URI of the stored draft message 1222 * @throws IllegalArgumentException if pdu is empty 1223 * {@hide} 1224 */ 1225 public Uri addMultimediaMessageDraft(Uri contentUri) { 1226 if (contentUri == null) { 1227 throw new IllegalArgumentException("Uri contentUri null"); 1228 } 1229 try { 1230 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1231 if (iMms != null) { 1232 return iMms.addMultimediaMessageDraft(ActivityThread.currentPackageName(), 1233 contentUri); 1234 } 1235 } catch (RemoteException ex) { 1236 // ignore it 1237 } 1238 return null; 1239 } 1240 1241 /** 1242 * Send a system stored text message. 1243 * 1244 * You can only send a failed text message or a draft text message. 1245 * 1246 * @param messageUri the URI of the stored message 1247 * @param scAddress is the service center address or null to use the current default SMSC 1248 * @param sentIntent if not NULL this <code>PendingIntent</code> is 1249 * broadcast when the message is successfully sent, or failed. 1250 * The result code will be <code>Activity.RESULT_OK</code> for success, 1251 * or one of these errors:<br> 1252 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 1253 * <code>RESULT_ERROR_RADIO_OFF</code><br> 1254 * <code>RESULT_ERROR_NULL_PDU</code><br> 1255 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 1256 * the extra "errorCode" containing a radio technology specific value, 1257 * generally only useful for troubleshooting.<br> 1258 * The per-application based SMS control checks sentIntent. If sentIntent 1259 * is NULL the caller will be checked against all unknown applications, 1260 * which cause smaller number of SMS to be sent in checking period. 1261 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 1262 * broadcast when the message is delivered to the recipient. The 1263 * raw pdu of the status report is in the extended data ("pdu"). 1264 * 1265 * @throws IllegalArgumentException if messageUri is empty 1266 * {@hide} 1267 */ 1268 public void sendStoredTextMessage(Uri messageUri, String scAddress, PendingIntent sentIntent, 1269 PendingIntent deliveryIntent) { 1270 if (messageUri == null) { 1271 throw new IllegalArgumentException("Empty message URI"); 1272 } 1273 try { 1274 ISms iccISms = getISmsServiceOrThrow(); 1275 iccISms.sendStoredText(getSubId(), ActivityThread.currentPackageName(), messageUri, 1276 scAddress, sentIntent, deliveryIntent); 1277 } catch (RemoteException ex) { 1278 // ignore it 1279 } 1280 } 1281 1282 /** 1283 * Send a system stored multi-part text message. 1284 * 1285 * You can only send a failed text message or a draft text message. 1286 * The provided <code>PendingIntent</code> lists should match the part number of the 1287 * divided text of the stored message by using <code>divideMessage</code> 1288 * 1289 * @param messageUri the URI of the stored message 1290 * @param scAddress is the service center address or null to use 1291 * the current default SMSC 1292 * @param sentIntents if not null, an <code>ArrayList</code> of 1293 * <code>PendingIntent</code>s (one for each message part) that is 1294 * broadcast when the corresponding message part has been sent. 1295 * The result code will be <code>Activity.RESULT_OK</code> for success, 1296 * or one of these errors:<br> 1297 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 1298 * <code>RESULT_ERROR_RADIO_OFF</code><br> 1299 * <code>RESULT_ERROR_NULL_PDU</code><br> 1300 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> each sentIntent may include 1301 * the extra "errorCode" containing a radio technology specific value, 1302 * generally only useful for troubleshooting.<br> 1303 * The per-application based SMS control checks sentIntent. If sentIntent 1304 * is NULL the caller will be checked against all unknown applications, 1305 * which cause smaller number of SMS to be sent in checking period. 1306 * @param deliveryIntents if not null, an <code>ArrayList</code> of 1307 * <code>PendingIntent</code>s (one for each message part) that is 1308 * broadcast when the corresponding message part has been delivered 1309 * to the recipient. The raw pdu of the status report is in the 1310 * extended data ("pdu"). 1311 * 1312 * @throws IllegalArgumentException if messageUri is empty 1313 * {@hide} 1314 */ 1315 public void sendStoredMultipartTextMessage(Uri messageUri, String scAddress, 1316 ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) { 1317 if (messageUri == null) { 1318 throw new IllegalArgumentException("Empty message URI"); 1319 } 1320 try { 1321 ISms iccISms = getISmsServiceOrThrow(); 1322 iccISms.sendStoredMultipartText(getSubId(), ActivityThread.currentPackageName(), messageUri, 1323 scAddress, sentIntents, deliveryIntents); 1324 } catch (RemoteException ex) { 1325 // ignore it 1326 } 1327 } 1328 1329 /** 1330 * Send a system stored MMS message 1331 * 1332 * This is used for sending a previously sent, but failed-to-send, message or 1333 * for sending a text message that has been stored as a draft. 1334 * 1335 * @param messageUri the URI of the stored message 1336 * @param configOverrides the carrier-specific messaging configuration values to override for 1337 * sending the message. 1338 * @param sentIntent if not NULL this <code>PendingIntent</code> is 1339 * broadcast when the message is successfully sent, or failed 1340 * @throws IllegalArgumentException if messageUri is empty 1341 * {@hide} 1342 */ 1343 public void sendStoredMultimediaMessage(Uri messageUri, Bundle configOverrides, 1344 PendingIntent sentIntent) { 1345 if (messageUri == null) { 1346 throw new IllegalArgumentException("Empty message URI"); 1347 } 1348 try { 1349 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1350 if (iMms != null) { 1351 iMms.sendStoredMessage(getSubId(), ActivityThread.currentPackageName(), messageUri, 1352 configOverrides, sentIntent); 1353 } 1354 } catch (RemoteException ex) { 1355 // ignore it 1356 } 1357 } 1358 1359 /** 1360 * Turns on/off the flag to automatically write sent/received SMS/MMS messages into system 1361 * 1362 * When this flag is on, all SMS/MMS sent/received are stored by system automatically 1363 * When this flag is off, only SMS/MMS sent by non-default SMS apps are stored by system 1364 * automatically 1365 * 1366 * This flag can only be changed by default SMS apps 1367 * 1368 * @param enabled Whether to enable message auto persisting 1369 * {@hide} 1370 */ 1371 public void setAutoPersisting(boolean enabled) { 1372 try { 1373 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1374 if (iMms != null) { 1375 iMms.setAutoPersisting(ActivityThread.currentPackageName(), enabled); 1376 } 1377 } catch (RemoteException ex) { 1378 // ignore it 1379 } 1380 } 1381 1382 /** 1383 * Get the value of the flag to automatically write sent/received SMS/MMS messages into system 1384 * 1385 * When this flag is on, all SMS/MMS sent/received are stored by system automatically 1386 * When this flag is off, only SMS/MMS sent by non-default SMS apps are stored by system 1387 * automatically 1388 * 1389 * @return the current value of the auto persist flag 1390 * {@hide} 1391 */ 1392 public boolean getAutoPersisting() { 1393 try { 1394 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1395 if (iMms != null) { 1396 return iMms.getAutoPersisting(); 1397 } 1398 } catch (RemoteException ex) { 1399 // ignore it 1400 } 1401 return false; 1402 } 1403 1404 /** 1405 * Get carrier-dependent configuration values. 1406 * 1407 * @return bundle key/values pairs of configuration values 1408 */ 1409 public Bundle getCarrierConfigValues() { 1410 try { 1411 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1412 if (iMms != null) { 1413 return iMms.getCarrierConfigValues(getSubId()); 1414 } 1415 } catch (RemoteException ex) { 1416 // ignore it 1417 } 1418 return null; 1419 } 1420 1421} 1422