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