/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.telephony; import android.app.ActivityThread; import android.app.PendingIntent; import android.os.RemoteException; import android.os.ServiceManager; import android.text.TextUtils; import com.android.internal.telephony.ISms; import com.android.internal.telephony.SmsRawData; import com.android.internal.telephony.uicc.IccConstants; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /* * TODO(code review): Curious question... Why are a lot of these * methods not declared as static, since they do not seem to require * any local object state? Presumably this cannot be changed without * interfering with the API... */ /** * Manages SMS operations such as sending data, text, and pdu SMS messages. * Get this object by calling the static method {@link #getDefault()}. * *
For information about how to behave as the default SMS app on Android 4.4 (API level 19) * and higher, see {@link android.provider.Telephony}. */ public final class SmsManager { /** Singleton object constructed during class initialization. */ private static final SmsManager sInstance = new SmsManager(); /** * Send a text based SMS. * *
Note: Using this method requires that your app has the * {@link android.Manifest.permission#SEND_SMS} permission.
* *Note: Beginning with Android 4.4 (API level 19), if * and only if an app is not selected as the default SMS app, the system automatically * writes messages sent using this method to the SMS Provider (the default SMS app is always * responsible for writing its sent messages to the SMS Provider). For information about * how to behave as the default SMS app, see {@link android.provider.Telephony}.
* * * @param destinationAddress the address to send the message to * @param scAddress is the service center address or null to use * the current default SMSC * @param text the body of the message to send * @param sentIntent if not NULL thisPendingIntent
is
* broadcast when the message is successfully sent, or failed.
* The result code will be Activity.RESULT_OK
for success,
* or one of these errors:RESULT_ERROR_GENERIC_FAILURE
RESULT_ERROR_RADIO_OFF
RESULT_ERROR_NULL_PDU
RESULT_ERROR_GENERIC_FAILURE
the sentIntent may include
* the extra "errorCode" containing a radio technology specific value,
* generally only useful for troubleshooting.PendingIntent
is
* broadcast when the message is delivered to the recipient. The
* raw pdu of the status report is in the extended data ("pdu").
*
* @throws IllegalArgumentException if destinationAddress or text are empty
*/
public void sendTextMessage(
String destinationAddress, String scAddress, String text,
PendingIntent sentIntent, PendingIntent deliveryIntent) {
if (TextUtils.isEmpty(destinationAddress)) {
throw new IllegalArgumentException("Invalid destinationAddress");
}
if (TextUtils.isEmpty(text)) {
throw new IllegalArgumentException("Invalid message body");
}
try {
ISms iccISms = getISmsServiceOrThrow();
iccISms.sendText(ActivityThread.currentPackageName(), destinationAddress,
scAddress, text, sentIntent, deliveryIntent);
} catch (RemoteException ex) {
// ignore it
}
}
/**
* Divide a message text into several fragments, none bigger than
* the maximum SMS message size.
*
* @param text the original message. Must not be null.
* @return an ArrayList
of strings that, in order,
* comprise the original message
*
* @throws IllegalArgumentException if text is null
*/
public ArrayListdivideMessage
.
*
* Note: Using this method requires that your app has the * {@link android.Manifest.permission#SEND_SMS} permission.
* *Note: Beginning with Android 4.4 (API level 19), if * and only if an app is not selected as the default SMS app, the system automatically * writes messages sent using this method to the SMS Provider (the default SMS app is always * responsible for writing its sent messages to the SMS Provider). For information about * how to behave as the default SMS app, see {@link android.provider.Telephony}.
* * @param destinationAddress the address to send the message to * @param scAddress is the service center address or null to use * the current default SMSC * @param parts anArrayList
of strings that, in order,
* comprise the original message
* @param sentIntents if not null, an ArrayList
of
* PendingIntent
s (one for each message part) that is
* broadcast when the corresponding message part has been sent.
* The result code will be Activity.RESULT_OK
for success,
* or one of these errors:RESULT_ERROR_GENERIC_FAILURE
RESULT_ERROR_RADIO_OFF
RESULT_ERROR_NULL_PDU
RESULT_ERROR_GENERIC_FAILURE
each sentIntent may include
* the extra "errorCode" containing a radio technology specific value,
* generally only useful for troubleshooting.ArrayList
of
* PendingIntent
s (one for each message part) that is
* broadcast when the corresponding message part has been delivered
* to the recipient. The raw pdu of the status report is in the
* extended data ("pdu").
*
* @throws IllegalArgumentException if destinationAddress or data are empty
*/
public void sendMultipartTextMessage(
String destinationAddress, String scAddress, ArrayListNote: Using this method requires that your app has the * {@link android.Manifest.permission#SEND_SMS} permission.
* * @param destinationAddress the address to send the message to * @param scAddress is the service center address or null to use * the current default SMSC * @param destinationPort the port to deliver the message to * @param data the body of the message to send * @param sentIntent if not NULL thisPendingIntent
is
* broadcast when the message is successfully sent, or failed.
* The result code will be Activity.RESULT_OK
for success,
* or one of these errors:RESULT_ERROR_GENERIC_FAILURE
RESULT_ERROR_RADIO_OFF
RESULT_ERROR_NULL_PDU
RESULT_ERROR_GENERIC_FAILURE
the sentIntent may include
* the extra "errorCode" containing a radio technology specific value,
* generally only useful for troubleshooting.PendingIntent
is
* broadcast when the message is delivered to the recipient. The
* raw pdu of the status report is in the extended data ("pdu").
*
* @throws IllegalArgumentException if destinationAddress or data are empty
*/
public void sendDataMessage(
String destinationAddress, String scAddress, short destinationPort,
byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
if (TextUtils.isEmpty(destinationAddress)) {
throw new IllegalArgumentException("Invalid destinationAddress");
}
if (data == null || data.length == 0) {
throw new IllegalArgumentException("Invalid message data");
}
try {
ISms iccISms = getISmsServiceOrThrow();
iccISms.sendData(ActivityThread.currentPackageName(),
destinationAddress, scAddress, destinationPort & 0xFFFF,
data, sentIntent, deliveryIntent);
} catch (RemoteException ex) {
// ignore it
}
}
/**
* Get the default instance of the SmsManager
*
* @return the default instance of the SmsManager
*/
public static SmsManager getDefault() {
return sInstance;
}
private SmsManager() {
//nothing
}
/**
* Returns the ISms service, or throws an UnsupportedOperationException if
* the service does not exist.
*/
private static ISms getISmsServiceOrThrow() {
ISms iccISms = getISmsService();
if (iccISms == null) {
throw new UnsupportedOperationException("Sms is not supported");
}
return iccISms;
}
private static ISms getISmsService() {
return ISms.Stub.asInterface(ServiceManager.getService("isms"));
}
/**
* Copy a raw SMS PDU to the ICC.
* ICC (Integrated Circuit Card) is the card of the device.
* For example, this can be the SIM or USIM for GSM.
*
* @param smsc the SMSC for this message, or NULL for the default SMSC
* @param pdu the raw PDU to store
* @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD,
* STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT)
* @return true for success
*
* @throws IllegalArgumentException if pdu is NULL
* {@hide}
*/
public boolean copyMessageToIcc(byte[] smsc, byte[] pdu, int status) {
boolean success = false;
if (null == pdu) {
throw new IllegalArgumentException("pdu is NULL");
}
try {
ISms iccISms = getISmsService();
if (iccISms != null) {
success = iccISms.copyMessageToIccEf(ActivityThread.currentPackageName(),
status, pdu, smsc);
}
} catch (RemoteException ex) {
// ignore it
}
return success;
}
/**
* Delete the specified message from the ICC.
* ICC (Integrated Circuit Card) is the card of the device.
* For example, this can be the SIM or USIM for GSM.
*
* @param messageIndex is the record index of the message on ICC
* @return true for success
*
* {@hide}
*/
public boolean
deleteMessageFromIcc(int messageIndex) {
boolean success = false;
byte[] pdu = new byte[IccConstants.SMS_RECORD_LENGTH-1];
Arrays.fill(pdu, (byte)0xff);
try {
ISms iccISms = getISmsService();
if (iccISms != null) {
success = iccISms.updateMessageOnIccEf(ActivityThread.currentPackageName(),
messageIndex, STATUS_ON_ICC_FREE, pdu);
}
} catch (RemoteException ex) {
// ignore it
}
return success;
}
/**
* Update the specified message on the ICC.
* ICC (Integrated Circuit Card) is the card of the device.
* For example, this can be the SIM or USIM for GSM.
*
* @param messageIndex record index of message to update
* @param newStatus new message status (STATUS_ON_ICC_READ,
* STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT,
* STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE)
* @param pdu the raw PDU to store
* @return true for success
*
* {@hide}
*/
public boolean updateMessageOnIcc(int messageIndex, int newStatus, byte[] pdu) {
boolean success = false;
try {
ISms iccISms = getISmsService();
if (iccISms != null) {
success = iccISms.updateMessageOnIccEf(ActivityThread.currentPackageName(),
messageIndex, newStatus, pdu);
}
} catch (RemoteException ex) {
// ignore it
}
return success;
}
/**
* Retrieves all messages currently stored on ICC.
* ICC (Integrated Circuit Card) is the card of the device.
* For example, this can be the SIM or USIM for GSM.
*
* @return ArrayList
of SmsMessage
objects
*
* {@hide}
*/
public static ArrayListSmsMessage
s from a list of RawSmsData
* records returned by getAllMessagesFromIcc()
*
* @param records SMS EF records, returned by
* getAllMessagesFromIcc
* @return ArrayList
of SmsMessage
objects.
*/
private static ArrayList