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 17 package android.telephony; 18 19 import android.app.ActivityThread; 20 import android.app.PendingIntent; 21 import android.content.ContentValues; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.net.Uri; 25 import android.os.Bundle; 26 import android.os.RemoteException; 27 import android.os.ServiceManager; 28 import android.provider.Telephony; 29 import android.text.TextUtils; 30 import android.util.ArrayMap; 31 import android.util.Log; 32 33 import com.android.internal.telephony.ISms; 34 import com.android.internal.telephony.SmsRawData; 35 import com.android.internal.telephony.IMms; 36 import com.android.internal.telephony.uicc.IccConstants; 37 38 import java.util.ArrayList; 39 import java.util.Arrays; 40 import java.util.List; 41 import 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 */ 57 public 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.sendText(ActivityThread.currentPackageName(), destinationAddress, 252 scAddress, text, sentIntent, deliveryIntent); 253 } catch (RemoteException ex) { 254 // ignore it 255 } 256 } 257 258 /** 259 * Inject an SMS PDU into the android application framework. 260 * 261 * The caller should have carrier privileges. 262 * @see android.telephony.TelephonyManager.hasCarrierPrivileges 263 * 264 * @param pdu is the byte array of pdu to be injected into android application framework 265 * @param format is the format of SMS pdu (3gpp or 3gpp2) 266 * @param receivedIntent if not NULL this <code>PendingIntent</code> is 267 * broadcast when the message is successfully received by the 268 * android application framework. This intent is broadcasted at 269 * the same time an SMS received from radio is acknowledged back. 270 * 271 * @throws IllegalArgumentException if format is not one of 3gpp and 3gpp2. 272 * {@hide} 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 * {@hide} 302 */ 303 public void updateSmsSendStatus(int messageRef, boolean success) { 304 try { 305 ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); 306 if (iccISms != null) { 307 iccISms.updateSmsSendStatus(messageRef, success); 308 } 309 } catch (RemoteException ex) { 310 // ignore it 311 } 312 } 313 314 /** 315 * Divide a message text into several fragments, none bigger than 316 * the maximum SMS message size. 317 * 318 * @param text the original message. Must not be null. 319 * @return an <code>ArrayList</code> of strings that, in order, 320 * comprise the original message 321 * 322 * @throws IllegalArgumentException if text is null 323 */ 324 public ArrayList<String> divideMessage(String text) { 325 if (null == text) { 326 throw new IllegalArgumentException("text is null"); 327 } 328 return SmsMessage.fragmentText(text); 329 } 330 331 /** 332 * Send a multi-part text based SMS. The callee should have already 333 * divided the message into correctly sized parts by calling 334 * <code>divideMessage</code>. 335 * 336 * <p class="note"><strong>Note:</strong> Using this method requires that your app has the 337 * {@link android.Manifest.permission#SEND_SMS} permission.</p> 338 * 339 * <p class="note"><strong>Note:</strong> Beginning with Android 4.4 (API level 19), if 340 * <em>and only if</em> an app is not selected as the default SMS app, the system automatically 341 * writes messages sent using this method to the SMS Provider (the default SMS app is always 342 * responsible for writing its sent messages to the SMS Provider). For information about 343 * how to behave as the default SMS app, see {@link android.provider.Telephony}.</p> 344 * 345 * @param destinationAddress the address to send the message to 346 * @param scAddress is the service center address or null to use 347 * the current default SMSC 348 * @param parts an <code>ArrayList</code> of strings that, in order, 349 * comprise the original message 350 * @param sentIntents if not null, an <code>ArrayList</code> of 351 * <code>PendingIntent</code>s (one for each message part) that is 352 * broadcast when the corresponding message part has been sent. 353 * The result code will be <code>Activity.RESULT_OK</code> for success, 354 * or one of these errors:<br> 355 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 356 * <code>RESULT_ERROR_RADIO_OFF</code><br> 357 * <code>RESULT_ERROR_NULL_PDU</code><br> 358 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> each sentIntent may include 359 * the extra "errorCode" containing a radio technology specific value, 360 * generally only useful for troubleshooting.<br> 361 * The per-application based SMS control checks sentIntent. If sentIntent 362 * is NULL the caller will be checked against all unknown applications, 363 * which cause smaller number of SMS to be sent in checking period. 364 * @param deliveryIntents if not null, an <code>ArrayList</code> of 365 * <code>PendingIntent</code>s (one for each message part) that is 366 * broadcast when the corresponding message part has been delivered 367 * to the recipient. The raw pdu of the status report is in the 368 * extended data ("pdu"). 369 * 370 * @throws IllegalArgumentException if destinationAddress or data are empty 371 */ 372 public void sendMultipartTextMessage( 373 String destinationAddress, String scAddress, ArrayList<String> parts, 374 ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) { 375 if (TextUtils.isEmpty(destinationAddress)) { 376 throw new IllegalArgumentException("Invalid destinationAddress"); 377 } 378 if (parts == null || parts.size() < 1) { 379 throw new IllegalArgumentException("Invalid message body"); 380 } 381 382 if (parts.size() > 1) { 383 try { 384 ISms iccISms = getISmsServiceOrThrow(); 385 iccISms.sendMultipartText(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.sendData(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 default instance of the SmsManager 458 * 459 * @return the default instance of the SmsManager 460 */ 461 public static SmsManager getDefault() { 462 return sInstance; 463 } 464 465 /** 466 * Get the the instance of the SmsManager associated with a particular subId 467 * 468 * @param subId a SMS subscription id, typically accessed using SubscriptionManager 469 * @return the instance of the SmsManager associated with subId 470 * 471 * {@hide} 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 SubscriptionManager.INVALID_SUB_ID if the default 493 * subId cannot be determined. 494 * 495 * @return associated subId 496 * 497 * {@hide} 498 */ 499 public long getSubId() { 500 // TODO(shri): Add javadoc link once SubscriptionManager is made public api 501 if (mSubId == DEFAULT_SUB_ID) { 502 return getDefaultSmsSubId(); 503 } 504 return mSubId; 505 } 506 507 /** 508 * Returns the ISms service, or throws an UnsupportedOperationException if 509 * the service does not exist. 510 */ 511 private static ISms getISmsServiceOrThrow() { 512 ISms iccISms = getISmsService(); 513 if (iccISms == null) { 514 throw new UnsupportedOperationException("Sms is not supported"); 515 } 516 return iccISms; 517 } 518 519 private static ISms getISmsService() { 520 return ISms.Stub.asInterface(ServiceManager.getService("isms")); 521 } 522 523 /** 524 * Copy a raw SMS PDU to the ICC. 525 * ICC (Integrated Circuit Card) is the card of the device. 526 * For example, this can be the SIM or USIM for GSM. 527 * 528 * @param smsc the SMSC for this message, or NULL for the default SMSC 529 * @param pdu the raw PDU to store 530 * @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD, 531 * STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT) 532 * @return true for success 533 * 534 * @throws IllegalArgumentException if pdu is NULL 535 * {@hide} 536 */ 537 public boolean copyMessageToIcc(byte[] smsc, byte[] pdu,int status) { 538 boolean success = false; 539 540 if (null == pdu) { 541 throw new IllegalArgumentException("pdu is NULL"); 542 } 543 try { 544 ISms iccISms = getISmsService(); 545 if (iccISms != null) { 546 success = iccISms.copyMessageToIccEf(ActivityThread.currentPackageName(), 547 status, pdu, smsc); 548 } 549 } catch (RemoteException ex) { 550 // ignore it 551 } 552 553 return success; 554 } 555 556 /** 557 * Delete the specified message from the ICC. 558 * ICC (Integrated Circuit Card) is the card of the device. 559 * For example, this can be the SIM or USIM for GSM. 560 * 561 * @param messageIndex is the record index of the message on ICC 562 * @return true for success 563 * 564 * {@hide} 565 */ 566 public boolean 567 deleteMessageFromIcc(int messageIndex) { 568 boolean success = false; 569 byte[] pdu = new byte[IccConstants.SMS_RECORD_LENGTH-1]; 570 Arrays.fill(pdu, (byte)0xff); 571 572 try { 573 ISms iccISms = getISmsService(); 574 if (iccISms != null) { 575 success = iccISms.updateMessageOnIccEf(ActivityThread.currentPackageName(), 576 messageIndex, STATUS_ON_ICC_FREE, pdu); 577 } 578 } catch (RemoteException ex) { 579 // ignore it 580 } 581 582 return success; 583 } 584 585 /** 586 * Update the specified message on the ICC. 587 * ICC (Integrated Circuit Card) is the card of the device. 588 * For example, this can be the SIM or USIM for GSM. 589 * 590 * @param messageIndex record index of message to update 591 * @param newStatus new message status (STATUS_ON_ICC_READ, 592 * STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT, 593 * STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE) 594 * @param pdu the raw PDU to store 595 * @return true for success 596 * 597 * {@hide} 598 */ 599 public boolean updateMessageOnIcc(int messageIndex, int newStatus, byte[] pdu) { 600 boolean success = false; 601 602 try { 603 ISms iccISms = getISmsService(); 604 if (iccISms != null) { 605 success = iccISms.updateMessageOnIccEf(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.getAllMessagesFromIccEf(ActivityThread.currentPackageName()); 631 } 632 } catch (RemoteException ex) { 633 // ignore it 634 } 635 636 return createMessageListFromRawRecords(records); 637 } 638 639 /** 640 * Enable reception of cell broadcast (SMS-CB) messages with the given 641 * message identifier. Note that if two different clients enable the same 642 * message identifier, they must both disable it for the device to stop 643 * receiving those messages. All received messages will be broadcast in an 644 * intent with the action "android.provider.Telephony.SMS_CB_RECEIVED". 645 * Note: This call is blocking, callers may want to avoid calling it from 646 * the main thread of an application. 647 * 648 * @param messageIdentifier Message identifier as specified in TS 23.041 (3GPP) 649 * or C.R1001-G (3GPP2) 650 * @return true if successful, false otherwise 651 * @see #disableCellBroadcast(int) 652 * 653 * {@hide} 654 */ 655 public boolean enableCellBroadcast(int messageIdentifier) { 656 boolean success = false; 657 658 try { 659 ISms iccISms = getISmsService(); 660 if (iccISms != null) { 661 success = iccISms.enableCellBroadcast(messageIdentifier); 662 } 663 } catch (RemoteException ex) { 664 // ignore it 665 } 666 667 return success; 668 } 669 670 /** 671 * Disable reception of cell broadcast (SMS-CB) messages with the given 672 * message identifier. Note that if two different clients enable the same 673 * message identifier, they must both disable it for the device to stop 674 * receiving those messages. 675 * Note: This call is blocking, callers may want to avoid calling it from 676 * the main thread of an application. 677 * 678 * @param messageIdentifier Message identifier as specified in TS 23.041 (3GPP) 679 * or C.R1001-G (3GPP2) 680 * @return true if successful, false otherwise 681 * 682 * @see #enableCellBroadcast(int) 683 * 684 * {@hide} 685 */ 686 public boolean disableCellBroadcast(int messageIdentifier) { 687 boolean success = false; 688 689 try { 690 ISms iccISms = getISmsService(); 691 if (iccISms != null) { 692 success = iccISms.disableCellBroadcast(messageIdentifier); 693 } 694 } catch (RemoteException ex) { 695 // ignore it 696 } 697 698 return success; 699 } 700 701 /** 702 * Enable reception of cell broadcast (SMS-CB) messages with the given 703 * message identifier range. Note that if two different clients enable the same 704 * message identifier, they must both disable it for the device to stop 705 * receiving those messages. All received messages will be broadcast in an 706 * intent with the action "android.provider.Telephony.SMS_CB_RECEIVED". 707 * Note: This call is blocking, callers may want to avoid calling it from 708 * the main thread of an application. 709 * 710 * @param startMessageId first message identifier as specified in TS 23.041 (3GPP) 711 * or C.R1001-G (3GPP2) 712 * @param endMessageId last message identifier as specified in TS 23.041 (3GPP) 713 * or C.R1001-G (3GPP2) 714 * @return true if successful, false otherwise 715 * @see #disableCellBroadcastRange(int, int) 716 * 717 * @throws IllegalArgumentException if endMessageId < startMessageId 718 * {@hide} 719 */ 720 public boolean enableCellBroadcastRange(int startMessageId, int endMessageId) { 721 boolean success = false; 722 723 if (endMessageId < startMessageId) { 724 throw new IllegalArgumentException("endMessageId < startMessageId"); 725 } 726 try { 727 ISms iccISms = getISmsService(); 728 if (iccISms != null) { 729 success = iccISms.enableCellBroadcastRange(startMessageId, endMessageId); 730 } 731 } catch (RemoteException ex) { 732 // ignore it 733 } 734 735 return success; 736 } 737 738 /** 739 * Disable reception of cell broadcast (SMS-CB) messages with the given 740 * message identifier range. Note that if two different clients enable the same 741 * message identifier, they must both disable it for the device to stop 742 * receiving those messages. 743 * Note: This call is blocking, callers may want to avoid calling it from 744 * the main thread of an application. 745 * 746 * @param startMessageId first message identifier as specified in TS 23.041 (3GPP) 747 * or C.R1001-G (3GPP2) 748 * @param endMessageId last message identifier as specified in TS 23.041 (3GPP) 749 * or C.R1001-G (3GPP2) 750 * @return true if successful, false otherwise 751 * 752 * @see #enableCellBroadcastRange(int, int) 753 * 754 * @throws IllegalArgumentException if endMessageId < startMessageId 755 * {@hide} 756 */ 757 public boolean disableCellBroadcastRange(int startMessageId, int endMessageId) { 758 boolean success = false; 759 760 if (endMessageId < startMessageId) { 761 throw new IllegalArgumentException("endMessageId < startMessageId"); 762 } 763 try { 764 ISms iccISms = getISmsService(); 765 if (iccISms != null) { 766 success = iccISms.disableCellBroadcastRange(startMessageId, endMessageId); 767 } 768 } catch (RemoteException ex) { 769 // ignore it 770 } 771 772 return success; 773 } 774 775 /** 776 * Create a list of <code>SmsMessage</code>s from a list of RawSmsData 777 * records returned by <code>getAllMessagesFromIcc()</code> 778 * 779 * @param records SMS EF records, returned by 780 * <code>getAllMessagesFromIcc</code> 781 * @return <code>ArrayList</code> of <code>SmsMessage</code> objects. 782 */ 783 private static ArrayList<SmsMessage> createMessageListFromRawRecords(List<SmsRawData> records) { 784 ArrayList<SmsMessage> messages = new ArrayList<SmsMessage>(); 785 if (records != null) { 786 int count = records.size(); 787 for (int i = 0; i < count; i++) { 788 SmsRawData data = records.get(i); 789 // List contains all records, including "free" records (null) 790 if (data != null) { 791 SmsMessage sms = SmsMessage.createFromEfRecord(i+1, data.getBytes()); 792 if (sms != null) { 793 messages.add(sms); 794 } 795 } 796 } 797 } 798 return messages; 799 } 800 801 /** 802 * SMS over IMS is supported if IMS is registered and SMS is supported 803 * on IMS. 804 * 805 * @return true if SMS over IMS is supported, false otherwise 806 * 807 * @see #getImsSmsFormat() 808 * 809 * @hide 810 */ 811 public boolean isImsSmsSupported() { 812 boolean boSupported = false; 813 try { 814 ISms iccISms = getISmsService(); 815 if (iccISms != null) { 816 boSupported = iccISms.isImsSmsSupported(); 817 } 818 } catch (RemoteException ex) { 819 // ignore it 820 } 821 return boSupported; 822 } 823 824 /** 825 * Gets SMS format supported on IMS. SMS over IMS format is 826 * either 3GPP or 3GPP2. 827 * 828 * @return SmsMessage.FORMAT_3GPP, 829 * SmsMessage.FORMAT_3GPP2 830 * or SmsMessage.FORMAT_UNKNOWN 831 * 832 * @see #isImsSmsSupported() 833 * 834 * @hide 835 */ 836 public String getImsSmsFormat() { 837 String format = com.android.internal.telephony.SmsConstants.FORMAT_UNKNOWN; 838 try { 839 ISms iccISms = getISmsService(); 840 if (iccISms != null) { 841 format = iccISms.getImsSmsFormat(); 842 } 843 } catch (RemoteException ex) { 844 // ignore it 845 } 846 return format; 847 } 848 849 /** 850 * Get the default sms subId 851 * 852 * @return the default subId 853 * @hide 854 */ 855 public static long getDefaultSmsSubId() { 856 ISms iccISms = null; 857 try { 858 iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); 859 return (long) iccISms.getPreferredSmsSubscription(); 860 } catch (RemoteException ex) { 861 return DEFAULT_SUB_ID; 862 } catch (NullPointerException ex) { 863 return DEFAULT_SUB_ID; 864 } 865 } 866 867 /** 868 * Get SMS prompt property, enabled or not 869 * 870 * @return true if enabled, false otherwise 871 * @hide 872 */ 873 public boolean isSMSPromptEnabled() { 874 ISms iccISms = null; 875 try { 876 iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); 877 return iccISms.isSMSPromptEnabled(); 878 } catch (RemoteException ex) { 879 return false; 880 } catch (NullPointerException ex) { 881 return false; 882 } 883 } 884 885 // see SmsMessage.getStatusOnIcc 886 887 /** Free space (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 888 static public final int STATUS_ON_ICC_FREE = 0; 889 890 /** Received and read (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 891 static public final int STATUS_ON_ICC_READ = 1; 892 893 /** Received and unread (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 894 static public final int STATUS_ON_ICC_UNREAD = 3; 895 896 /** Stored and sent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 897 static public final int STATUS_ON_ICC_SENT = 5; 898 899 /** Stored and unsent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 900 static public final int STATUS_ON_ICC_UNSENT = 7; 901 902 // SMS send failure result codes 903 904 /** Generic failure cause */ 905 static public final int RESULT_ERROR_GENERIC_FAILURE = 1; 906 /** Failed because radio was explicitly turned off */ 907 static public final int RESULT_ERROR_RADIO_OFF = 2; 908 /** Failed because no pdu provided */ 909 static public final int RESULT_ERROR_NULL_PDU = 3; 910 /** Failed because service is currently unavailable */ 911 static public final int RESULT_ERROR_NO_SERVICE = 4; 912 /** Failed because we reached the sending queue limit. {@hide} */ 913 static public final int RESULT_ERROR_LIMIT_EXCEEDED = 5; 914 /** Failed because FDN is enabled. {@hide} */ 915 static public final int RESULT_ERROR_FDN_CHECK_FAILURE = 6; 916 917 static private final String PHONE_PACKAGE_NAME = "com.android.phone"; 918 919 /** 920 * Send an MMS message 921 * 922 * @param context application context 923 * @param contentUri the content Uri from which the message pdu will be read 924 * @param locationUrl the optional location url where message should be sent to 925 * @param configOverrides the carrier-specific messaging configuration values to override for 926 * sending the message. 927 * @param sentIntent if not NULL this <code>PendingIntent</code> is 928 * broadcast when the message is successfully sent, or failed 929 * @throws IllegalArgumentException if contentUri is empty 930 */ 931 public void sendMultimediaMessage(Context context, Uri contentUri, String locationUrl, 932 Bundle configOverrides, PendingIntent sentIntent) { 933 if (contentUri == null) { 934 throw new IllegalArgumentException("Uri contentUri null"); 935 } 936 try { 937 final IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 938 if (iMms == null) { 939 return; 940 } 941 context.grantUriPermission(PHONE_PACKAGE_NAME, contentUri, 942 Intent.FLAG_GRANT_READ_URI_PERMISSION); 943 grantCarrierPackageUriPermission(context, contentUri, 944 Telephony.Mms.Intents.MMS_SEND_ACTION, Intent.FLAG_GRANT_READ_URI_PERMISSION); 945 946 iMms.sendMessage(getSubId(), ActivityThread.currentPackageName(), contentUri, 947 locationUrl, configOverrides, sentIntent); 948 } catch (RemoteException e) { 949 // Ignore it 950 } 951 } 952 953 private void grantCarrierPackageUriPermission(Context context, Uri contentUri, String action, 954 int permission) { 955 Intent intent = new Intent(action); 956 TelephonyManager telephonyManager = 957 (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 958 List<String> carrierPackages = telephonyManager.getCarrierPackageNamesForIntent( 959 intent); 960 if (carrierPackages != null && carrierPackages.size() == 1) { 961 context.grantUriPermission(carrierPackages.get(0), contentUri, permission); 962 } 963 } 964 965 /** 966 * Download an MMS message from carrier by a given location URL 967 * 968 * @param context application context 969 * @param locationUrl the location URL of the MMS message to be downloaded, usually obtained 970 * from the MMS WAP push notification 971 * @param contentUri the content uri to which the downloaded pdu will be written 972 * @param configOverrides the carrier-specific messaging configuration values to override for 973 * downloading the message. 974 * @param downloadedIntent if not NULL this <code>PendingIntent</code> is 975 * broadcast when the message is downloaded, or the download is failed 976 * @throws IllegalArgumentException if locationUrl or contentUri is empty 977 */ 978 public void downloadMultimediaMessage(Context context, String locationUrl, Uri contentUri, 979 Bundle configOverrides, PendingIntent downloadedIntent) { 980 if (TextUtils.isEmpty(locationUrl)) { 981 throw new IllegalArgumentException("Empty MMS location URL"); 982 } 983 if (contentUri == null) { 984 throw new IllegalArgumentException("Uri contentUri null"); 985 } 986 try { 987 final IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 988 if (iMms == null) { 989 return; 990 } 991 context.grantUriPermission(PHONE_PACKAGE_NAME, contentUri, 992 Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 993 994 grantCarrierPackageUriPermission(context, contentUri, 995 Telephony.Mms.Intents.MMS_DOWNLOAD_ACTION, 996 Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 997 998 iMms.downloadMessage(getSubId(), ActivityThread.currentPackageName(), locationUrl, 999 contentUri, configOverrides, downloadedIntent); 1000 } catch (RemoteException e) { 1001 // Ignore it 1002 } 1003 } 1004 1005 // MMS send/download failure result codes 1006 public static final int MMS_ERROR_UNSPECIFIED = 1; 1007 public static final int MMS_ERROR_INVALID_APN = 2; 1008 public static final int MMS_ERROR_UNABLE_CONNECT_MMS = 3; 1009 public static final int MMS_ERROR_HTTP_FAILURE = 4; 1010 public static final int MMS_ERROR_IO_ERROR = 5; 1011 public static final int MMS_ERROR_RETRY = 6; 1012 public static final int MMS_ERROR_CONFIGURATION_ERROR = 7; 1013 1014 // Intent extra name for result data 1015 public static final String EXTRA_MMS_DATA = "android.telephony.extra.MMS_DATA"; 1016 1017 /** 1018 * Update the status of a pending (send-by-IP) MMS message handled by the carrier app. 1019 * If the carrier app fails to send this message, it may be resent via carrier network 1020 * depending on the status code. 1021 * 1022 * The caller should have carrier privileges. 1023 * @see android.telephony.TelephonyManager.hasCarrierPrivileges 1024 * 1025 * @param context application context 1026 * @param messageRef the reference number of the MMS message. 1027 * @param pdu non-empty (contains the SendConf PDU) if the message was sent successfully, 1028 * otherwise, this param should be null. 1029 * @param status send status. It can be Activity.RESULT_OK or one of the MMS error codes. 1030 * If status is Activity.RESULT_OK, the MMS was sent successfully. 1031 * If status is MMS_ERROR_RETRY, this message would be resent via carrier 1032 * network. The message will not be resent for other MMS error statuses. 1033 * @param contentUri the URI of the sent message 1034 * {@hide} 1035 */ 1036 public void updateMmsSendStatus(Context context, int messageRef, byte[] pdu, int status, 1037 Uri contentUri) { 1038 try { 1039 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1040 if (iMms == null) { 1041 return; 1042 } 1043 iMms.updateMmsSendStatus(messageRef, pdu, status); 1044 } catch (RemoteException ex) { 1045 // ignore it 1046 } 1047 if (contentUri != null) { 1048 context.revokeUriPermission(contentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION); 1049 } 1050 } 1051 1052 /** 1053 * Update the status of a pending (download-by-IP) MMS message handled by the carrier app. 1054 * If the carrier app fails to download this message, it may be re-downloaded via carrier 1055 * network depending on the status code. 1056 * 1057 * The caller should have carrier privileges. 1058 * @see android.telephony.TelephonyManager.hasCarrierPrivileges 1059 * 1060 * @param context application context 1061 * @param messageRef the reference number of the MMS message. 1062 * @param status download status. It can be Activity.RESULT_OK or one of the MMS error codes. 1063 * If status is Activity.RESULT_OK, the MMS was downloaded successfully. 1064 * If status is MMS_ERROR_RETRY, this message would be re-downloaded via carrier 1065 * network. The message will not be re-downloaded for other MMS error statuses. 1066 * @param contentUri the URI of the downloaded message 1067 * {@hide} 1068 */ 1069 public void updateMmsDownloadStatus(Context context, int messageRef, int status, 1070 Uri contentUri) { 1071 try { 1072 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1073 if (iMms == null) { 1074 return; 1075 } 1076 iMms.updateMmsDownloadStatus(messageRef, status); 1077 } catch (RemoteException ex) { 1078 // ignore it 1079 } 1080 if (contentUri != null) { 1081 context.revokeUriPermission(contentUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 1082 } 1083 } 1084 1085 /** 1086 * Import a text message into system's SMS store 1087 * 1088 * Only default SMS apps can import SMS 1089 * 1090 * @param address the destination(source) address of the sent(received) message 1091 * @param type the type of the message 1092 * @param text the message text 1093 * @param timestampMillis the message timestamp in milliseconds 1094 * @param seen if the message is seen 1095 * @param read if the message is read 1096 * @return the message URI, null if failed 1097 * @hide 1098 */ 1099 public Uri importTextMessage(String address, int type, String text, long timestampMillis, 1100 boolean seen, boolean read) { 1101 try { 1102 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1103 if (iMms != null) { 1104 return iMms.importTextMessage(ActivityThread.currentPackageName(), 1105 address, type, text, timestampMillis, seen, read); 1106 } 1107 } catch (RemoteException ex) { 1108 // ignore it 1109 } 1110 return null; 1111 } 1112 1113 /** Represents the received SMS message for importing {@hide} */ 1114 public static final int SMS_TYPE_INCOMING = 0; 1115 /** Represents the sent SMS message for importing {@hide} */ 1116 public static final int SMS_TYPE_OUTGOING = 1; 1117 1118 /** 1119 * Import a multimedia message into system's MMS store. Only the following PDU type is 1120 * supported: Retrieve.conf, Send.req, Notification.ind, Delivery.ind, Read-Orig.ind 1121 * 1122 * Only default SMS apps can import MMS 1123 * 1124 * @param contentUri the content uri from which to read the PDU of the message to import 1125 * @param messageId the optional message id. Use null if not specifying 1126 * @param timestampSecs the optional message timestamp. Use -1 if not specifying 1127 * @param seen if the message is seen 1128 * @param read if the message is read 1129 * @return the message URI, null if failed 1130 * @throws IllegalArgumentException if pdu is empty 1131 * {@hide} 1132 */ 1133 public Uri importMultimediaMessage(Uri contentUri, String messageId, long timestampSecs, 1134 boolean seen, boolean read) { 1135 if (contentUri == null) { 1136 throw new IllegalArgumentException("Uri contentUri null"); 1137 } 1138 try { 1139 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1140 if (iMms != null) { 1141 return iMms.importMultimediaMessage(ActivityThread.currentPackageName(), 1142 contentUri, messageId, timestampSecs, seen, read); 1143 } 1144 } catch (RemoteException ex) { 1145 // ignore it 1146 } 1147 return null; 1148 } 1149 1150 /** 1151 * Delete a system stored SMS or MMS message 1152 * 1153 * Only default SMS apps can delete system stored SMS and MMS messages 1154 * 1155 * @param messageUri the URI of the stored message 1156 * @return true if deletion is successful, false otherwise 1157 * @throws IllegalArgumentException if messageUri is empty 1158 * {@hide} 1159 */ 1160 public boolean deleteStoredMessage(Uri messageUri) { 1161 if (messageUri == null) { 1162 throw new IllegalArgumentException("Empty message URI"); 1163 } 1164 try { 1165 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1166 if (iMms != null) { 1167 return iMms.deleteStoredMessage(ActivityThread.currentPackageName(), messageUri); 1168 } 1169 } catch (RemoteException ex) { 1170 // ignore it 1171 } 1172 return false; 1173 } 1174 1175 /** 1176 * Delete a system stored SMS or MMS thread 1177 * 1178 * Only default SMS apps can delete system stored SMS and MMS conversations 1179 * 1180 * @param conversationId the ID of the message conversation 1181 * @return true if deletion is successful, false otherwise 1182 * {@hide} 1183 */ 1184 public boolean deleteStoredConversation(long conversationId) { 1185 try { 1186 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1187 if (iMms != null) { 1188 return iMms.deleteStoredConversation( 1189 ActivityThread.currentPackageName(), conversationId); 1190 } 1191 } catch (RemoteException ex) { 1192 // ignore it 1193 } 1194 return false; 1195 } 1196 1197 /** 1198 * Update the status properties of a system stored SMS or MMS message, e.g. 1199 * the read status of a message, etc. 1200 * 1201 * @param messageUri the URI of the stored message 1202 * @param statusValues a list of status properties in key-value pairs to update 1203 * @return true if update is successful, false otherwise 1204 * @throws IllegalArgumentException if messageUri is empty 1205 * {@hide} 1206 */ 1207 public boolean updateStoredMessageStatus(Uri messageUri, ContentValues statusValues) { 1208 if (messageUri == null) { 1209 throw new IllegalArgumentException("Empty message URI"); 1210 } 1211 try { 1212 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1213 if (iMms != null) { 1214 return iMms.updateStoredMessageStatus(ActivityThread.currentPackageName(), 1215 messageUri, statusValues); 1216 } 1217 } catch (RemoteException ex) { 1218 // ignore it 1219 } 1220 return false; 1221 } 1222 1223 /** Message status property: whether the message has been seen. 1 means seen, 0 not {@hide} */ 1224 public static final String MESSAGE_STATUS_SEEN = "seen"; 1225 /** Message status property: whether the message has been read. 1 means read, 0 not {@hide} */ 1226 public static final String MESSAGE_STATUS_READ = "read"; 1227 1228 /** 1229 * Archive or unarchive a stored conversation 1230 * 1231 * @param conversationId the ID of the message conversation 1232 * @param archived true to archive the conversation, false to unarchive 1233 * @return true if update is successful, false otherwise 1234 * {@hide} 1235 */ 1236 public boolean archiveStoredConversation(long conversationId, boolean archived) { 1237 try { 1238 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1239 if (iMms != null) { 1240 return iMms.archiveStoredConversation(ActivityThread.currentPackageName(), 1241 conversationId, archived); 1242 } 1243 } catch (RemoteException ex) { 1244 // ignore it 1245 } 1246 return false; 1247 } 1248 1249 /** 1250 * Add a text message draft to system SMS store 1251 * 1252 * Only default SMS apps can add SMS draft 1253 * 1254 * @param address the destination address of message 1255 * @param text the body of the message to send 1256 * @return the URI of the stored draft message 1257 * {@hide} 1258 */ 1259 public Uri addTextMessageDraft(String address, String text) { 1260 try { 1261 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1262 if (iMms != null) { 1263 return iMms.addTextMessageDraft(ActivityThread.currentPackageName(), address, text); 1264 } 1265 } catch (RemoteException ex) { 1266 // ignore it 1267 } 1268 return null; 1269 } 1270 1271 /** 1272 * Add a multimedia message draft to system MMS store 1273 * 1274 * Only default SMS apps can add MMS draft 1275 * 1276 * @param contentUri the content uri from which to read the PDU data of the draft MMS 1277 * @return the URI of the stored draft message 1278 * @throws IllegalArgumentException if pdu is empty 1279 * {@hide} 1280 */ 1281 public Uri addMultimediaMessageDraft(Uri contentUri) { 1282 if (contentUri == null) { 1283 throw new IllegalArgumentException("Uri contentUri null"); 1284 } 1285 try { 1286 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1287 if (iMms != null) { 1288 return iMms.addMultimediaMessageDraft(ActivityThread.currentPackageName(), 1289 contentUri); 1290 } 1291 } catch (RemoteException ex) { 1292 // ignore it 1293 } 1294 return null; 1295 } 1296 1297 /** 1298 * Send a system stored text message. 1299 * 1300 * You can only send a failed text message or a draft text message. 1301 * 1302 * @param messageUri the URI of the stored message 1303 * @param scAddress is the service center address or null to use the current default SMSC 1304 * @param sentIntent if not NULL this <code>PendingIntent</code> is 1305 * broadcast when the message is successfully sent, or failed. 1306 * The result code will be <code>Activity.RESULT_OK</code> for success, 1307 * or one of these errors:<br> 1308 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 1309 * <code>RESULT_ERROR_RADIO_OFF</code><br> 1310 * <code>RESULT_ERROR_NULL_PDU</code><br> 1311 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 1312 * the extra "errorCode" containing a radio technology specific value, 1313 * generally only useful for troubleshooting.<br> 1314 * The per-application based SMS control checks sentIntent. If sentIntent 1315 * is NULL the caller will be checked against all unknown applications, 1316 * which cause smaller number of SMS to be sent in checking period. 1317 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 1318 * broadcast when the message is delivered to the recipient. The 1319 * raw pdu of the status report is in the extended data ("pdu"). 1320 * 1321 * @throws IllegalArgumentException if messageUri is empty 1322 * {@hide} 1323 */ 1324 public void sendStoredTextMessage(Uri messageUri, String scAddress, PendingIntent sentIntent, 1325 PendingIntent deliveryIntent) { 1326 if (messageUri == null) { 1327 throw new IllegalArgumentException("Empty message URI"); 1328 } 1329 try { 1330 ISms iccISms = getISmsServiceOrThrow(); 1331 iccISms.sendStoredText(getSubId(), ActivityThread.currentPackageName(), messageUri, 1332 scAddress, sentIntent, deliveryIntent); 1333 } catch (RemoteException ex) { 1334 // ignore it 1335 } 1336 } 1337 1338 /** 1339 * Send a system stored multi-part text message. 1340 * 1341 * You can only send a failed text message or a draft text message. 1342 * The provided <code>PendingIntent</code> lists should match the part number of the 1343 * divided text of the stored message by using <code>divideMessage</code> 1344 * 1345 * @param messageUri the URI of the stored message 1346 * @param scAddress is the service center address or null to use 1347 * the current default SMSC 1348 * @param sentIntents if not null, an <code>ArrayList</code> of 1349 * <code>PendingIntent</code>s (one for each message part) that is 1350 * broadcast when the corresponding message part has been sent. 1351 * The result code will be <code>Activity.RESULT_OK</code> for success, 1352 * or one of these errors:<br> 1353 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 1354 * <code>RESULT_ERROR_RADIO_OFF</code><br> 1355 * <code>RESULT_ERROR_NULL_PDU</code><br> 1356 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> each sentIntent may include 1357 * the extra "errorCode" containing a radio technology specific value, 1358 * generally only useful for troubleshooting.<br> 1359 * The per-application based SMS control checks sentIntent. If sentIntent 1360 * is NULL the caller will be checked against all unknown applications, 1361 * which cause smaller number of SMS to be sent in checking period. 1362 * @param deliveryIntents if not null, an <code>ArrayList</code> of 1363 * <code>PendingIntent</code>s (one for each message part) that is 1364 * broadcast when the corresponding message part has been delivered 1365 * to the recipient. The raw pdu of the status report is in the 1366 * extended data ("pdu"). 1367 * 1368 * @throws IllegalArgumentException if messageUri is empty 1369 * {@hide} 1370 */ 1371 public void sendStoredMultipartTextMessage(Uri messageUri, String scAddress, 1372 ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) { 1373 if (messageUri == null) { 1374 throw new IllegalArgumentException("Empty message URI"); 1375 } 1376 try { 1377 ISms iccISms = getISmsServiceOrThrow(); 1378 iccISms.sendStoredMultipartText(getSubId(), ActivityThread.currentPackageName(), messageUri, 1379 scAddress, sentIntents, deliveryIntents); 1380 } catch (RemoteException ex) { 1381 // ignore it 1382 } 1383 } 1384 1385 /** 1386 * Send a system stored MMS message 1387 * 1388 * This is used for sending a previously sent, but failed-to-send, message or 1389 * for sending a text message that has been stored as a draft. 1390 * 1391 * @param messageUri the URI of the stored message 1392 * @param configOverrides the carrier-specific messaging configuration values to override for 1393 * sending the message. 1394 * @param sentIntent if not NULL this <code>PendingIntent</code> is 1395 * broadcast when the message is successfully sent, or failed 1396 * @throws IllegalArgumentException if messageUri is empty 1397 * {@hide} 1398 */ 1399 public void sendStoredMultimediaMessage(Uri messageUri, Bundle configOverrides, 1400 PendingIntent sentIntent) { 1401 if (messageUri == null) { 1402 throw new IllegalArgumentException("Empty message URI"); 1403 } 1404 try { 1405 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1406 if (iMms != null) { 1407 iMms.sendStoredMessage(getSubId(), ActivityThread.currentPackageName(), messageUri, 1408 configOverrides, sentIntent); 1409 } 1410 } catch (RemoteException ex) { 1411 // ignore it 1412 } 1413 } 1414 1415 /** 1416 * Turns on/off the flag to automatically write sent/received SMS/MMS messages into system 1417 * 1418 * When this flag is on, all SMS/MMS sent/received are stored by system automatically 1419 * When this flag is off, only SMS/MMS sent by non-default SMS apps are stored by system 1420 * automatically 1421 * 1422 * This flag can only be changed by default SMS apps 1423 * 1424 * @param enabled Whether to enable message auto persisting 1425 * {@hide} 1426 */ 1427 public void setAutoPersisting(boolean enabled) { 1428 try { 1429 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1430 if (iMms != null) { 1431 iMms.setAutoPersisting(ActivityThread.currentPackageName(), enabled); 1432 } 1433 } catch (RemoteException ex) { 1434 // ignore it 1435 } 1436 } 1437 1438 /** 1439 * Get the value of the flag to automatically write sent/received SMS/MMS messages into system 1440 * 1441 * When this flag is on, all SMS/MMS sent/received are stored by system automatically 1442 * When this flag is off, only SMS/MMS sent by non-default SMS apps are stored by system 1443 * automatically 1444 * 1445 * @return the current value of the auto persist flag 1446 * {@hide} 1447 */ 1448 public boolean getAutoPersisting() { 1449 try { 1450 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1451 if (iMms != null) { 1452 return iMms.getAutoPersisting(); 1453 } 1454 } catch (RemoteException ex) { 1455 // ignore it 1456 } 1457 return false; 1458 } 1459 1460 /** 1461 * Get carrier-dependent configuration values. 1462 * 1463 * @return bundle key/values pairs of configuration values 1464 */ 1465 public Bundle getCarrierConfigValues() { 1466 try { 1467 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1468 if (iMms != null) { 1469 return iMms.getCarrierConfigValues(getSubId()); 1470 } 1471 } catch (RemoteException ex) { 1472 // ignore it 1473 } 1474 return null; 1475 } 1476 1477 } 1478