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