SmsManager.java revision 9dbb6ad72f064bde732111fe40ded4543b34295e
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 context.grantUriPermission(PHONE_PACKAGE_NAME, contentUri, 976 Intent.FLAG_GRANT_READ_URI_PERMISSION); 977 grantCarrierPackageUriPermission(context, contentUri, 978 Telephony.Mms.Intents.MMS_SEND_ACTION, Intent.FLAG_GRANT_READ_URI_PERMISSION); 979 980 iMms.sendMessage(getSubscriptionId(), ActivityThread.currentPackageName(), contentUri, 981 locationUrl, configOverrides, sentIntent); 982 } catch (RemoteException e) { 983 // Ignore it 984 } 985 } 986 987 private void grantCarrierPackageUriPermission(Context context, Uri contentUri, String action, 988 int permission) { 989 Intent intent = new Intent(action); 990 TelephonyManager telephonyManager = 991 (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 992 List<String> carrierPackages = telephonyManager.getCarrierPackageNamesForIntent( 993 intent); 994 if (carrierPackages != null && carrierPackages.size() == 1) { 995 context.grantUriPermission(carrierPackages.get(0), contentUri, permission); 996 } 997 } 998 999 /** 1000 * Download an MMS message from carrier by a given location URL 1001 * 1002 * @param context application context 1003 * @param locationUrl the location URL of the MMS message to be downloaded, usually obtained 1004 * from the MMS WAP push notification 1005 * @param contentUri the content uri to which the downloaded pdu will be written 1006 * @param configOverrides the carrier-specific messaging configuration values to override for 1007 * downloading the message. 1008 * @param downloadedIntent if not NULL this <code>PendingIntent</code> is 1009 * broadcast when the message is downloaded, or the download is failed 1010 * @throws IllegalArgumentException if locationUrl or contentUri is empty 1011 */ 1012 public void downloadMultimediaMessage(Context context, String locationUrl, Uri contentUri, 1013 Bundle configOverrides, PendingIntent downloadedIntent) { 1014 if (TextUtils.isEmpty(locationUrl)) { 1015 throw new IllegalArgumentException("Empty MMS location URL"); 1016 } 1017 if (contentUri == null) { 1018 throw new IllegalArgumentException("Uri contentUri null"); 1019 } 1020 try { 1021 final IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1022 if (iMms == null) { 1023 return; 1024 } 1025 context.grantUriPermission(PHONE_PACKAGE_NAME, contentUri, 1026 Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 1027 1028 grantCarrierPackageUriPermission(context, contentUri, 1029 Telephony.Mms.Intents.MMS_DOWNLOAD_ACTION, 1030 Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 1031 1032 iMms.downloadMessage( 1033 getSubscriptionId(), ActivityThread.currentPackageName(), locationUrl, 1034 contentUri, configOverrides, downloadedIntent); 1035 } catch (RemoteException e) { 1036 // Ignore it 1037 } 1038 } 1039 1040 // MMS send/download failure result codes 1041 public static final int MMS_ERROR_UNSPECIFIED = 1; 1042 public static final int MMS_ERROR_INVALID_APN = 2; 1043 public static final int MMS_ERROR_UNABLE_CONNECT_MMS = 3; 1044 public static final int MMS_ERROR_HTTP_FAILURE = 4; 1045 public static final int MMS_ERROR_IO_ERROR = 5; 1046 public static final int MMS_ERROR_RETRY = 6; 1047 public static final int MMS_ERROR_CONFIGURATION_ERROR = 7; 1048 1049 /** Intent extra name for MMS sending result data in byte array type */ 1050 public static final String EXTRA_MMS_DATA = "android.telephony.extra.MMS_DATA"; 1051 /** Intent extra name for HTTP status code for MMS HTTP failure in integer type */ 1052 public static final String EXTRA_MMS_HTTP_STATUS = "android.telephony.extra.MMS_HTTP_STATUS"; 1053 1054 /** 1055 * Update the status of a pending (send-by-IP) MMS message handled by the carrier app. 1056 * If the carrier app fails to send this message, it may be resent via carrier network 1057 * depending on the status code. 1058 * 1059 * The caller should have carrier privileges. 1060 * @see android.telephony.TelephonyManager.hasCarrierPrivileges 1061 * 1062 * @param context application context 1063 * @param messageRef the reference number of the MMS message. 1064 * @param pdu non-empty (contains the SendConf PDU) if the message was sent successfully, 1065 * otherwise, this param should be null. 1066 * @param status send status. It can be Activity.RESULT_OK or one of the MMS error codes. 1067 * If status is Activity.RESULT_OK, the MMS was sent successfully. 1068 * If status is MMS_ERROR_RETRY, this message would be resent via carrier 1069 * network. The message will not be resent for other MMS error statuses. 1070 * @param contentUri the URI of the sent message 1071 */ 1072 public void updateMmsSendStatus(Context context, int messageRef, byte[] pdu, int status, 1073 Uri contentUri) { 1074 try { 1075 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1076 if (iMms == null) { 1077 return; 1078 } 1079 iMms.updateMmsSendStatus(messageRef, pdu, status); 1080 } catch (RemoteException ex) { 1081 // ignore it 1082 } 1083 if (contentUri != null) { 1084 context.revokeUriPermission(contentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION); 1085 } 1086 } 1087 1088 /** 1089 * Update the status of a pending (download-by-IP) MMS message handled by the carrier app. 1090 * If the carrier app fails to download this message, it may be re-downloaded via carrier 1091 * network depending on the status code. 1092 * 1093 * The caller should have carrier privileges. 1094 * @see android.telephony.TelephonyManager.hasCarrierPrivileges 1095 * 1096 * @param context application context 1097 * @param messageRef the reference number of the MMS message. 1098 * @param status download status. It can be Activity.RESULT_OK or one of the MMS error codes. 1099 * If status is Activity.RESULT_OK, the MMS was downloaded successfully. 1100 * If status is MMS_ERROR_RETRY, this message would be re-downloaded via carrier 1101 * network. The message will not be re-downloaded for other MMS error statuses. 1102 * @param contentUri the URI of the downloaded message 1103 */ 1104 public void updateMmsDownloadStatus(Context context, int messageRef, int status, 1105 Uri contentUri) { 1106 try { 1107 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1108 if (iMms == null) { 1109 return; 1110 } 1111 iMms.updateMmsDownloadStatus(messageRef, status); 1112 } catch (RemoteException ex) { 1113 // ignore it 1114 } 1115 if (contentUri != null) { 1116 context.revokeUriPermission(contentUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 1117 } 1118 } 1119 1120 /** 1121 * Import a text message into system's SMS store 1122 * 1123 * Only default SMS apps can import SMS 1124 * 1125 * @param address the destination(source) address of the sent(received) message 1126 * @param type the type of the message 1127 * @param text the message text 1128 * @param timestampMillis the message timestamp in milliseconds 1129 * @param seen if the message is seen 1130 * @param read if the message is read 1131 * @return the message URI, null if failed 1132 * @hide 1133 */ 1134 public Uri importTextMessage(String address, int type, String text, long timestampMillis, 1135 boolean seen, boolean read) { 1136 try { 1137 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1138 if (iMms != null) { 1139 return iMms.importTextMessage(ActivityThread.currentPackageName(), 1140 address, type, text, timestampMillis, seen, read); 1141 } 1142 } catch (RemoteException ex) { 1143 // ignore it 1144 } 1145 return null; 1146 } 1147 1148 /** Represents the received SMS message for importing {@hide} */ 1149 public static final int SMS_TYPE_INCOMING = 0; 1150 /** Represents the sent SMS message for importing {@hide} */ 1151 public static final int SMS_TYPE_OUTGOING = 1; 1152 1153 /** 1154 * Import a multimedia message into system's MMS store. Only the following PDU type is 1155 * supported: Retrieve.conf, Send.req, Notification.ind, Delivery.ind, Read-Orig.ind 1156 * 1157 * Only default SMS apps can import MMS 1158 * 1159 * @param contentUri the content uri from which to read the PDU of the message to import 1160 * @param messageId the optional message id. Use null if not specifying 1161 * @param timestampSecs the optional message timestamp. Use -1 if not specifying 1162 * @param seen if the message is seen 1163 * @param read if the message is read 1164 * @return the message URI, null if failed 1165 * @throws IllegalArgumentException if pdu is empty 1166 * {@hide} 1167 */ 1168 public Uri importMultimediaMessage(Uri contentUri, String messageId, long timestampSecs, 1169 boolean seen, boolean read) { 1170 if (contentUri == null) { 1171 throw new IllegalArgumentException("Uri contentUri null"); 1172 } 1173 try { 1174 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1175 if (iMms != null) { 1176 return iMms.importMultimediaMessage(ActivityThread.currentPackageName(), 1177 contentUri, messageId, timestampSecs, seen, read); 1178 } 1179 } catch (RemoteException ex) { 1180 // ignore it 1181 } 1182 return null; 1183 } 1184 1185 /** 1186 * Delete a system stored SMS or MMS message 1187 * 1188 * Only default SMS apps can delete system stored SMS and MMS messages 1189 * 1190 * @param messageUri the URI of the stored message 1191 * @return true if deletion is successful, false otherwise 1192 * @throws IllegalArgumentException if messageUri is empty 1193 * {@hide} 1194 */ 1195 public boolean deleteStoredMessage(Uri messageUri) { 1196 if (messageUri == null) { 1197 throw new IllegalArgumentException("Empty message URI"); 1198 } 1199 try { 1200 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1201 if (iMms != null) { 1202 return iMms.deleteStoredMessage(ActivityThread.currentPackageName(), messageUri); 1203 } 1204 } catch (RemoteException ex) { 1205 // ignore it 1206 } 1207 return false; 1208 } 1209 1210 /** 1211 * Delete a system stored SMS or MMS thread 1212 * 1213 * Only default SMS apps can delete system stored SMS and MMS conversations 1214 * 1215 * @param conversationId the ID of the message conversation 1216 * @return true if deletion is successful, false otherwise 1217 * {@hide} 1218 */ 1219 public boolean deleteStoredConversation(long conversationId) { 1220 try { 1221 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1222 if (iMms != null) { 1223 return iMms.deleteStoredConversation( 1224 ActivityThread.currentPackageName(), conversationId); 1225 } 1226 } catch (RemoteException ex) { 1227 // ignore it 1228 } 1229 return false; 1230 } 1231 1232 /** 1233 * Update the status properties of a system stored SMS or MMS message, e.g. 1234 * the read status of a message, etc. 1235 * 1236 * @param messageUri the URI of the stored message 1237 * @param statusValues a list of status properties in key-value pairs to update 1238 * @return true if update is successful, false otherwise 1239 * @throws IllegalArgumentException if messageUri is empty 1240 * {@hide} 1241 */ 1242 public boolean updateStoredMessageStatus(Uri messageUri, ContentValues statusValues) { 1243 if (messageUri == null) { 1244 throw new IllegalArgumentException("Empty message URI"); 1245 } 1246 try { 1247 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1248 if (iMms != null) { 1249 return iMms.updateStoredMessageStatus(ActivityThread.currentPackageName(), 1250 messageUri, statusValues); 1251 } 1252 } catch (RemoteException ex) { 1253 // ignore it 1254 } 1255 return false; 1256 } 1257 1258 /** Message status property: whether the message has been seen. 1 means seen, 0 not {@hide} */ 1259 public static final String MESSAGE_STATUS_SEEN = "seen"; 1260 /** Message status property: whether the message has been read. 1 means read, 0 not {@hide} */ 1261 public static final String MESSAGE_STATUS_READ = "read"; 1262 1263 /** 1264 * Archive or unarchive a stored conversation 1265 * 1266 * @param conversationId the ID of the message conversation 1267 * @param archived true to archive the conversation, false to unarchive 1268 * @return true if update is successful, false otherwise 1269 * {@hide} 1270 */ 1271 public boolean archiveStoredConversation(long conversationId, boolean archived) { 1272 try { 1273 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1274 if (iMms != null) { 1275 return iMms.archiveStoredConversation(ActivityThread.currentPackageName(), 1276 conversationId, archived); 1277 } 1278 } catch (RemoteException ex) { 1279 // ignore it 1280 } 1281 return false; 1282 } 1283 1284 /** 1285 * Add a text message draft to system SMS store 1286 * 1287 * Only default SMS apps can add SMS draft 1288 * 1289 * @param address the destination address of message 1290 * @param text the body of the message to send 1291 * @return the URI of the stored draft message 1292 * {@hide} 1293 */ 1294 public Uri addTextMessageDraft(String address, String text) { 1295 try { 1296 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1297 if (iMms != null) { 1298 return iMms.addTextMessageDraft(ActivityThread.currentPackageName(), address, text); 1299 } 1300 } catch (RemoteException ex) { 1301 // ignore it 1302 } 1303 return null; 1304 } 1305 1306 /** 1307 * Add a multimedia message draft to system MMS store 1308 * 1309 * Only default SMS apps can add MMS draft 1310 * 1311 * @param contentUri the content uri from which to read the PDU data of the draft MMS 1312 * @return the URI of the stored draft message 1313 * @throws IllegalArgumentException if pdu is empty 1314 * {@hide} 1315 */ 1316 public Uri addMultimediaMessageDraft(Uri contentUri) { 1317 if (contentUri == null) { 1318 throw new IllegalArgumentException("Uri contentUri null"); 1319 } 1320 try { 1321 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1322 if (iMms != null) { 1323 return iMms.addMultimediaMessageDraft(ActivityThread.currentPackageName(), 1324 contentUri); 1325 } 1326 } catch (RemoteException ex) { 1327 // ignore it 1328 } 1329 return null; 1330 } 1331 1332 /** 1333 * Send a system stored text message. 1334 * 1335 * You can only send a failed text message or a draft text message. 1336 * 1337 * @param messageUri the URI of the stored message 1338 * @param scAddress is the service center address or null to use the current default SMSC 1339 * @param sentIntent if not NULL this <code>PendingIntent</code> is 1340 * broadcast when the message is successfully sent, or failed. 1341 * The result code will be <code>Activity.RESULT_OK</code> for success, 1342 * or one of these errors:<br> 1343 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 1344 * <code>RESULT_ERROR_RADIO_OFF</code><br> 1345 * <code>RESULT_ERROR_NULL_PDU</code><br> 1346 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 1347 * the extra "errorCode" containing a radio technology specific value, 1348 * generally only useful for troubleshooting.<br> 1349 * The per-application based SMS control checks sentIntent. If sentIntent 1350 * is NULL the caller will be checked against all unknown applications, 1351 * which cause smaller number of SMS to be sent in checking period. 1352 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 1353 * broadcast when the message is delivered to the recipient. The 1354 * raw pdu of the status report is in the extended data ("pdu"). 1355 * 1356 * @throws IllegalArgumentException if messageUri is empty 1357 * {@hide} 1358 */ 1359 public void sendStoredTextMessage(Uri messageUri, String scAddress, PendingIntent sentIntent, 1360 PendingIntent deliveryIntent) { 1361 if (messageUri == null) { 1362 throw new IllegalArgumentException("Empty message URI"); 1363 } 1364 try { 1365 ISms iccISms = getISmsServiceOrThrow(); 1366 iccISms.sendStoredText( 1367 getSubscriptionId(), ActivityThread.currentPackageName(), messageUri, 1368 scAddress, sentIntent, deliveryIntent); 1369 } catch (RemoteException ex) { 1370 // ignore it 1371 } 1372 } 1373 1374 /** 1375 * Send a system stored multi-part text message. 1376 * 1377 * You can only send a failed text message or a draft text message. 1378 * The provided <code>PendingIntent</code> lists should match the part number of the 1379 * divided text of the stored message by using <code>divideMessage</code> 1380 * 1381 * @param messageUri the URI of the stored message 1382 * @param scAddress is the service center address or null to use 1383 * the current default SMSC 1384 * @param sentIntents if not null, an <code>ArrayList</code> of 1385 * <code>PendingIntent</code>s (one for each message part) that is 1386 * broadcast when the corresponding message part has been sent. 1387 * The result code will be <code>Activity.RESULT_OK</code> for success, 1388 * or one of these errors:<br> 1389 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 1390 * <code>RESULT_ERROR_RADIO_OFF</code><br> 1391 * <code>RESULT_ERROR_NULL_PDU</code><br> 1392 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> each sentIntent may include 1393 * the extra "errorCode" containing a radio technology specific value, 1394 * generally only useful for troubleshooting.<br> 1395 * The per-application based SMS control checks sentIntent. If sentIntent 1396 * is NULL the caller will be checked against all unknown applications, 1397 * which cause smaller number of SMS to be sent in checking period. 1398 * @param deliveryIntents if not null, an <code>ArrayList</code> of 1399 * <code>PendingIntent</code>s (one for each message part) that is 1400 * broadcast when the corresponding message part has been delivered 1401 * to the recipient. The raw pdu of the status report is in the 1402 * extended data ("pdu"). 1403 * 1404 * @throws IllegalArgumentException if messageUri is empty 1405 * {@hide} 1406 */ 1407 public void sendStoredMultipartTextMessage(Uri messageUri, String scAddress, 1408 ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) { 1409 if (messageUri == null) { 1410 throw new IllegalArgumentException("Empty message URI"); 1411 } 1412 try { 1413 ISms iccISms = getISmsServiceOrThrow(); 1414 iccISms.sendStoredMultipartText( 1415 getSubscriptionId(), ActivityThread.currentPackageName(), messageUri, 1416 scAddress, sentIntents, deliveryIntents); 1417 } catch (RemoteException ex) { 1418 // ignore it 1419 } 1420 } 1421 1422 /** 1423 * Send a system stored MMS message 1424 * 1425 * This is used for sending a previously sent, but failed-to-send, message or 1426 * for sending a text message that has been stored as a draft. 1427 * 1428 * @param messageUri the URI of the stored message 1429 * @param configOverrides the carrier-specific messaging configuration values to override for 1430 * sending the message. 1431 * @param sentIntent if not NULL this <code>PendingIntent</code> is 1432 * broadcast when the message is successfully sent, or failed 1433 * @throws IllegalArgumentException if messageUri is empty 1434 * {@hide} 1435 */ 1436 public void sendStoredMultimediaMessage(Uri messageUri, Bundle configOverrides, 1437 PendingIntent sentIntent) { 1438 if (messageUri == null) { 1439 throw new IllegalArgumentException("Empty message URI"); 1440 } 1441 try { 1442 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1443 if (iMms != null) { 1444 iMms.sendStoredMessage( 1445 getSubscriptionId(), ActivityThread.currentPackageName(), messageUri, 1446 configOverrides, sentIntent); 1447 } 1448 } catch (RemoteException ex) { 1449 // ignore it 1450 } 1451 } 1452 1453 /** 1454 * Turns on/off 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 * This flag can only be changed by default SMS apps 1461 * 1462 * @param enabled Whether to enable message auto persisting 1463 * {@hide} 1464 */ 1465 public void setAutoPersisting(boolean enabled) { 1466 try { 1467 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1468 if (iMms != null) { 1469 iMms.setAutoPersisting(ActivityThread.currentPackageName(), enabled); 1470 } 1471 } catch (RemoteException ex) { 1472 // ignore it 1473 } 1474 } 1475 1476 /** 1477 * Get the value of the flag to automatically write sent/received SMS/MMS messages into system 1478 * 1479 * When this flag is on, all SMS/MMS sent/received are stored by system automatically 1480 * When this flag is off, only SMS/MMS sent by non-default SMS apps are stored by system 1481 * automatically 1482 * 1483 * @return the current value of the auto persist flag 1484 * {@hide} 1485 */ 1486 public boolean getAutoPersisting() { 1487 try { 1488 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1489 if (iMms != null) { 1490 return iMms.getAutoPersisting(); 1491 } 1492 } catch (RemoteException ex) { 1493 // ignore it 1494 } 1495 return false; 1496 } 1497 1498 /** 1499 * Get carrier-dependent configuration values. 1500 * 1501 * @return bundle key/values pairs of configuration values 1502 */ 1503 public Bundle getCarrierConfigValues() { 1504 try { 1505 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1506 if (iMms != null) { 1507 return iMms.getCarrierConfigValues(getSubscriptionId()); 1508 } 1509 } catch (RemoteException ex) { 1510 // ignore it 1511 } 1512 return null; 1513 } 1514 1515} 1516