Android短信群发
目前手上有小项目,需要实现短信群发功能,主要需求如下:1)短信收件人为多个时,需要能够在同一个会话中显示;
2)需要有发送结果的反馈,如(1/3)人发送成功。
代码清单:
1、发送短信接口函数javaSendSMS
// ////////////////////////////////////////////////////////////////////////////////
// send sms.
public boolean javaSendSMS(String messageAddress, String messageContent,
boolean bSilentMode) {
if (bSilentMode) {
SmsManager smsManager = SmsManager.getDefault();
if (messageAddress.trim().length() != 0 && messageContent.trim().length() != 0) {
try {
final String SENT_SMS_ACTION = "SENT_SMS_ACTION";
final String DELIVERED_SMS_ACTION = "DELIVERED_SMS_ACTION";
final Uri SMS_URI = Uri.parse("content://sms/");
// 初始化静态变量
index = 1;
smsCount = 0;
smsSuccess = 0;
// 获取联系人列表
String[] addressList = messageAddress.trim().split(";");
SmsManager msg = SmsManager.getDefault();
smsCount = addressList.length;
// 短信发送广播
Intent send = new Intent(SENT_SMS_ACTION);
PendingIntent sendPI = PendingIntent.getBroadcast(VenusActivity.appContext, 0, send, 0);
registerSMSBroadcastReceiver();
// 发送结果广播
Intent delive = new Intent(DELIVERED_SMS_ACTION);
PendingIntent deliverPI = PendingIntent.getBroadcast(VenusActivity.appContext, 0, delive, 0);
Set<String> phoneSet = new HashSet<String>(Arrays.asList(addressList));
// 创建或获取会话编号
long threadId = Threads.getOrCreateThreadId(appActivity, phoneSet);
// 迭代发送短信
ContentValues cv = new ContentValues();
for(String phoneNo : phoneSet) {
msg.sendTextMessage(phoneNo, null, messageContent, sendPI, deliverPI);
// 写入到数据库
cv.put("thread_id", threadId);
cv.put("date", System.currentTimeMillis());
cv.put("body", messageContent);
cv.put("read", 0);
cv.put("type", 2);
cv.put("address", phoneNo);
appContext.getContentResolver().insert(SMS_URI, cv);
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
} else {
Util.Trace("Call System SMS");
Uri smsUri = Uri.parse("smsto:" + messageAddress);
Intent smsIntent = new Intent(Intent.ACTION_VIEW, smsUri);
smsIntent.putExtra("sms_body", messageContent);
appActivity.startActivity(smsIntent);
}
return true;
}
2、短信发送成功后的广播处理如下
/**
* @Description 注册短信广播发送结果的显示
* @author hewu <hewu2008@gmail.com>
* @date 2013-9-12 下午15:05:56
*/
protected void registerSMSBroadcastReceiver() {
final String DELIVERED_SMS_ACTION = "DELIVERED_SMS_ACTION";
appContext.registerReceiver(new BroadcastReceiver(){
@Override
public void onReceive(Context arg0, Intent intent) {
Log.d(TAG, "[onReceive] index:" + index);
switch (getResultCode()){
case Activity.RESULT_OK:
if (index >= smsCount && smsCount > 1) {
smsSuccess++;
Toast.makeText(appContext, "(" + smsSuccess + "/" + smsCount + ")发送成功", Toast.LENGTH_SHORT).show();
smsSuccess = 0;
smsCount = 0;
index = 1;
}
smsSuccess++;
break;
default:
break;
}
index = index + 1;
}
}, new IntentFilter(DELIVERED_SMS_ACTION));
}
3、由于需要写入到同一个会话,从framework中使用如下代码
Threads.java文件如下:
package com.wondertek.video.luatojava;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.BaseColumns;
import android.text.TextUtils;
import android.util.Log;
import android.util.Patterns;
public final class Threads implements ThreadsColumns {
private static final String[] ID_PROJECTION = { BaseColumns._ID };
private static final String STANDARD_ENCODING = "UTF-8";
private static final Uri THREAD_ID_CONTENT_URI = Uri
.parse("content://mms-sms/threadID");
public static final Uri CONTENT_URI = Uri.withAppendedPath(
Uri.parse("content://mms-sms/"), "conversations");
public static final Uri OBSOLETE_THREADS_URI = Uri.withAppendedPath(
CONTENT_URI, "obsolete");
public static final Pattern NAME_ADDR_EMAIL_PATTERN = Pattern
.compile("\\s*(\"[^\"]*\"|[^<>\"]+)\\s*<([^<>]+)>\\s*");
public static final int COMMON_THREAD = 0;
public static final int BROADCAST_THREAD = 1;
// No one should construct an instance of this class.
private Threads() {
}
/**
* This is a single-recipient version of getOrCreateThreadId. It's
* convenient for use with SMS messages.
*/
public static long getOrCreateThreadId(Context context, String recipient) {
Set<String> recipients = new HashSet<String>();
recipients.add(recipient);
return getOrCreateThreadId(context, recipients);
}
/**
* Given the recipients list and subject of an unsaved message, return its
* thread ID. If the message starts a new thread, allocate a new thread ID.
* Otherwise, use the appropriate existing thread ID.
*
* Find the thread ID of the same set of recipients (in any order, without
* any additions). If one is found, return it. Otherwise, return a unique
* thread ID.
*/
public static long getOrCreateThreadId(Context context,
Set<String> recipients) {
Uri.Builder uriBuilder = THREAD_ID_CONTENT_URI.buildUpon();
for (String recipient : recipients) {
if (isEmailAddress(recipient)) {
recipient = extractAddrSpec(recipient);
}
uriBuilder.appendQueryParameter("recipient", recipient);
}
Uri uri = uriBuilder.build();
// if (DEBUG) Log.v(TAG, "getOrCreateThreadId uri: " + uri);
Cursor cursor = context.getContentResolver().query(uri, ID_PROJECTION,
null, null, null);
if (true) {
Log.v("Threads", "getOrCreateThreadId cursor cnt: " + cursor.getCount());
}
if (cursor != null) {
try {
if (cursor.moveToFirst()) {
return cursor.getLong(0);
} else {
Log.e("Threads", "getOrCreateThreadId returned no rows!");
}
} finally {
cursor.close();
}
}
Log.e("Threads",
"getOrCreateThreadId failed with uri " + uri.toString());
throw new IllegalArgumentException(
"Unable to find or allocate a thread ID.");
}
public static String extractAddrSpec(String address) {
Matcher match = NAME_ADDR_EMAIL_PATTERN.matcher(address);
if (match.matches()) {
return match.group(2);
}
return address;
}
/**
* Returns true if the address is an email address
*
* @param address the input address to be tested
* @return true if address is an email address
*/
public static boolean isEmailAddress(String address) {
if (TextUtils.isEmpty(address)) {
return false;
}
String s = extractAddrSpec(address);
Matcher match = Patterns.EMAIL_ADDRESS.matcher(s);
return match.matches();
}
}
/**
* Columns for the "threads" table used by MMS and SMS.
*/
interface ThreadsColumns extends BaseColumns {
/**
* The date at which the thread was created.
*
* <P>
* Type: INTEGER (long)
* </P>
*/
public static final String DATE = "date";
/**
* A string encoding of the recipient IDs of the recipients of the
* message, in numerical order and separated by spaces.
* <P>
* Type: TEXT
* </P>
*/
public static final String RECIPIENT_IDS = "recipient_ids";
/**
* The message count of the thread.
* <P>
* Type: INTEGER
* </P>
*/
public static final String MESSAGE_COUNT = "message_count";
/**
* Indicates whether all messages of the thread have been read.
* <P>
* Type: INTEGER
* </P>
*/
public static final String READ = "read";
/**
* The snippet of the latest message in the thread.
* <P>
* Type: TEXT
* </P>
*/
public static final String SNIPPET = "snippet";
/**
* The charset of the snippet.
* <P>
* Type: INTEGER
* </P>
*/
public static final String SNIPPET_CHARSET = "snippet_cs";
/**
* Type of the thread, either Threads.COMMON_THREAD or
* Threads.BROADCAST_THREAD.
* <P>
* Type: INTEGER
* </P>
*/
public static final String TYPE = "type";
/**
* Indicates whether there is a transmission error in the thread.
* <P>
* Type: INTEGER
* </P>
*/
public static final String ERROR = "error";
/**
* Indicates whether this thread contains any attachments.
* <P>
* Type: INTEGER
* </P>
*/
public static final String HAS_ATTACHMENT = "has_attachment";
}
但是仍然存在以下问题:
1)多个收件人无法显示在同一会话中;
2)短信发送后会受到多条广播 android 短信 broadcastreceiver
补充:移动开发 , Android