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