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