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