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