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