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