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.annotation.RequiresPermission; 20import android.annotation.SuppressAutoDoc; 21import android.annotation.SystemApi; 22import android.app.ActivityThread; 23import android.app.PendingIntent; 24import android.content.ActivityNotFoundException; 25import android.content.ContentValues; 26import android.content.Context; 27import android.content.Intent; 28import android.net.Uri; 29import android.os.BaseBundle; 30import android.os.Bundle; 31import android.os.RemoteException; 32import android.os.ServiceManager; 33import android.text.TextUtils; 34import android.util.ArrayMap; 35import android.util.Log; 36 37import com.android.internal.telephony.IMms; 38import com.android.internal.telephony.ISms; 39import com.android.internal.telephony.SmsRawData; 40 41import java.util.ArrayList; 42import java.util.Arrays; 43import java.util.List; 44import java.util.Map; 45 46/* 47 * TODO(code review): Curious question... Why are a lot of these 48 * methods not declared as static, since they do not seem to require 49 * any local object state? Presumably this cannot be changed without 50 * interfering with the API... 51 */ 52 53/** 54 * Manages SMS operations such as sending data, text, and pdu SMS messages. 55 * Get this object by calling the static method {@link #getDefault()}. 56 * 57 * <p>For information about how to behave as the default SMS app on Android 4.4 (API level 19) 58 * and higher, see {@link android.provider.Telephony}. 59 */ 60public final class SmsManager { 61 private static final String TAG = "SmsManager"; 62 /** 63 * A psuedo-subId that represents the default subId at any given time. The actual subId it 64 * represents changes as the default subId is changed. 65 */ 66 private static final int DEFAULT_SUBSCRIPTION_ID = -1002; 67 68 /** Singleton object constructed during class initialization. */ 69 private static final SmsManager sInstance = new SmsManager(DEFAULT_SUBSCRIPTION_ID); 70 private static final Object sLockObject = new Object(); 71 72 /** @hide */ 73 public static final int CELL_BROADCAST_RAN_TYPE_GSM = 0; 74 /** @hide */ 75 public static final int CELL_BROADCAST_RAN_TYPE_CDMA = 1; 76 77 /** SMS record length from TS 51.011 10.5.3 78 * @hide 79 */ 80 public static final int SMS_RECORD_LENGTH = 176; 81 82 /** SMS record length from C.S0023 3.4.27 83 * @hide 84 */ 85 public static final int CDMA_SMS_RECORD_LENGTH = 255; 86 87 private static final Map<Integer, SmsManager> sSubInstances = 88 new ArrayMap<Integer, SmsManager>(); 89 90 /** A concrete subscription id, or the pseudo DEFAULT_SUBSCRIPTION_ID */ 91 private int mSubId; 92 93 /* 94 * Key for the various carrier-dependent configuration values. 95 * Some of the values are used by the system in processing SMS or MMS messages. Others 96 * are provided for the convenience of SMS applications. 97 */ 98 99 /** 100 * Whether to append transaction id to MMS WAP Push M-Notification.ind's content location URI 101 * when constructing the download URL of a new MMS (boolean type) 102 */ 103 public static final String MMS_CONFIG_APPEND_TRANSACTION_ID = 104 CarrierConfigManager.KEY_MMS_APPEND_TRANSACTION_ID_BOOL; 105 /** 106 * Whether MMS is enabled for the current carrier (boolean type) 107 */ 108 public static final String 109 MMS_CONFIG_MMS_ENABLED = CarrierConfigManager.KEY_MMS_MMS_ENABLED_BOOL; 110 /** 111 * Whether group MMS is enabled for the current carrier (boolean type) 112 */ 113 public static final String 114 MMS_CONFIG_GROUP_MMS_ENABLED = CarrierConfigManager.KEY_MMS_GROUP_MMS_ENABLED_BOOL; 115 /** 116 * If this is enabled, M-NotifyResp.ind should be sent to the WAP Push content location instead 117 * of the default MMSC (boolean type) 118 */ 119 public static final String MMS_CONFIG_NOTIFY_WAP_MMSC_ENABLED = 120 CarrierConfigManager.KEY_MMS_NOTIFY_WAP_MMSC_ENABLED_BOOL; 121 /** 122 * Whether alias is enabled (boolean type) 123 */ 124 public static final String 125 MMS_CONFIG_ALIAS_ENABLED = CarrierConfigManager.KEY_MMS_ALIAS_ENABLED_BOOL; 126 /** 127 * Whether audio is allowed to be attached for MMS messages (boolean type) 128 */ 129 public static final String 130 MMS_CONFIG_ALLOW_ATTACH_AUDIO = CarrierConfigManager.KEY_MMS_ALLOW_ATTACH_AUDIO_BOOL; 131 /** 132 * Whether multipart SMS is enabled (boolean type) 133 */ 134 public static final String MMS_CONFIG_MULTIPART_SMS_ENABLED = 135 CarrierConfigManager.KEY_MMS_MULTIPART_SMS_ENABLED_BOOL; 136 /** 137 * Whether SMS delivery report is enabled (boolean type) 138 */ 139 public static final String MMS_CONFIG_SMS_DELIVERY_REPORT_ENABLED = 140 CarrierConfigManager.KEY_MMS_SMS_DELIVERY_REPORT_ENABLED_BOOL; 141 /** 142 * Whether content-disposition field should be expected in an MMS PDU (boolean type) 143 */ 144 public static final String MMS_CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION = 145 CarrierConfigManager.KEY_MMS_SUPPORT_MMS_CONTENT_DISPOSITION_BOOL; 146 /** 147 * Whether multipart SMS should be sent as separate messages 148 */ 149 public static final String MMS_CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES = 150 CarrierConfigManager.KEY_MMS_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES_BOOL; 151 /** 152 * Whether MMS read report is enabled (boolean type) 153 */ 154 public static final String MMS_CONFIG_MMS_READ_REPORT_ENABLED = 155 CarrierConfigManager.KEY_MMS_MMS_READ_REPORT_ENABLED_BOOL; 156 /** 157 * Whether MMS delivery report is enabled (boolean type) 158 */ 159 public static final String MMS_CONFIG_MMS_DELIVERY_REPORT_ENABLED = 160 CarrierConfigManager.KEY_MMS_MMS_DELIVERY_REPORT_ENABLED_BOOL; 161 /** 162 * Max MMS message size in bytes (int type) 163 */ 164 public static final String 165 MMS_CONFIG_MAX_MESSAGE_SIZE = CarrierConfigManager.KEY_MMS_MAX_MESSAGE_SIZE_INT; 166 /** 167 * Max MMS image width (int type) 168 */ 169 public static final String 170 MMS_CONFIG_MAX_IMAGE_WIDTH = CarrierConfigManager.KEY_MMS_MAX_IMAGE_WIDTH_INT; 171 /** 172 * Max MMS image height (int type) 173 */ 174 public static final String 175 MMS_CONFIG_MAX_IMAGE_HEIGHT = CarrierConfigManager.KEY_MMS_MAX_IMAGE_HEIGHT_INT; 176 /** 177 * Limit of recipients of MMS messages (int type) 178 */ 179 public static final String 180 MMS_CONFIG_RECIPIENT_LIMIT = CarrierConfigManager.KEY_MMS_RECIPIENT_LIMIT_INT; 181 /** 182 * Min alias character count (int type) 183 */ 184 public static final String 185 MMS_CONFIG_ALIAS_MIN_CHARS = CarrierConfigManager.KEY_MMS_ALIAS_MIN_CHARS_INT; 186 /** 187 * Max alias character count (int type) 188 */ 189 public static final String 190 MMS_CONFIG_ALIAS_MAX_CHARS = CarrierConfigManager.KEY_MMS_ALIAS_MAX_CHARS_INT; 191 /** 192 * When the number of parts of a multipart SMS reaches this threshold, it should be converted 193 * into an MMS (int type) 194 */ 195 public static final String MMS_CONFIG_SMS_TO_MMS_TEXT_THRESHOLD = 196 CarrierConfigManager.KEY_MMS_SMS_TO_MMS_TEXT_THRESHOLD_INT; 197 /** 198 * Some carriers require SMS to be converted into MMS when text length reaches this threshold 199 * (int type) 200 */ 201 public static final String MMS_CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD = 202 CarrierConfigManager.KEY_MMS_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD_INT; 203 /** 204 * Max message text size (int type) 205 */ 206 public static final String MMS_CONFIG_MESSAGE_TEXT_MAX_SIZE = 207 CarrierConfigManager.KEY_MMS_MESSAGE_TEXT_MAX_SIZE_INT; 208 /** 209 * Max message subject length (int type) 210 */ 211 public static final String 212 MMS_CONFIG_SUBJECT_MAX_LENGTH = CarrierConfigManager.KEY_MMS_SUBJECT_MAX_LENGTH_INT; 213 /** 214 * MMS HTTP socket timeout in milliseconds (int type) 215 */ 216 public static final String 217 MMS_CONFIG_HTTP_SOCKET_TIMEOUT = CarrierConfigManager.KEY_MMS_HTTP_SOCKET_TIMEOUT_INT; 218 /** 219 * The name of the UA Prof URL HTTP header for MMS HTTP request (String type) 220 */ 221 public static final String 222 MMS_CONFIG_UA_PROF_TAG_NAME = CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING; 223 /** 224 * The User-Agent header value for MMS HTTP request (String type) 225 */ 226 public static final String 227 MMS_CONFIG_USER_AGENT = CarrierConfigManager.KEY_MMS_USER_AGENT_STRING; 228 /** 229 * The UA Profile URL header value for MMS HTTP request (String type) 230 */ 231 public static final String 232 MMS_CONFIG_UA_PROF_URL = CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING; 233 /** 234 * A list of HTTP headers to add to MMS HTTP request, separated by "|" (String type) 235 */ 236 public static final String 237 MMS_CONFIG_HTTP_PARAMS = CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING; 238 /** 239 * Email gateway number (String type) 240 */ 241 public static final String MMS_CONFIG_EMAIL_GATEWAY_NUMBER = 242 CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING; 243 /** 244 * The suffix to append to the NAI header value for MMS HTTP request (String type) 245 */ 246 public static final String 247 MMS_CONFIG_NAI_SUFFIX = CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING; 248 /** 249 * If true, show the cell broadcast (amber alert) in the SMS settings. Some carriers don't want 250 * this shown. (Boolean type) 251 */ 252 public static final String MMS_CONFIG_SHOW_CELL_BROADCAST_APP_LINKS = 253 CarrierConfigManager.KEY_MMS_SHOW_CELL_BROADCAST_APP_LINKS_BOOL; 254 /** 255 * Whether the carrier MMSC supports charset field in Content-Type header. If this is false, 256 * then we don't add "charset" to "Content-Type" 257 */ 258 public static final String MMS_CONFIG_SUPPORT_HTTP_CHARSET_HEADER = 259 CarrierConfigManager.KEY_MMS_SUPPORT_HTTP_CHARSET_HEADER_BOOL; 260 /** 261 * If true, add "Connection: close" header to MMS HTTP requests so the connection 262 * is immediately closed (disabling keep-alive). (Boolean type) 263 * @hide 264 */ 265 public static final String MMS_CONFIG_CLOSE_CONNECTION = 266 CarrierConfigManager.KEY_MMS_CLOSE_CONNECTION_BOOL; 267 268 /* 269 * Forwarded constants from SimDialogActivity. 270 */ 271 private static String DIALOG_TYPE_KEY = "dialog_type"; 272 private static final int SMS_PICK = 2; 273 274 /** 275 * Send a text based SMS. 276 * 277 * <p class="note"><strong>Note:</strong> Using this method requires that your app has the 278 * {@link android.Manifest.permission#SEND_SMS} permission.</p> 279 * 280 * <p class="note"><strong>Note:</strong> Beginning with Android 4.4 (API level 19), if 281 * <em>and only if</em> an app is not selected as the default SMS app, the system automatically 282 * writes messages sent using this method to the SMS Provider (the default SMS app is always 283 * responsible for writing its sent messages to the SMS Provider). For information about 284 * how to behave as the default SMS app, see {@link android.provider.Telephony}.</p> 285 * 286 * 287 * @param destinationAddress the address to send the message to 288 * @param scAddress is the service center address or null to use 289 * the current default SMSC 290 * @param text the body of the message to send 291 * @param sentIntent if not NULL this <code>PendingIntent</code> is 292 * broadcast when the message is successfully sent, or failed. 293 * The result code will be <code>Activity.RESULT_OK</code> for success, 294 * or one of these errors:<br> 295 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 296 * <code>RESULT_ERROR_RADIO_OFF</code><br> 297 * <code>RESULT_ERROR_NULL_PDU</code><br> 298 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 299 * the extra "errorCode" containing a radio technology specific value, 300 * generally only useful for troubleshooting.<br> 301 * The per-application based SMS control checks sentIntent. If sentIntent 302 * is NULL the caller will be checked against all unknown applications, 303 * which cause smaller number of SMS to be sent in checking period. 304 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 305 * broadcast when the message is delivered to the recipient. The 306 * raw pdu of the status report is in the extended data ("pdu"). 307 * 308 * @throws IllegalArgumentException if destinationAddress or text are empty 309 */ 310 public void sendTextMessage( 311 String destinationAddress, String scAddress, String text, 312 PendingIntent sentIntent, PendingIntent deliveryIntent) { 313 sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent, 314 true /* persistMessage*/); 315 } 316 317 private void sendTextMessageInternal(String destinationAddress, String scAddress, 318 String text, PendingIntent sentIntent, PendingIntent deliveryIntent, 319 boolean persistMessage) { 320 if (TextUtils.isEmpty(destinationAddress)) { 321 throw new IllegalArgumentException("Invalid destinationAddress"); 322 } 323 324 if (TextUtils.isEmpty(text)) { 325 throw new IllegalArgumentException("Invalid message body"); 326 } 327 328 try { 329 ISms iccISms = getISmsServiceOrThrow(); 330 iccISms.sendTextForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(), 331 destinationAddress, 332 scAddress, text, sentIntent, deliveryIntent, 333 persistMessage); 334 } catch (RemoteException ex) { 335 // ignore it 336 } 337 } 338 339 /** 340 * Send a text based SMS without writing it into the SMS Provider. 341 * 342 * <p> 343 * The message will be sent directly over the network and will not be visible in SMS 344 * applications. Intended for internal carrier use only. 345 * </p> 346 * 347 * <p>Requires Permission: Both {@link android.Manifest.permission#SEND_SMS} and 348 * {@link android.Manifest.permission#MODIFY_PHONE_STATE}, or that the calling app has carrier 349 * privileges (see {@link TelephonyManager#hasCarrierPrivileges}), or that the calling app is 350 * the default IMS app (see 351 * {@link CarrierConfigManager#KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING}). 352 * 353 * @see #sendTextMessage(String, String, String, PendingIntent, PendingIntent) 354 */ 355 @SystemApi 356 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 357 @RequiresPermission(allOf = { 358 android.Manifest.permission.MODIFY_PHONE_STATE, 359 android.Manifest.permission.SEND_SMS 360 }) 361 public void sendTextMessageWithoutPersisting( 362 String destinationAddress, String scAddress, String text, 363 PendingIntent sentIntent, PendingIntent deliveryIntent) { 364 sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent, 365 false /* persistMessage */); 366 } 367 368 /** 369 * A variant of {@link SmsManager#sendTextMessage} that allows self to be the caller. This is 370 * for internal use only. 371 * 372 * @param persistMessage whether to persist the sent message in the SMS app. the caller must be 373 * the Phone process if set to false. 374 * 375 * @hide 376 */ 377 public void sendTextMessageWithSelfPermissions( 378 String destinationAddress, String scAddress, String text, 379 PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessage) { 380 if (TextUtils.isEmpty(destinationAddress)) { 381 throw new IllegalArgumentException("Invalid destinationAddress"); 382 } 383 384 if (TextUtils.isEmpty(text)) { 385 throw new IllegalArgumentException("Invalid message body"); 386 } 387 388 try { 389 ISms iccISms = getISmsServiceOrThrow(); 390 iccISms.sendTextForSubscriberWithSelfPermissions(getSubscriptionId(), 391 ActivityThread.currentPackageName(), 392 destinationAddress, 393 scAddress, text, sentIntent, deliveryIntent, persistMessage); 394 } catch (RemoteException ex) { 395 // ignore it 396 } 397 } 398 399 /** 400 * Send a text based SMS with messaging options. 401 * 402 * @param destinationAddress the address to send the message to 403 * @param scAddress is the service center address or null to use 404 * the current default SMSC 405 * @param text the body of the message to send 406 * @param sentIntent if not NULL this <code>PendingIntent</code> is 407 * broadcast when the message is successfully sent, or failed. 408 * The result code will be <code>Activity.RESULT_OK</code> for success, 409 * or one of these errors:<br> 410 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 411 * <code>RESULT_ERROR_RADIO_OFF</code><br> 412 * <code>RESULT_ERROR_NULL_PDU</code><br> 413 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 414 * the extra "errorCode" containing a radio technology specific value, 415 * generally only useful for troubleshooting.<br> 416 * The per-application based SMS control checks sentIntent. If sentIntent 417 * is NULL the caller will be checked against all unknown applications, 418 * which cause smaller number of SMS to be sent in checking period. 419 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 420 * broadcast when the message is delivered to the recipient. The 421 * raw pdu of the status report is in the extended data ("pdu"). 422 * @param priority Priority level of the message 423 * Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1 424 * --------------------------------- 425 * PRIORITY | Level of Priority 426 * --------------------------------- 427 * '00' | Normal 428 * '01' | Interactive 429 * '10' | Urgent 430 * '11' | Emergency 431 * ---------------------------------- 432 * Any Other values included Negative considered as Invalid Priority Indicator of the message. 433 * @param expectMore is a boolean to indicate the sending messages through same link or not. 434 * @param validityPeriod Validity Period of the message in mins. 435 * Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1. 436 * Validity Period(Minimum) -> 5 mins 437 * Validity Period(Maximum) -> 635040 mins(i.e.63 weeks). 438 * Any Other values included Negative considered as Invalid Validity Period of the message. 439 * 440 * @throws IllegalArgumentException if destinationAddress or text are empty 441 * {@hide} 442 */ 443 public void sendTextMessage( 444 String destinationAddress, String scAddress, String text, 445 PendingIntent sentIntent, PendingIntent deliveryIntent, 446 int priority, boolean expectMore, int validityPeriod) { 447 sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent, 448 true /* persistMessage*/, priority, expectMore, validityPeriod); 449 } 450 451 private void sendTextMessageInternal( 452 String destinationAddress, String scAddress, String text, 453 PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessage, 454 int priority, boolean expectMore, int validityPeriod) { 455 if (TextUtils.isEmpty(destinationAddress)) { 456 throw new IllegalArgumentException("Invalid destinationAddress"); 457 } 458 459 if (TextUtils.isEmpty(text)) { 460 throw new IllegalArgumentException("Invalid message body"); 461 } 462 463 if (priority < 0x00 || priority > 0x03) { 464 throw new IllegalArgumentException("Invalid priority"); 465 } 466 467 if (validityPeriod < 0x05 || validityPeriod > 0x09b0a0) { 468 throw new IllegalArgumentException("Invalid validity period"); 469 } 470 471 try { 472 ISms iccISms = getISmsServiceOrThrow(); 473 if (iccISms != null) { 474 iccISms.sendTextForSubscriberWithOptions(getSubscriptionId(), 475 ActivityThread.currentPackageName(), destinationAddress, scAddress, text, 476 sentIntent, deliveryIntent, persistMessage, priority, expectMore, 477 validityPeriod); 478 } 479 } catch (RemoteException ex) { 480 // ignore it 481 } 482 } 483 484 /** 485 * Send a text based SMS without writing it into the SMS Provider. 486 * 487 * <p>Requires Permission: 488 * {@link android.Manifest.permission#MODIFY_PHONE_STATE} or the calling app has carrier 489 * privileges. 490 * </p> 491 * 492 * @see #sendTextMessage(String, String, String, PendingIntent, 493 * PendingIntent, int, boolean, int) 494 * @hide 495 */ 496 public void sendTextMessageWithoutPersisting( 497 String destinationAddress, String scAddress, String text, 498 PendingIntent sentIntent, PendingIntent deliveryIntent, int priority, 499 boolean expectMore, int validityPeriod) { 500 sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent, 501 false /* persistMessage */, priority, expectMore, validityPeriod); 502 } 503 504 /** 505 * 506 * Inject an SMS PDU into the android application framework. 507 * 508 * <p>Requires permission: {@link android.Manifest.permission#MODIFY_PHONE_STATE} or carrier 509 * privileges per {@link android.telephony.TelephonyManager#hasCarrierPrivileges}. 510 * 511 * @param pdu is the byte array of pdu to be injected into android application framework 512 * @param format is the format of SMS pdu ({@link SmsMessage#FORMAT_3GPP} or 513 * {@link SmsMessage#FORMAT_3GPP2}) 514 * @param receivedIntent if not NULL this <code>PendingIntent</code> is 515 * broadcast when the message is successfully received by the 516 * android application framework, or failed. This intent is broadcasted at 517 * the same time an SMS received from radio is acknowledged back. 518 * The result code will be {@link android.provider.Telephony.Sms.Intents#RESULT_SMS_HANDLED} 519 * for success, or {@link android.provider.Telephony.Sms.Intents#RESULT_SMS_GENERIC_ERROR} for 520 * error. 521 * 522 * @throws IllegalArgumentException if the format is invalid. 523 */ 524 public void injectSmsPdu( 525 byte[] pdu, @SmsMessage.Format String format, PendingIntent receivedIntent) { 526 if (!format.equals(SmsMessage.FORMAT_3GPP) && !format.equals(SmsMessage.FORMAT_3GPP2)) { 527 // Format must be either 3gpp or 3gpp2. 528 throw new IllegalArgumentException( 529 "Invalid pdu format. format must be either 3gpp or 3gpp2"); 530 } 531 try { 532 ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); 533 if (iccISms != null) { 534 iccISms.injectSmsPduForSubscriber( 535 getSubscriptionId(), pdu, format, receivedIntent); 536 } 537 } catch (RemoteException ex) { 538 // ignore it 539 } 540 } 541 542 /** 543 * Divide a message text into several fragments, none bigger than 544 * the maximum SMS message size. 545 * 546 * @param text the original message. Must not be null. 547 * @return an <code>ArrayList</code> of strings that, in order, 548 * comprise the original message 549 * 550 * @throws IllegalArgumentException if text is null 551 */ 552 public ArrayList<String> divideMessage(String text) { 553 if (null == text) { 554 throw new IllegalArgumentException("text is null"); 555 } 556 return SmsMessage.fragmentText(text); 557 } 558 559 /** 560 * Send a multi-part text based SMS. The callee should have already 561 * divided the message into correctly sized parts by calling 562 * <code>divideMessage</code>. 563 * 564 * <p class="note"><strong>Note:</strong> Using this method requires that your app has the 565 * {@link android.Manifest.permission#SEND_SMS} permission.</p> 566 * 567 * <p class="note"><strong>Note:</strong> Beginning with Android 4.4 (API level 19), if 568 * <em>and only if</em> an app is not selected as the default SMS app, the system automatically 569 * writes messages sent using this method to the SMS Provider (the default SMS app is always 570 * responsible for writing its sent messages to the SMS Provider). For information about 571 * how to behave as the default SMS app, see {@link android.provider.Telephony}.</p> 572 * 573 * @param destinationAddress the address to send the message to 574 * @param scAddress is the service center address or null to use 575 * the current default SMSC 576 * @param parts an <code>ArrayList</code> of strings that, in order, 577 * comprise the original message 578 * @param sentIntents if not null, an <code>ArrayList</code> of 579 * <code>PendingIntent</code>s (one for each message part) that is 580 * broadcast when the corresponding message part has been sent. 581 * The result code will be <code>Activity.RESULT_OK</code> for success, 582 * or one of these errors:<br> 583 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 584 * <code>RESULT_ERROR_RADIO_OFF</code><br> 585 * <code>RESULT_ERROR_NULL_PDU</code><br> 586 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> each sentIntent may include 587 * the extra "errorCode" containing a radio technology specific value, 588 * generally only useful for troubleshooting.<br> 589 * The per-application based SMS control checks sentIntent. If sentIntent 590 * is NULL the caller will be checked against all unknown applications, 591 * which cause smaller number of SMS to be sent in checking period. 592 * @param deliveryIntents if not null, an <code>ArrayList</code> of 593 * <code>PendingIntent</code>s (one for each message part) that is 594 * broadcast when the corresponding message part has been delivered 595 * to the recipient. The raw pdu of the status report is in the 596 * extended data ("pdu"). 597 * 598 * @throws IllegalArgumentException if destinationAddress or data are empty 599 */ 600 public void sendMultipartTextMessage( 601 String destinationAddress, String scAddress, ArrayList<String> parts, 602 ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) { 603 sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents, 604 deliveryIntents, true /* persistMessage*/); 605 } 606 607 private void sendMultipartTextMessageInternal( 608 String destinationAddress, String scAddress, List<String> parts, 609 List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents, 610 boolean persistMessage) { 611 if (TextUtils.isEmpty(destinationAddress)) { 612 throw new IllegalArgumentException("Invalid destinationAddress"); 613 } 614 if (parts == null || parts.size() < 1) { 615 throw new IllegalArgumentException("Invalid message body"); 616 } 617 618 if (parts.size() > 1) { 619 try { 620 ISms iccISms = getISmsServiceOrThrow(); 621 iccISms.sendMultipartTextForSubscriber(getSubscriptionId(), 622 ActivityThread.currentPackageName(), 623 destinationAddress, scAddress, parts, 624 sentIntents, deliveryIntents, persistMessage); 625 } catch (RemoteException ex) { 626 // ignore it 627 } 628 } else { 629 PendingIntent sentIntent = null; 630 PendingIntent deliveryIntent = null; 631 if (sentIntents != null && sentIntents.size() > 0) { 632 sentIntent = sentIntents.get(0); 633 } 634 if (deliveryIntents != null && deliveryIntents.size() > 0) { 635 deliveryIntent = deliveryIntents.get(0); 636 } 637 sendTextMessage(destinationAddress, scAddress, parts.get(0), 638 sentIntent, deliveryIntent); 639 } 640 } 641 642 /** 643 * Send a multi-part text based SMS without writing it into the SMS Provider. 644 * 645 * <p>Requires Permission: 646 * {@link android.Manifest.permission#MODIFY_PHONE_STATE} or the calling app has carrier 647 * privileges. 648 * </p> 649 * 650 * @see #sendMultipartTextMessage(String, String, ArrayList, ArrayList, ArrayList) 651 * @hide 652 **/ 653 @SystemApi 654 @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) 655 public void sendMultipartTextMessageWithoutPersisting( 656 String destinationAddress, String scAddress, List<String> parts, 657 List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) { 658 sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents, 659 deliveryIntents, false /* persistMessage*/); 660 } 661 662 /** 663 * Send a multi-part text based SMS with messaging options. The callee should have already 664 * divided the message into correctly sized parts by calling 665 * <code>divideMessage</code>. 666 * 667 * <p class="note"><strong>Note:</strong> Using this method requires that your app has the 668 * {@link android.Manifest.permission#SEND_SMS} permission.</p> 669 * 670 * <p class="note"><strong>Note:</strong> Beginning with Android 4.4 (API level 19), if 671 * <em>and only if</em> an app is not selected as the default SMS app, the system automatically 672 * writes messages sent using this method to the SMS Provider (the default SMS app is always 673 * responsible for writing its sent messages to the SMS Provider). For information about 674 * how to behave as the default SMS app, see {@link android.provider.Telephony}.</p> 675 * 676 * @param destinationAddress the address to send the message to 677 * @param scAddress is the service center address or null to use 678 * the current default SMSC 679 * @param parts an <code>ArrayList</code> of strings that, in order, 680 * comprise the original message 681 * @param sentIntents if not null, an <code>ArrayList</code> of 682 * <code>PendingIntent</code>s (one for each message part) that is 683 * broadcast when the corresponding message part has been sent. 684 * The result code will be <code>Activity.RESULT_OK</code> for success, 685 * or one of these errors:<br> 686 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 687 * <code>RESULT_ERROR_RADIO_OFF</code><br> 688 * <code>RESULT_ERROR_NULL_PDU</code><br> 689 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> each sentIntent may include 690 * the extra "errorCode" containing a radio technology specific value, 691 * generally only useful for troubleshooting.<br> 692 * The per-application based SMS control checks sentIntent. If sentIntent 693 * is NULL the caller will be checked against all unknown applications, 694 * which cause smaller number of SMS to be sent in checking period. 695 * @param deliveryIntents if not null, an <code>ArrayList</code> of 696 * <code>PendingIntent</code>s (one for each message part) that is 697 * broadcast when the corresponding message part has been delivered 698 * to the recipient. The raw pdu of the status report is in the 699 * extended data ("pdu"). 700 * @param priority Priority level of the message 701 * Refer specification See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1 702 * --------------------------------- 703 * PRIORITY | Level of Priority 704 * --------------------------------- 705 * '00' | Normal 706 * '01' | Interactive 707 * '10' | Urgent 708 * '11' | Emergency 709 * ---------------------------------- 710 * Any Other values included Negative considered as Invalid Priority Indicator of the message. 711 * @param expectMore is a boolean to indicate the sending messages through same link or not. 712 * @param validityPeriod Validity Period of the message in mins. 713 * Refer specification 3GPP TS 23.040 V6.8.1 section 9.2.3.12.1. 714 * Validity Period(Minimum) -> 5 mins 715 * Validity Period(Maximum) -> 635040 mins(i.e.63 weeks). 716 * Any Other values included Negative considered as Invalid Validity Period of the message. 717 * 718 * @throws IllegalArgumentException if destinationAddress or data are empty 719 * {@hide} 720 */ 721 public void sendMultipartTextMessage( 722 String destinationAddress, String scAddress, ArrayList<String> parts, 723 ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents, 724 int priority, boolean expectMore, int validityPeriod) { 725 sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents, 726 deliveryIntents, true /* persistMessage*/); 727 } 728 729 private void sendMultipartTextMessageInternal( 730 String destinationAddress, String scAddress, List<String> parts, 731 List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents, 732 boolean persistMessage, int priority, boolean expectMore, int validityPeriod) { 733 if (TextUtils.isEmpty(destinationAddress)) { 734 throw new IllegalArgumentException("Invalid destinationAddress"); 735 } 736 if (parts == null || parts.size() < 1) { 737 throw new IllegalArgumentException("Invalid message body"); 738 } 739 740 if (priority < 0x00 || priority > 0x03) { 741 throw new IllegalArgumentException("Invalid priority"); 742 } 743 744 if (validityPeriod < 0x05 || validityPeriod > 0x09b0a0) { 745 throw new IllegalArgumentException("Invalid validity period"); 746 } 747 748 if (parts.size() > 1) { 749 try { 750 ISms iccISms = getISmsServiceOrThrow(); 751 if (iccISms != null) { 752 iccISms.sendMultipartTextForSubscriberWithOptions(getSubscriptionId(), 753 ActivityThread.currentPackageName(), destinationAddress, scAddress, 754 parts, sentIntents, deliveryIntents, persistMessage, priority, 755 expectMore, validityPeriod); 756 } 757 } catch (RemoteException ex) { 758 // ignore it 759 } 760 } else { 761 PendingIntent sentIntent = null; 762 PendingIntent deliveryIntent = null; 763 if (sentIntents != null && sentIntents.size() > 0) { 764 sentIntent = sentIntents.get(0); 765 } 766 if (deliveryIntents != null && deliveryIntents.size() > 0) { 767 deliveryIntent = deliveryIntents.get(0); 768 } 769 sendTextMessageInternal(destinationAddress, scAddress, parts.get(0), 770 sentIntent, deliveryIntent, persistMessage, priority, expectMore, 771 validityPeriod); 772 } 773 } 774 775 /** 776 * Send a multi-part text based SMS without writing it into the SMS Provider. 777 * 778 * <p>Requires Permission: 779 * {@link android.Manifest.permission#MODIFY_PHONE_STATE} or the calling app has carrier 780 * privileges. 781 * </p> 782 * 783 * @see #sendMultipartTextMessage(String, String, ArrayList, ArrayList, 784 * ArrayList, int, boolean, int) 785 * @hide 786 **/ 787 public void sendMultipartTextMessageWithoutPersisting( 788 String destinationAddress, String scAddress, List<String> parts, 789 List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents, 790 int priority, boolean expectMore, int validityPeriod) { 791 sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents, 792 deliveryIntents, false /* persistMessage*/, priority, expectMore, 793 validityPeriod); 794 } 795 796 /** 797 * Send a data based SMS to a specific application port. 798 * 799 * <p class="note"><strong>Note:</strong> Using this method requires that your app has the 800 * {@link android.Manifest.permission#SEND_SMS} permission.</p> 801 * 802 * @param destinationAddress the address to send the message to 803 * @param scAddress is the service center address or null to use 804 * the current default SMSC 805 * @param destinationPort the port to deliver the message to 806 * @param data the body of the message to send 807 * @param sentIntent if not NULL this <code>PendingIntent</code> is 808 * broadcast when the message is successfully sent, or failed. 809 * The result code will be <code>Activity.RESULT_OK</code> for success, 810 * or one of these errors:<br> 811 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 812 * <code>RESULT_ERROR_RADIO_OFF</code><br> 813 * <code>RESULT_ERROR_NULL_PDU</code><br> 814 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 815 * the extra "errorCode" containing a radio technology specific value, 816 * generally only useful for troubleshooting.<br> 817 * The per-application based SMS control checks sentIntent. If sentIntent 818 * is NULL the caller will be checked against all unknown applications, 819 * which cause smaller number of SMS to be sent in checking period. 820 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 821 * broadcast when the message is delivered to the recipient. The 822 * raw pdu of the status report is in the extended data ("pdu"). 823 * 824 * @throws IllegalArgumentException if destinationAddress or data are empty 825 */ 826 public void sendDataMessage( 827 String destinationAddress, String scAddress, short destinationPort, 828 byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) { 829 if (TextUtils.isEmpty(destinationAddress)) { 830 throw new IllegalArgumentException("Invalid destinationAddress"); 831 } 832 833 if (data == null || data.length == 0) { 834 throw new IllegalArgumentException("Invalid message data"); 835 } 836 837 try { 838 ISms iccISms = getISmsServiceOrThrow(); 839 iccISms.sendDataForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(), 840 destinationAddress, scAddress, destinationPort & 0xFFFF, 841 data, sentIntent, deliveryIntent); 842 } catch (RemoteException ex) { 843 // ignore it 844 } 845 } 846 847 /** 848 * A variant of {@link SmsManager#sendDataMessage} that allows self to be the caller. This is 849 * for internal use only. 850 * 851 * @hide 852 */ 853 public void sendDataMessageWithSelfPermissions( 854 String destinationAddress, String scAddress, short destinationPort, 855 byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) { 856 if (TextUtils.isEmpty(destinationAddress)) { 857 throw new IllegalArgumentException("Invalid destinationAddress"); 858 } 859 860 if (data == null || data.length == 0) { 861 throw new IllegalArgumentException("Invalid message data"); 862 } 863 864 try { 865 ISms iccISms = getISmsServiceOrThrow(); 866 iccISms.sendDataForSubscriberWithSelfPermissions(getSubscriptionId(), 867 ActivityThread.currentPackageName(), destinationAddress, scAddress, 868 destinationPort & 0xFFFF, data, sentIntent, deliveryIntent); 869 } catch (RemoteException ex) { 870 // ignore it 871 } 872 } 873 874 875 876 /** 877 * Get the SmsManager associated with the default subscription id. The instance will always be 878 * associated with the default subscription id, even if the default subscription id is changed. 879 * 880 * @return the SmsManager associated with the default subscription id 881 */ 882 public static SmsManager getDefault() { 883 return sInstance; 884 } 885 886 /** 887 * Get the the instance of the SmsManager associated with a particular subscription id 888 * 889 * @param subId an SMS subscription id, typically accessed using 890 * {@link android.telephony.SubscriptionManager} 891 * @return the instance of the SmsManager associated with subId 892 */ 893 public static SmsManager getSmsManagerForSubscriptionId(int subId) { 894 // TODO(shri): Add javadoc link once SubscriptionManager is made public api 895 synchronized(sLockObject) { 896 SmsManager smsManager = sSubInstances.get(subId); 897 if (smsManager == null) { 898 smsManager = new SmsManager(subId); 899 sSubInstances.put(subId, smsManager); 900 } 901 return smsManager; 902 } 903 } 904 905 private SmsManager(int subId) { 906 mSubId = subId; 907 } 908 909 /** 910 * Get the associated subscription id. If the instance was returned by {@link #getDefault()}, 911 * then this method may return different values at different points in time (if the user 912 * changes the default subscription id). It will return < 0 if the default subscription id 913 * cannot be determined. 914 * 915 * Additionally, to support legacy applications that are not multi-SIM aware, 916 * if the following are true: 917 * - We are using a multi-SIM device 918 * - A default SMS SIM has not been selected 919 * - At least one SIM subscription is available 920 * then ask the user to set the default SMS SIM. 921 * 922 * @return associated subscription id 923 */ 924 public int getSubscriptionId() { 925 final int subId = (mSubId == DEFAULT_SUBSCRIPTION_ID) 926 ? getDefaultSmsSubscriptionId() : mSubId; 927 boolean isSmsSimPickActivityNeeded = false; 928 final Context context = ActivityThread.currentApplication().getApplicationContext(); 929 try { 930 ISms iccISms = getISmsService(); 931 if (iccISms != null) { 932 isSmsSimPickActivityNeeded = iccISms.isSmsSimPickActivityNeeded(subId); 933 } 934 } catch (RemoteException ex) { 935 Log.e(TAG, "Exception in getSubscriptionId"); 936 } 937 938 if (isSmsSimPickActivityNeeded) { 939 Log.d(TAG, "getSubscriptionId isSmsSimPickActivityNeeded is true"); 940 // ask the user for a default SMS SIM. 941 Intent intent = new Intent(); 942 intent.setClassName("com.android.settings", 943 "com.android.settings.sim.SimDialogActivity"); 944 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 945 intent.putExtra(DIALOG_TYPE_KEY, SMS_PICK); 946 try { 947 context.startActivity(intent); 948 } catch (ActivityNotFoundException anfe) { 949 // If Settings is not installed, only log the error as we do not want to break 950 // legacy applications. 951 Log.e(TAG, "Unable to launch Settings application."); 952 } 953 } 954 955 return subId; 956 } 957 958 /** 959 * Returns the ISms service, or throws an UnsupportedOperationException if 960 * the service does not exist. 961 */ 962 private static ISms getISmsServiceOrThrow() { 963 ISms iccISms = getISmsService(); 964 if (iccISms == null) { 965 throw new UnsupportedOperationException("Sms is not supported"); 966 } 967 return iccISms; 968 } 969 970 private static ISms getISmsService() { 971 return ISms.Stub.asInterface(ServiceManager.getService("isms")); 972 } 973 974 /** 975 * Copy a raw SMS PDU to the ICC. 976 * ICC (Integrated Circuit Card) is the card of the device. 977 * For example, this can be the SIM or USIM for GSM. 978 * 979 * @param smsc the SMSC for this message, or NULL for the default SMSC 980 * @param pdu the raw PDU to store 981 * @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD, 982 * STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT) 983 * @return true for success 984 * 985 * @throws IllegalArgumentException if pdu is NULL 986 * {@hide} 987 */ 988 public boolean copyMessageToIcc(byte[] smsc, byte[] pdu,int status) { 989 boolean success = false; 990 991 if (null == pdu) { 992 throw new IllegalArgumentException("pdu is NULL"); 993 } 994 try { 995 ISms iccISms = getISmsService(); 996 if (iccISms != null) { 997 success = iccISms.copyMessageToIccEfForSubscriber(getSubscriptionId(), 998 ActivityThread.currentPackageName(), 999 status, pdu, smsc); 1000 } 1001 } catch (RemoteException ex) { 1002 // ignore it 1003 } 1004 1005 return success; 1006 } 1007 1008 /** 1009 * Delete the specified message from the ICC. 1010 * ICC (Integrated Circuit Card) is the card of the device. 1011 * For example, this can be the SIM or USIM for GSM. 1012 * 1013 * @param messageIndex is the record index of the message on ICC 1014 * @return true for success 1015 * 1016 * {@hide} 1017 */ 1018 public boolean 1019 deleteMessageFromIcc(int messageIndex) { 1020 boolean success = false; 1021 byte[] pdu = new byte[SMS_RECORD_LENGTH-1]; 1022 Arrays.fill(pdu, (byte)0xff); 1023 1024 try { 1025 ISms iccISms = getISmsService(); 1026 if (iccISms != null) { 1027 success = iccISms.updateMessageOnIccEfForSubscriber(getSubscriptionId(), 1028 ActivityThread.currentPackageName(), 1029 messageIndex, STATUS_ON_ICC_FREE, pdu); 1030 } 1031 } catch (RemoteException ex) { 1032 // ignore it 1033 } 1034 1035 return success; 1036 } 1037 1038 /** 1039 * Update the specified message on the ICC. 1040 * ICC (Integrated Circuit Card) is the card of the device. 1041 * For example, this can be the SIM or USIM for GSM. 1042 * 1043 * @param messageIndex record index of message to update 1044 * @param newStatus new message status (STATUS_ON_ICC_READ, 1045 * STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT, 1046 * STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE) 1047 * @param pdu the raw PDU to store 1048 * @return true for success 1049 * 1050 * {@hide} 1051 */ 1052 public boolean updateMessageOnIcc(int messageIndex, int newStatus, byte[] pdu) { 1053 boolean success = false; 1054 1055 try { 1056 ISms iccISms = getISmsService(); 1057 if (iccISms != null) { 1058 success = iccISms.updateMessageOnIccEfForSubscriber(getSubscriptionId(), 1059 ActivityThread.currentPackageName(), 1060 messageIndex, newStatus, pdu); 1061 } 1062 } catch (RemoteException ex) { 1063 // ignore it 1064 } 1065 1066 return success; 1067 } 1068 1069 /** 1070 * Retrieves all messages currently stored on ICC. 1071 * ICC (Integrated Circuit Card) is the card of the device. 1072 * For example, this can be the SIM or USIM for GSM. 1073 * 1074 * @return <code>ArrayList</code> of <code>SmsMessage</code> objects 1075 * 1076 * {@hide} 1077 */ 1078 public ArrayList<SmsMessage> getAllMessagesFromIcc() { 1079 List<SmsRawData> records = null; 1080 1081 try { 1082 ISms iccISms = getISmsService(); 1083 if (iccISms != null) { 1084 records = iccISms.getAllMessagesFromIccEfForSubscriber( 1085 getSubscriptionId(), 1086 ActivityThread.currentPackageName()); 1087 } 1088 } catch (RemoteException ex) { 1089 // ignore it 1090 } 1091 1092 return createMessageListFromRawRecords(records); 1093 } 1094 1095 /** 1096 * Enable reception of cell broadcast (SMS-CB) messages with the given 1097 * message identifier and RAN type. The RAN type specify this message ID 1098 * belong to 3GPP (GSM) or 3GPP2(CDMA).Note that if two different clients 1099 * enable the same message identifier, they must both disable it for the device to stop 1100 * receiving those messages. All received messages will be broadcast in an 1101 * intent with the action "android.provider.Telephony.SMS_CB_RECEIVED". 1102 * Note: This call is blocking, callers may want to avoid calling it from 1103 * the main thread of an application. 1104 * 1105 * @param messageIdentifier Message identifier as specified in TS 23.041 (3GPP) 1106 * or C.R1001-G (3GPP2) 1107 * @param ranType as defined in class SmsManager, the value can be one of these: 1108 * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM 1109 * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA 1110 * @return true if successful, false otherwise 1111 * @see #disableCellBroadcast(int, int) 1112 * 1113 * {@hide} 1114 */ 1115 public boolean enableCellBroadcast(int messageIdentifier, int ranType) { 1116 boolean success = false; 1117 1118 try { 1119 ISms iccISms = getISmsService(); 1120 if (iccISms != null) { 1121 success = iccISms.enableCellBroadcastForSubscriber( 1122 getSubscriptionId(), messageIdentifier, ranType); 1123 } 1124 } catch (RemoteException ex) { 1125 // ignore it 1126 } 1127 1128 return success; 1129 } 1130 1131 /** 1132 * Disable reception of cell broadcast (SMS-CB) messages with the given 1133 * message identifier and RAN type. The RAN type specify this message ID 1134 * belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different clients 1135 * enable the same message identifier, they must both disable it for the 1136 * device to stop receiving those messages. 1137 * Note: This call is blocking, callers may want to avoid calling it from 1138 * the main thread of an application. 1139 * 1140 * @param messageIdentifier Message identifier as specified in TS 23.041 (3GPP) 1141 * or C.R1001-G (3GPP2) 1142 * @param ranType as defined in class SmsManager, the value can be one of these: 1143 * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM 1144 * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA 1145 * @return true if successful, false otherwise 1146 * 1147 * @see #enableCellBroadcast(int, int) 1148 * 1149 * {@hide} 1150 */ 1151 public boolean disableCellBroadcast(int messageIdentifier, int ranType) { 1152 boolean success = false; 1153 1154 try { 1155 ISms iccISms = getISmsService(); 1156 if (iccISms != null) { 1157 success = iccISms.disableCellBroadcastForSubscriber( 1158 getSubscriptionId(), messageIdentifier, ranType); 1159 } 1160 } catch (RemoteException ex) { 1161 // ignore it 1162 } 1163 1164 return success; 1165 } 1166 1167 /** 1168 * Enable reception of cell broadcast (SMS-CB) messages with the given 1169 * message identifier range and RAN type. The RAN type specify this message ID 1170 * belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different clients enable 1171 * the same message identifier, they must both disable it for the device to stop 1172 * receiving those messages. All received messages will be broadcast in an 1173 * intent with the action "android.provider.Telephony.SMS_CB_RECEIVED". 1174 * Note: This call is blocking, callers may want to avoid calling it from 1175 * the main thread of an application. 1176 * 1177 * @param startMessageId first message identifier as specified in TS 23.041 (3GPP) 1178 * or C.R1001-G (3GPP2) 1179 * @param endMessageId last message identifier as specified in TS 23.041 (3GPP) 1180 * or C.R1001-G (3GPP2) 1181 * @param ranType as defined in class SmsManager, the value can be one of these: 1182 * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM 1183 * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA 1184 * @return true if successful, false otherwise 1185 * @see #disableCellBroadcastRange(int, int, int) 1186 * 1187 * @throws IllegalArgumentException if endMessageId < startMessageId 1188 * {@hide} 1189 */ 1190 public boolean enableCellBroadcastRange(int startMessageId, int endMessageId, int ranType) { 1191 boolean success = false; 1192 1193 if (endMessageId < startMessageId) { 1194 throw new IllegalArgumentException("endMessageId < startMessageId"); 1195 } 1196 try { 1197 ISms iccISms = getISmsService(); 1198 if (iccISms != null) { 1199 success = iccISms.enableCellBroadcastRangeForSubscriber(getSubscriptionId(), 1200 startMessageId, endMessageId, ranType); 1201 } 1202 } catch (RemoteException ex) { 1203 // ignore it 1204 } 1205 1206 return success; 1207 } 1208 1209 /** 1210 * Disable reception of cell broadcast (SMS-CB) messages with the given 1211 * message identifier range and RAN type. The RAN type specify this message 1212 * ID range belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different 1213 * clients enable the same message identifier, they must both disable it for 1214 * the device to stop receiving those messages. 1215 * Note: This call is blocking, callers may want to avoid calling it from 1216 * the main thread of an application. 1217 * 1218 * @param startMessageId first message identifier as specified in TS 23.041 (3GPP) 1219 * or C.R1001-G (3GPP2) 1220 * @param endMessageId last message identifier as specified in TS 23.041 (3GPP) 1221 * or C.R1001-G (3GPP2) 1222 * @param ranType as defined in class SmsManager, the value can be one of these: 1223 * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM 1224 * android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA 1225 * @return true if successful, false otherwise 1226 * 1227 * @see #enableCellBroadcastRange(int, int, int) 1228 * 1229 * @throws IllegalArgumentException if endMessageId < startMessageId 1230 * {@hide} 1231 */ 1232 public boolean disableCellBroadcastRange(int startMessageId, int endMessageId, int ranType) { 1233 boolean success = false; 1234 1235 if (endMessageId < startMessageId) { 1236 throw new IllegalArgumentException("endMessageId < startMessageId"); 1237 } 1238 try { 1239 ISms iccISms = getISmsService(); 1240 if (iccISms != null) { 1241 success = iccISms.disableCellBroadcastRangeForSubscriber(getSubscriptionId(), 1242 startMessageId, endMessageId, ranType); 1243 } 1244 } catch (RemoteException ex) { 1245 // ignore it 1246 } 1247 1248 return success; 1249 } 1250 1251 /** 1252 * Create a list of <code>SmsMessage</code>s from a list of RawSmsData 1253 * records returned by <code>getAllMessagesFromIcc()</code> 1254 * 1255 * @param records SMS EF records, returned by 1256 * <code>getAllMessagesFromIcc</code> 1257 * @return <code>ArrayList</code> of <code>SmsMessage</code> objects. 1258 */ 1259 private ArrayList<SmsMessage> createMessageListFromRawRecords(List<SmsRawData> records) { 1260 ArrayList<SmsMessage> messages = new ArrayList<SmsMessage>(); 1261 if (records != null) { 1262 int count = records.size(); 1263 for (int i = 0; i < count; i++) { 1264 SmsRawData data = records.get(i); 1265 // List contains all records, including "free" records (null) 1266 if (data != null) { 1267 SmsMessage sms = SmsMessage.createFromEfRecord(i+1, data.getBytes(), 1268 getSubscriptionId()); 1269 if (sms != null) { 1270 messages.add(sms); 1271 } 1272 } 1273 } 1274 } 1275 return messages; 1276 } 1277 1278 /** 1279 * SMS over IMS is supported if IMS is registered and SMS is supported 1280 * on IMS. 1281 * 1282 * @return true if SMS over IMS is supported, false otherwise 1283 * 1284 * @see #getImsSmsFormat() 1285 * 1286 * @hide 1287 */ 1288 public boolean isImsSmsSupported() { 1289 boolean boSupported = false; 1290 try { 1291 ISms iccISms = getISmsService(); 1292 if (iccISms != null) { 1293 boSupported = iccISms.isImsSmsSupportedForSubscriber(getSubscriptionId()); 1294 } 1295 } catch (RemoteException ex) { 1296 // ignore it 1297 } 1298 return boSupported; 1299 } 1300 1301 /** 1302 * Gets SMS format supported on IMS. SMS over IMS format is 1303 * either 3GPP or 3GPP2. 1304 * 1305 * @return SmsMessage.FORMAT_3GPP, 1306 * SmsMessage.FORMAT_3GPP2 1307 * or SmsMessage.FORMAT_UNKNOWN 1308 * 1309 * @see #isImsSmsSupported() 1310 * 1311 * @hide 1312 */ 1313 public String getImsSmsFormat() { 1314 String format = com.android.internal.telephony.SmsConstants.FORMAT_UNKNOWN; 1315 try { 1316 ISms iccISms = getISmsService(); 1317 if (iccISms != null) { 1318 format = iccISms.getImsSmsFormatForSubscriber(getSubscriptionId()); 1319 } 1320 } catch (RemoteException ex) { 1321 // ignore it 1322 } 1323 return format; 1324 } 1325 1326 /** 1327 * Get default sms subscription id 1328 * 1329 * @return the default SMS subscription id 1330 */ 1331 public static int getDefaultSmsSubscriptionId() { 1332 ISms iccISms = null; 1333 try { 1334 iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); 1335 return iccISms.getPreferredSmsSubscription(); 1336 } catch (RemoteException ex) { 1337 return -1; 1338 } catch (NullPointerException ex) { 1339 return -1; 1340 } 1341 } 1342 1343 /** 1344 * Get SMS prompt property, enabled or not 1345 * 1346 * @return true if enabled, false otherwise 1347 * @hide 1348 */ 1349 public boolean isSMSPromptEnabled() { 1350 ISms iccISms = null; 1351 try { 1352 iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms")); 1353 return iccISms.isSMSPromptEnabled(); 1354 } catch (RemoteException ex) { 1355 return false; 1356 } catch (NullPointerException ex) { 1357 return false; 1358 } 1359 } 1360 1361 // see SmsMessage.getStatusOnIcc 1362 1363 /** Free space (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 1364 static public final int STATUS_ON_ICC_FREE = 0; 1365 1366 /** Received and read (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 1367 static public final int STATUS_ON_ICC_READ = 1; 1368 1369 /** Received and unread (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 1370 static public final int STATUS_ON_ICC_UNREAD = 3; 1371 1372 /** Stored and sent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 1373 static public final int STATUS_ON_ICC_SENT = 5; 1374 1375 /** Stored and unsent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */ 1376 static public final int STATUS_ON_ICC_UNSENT = 7; 1377 1378 // SMS send failure result codes 1379 1380 /** 1381 * No error. 1382 * @hide 1383 */ 1384 @SystemApi 1385 static public final int RESULT_ERROR_NONE = 0; 1386 /** Generic failure cause */ 1387 static public final int RESULT_ERROR_GENERIC_FAILURE = 1; 1388 /** Failed because radio was explicitly turned off */ 1389 static public final int RESULT_ERROR_RADIO_OFF = 2; 1390 /** Failed because no pdu provided */ 1391 static public final int RESULT_ERROR_NULL_PDU = 3; 1392 /** Failed because service is currently unavailable */ 1393 static public final int RESULT_ERROR_NO_SERVICE = 4; 1394 /** Failed because we reached the sending queue limit. */ 1395 static public final int RESULT_ERROR_LIMIT_EXCEEDED = 5; 1396 /** 1397 * Failed because FDN is enabled. 1398 * @hide 1399 */ 1400 @SystemApi 1401 static public final int RESULT_ERROR_FDN_CHECK_FAILURE = 6; 1402 /** Failed because user denied the sending of this short code. */ 1403 static public final int RESULT_ERROR_SHORT_CODE_NOT_ALLOWED = 7; 1404 /** Failed because the user has denied this app ever send premium short codes. */ 1405 static public final int RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED = 8; 1406 /** 1407 * Failed because the radio was not available 1408 * @hide 1409 */ 1410 @SystemApi 1411 static public final int RESULT_RADIO_NOT_AVAILABLE = 9; 1412 /** 1413 * Failed because of network rejection 1414 * @hide 1415 */ 1416 @SystemApi 1417 static public final int RESULT_NETWORK_REJECT = 10; 1418 /** 1419 * Failed because of invalid arguments 1420 * @hide 1421 */ 1422 @SystemApi 1423 static public final int RESULT_INVALID_ARGUMENTS = 11; 1424 /** 1425 * Failed because of an invalid state 1426 * @hide 1427 */ 1428 @SystemApi 1429 static public final int RESULT_INVALID_STATE = 12; 1430 /** 1431 * Failed because there is no memory 1432 * @hide 1433 */ 1434 @SystemApi 1435 static public final int RESULT_NO_MEMORY = 13; 1436 /** 1437 * Failed because the sms format is not valid 1438 * @hide 1439 */ 1440 @SystemApi 1441 static public final int RESULT_INVALID_SMS_FORMAT = 14; 1442 /** 1443 * Failed because of a system error 1444 * @hide 1445 */ 1446 @SystemApi 1447 static public final int RESULT_SYSTEM_ERROR = 15; 1448 /** 1449 * Failed because of a modem error 1450 * @hide 1451 */ 1452 @SystemApi 1453 static public final int RESULT_MODEM_ERROR = 16; 1454 /** 1455 * Failed because of a network error 1456 * @hide 1457 */ 1458 @SystemApi 1459 static public final int RESULT_NETWORK_ERROR = 17; 1460 /** 1461 * Failed because of an encoding error 1462 * @hide 1463 */ 1464 @SystemApi 1465 static public final int RESULT_ENCODING_ERROR = 18; 1466 /** 1467 * Failed because of an invalid smsc address 1468 * @hide 1469 */ 1470 @SystemApi 1471 static public final int RESULT_INVALID_SMSC_ADDRESS = 19; 1472 /** 1473 * Failed because the operation is not allowed 1474 * @hide 1475 */ 1476 @SystemApi 1477 static public final int RESULT_OPERATION_NOT_ALLOWED = 20; 1478 /** 1479 * Failed because of an internal error 1480 * @hide 1481 */ 1482 @SystemApi 1483 static public final int RESULT_INTERNAL_ERROR = 21; 1484 /** 1485 * Failed because there are no resources 1486 * @hide 1487 */ 1488 @SystemApi 1489 static public final int RESULT_NO_RESOURCES = 22; 1490 /** 1491 * Failed because the operation was cancelled 1492 * @hide 1493 */ 1494 @SystemApi 1495 static public final int RESULT_CANCELLED = 23; 1496 /** 1497 * Failed because the request is not supported 1498 * @hide 1499 */ 1500 @SystemApi 1501 static public final int RESULT_REQUEST_NOT_SUPPORTED = 24; 1502 1503 1504 static private final String PHONE_PACKAGE_NAME = "com.android.phone"; 1505 1506 /** 1507 * Send an MMS message 1508 * 1509 * @param context application context 1510 * @param contentUri the content Uri from which the message pdu will be read 1511 * @param locationUrl the optional location url where message should be sent to 1512 * @param configOverrides the carrier-specific messaging configuration values to override for 1513 * sending the message. 1514 * @param sentIntent if not NULL this <code>PendingIntent</code> is 1515 * broadcast when the message is successfully sent, or failed 1516 * @throws IllegalArgumentException if contentUri is empty 1517 */ 1518 public void sendMultimediaMessage(Context context, Uri contentUri, String locationUrl, 1519 Bundle configOverrides, PendingIntent sentIntent) { 1520 if (contentUri == null) { 1521 throw new IllegalArgumentException("Uri contentUri null"); 1522 } 1523 try { 1524 final IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1525 if (iMms == null) { 1526 return; 1527 } 1528 1529 iMms.sendMessage(getSubscriptionId(), ActivityThread.currentPackageName(), contentUri, 1530 locationUrl, configOverrides, sentIntent); 1531 } catch (RemoteException e) { 1532 // Ignore it 1533 } 1534 } 1535 1536 /** 1537 * Download an MMS message from carrier by a given location URL 1538 * 1539 * @param context application context 1540 * @param locationUrl the location URL of the MMS message to be downloaded, usually obtained 1541 * from the MMS WAP push notification 1542 * @param contentUri the content uri to which the downloaded pdu will be written 1543 * @param configOverrides the carrier-specific messaging configuration values to override for 1544 * downloading the message. 1545 * @param downloadedIntent if not NULL this <code>PendingIntent</code> is 1546 * broadcast when the message is downloaded, or the download is failed 1547 * @throws IllegalArgumentException if locationUrl or contentUri is empty 1548 */ 1549 public void downloadMultimediaMessage(Context context, String locationUrl, Uri contentUri, 1550 Bundle configOverrides, PendingIntent downloadedIntent) { 1551 if (TextUtils.isEmpty(locationUrl)) { 1552 throw new IllegalArgumentException("Empty MMS location URL"); 1553 } 1554 if (contentUri == null) { 1555 throw new IllegalArgumentException("Uri contentUri null"); 1556 } 1557 try { 1558 final IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1559 if (iMms == null) { 1560 return; 1561 } 1562 iMms.downloadMessage( 1563 getSubscriptionId(), ActivityThread.currentPackageName(), locationUrl, 1564 contentUri, configOverrides, downloadedIntent); 1565 } catch (RemoteException e) { 1566 // Ignore it 1567 } 1568 } 1569 1570 // MMS send/download failure result codes 1571 public static final int MMS_ERROR_UNSPECIFIED = 1; 1572 public static final int MMS_ERROR_INVALID_APN = 2; 1573 public static final int MMS_ERROR_UNABLE_CONNECT_MMS = 3; 1574 public static final int MMS_ERROR_HTTP_FAILURE = 4; 1575 public static final int MMS_ERROR_IO_ERROR = 5; 1576 public static final int MMS_ERROR_RETRY = 6; 1577 public static final int MMS_ERROR_CONFIGURATION_ERROR = 7; 1578 public static final int MMS_ERROR_NO_DATA_NETWORK = 8; 1579 1580 /** Intent extra name for MMS sending result data in byte array type */ 1581 public static final String EXTRA_MMS_DATA = "android.telephony.extra.MMS_DATA"; 1582 /** Intent extra name for HTTP status code for MMS HTTP failure in integer type */ 1583 public static final String EXTRA_MMS_HTTP_STATUS = "android.telephony.extra.MMS_HTTP_STATUS"; 1584 1585 /** 1586 * Import a text message into system's SMS store 1587 * 1588 * Only default SMS apps can import SMS 1589 * 1590 * @param address the destination(source) address of the sent(received) message 1591 * @param type the type of the message 1592 * @param text the message text 1593 * @param timestampMillis the message timestamp in milliseconds 1594 * @param seen if the message is seen 1595 * @param read if the message is read 1596 * @return the message URI, null if failed 1597 * @hide 1598 */ 1599 public Uri importTextMessage(String address, int type, String text, long timestampMillis, 1600 boolean seen, boolean read) { 1601 try { 1602 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1603 if (iMms != null) { 1604 return iMms.importTextMessage(ActivityThread.currentPackageName(), 1605 address, type, text, timestampMillis, seen, read); 1606 } 1607 } catch (RemoteException ex) { 1608 // ignore it 1609 } 1610 return null; 1611 } 1612 1613 /** Represents the received SMS message for importing {@hide} */ 1614 public static final int SMS_TYPE_INCOMING = 0; 1615 /** Represents the sent SMS message for importing {@hide} */ 1616 public static final int SMS_TYPE_OUTGOING = 1; 1617 1618 /** 1619 * Import a multimedia message into system's MMS store. Only the following PDU type is 1620 * supported: Retrieve.conf, Send.req, Notification.ind, Delivery.ind, Read-Orig.ind 1621 * 1622 * Only default SMS apps can import MMS 1623 * 1624 * @param contentUri the content uri from which to read the PDU of the message to import 1625 * @param messageId the optional message id. Use null if not specifying 1626 * @param timestampSecs the optional message timestamp. Use -1 if not specifying 1627 * @param seen if the message is seen 1628 * @param read if the message is read 1629 * @return the message URI, null if failed 1630 * @throws IllegalArgumentException if pdu is empty 1631 * {@hide} 1632 */ 1633 public Uri importMultimediaMessage(Uri contentUri, String messageId, long timestampSecs, 1634 boolean seen, boolean read) { 1635 if (contentUri == null) { 1636 throw new IllegalArgumentException("Uri contentUri null"); 1637 } 1638 try { 1639 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1640 if (iMms != null) { 1641 return iMms.importMultimediaMessage(ActivityThread.currentPackageName(), 1642 contentUri, messageId, timestampSecs, seen, read); 1643 } 1644 } catch (RemoteException ex) { 1645 // ignore it 1646 } 1647 return null; 1648 } 1649 1650 /** 1651 * Delete a system stored SMS or MMS message 1652 * 1653 * Only default SMS apps can delete system stored SMS and MMS messages 1654 * 1655 * @param messageUri the URI of the stored message 1656 * @return true if deletion is successful, false otherwise 1657 * @throws IllegalArgumentException if messageUri is empty 1658 * {@hide} 1659 */ 1660 public boolean deleteStoredMessage(Uri messageUri) { 1661 if (messageUri == null) { 1662 throw new IllegalArgumentException("Empty message URI"); 1663 } 1664 try { 1665 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1666 if (iMms != null) { 1667 return iMms.deleteStoredMessage(ActivityThread.currentPackageName(), messageUri); 1668 } 1669 } catch (RemoteException ex) { 1670 // ignore it 1671 } 1672 return false; 1673 } 1674 1675 /** 1676 * Delete a system stored SMS or MMS thread 1677 * 1678 * Only default SMS apps can delete system stored SMS and MMS conversations 1679 * 1680 * @param conversationId the ID of the message conversation 1681 * @return true if deletion is successful, false otherwise 1682 * {@hide} 1683 */ 1684 public boolean deleteStoredConversation(long conversationId) { 1685 try { 1686 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1687 if (iMms != null) { 1688 return iMms.deleteStoredConversation( 1689 ActivityThread.currentPackageName(), conversationId); 1690 } 1691 } catch (RemoteException ex) { 1692 // ignore it 1693 } 1694 return false; 1695 } 1696 1697 /** 1698 * Update the status properties of a system stored SMS or MMS message, e.g. 1699 * the read status of a message, etc. 1700 * 1701 * @param messageUri the URI of the stored message 1702 * @param statusValues a list of status properties in key-value pairs to update 1703 * @return true if update is successful, false otherwise 1704 * @throws IllegalArgumentException if messageUri is empty 1705 * {@hide} 1706 */ 1707 public boolean updateStoredMessageStatus(Uri messageUri, ContentValues statusValues) { 1708 if (messageUri == null) { 1709 throw new IllegalArgumentException("Empty message URI"); 1710 } 1711 try { 1712 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1713 if (iMms != null) { 1714 return iMms.updateStoredMessageStatus(ActivityThread.currentPackageName(), 1715 messageUri, statusValues); 1716 } 1717 } catch (RemoteException ex) { 1718 // ignore it 1719 } 1720 return false; 1721 } 1722 1723 /** Message status property: whether the message has been seen. 1 means seen, 0 not {@hide} */ 1724 public static final String MESSAGE_STATUS_SEEN = "seen"; 1725 /** Message status property: whether the message has been read. 1 means read, 0 not {@hide} */ 1726 public static final String MESSAGE_STATUS_READ = "read"; 1727 1728 /** 1729 * Archive or unarchive a stored conversation 1730 * 1731 * @param conversationId the ID of the message conversation 1732 * @param archived true to archive the conversation, false to unarchive 1733 * @return true if update is successful, false otherwise 1734 * {@hide} 1735 */ 1736 public boolean archiveStoredConversation(long conversationId, boolean archived) { 1737 try { 1738 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1739 if (iMms != null) { 1740 return iMms.archiveStoredConversation(ActivityThread.currentPackageName(), 1741 conversationId, archived); 1742 } 1743 } catch (RemoteException ex) { 1744 // ignore it 1745 } 1746 return false; 1747 } 1748 1749 /** 1750 * Add a text message draft to system SMS store 1751 * 1752 * Only default SMS apps can add SMS draft 1753 * 1754 * @param address the destination address of message 1755 * @param text the body of the message to send 1756 * @return the URI of the stored draft message 1757 * {@hide} 1758 */ 1759 public Uri addTextMessageDraft(String address, String text) { 1760 try { 1761 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1762 if (iMms != null) { 1763 return iMms.addTextMessageDraft(ActivityThread.currentPackageName(), address, text); 1764 } 1765 } catch (RemoteException ex) { 1766 // ignore it 1767 } 1768 return null; 1769 } 1770 1771 /** 1772 * Add a multimedia message draft to system MMS store 1773 * 1774 * Only default SMS apps can add MMS draft 1775 * 1776 * @param contentUri the content uri from which to read the PDU data of the draft MMS 1777 * @return the URI of the stored draft message 1778 * @throws IllegalArgumentException if pdu is empty 1779 * {@hide} 1780 */ 1781 public Uri addMultimediaMessageDraft(Uri contentUri) { 1782 if (contentUri == null) { 1783 throw new IllegalArgumentException("Uri contentUri null"); 1784 } 1785 try { 1786 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1787 if (iMms != null) { 1788 return iMms.addMultimediaMessageDraft(ActivityThread.currentPackageName(), 1789 contentUri); 1790 } 1791 } catch (RemoteException ex) { 1792 // ignore it 1793 } 1794 return null; 1795 } 1796 1797 /** 1798 * Send a system stored text message. 1799 * 1800 * You can only send a failed text message or a draft text message. 1801 * 1802 * @param messageUri the URI of the stored message 1803 * @param scAddress is the service center address or null to use the current default SMSC 1804 * @param sentIntent if not NULL this <code>PendingIntent</code> is 1805 * broadcast when the message is successfully sent, or failed. 1806 * The result code will be <code>Activity.RESULT_OK</code> for success, 1807 * or one of these errors:<br> 1808 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 1809 * <code>RESULT_ERROR_RADIO_OFF</code><br> 1810 * <code>RESULT_ERROR_NULL_PDU</code><br> 1811 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include 1812 * the extra "errorCode" containing a radio technology specific value, 1813 * generally only useful for troubleshooting.<br> 1814 * The per-application based SMS control checks sentIntent. If sentIntent 1815 * is NULL the caller will be checked against all unknown applications, 1816 * which cause smaller number of SMS to be sent in checking period. 1817 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is 1818 * broadcast when the message is delivered to the recipient. The 1819 * raw pdu of the status report is in the extended data ("pdu"). 1820 * 1821 * @throws IllegalArgumentException if messageUri is empty 1822 * {@hide} 1823 */ 1824 public void sendStoredTextMessage(Uri messageUri, String scAddress, PendingIntent sentIntent, 1825 PendingIntent deliveryIntent) { 1826 if (messageUri == null) { 1827 throw new IllegalArgumentException("Empty message URI"); 1828 } 1829 try { 1830 ISms iccISms = getISmsServiceOrThrow(); 1831 iccISms.sendStoredText( 1832 getSubscriptionId(), ActivityThread.currentPackageName(), messageUri, 1833 scAddress, sentIntent, deliveryIntent); 1834 } catch (RemoteException ex) { 1835 // ignore it 1836 } 1837 } 1838 1839 /** 1840 * Send a system stored multi-part text message. 1841 * 1842 * You can only send a failed text message or a draft text message. 1843 * The provided <code>PendingIntent</code> lists should match the part number of the 1844 * divided text of the stored message by using <code>divideMessage</code> 1845 * 1846 * @param messageUri the URI of the stored message 1847 * @param scAddress is the service center address or null to use 1848 * the current default SMSC 1849 * @param sentIntents if not null, an <code>ArrayList</code> of 1850 * <code>PendingIntent</code>s (one for each message part) that is 1851 * broadcast when the corresponding message part has been sent. 1852 * The result code will be <code>Activity.RESULT_OK</code> for success, 1853 * or one of these errors:<br> 1854 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br> 1855 * <code>RESULT_ERROR_RADIO_OFF</code><br> 1856 * <code>RESULT_ERROR_NULL_PDU</code><br> 1857 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> each sentIntent may include 1858 * the extra "errorCode" containing a radio technology specific value, 1859 * generally only useful for troubleshooting.<br> 1860 * The per-application based SMS control checks sentIntent. If sentIntent 1861 * is NULL the caller will be checked against all unknown applications, 1862 * which cause smaller number of SMS to be sent in checking period. 1863 * @param deliveryIntents if not null, an <code>ArrayList</code> of 1864 * <code>PendingIntent</code>s (one for each message part) that is 1865 * broadcast when the corresponding message part has been delivered 1866 * to the recipient. The raw pdu of the status report is in the 1867 * extended data ("pdu"). 1868 * 1869 * @throws IllegalArgumentException if messageUri is empty 1870 * {@hide} 1871 */ 1872 public void sendStoredMultipartTextMessage(Uri messageUri, String scAddress, 1873 ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) { 1874 if (messageUri == null) { 1875 throw new IllegalArgumentException("Empty message URI"); 1876 } 1877 try { 1878 ISms iccISms = getISmsServiceOrThrow(); 1879 iccISms.sendStoredMultipartText( 1880 getSubscriptionId(), ActivityThread.currentPackageName(), messageUri, 1881 scAddress, sentIntents, deliveryIntents); 1882 } catch (RemoteException ex) { 1883 // ignore it 1884 } 1885 } 1886 1887 /** 1888 * Send a system stored MMS message 1889 * 1890 * This is used for sending a previously sent, but failed-to-send, message or 1891 * for sending a text message that has been stored as a draft. 1892 * 1893 * @param messageUri the URI of the stored message 1894 * @param configOverrides the carrier-specific messaging configuration values to override for 1895 * sending the message. 1896 * @param sentIntent if not NULL this <code>PendingIntent</code> is 1897 * broadcast when the message is successfully sent, or failed 1898 * @throws IllegalArgumentException if messageUri is empty 1899 * {@hide} 1900 */ 1901 public void sendStoredMultimediaMessage(Uri messageUri, Bundle configOverrides, 1902 PendingIntent sentIntent) { 1903 if (messageUri == null) { 1904 throw new IllegalArgumentException("Empty message URI"); 1905 } 1906 try { 1907 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1908 if (iMms != null) { 1909 iMms.sendStoredMessage( 1910 getSubscriptionId(), ActivityThread.currentPackageName(), messageUri, 1911 configOverrides, sentIntent); 1912 } 1913 } catch (RemoteException ex) { 1914 // ignore it 1915 } 1916 } 1917 1918 /** 1919 * Turns on/off the flag to automatically write sent/received SMS/MMS messages into system 1920 * 1921 * When this flag is on, all SMS/MMS sent/received are stored by system automatically 1922 * When this flag is off, only SMS/MMS sent by non-default SMS apps are stored by system 1923 * automatically 1924 * 1925 * This flag can only be changed by default SMS apps 1926 * 1927 * @param enabled Whether to enable message auto persisting 1928 * {@hide} 1929 */ 1930 public void setAutoPersisting(boolean enabled) { 1931 try { 1932 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1933 if (iMms != null) { 1934 iMms.setAutoPersisting(ActivityThread.currentPackageName(), enabled); 1935 } 1936 } catch (RemoteException ex) { 1937 // ignore it 1938 } 1939 } 1940 1941 /** 1942 * Get the value of the flag to automatically write sent/received SMS/MMS messages into system 1943 * 1944 * When this flag is on, all SMS/MMS sent/received are stored by system automatically 1945 * When this flag is off, only SMS/MMS sent by non-default SMS apps are stored by system 1946 * automatically 1947 * 1948 * @return the current value of the auto persist flag 1949 * {@hide} 1950 */ 1951 public boolean getAutoPersisting() { 1952 try { 1953 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1954 if (iMms != null) { 1955 return iMms.getAutoPersisting(); 1956 } 1957 } catch (RemoteException ex) { 1958 // ignore it 1959 } 1960 return false; 1961 } 1962 1963 /** 1964 * Get carrier-dependent configuration values. 1965 * 1966 * @return bundle key/values pairs of configuration values 1967 */ 1968 public Bundle getCarrierConfigValues() { 1969 try { 1970 IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); 1971 if (iMms != null) { 1972 return iMms.getCarrierConfigValues(getSubscriptionId()); 1973 } 1974 } catch (RemoteException ex) { 1975 // ignore it 1976 } 1977 return null; 1978 } 1979 1980 /** 1981 * Create a single use app specific incoming SMS request for the the calling package. 1982 * 1983 * This method returns a token that if included in a subsequent incoming SMS message will cause 1984 * {@code intent} to be sent with the SMS data. 1985 * 1986 * The token is only good for one use, after an SMS has been received containing the token all 1987 * subsequent SMS messages with the token will be routed as normal. 1988 * 1989 * An app can only have one request at a time, if the app already has a request pending it will 1990 * be replaced with a new request. 1991 * 1992 * @return Token to include in an SMS message. The token will be 11 characters long. 1993 * @see android.provider.Telephony.Sms.Intents#getMessagesFromIntent 1994 */ 1995 public String createAppSpecificSmsToken(PendingIntent intent) { 1996 try { 1997 ISms iccSms = getISmsServiceOrThrow(); 1998 return iccSms.createAppSpecificSmsToken(getSubscriptionId(), 1999 ActivityThread.currentPackageName(), intent); 2000 2001 } catch (RemoteException ex) { 2002 ex.rethrowFromSystemServer(); 2003 return null; 2004 } 2005 } 2006 2007 /** 2008 * Filters a bundle to only contain MMS config variables. 2009 * 2010 * This is for use with bundles returned by {@link CarrierConfigManager} which contain MMS 2011 * config and unrelated config. It is assumed that all MMS_CONFIG_* keys are present in the 2012 * supplied bundle. 2013 * 2014 * @param config a Bundle that contains MMS config variables and possibly more. 2015 * @return a new Bundle that only contains the MMS_CONFIG_* keys defined above. 2016 * @hide 2017 */ 2018 public static Bundle getMmsConfig(BaseBundle config) { 2019 Bundle filtered = new Bundle(); 2020 filtered.putBoolean(MMS_CONFIG_APPEND_TRANSACTION_ID, 2021 config.getBoolean(MMS_CONFIG_APPEND_TRANSACTION_ID)); 2022 filtered.putBoolean(MMS_CONFIG_MMS_ENABLED, config.getBoolean(MMS_CONFIG_MMS_ENABLED)); 2023 filtered.putBoolean(MMS_CONFIG_GROUP_MMS_ENABLED, 2024 config.getBoolean(MMS_CONFIG_GROUP_MMS_ENABLED)); 2025 filtered.putBoolean(MMS_CONFIG_NOTIFY_WAP_MMSC_ENABLED, 2026 config.getBoolean(MMS_CONFIG_NOTIFY_WAP_MMSC_ENABLED)); 2027 filtered.putBoolean(MMS_CONFIG_ALIAS_ENABLED, config.getBoolean(MMS_CONFIG_ALIAS_ENABLED)); 2028 filtered.putBoolean(MMS_CONFIG_ALLOW_ATTACH_AUDIO, 2029 config.getBoolean(MMS_CONFIG_ALLOW_ATTACH_AUDIO)); 2030 filtered.putBoolean(MMS_CONFIG_MULTIPART_SMS_ENABLED, 2031 config.getBoolean(MMS_CONFIG_MULTIPART_SMS_ENABLED)); 2032 filtered.putBoolean(MMS_CONFIG_SMS_DELIVERY_REPORT_ENABLED, 2033 config.getBoolean(MMS_CONFIG_SMS_DELIVERY_REPORT_ENABLED)); 2034 filtered.putBoolean(MMS_CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION, 2035 config.getBoolean(MMS_CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION)); 2036 filtered.putBoolean(MMS_CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES, 2037 config.getBoolean(MMS_CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES)); 2038 filtered.putBoolean(MMS_CONFIG_MMS_READ_REPORT_ENABLED, 2039 config.getBoolean(MMS_CONFIG_MMS_READ_REPORT_ENABLED)); 2040 filtered.putBoolean(MMS_CONFIG_MMS_DELIVERY_REPORT_ENABLED, 2041 config.getBoolean(MMS_CONFIG_MMS_DELIVERY_REPORT_ENABLED)); 2042 filtered.putBoolean(MMS_CONFIG_CLOSE_CONNECTION, 2043 config.getBoolean(MMS_CONFIG_CLOSE_CONNECTION)); 2044 filtered.putInt(MMS_CONFIG_MAX_MESSAGE_SIZE, config.getInt(MMS_CONFIG_MAX_MESSAGE_SIZE)); 2045 filtered.putInt(MMS_CONFIG_MAX_IMAGE_WIDTH, config.getInt(MMS_CONFIG_MAX_IMAGE_WIDTH)); 2046 filtered.putInt(MMS_CONFIG_MAX_IMAGE_HEIGHT, config.getInt(MMS_CONFIG_MAX_IMAGE_HEIGHT)); 2047 filtered.putInt(MMS_CONFIG_RECIPIENT_LIMIT, config.getInt(MMS_CONFIG_RECIPIENT_LIMIT)); 2048 filtered.putInt(MMS_CONFIG_ALIAS_MIN_CHARS, config.getInt(MMS_CONFIG_ALIAS_MIN_CHARS)); 2049 filtered.putInt(MMS_CONFIG_ALIAS_MAX_CHARS, config.getInt(MMS_CONFIG_ALIAS_MAX_CHARS)); 2050 filtered.putInt(MMS_CONFIG_SMS_TO_MMS_TEXT_THRESHOLD, 2051 config.getInt(MMS_CONFIG_SMS_TO_MMS_TEXT_THRESHOLD)); 2052 filtered.putInt(MMS_CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD, 2053 config.getInt(MMS_CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD)); 2054 filtered.putInt(MMS_CONFIG_MESSAGE_TEXT_MAX_SIZE, 2055 config.getInt(MMS_CONFIG_MESSAGE_TEXT_MAX_SIZE)); 2056 filtered.putInt(MMS_CONFIG_SUBJECT_MAX_LENGTH, 2057 config.getInt(MMS_CONFIG_SUBJECT_MAX_LENGTH)); 2058 filtered.putInt(MMS_CONFIG_HTTP_SOCKET_TIMEOUT, 2059 config.getInt(MMS_CONFIG_HTTP_SOCKET_TIMEOUT)); 2060 filtered.putString(MMS_CONFIG_UA_PROF_TAG_NAME, 2061 config.getString(MMS_CONFIG_UA_PROF_TAG_NAME)); 2062 filtered.putString(MMS_CONFIG_USER_AGENT, config.getString(MMS_CONFIG_USER_AGENT)); 2063 filtered.putString(MMS_CONFIG_UA_PROF_URL, config.getString(MMS_CONFIG_UA_PROF_URL)); 2064 filtered.putString(MMS_CONFIG_HTTP_PARAMS, config.getString(MMS_CONFIG_HTTP_PARAMS)); 2065 filtered.putString(MMS_CONFIG_EMAIL_GATEWAY_NUMBER, 2066 config.getString(MMS_CONFIG_EMAIL_GATEWAY_NUMBER)); 2067 filtered.putString(MMS_CONFIG_NAI_SUFFIX, config.getString(MMS_CONFIG_NAI_SUFFIX)); 2068 filtered.putBoolean(MMS_CONFIG_SHOW_CELL_BROADCAST_APP_LINKS, 2069 config.getBoolean(MMS_CONFIG_SHOW_CELL_BROADCAST_APP_LINKS)); 2070 filtered.putBoolean(MMS_CONFIG_SUPPORT_HTTP_CHARSET_HEADER, 2071 config.getBoolean(MMS_CONFIG_SUPPORT_HTTP_CHARSET_HEADER)); 2072 return filtered; 2073 } 2074 2075} 2076