Android发送短信
获取OR创建ThreadId
private long getOrCreateThreadId() {
Set<String> recipients = new HashSet<String>();
String[] numbers = mNumber.split(",");
for(int i=0;i<numbers.length;i++) {
recipients.add(numbers[i]);
}
return Threads.getOrCreateThreadId(mContext, recipients);
}
参考资料
android 中调用接口发送短信
发送短信代码判断
private void sendMsg(String destAddress, String content,
PendingIntent sentIntent, PendingIntent deliveryIntent) {
SmsManager smsManager = SmsManager.getDefault();
List<String> divideContents = smsManager.divideMessage(content);
for (String text : divideContents) {
smsManager.sendTextMessage(destAddress, null, text, sentIntent,
deliveryIntent);
}
}
查看发送短信有关API
1. android.telephony.SmsManager
Manages SMS operations such as sending data, text, and pdu SMS messages. Get this object by calling the static method SmsManager.getDefault().
2. android.telephony.SmsManager.sendTextMessage()
void android.telephony.SmsManager.sendTextMessage(String destinationAddress, String scAddress, String text, PendingIntent sentIntent, PendingIntent deliveryIntent)
Send a text based SMS.
Parameters:
destinationAddress the address to send the message to
scAddress is the service center address or null to use the current default SMSC
text the body of the message to send
sentIntent if not NULL this PendingIntent is broadcast when the message is sucessfully 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
For RESULT_ERROR_GENERIC_FAILURE the sentIntent may include the extra "errorCode" containing a radio technology specific value, generally only useful for troubleshooting.
The per-application based SMS control checks sentIntent. If sentIntent is NULL the caller will be checked against all unknown applications, which cause smaller number of SMS to be sent in checking period.
deliveryIntent if not NULL this 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
3. android.app.PendingIntent.getBroadcast()
PendingIntent android.app.PendingIntent.getBroadcast(Context context, int requestCode, Intent intent, int flags)
Retrieve a PendingIntent that will perform a broadcast, like calling Context.sendBroadcast().
Parameters:
context The Context in which this PendingIntent should perform the broadcast.
requestCode Private request code for the sender (currently not used).
intent The Intent to be broadcast.
flags May be FLAG_ONE_SHOT, FLAG_NO_CREATE, FLAG_CANCEL_CURRENT, FLAG_UPDATE_CURRENT, or any of the flags as supported by Intent.fillIn() to control which unspecified parts of the intent that can be supplied when the actual send happens.
Returns:
Returns an existing or new PendingIntent matching the given parameters. May return null only if FLAG_NO_CREATE has been supplied.
4. android.content.Context.sendBroadcast()
void android.content.Context.sendBroadcast(Intent intent)
Broadcast the given intent to all interested BroadcastReceivers. This call is asynchronous; it returns immediately, and you will continue executing while the receivers are run. No results are propagated from receivers and receivers can not abort the broadcast. If you want to allow receivers to propagate results or abort the broadcast, you must send an ordered broadcast using sendOrderedBroadcast(Intent, String).
See BroadcastReceiver for more information on Intent broadcasts.
Parameters:
intent The Intent to broadcast; all receivers matching this Intent will receive the broadcast.
See Also:
android.content.BroadcastReceiver
registerReceiver
sendBroadcast(Intent, String)
sendOrderedBroadcast(Intent, String)
sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)
5. Telephony.Sms.Outbox.addMessage()
Uri com.txrj.sms.system.Telephony.Sms.Outbox.addMessage(ContentResolver resolver, String address, String body, String subject, Long date, boolean deliveryReport, long threadId)
Add an SMS to the Out box.
Parameters:
resolver the content resolver to use
address the address of the sender
body the body of the message
subject the psuedo-subject of the message
date the timestamp for the message
deliveryReport whether a delivery report was requested for the message
threadId
Returns:
the URI for the new message
发送短信给10010和10011出错
07-14 16:55:53.023: E/AndroidRuntime(4078): FATAL EXCEPTION: main
07-14 16:55:53.023: E/AndroidRuntime(4078): java.lang.SecurityException: Sending SMS message: Neither user 10110 nor current process has android.permission.SEND_SMS.
调用Telephony.Sms.Outbox.addMessage()出现异常
07-14 22:18:53.465: E/AndroidRuntime(8912): FATAL EXCEPTION: main
07-14 22:18:53.465: E/AndroidRuntime(8912): java.lang.SecurityException: Permission Denial: writing com.android.providers.telephony.SmsProvider uri content://sms/outbox from pid=8912, uid=10110 requires android.permission.WRITE_SMS
发送信息到10010日志
07-14 22:21:36.935: I/txrjsms(9352): send msg to 10010, content:
07-14 22:21:36.935: I/txrjsms(9352): 1314649
07-14 22:21:39.857: I/txrjsms(9352): send Msg success.
07-14 22:21:43.171: I/txrjsms(9352): message arrived.
将发送的信息添加到outBox中
Uri uri = Telephony.Sms.Outbox.addMessage(getContentResolver(), "13146491234", content,
null, System.currentTimeMillis(), false, getOrCreateThreadId());
onOutboxAddMessage(uri);
//…
private void onOutboxAddMessage(Uri uri) {
Cursor cursor = getContentResolver().query(uri,
new String[]{Sms._ID, Sms.THREAD_ID, Sms.TYPE, Sms.BODY, Sms.DATE},
null, null, null);
TxrjMessage msg = null;
if(cursor != null) {
if(cursor.moveToFirst()) {
msg = new TxrjMessage();
msg.setMessageId(cursor.getInt(cursor.getColumnIndex(Sms._ID)));
msg.setThreadId(cursor.getInt(cursor.getColumnIndex(Sms.THREAD_ID)));
msg.setType(cursor.getInt(cursor.getColumnIndex(Sms.TYPE)));
msg.setBody(cursor.getString(cursor.getColumnIndex(Sms.BODY)));
msg.setTime(cursor.getLong(cursor.getColumnIndex(Sms.DATE)));
mMessages.add(msg);
mListAdapter.notifyDataSetChanged();
if(!uriMap.containsKey(msg.getMessageId())){
uriMap.put(msg.getMessageId(), uri);
}
}
cursor.close();
}
}
注册ContentObserver需要API至少是16
Call requires API level 16 (current min is 11): android.database.ContentObserver#onChange
private void onMsgStatusChanged(Uri uri, int msgId) {
ContentObserver observer = new ContentObserver(null) {
@Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
}
};
getContentResolver().registerContentObserver(uri, false, observer);
}
实现onMsgStatusChanged()
private void onMsgStatusChanged(final Uri uri, final int msgId) {
final Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
mListAdapter.notifyDataSetChanged();
mListView.setSelection(mListView.getBottom());
}
};
ContentObserver observer = new ContentObserver(null) {
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
Cursor cursor = getContentResolver().query(uri,
new String[]{Sms._ID, Sms.THREAD_ID, Sms.TYPE, Sms.BODY, Sms.DATE},
null, null, null);
if(cursor != null) {
if(cursor.moveToFirst()) {
int type = cursor.getInt(cursor.getColumnIndex(Sms.TYPE));
for (int i = mMessages.size() - 1; i >= 0; i--) {
if(mMessages.get(i).getMessageId() == msgId) {
mMessages.get(i).setType(type);
break;
}
}
handler.sendMessage(handler.obtainMessage());
getContentResolver().unregisterContentObserver(this);
}
cursor.close();
}
}
};
getContentResolver().registerContentObserver(uri, false, observer);
}
发送信息成功或失败时修改信息状态
private void updateMsgType(Uri uri, int type) {
ContentValues values = new ContentValues();
values.put(Sms.TYPE, type);
getContentResolver().update(uri, values, null, null);
}
private PendingIntent getSentIntent(final Uri uri) {
BroadcastReceiver receiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
int resultCode = getResultCode();
if(resultCode == RESULT_OK) {
Toast.makeText(context, "send message success.", Toast.LENGTH_SHORT).show();
Log.i("txrjsms", "send message success.");
updateMsgType(uri, Sms.MESSAGE_TYPE_SENT);
} else if(resultCode == SmsManager.RESULT_ERROR_GENERIC_FAILURE) {
Toast.makeText(context, "Generic failure.", Toast.LENGTH_SHORT).show();
updateMsgType(uri, Sms.MESSAGE_TYPE_FAILED);
} else if(resultCode == SmsManager.RESULT_ERROR_NO_SERVICE) {
Toast.makeText(context, "service is currently unavailable.", Toast.LENGTH_SHORT).show();
updateMsgType(uri, Sms.MESSAGE_TYPE_FAILED);
} else if(resultCode == SmsManager.RESULT_ERROR_NULL_PDU) {
Toast.makeText(context, "no pdu provided.", Toast.LENGTH_SHORT).show();
updateMsgType(uri, Sms.MESSAGE_TYPE_FAILED);
} else if(resultCode == SmsManager.RESULT_ERROR_RADIO_OFF) {
Toast.makeText(context, "radio was explicitly turned off.", Toast.LENGTH_SHORT).show();
updateMsgType(uri, Sms.MESSAGE_TYPE_FAILED);
}
}
};
IntentFilter filter = new IntentFilter(TxrjConstant.ACTION_SEND_SMS);
mContext.registerReceiver(receiver, filter);
Intent sentIntent = new Intent(TxrjConstant.ACTION_SEND_SMS);
return PendingIntent.getBroadcast(mContext, 0, sentIntent, 0);
}
发送短信代码
private void sendMessage(String destAddr, String content) {
SmsManager smsManager = SmsManager.getDefault();
List<String> divideContents = smsManager.divideMessage(content);
for (String text : divideContents) {
Log.i("txrjsms", "send msg to " + destAddr + ", content:\n" + text);
smsManager.sendTextMessage(destAddr, null, text, getSentIntent(),
getDeliveryIntent());
}
}
private PendingIntent getSentIntent() {
Intent sentIntent = new Intent(TxrjConstant.ACTION_SEND_SMS);
BroadcastReceiver receiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
int resultCode = getResultCode();
if(resultCode == RESULT_OK) {
Toast.makeText(context, "send Msg success.", Toast.LENGTH_SHORT).show();
Log.i("txrjsms", "send Msg success.");
} else if(resultCode == SmsManager.RESULT_ERROR_GENERIC_FAILURE) {
} else if(resultCode == SmsManager.RESULT_ERROR_NO_SERVICE) {
} else if(resultCode == SmsManager.RESULT_ERROR_NULL_PDU) {
} else if(resultCode == SmsManager.RESULT_ERROR_RADIO_OFF) {
}
}
};
IntentFilter filter = new IntentFilter(TxrjConstant.ACTION_SEND_SMS);
mContext.registerReceiver(receiver, filter);
return PendingIntent.getBroadcast(mContext, 0, sentIntent, 0);
}
private PendingIntent getDeliveryIntent() {
Intent deliveryIntent = new Intent(TxrjConstant.ACTION_DELIVERY_SMS);
BroadcastReceiver receiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "message arrived.", Toast.LENGTH_SHORT).show();
Log.i("txrjsms", "message arrived.");
}
};
IntentFilter filter = new IntentFilter(TxrjConstant.ACTION_DELIVERY_SMS);
mContext.registerReceiver(receiver, filter);
return PendingIntent.getBroadcast(mContext, 0, deliveryIntent, 0);
}
发送短信LOG
07-14 16:58:29.746: I/txrjsms(4782): send msg to 10010, content:
07-14 16:58:29.746: I/txrjsms(4782): 102
07-14 16:58:29.906: I/txrjsms(4782): send msg to 10011, content:
07-14 16:58:29.906: I/txrjsms(4782): 102
07-14 16:58:33.620: I/txrjsms(4782): send Msg success.
07-14 16:58:33.650: I/txrjsms(4782): send Msg success.
07-14 16:58:36.583: I/txrjsms(4782): message arrived.
07-14 16:58:36.583: I/txrjsms(4782): message arrived.
07-14 16:58:37.554: I/txrjsms(4782): send Msg success.
07-14 16:58:37.564: I/txrjsms(4782): send Msg success.