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