android 判断线程状态多条短信息发出后的状态怎样判断

android 功能实现技巧(29)
前端时间通过客户端对短信发送数量做日志统计,后来发现没那么简单,只从手机端很难做到准确统计。因为存在一下问题:
1.短信作为长短信发送,但是移动会按实际字数,70字一条收取费用。
2.很难获得发送成功的状态(下面详解)。
首先发送短信的详细过程:
public static boolean sendSMSMsgLog(Context context, String number,
String message ,int type, String flags, String flag, String id) {
/** 发送与接收的广播 **/
String SENT_SMS_ACTION = &SENT_SMS_ACTION&;
String DELIVERED_SMS_ACTION = &DELIVERED_SMS_ACTION&;
boolean flag1 =
int m=i++;
MLog.i(&CommonUtils&, &发送短信内容:& + message);
SmsManager smsMgr = SmsManager.getDefault();
Intent intent=new Intent(SENT_SMS_ACTION);
intent.putExtra(&phoneNumber&,number);
PendingIntent sentPI = PendingIntent.getBroadcast(context, m,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
ArrayList&PendingIntent& sentIntents = new ArrayList&PendingIntent&();
sentIntents.add(sentPI);
Intent intentRe=new Intent(DELIVERED_SMS_ACTION);
intentRe.putExtra(&phoneNumber&,number);
intentRe.putExtra(&type&,type);
intentRe.putExtra(&flags&,flags);
intentRe.putExtra(&flag&,flag);
intentRe.putExtra(&id&,id);
PendingIntent deliverPI = PendingIntent.getBroadcast(context, m,
intentRe, PendingIntent.FLAG_UPDATE_CURRENT);
ArrayList&PendingIntent& deliverIntents = new ArrayList&PendingIntent&();
deliverIntents.add(deliverPI);
// 按照短信,最大容量拆分成多条短信
ArrayList&String& divideContents = smsMgr.divideMessage(message);
// for (String text : divideContents)
smsMgr.sendMultipartTextMessage(number, null, divideContents,
sentIntents, deliverIntents);
} catch (Exception e) {
} finally {
return flag1;
第一,分析长短信问题:
&&&&& 如代码的红色部分,就是对短信的拆分发送。如果拆分用户接受到的就是多条短信,如果不拆分用户接受到的就是一条短信,但是运营商收取的费用是一样的,是不是很坑爹。
第二,分析数据传递问题:
&&& 如代码蓝色部分,就是在触发DELIVERED_SMS_ACTION(短信接收成功)监听时,传递数据,只要在广播接收者里,捕捉到DELIVERED_SMS_ACTION后,从意图获取数据即可,如手机号、发送信息的id等等。(代码演示会在问题三种看到)
第三,分析发送状态获取:
&很多人都知道短信发送有两个状态广播:
** 发送与接收的广播 **/
String SENT_SMS_ACTION = &SENT_SMS_ACTION&;
String DELIVERED_SMS_ACTION = &DELIVERED_SMS_ACTION&;
&&&&& 我现在要统计的是计费成功的短信,也就是接收成功的短信。
&&&&& 首先说&SENT_SMS_ACTION&,这个广播每条短信都可以捕获,他只说明发送成功或失败,只是短信已经发送到短信平台,对方有没有接收是不确定的。有很多异常情况但是都是发送成功的广播,比如:给一个座机号发送、给一个停机的手机号发送、给免费通道发送等等,也就是通过发送广播统计不现实。
&&&&&&&再说&DELIVERED_SMS_ACTION&,接收短信广播。表面上看这个确实可行,因为这个广播收到的话说明对方接受到了短信,上代码看下广播接收者:
class SendSMSReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(DELIVERED_SMS_ACTION)) {
int smsType = intent.getExtras().getInt(&type&);
String thisPhone = intent.getExtras().getString(&phoneNumber&);
String flags = intent.getExtras().getString(&flags&);
String flag = intent.getExtras().getString(&flag&);
String id = intent.getExtras().getString(&id&);
int status = 0;
String sendDate = new SimpleDateFormat(&yyyyMMddHHmmss&)
.format(new Date(System.currentTimeMillis()));
switch (getResultCode()) {
case Activity.RESULT_OK:
status = 0;
status = 1;
String logStr = &&;
logStr = logStr + thisPhone + &,& + status + &,& + sendD
if (smsType == SmsType.ONE_SMS) {
if (&7&.equals(flags)) {
messageSendCodeTotal(Config.SESSIONID, &6&, &1&, id, logStr);
messageSendCodeTotal(Config.SESSIONID, flag, &1&, id,
thisPhone);
}else if(smsType == SmsType.GROUP_SMS){
tenSmsGroupStr=logStr+tenSmsGroupStr+ &;&;
if(tenSmsGroupStr.split(&;&).length==11){
tenSmsGroupStr=tenSmsGroupStr.substring(0, tenSmsGroupStr.lastIndexOf(&;&));
if (&7&.equals(flags)) {
·messageSendCodeTotal(Config.SESSIONID, &6&, &2&, id, tenSmsGroupStr);
messageSendCodeTotal(Config.SESSIONID, flag, &2&, id, tenSmsGroupStr);
tenSmsGroupStr=&&;
&&&&&& 以上为,获取到广播后,蓝色部分为获取传递的数据,根据数据判断做业务处理,业务处理部分不要理会,用的话换成自己的。但是要注意:
&&&&&& 第一:这个广播接收者最好放到服务里,因为你接收到这个广播时间是不确定的,比如,你发送的对象关机了,当他开机后受到短信,你才能收到这个广播。
&&&&&& 第二:一定要传递你想要的参数,除了业务需求以外,还有个重要的作用,就是用来区分是不是你发送是那条短信,因为有可能通过系统和其他app来发短信。
&&&& 我按照以上来实现,基本上可以做到准确统计,但是我又发现了一个很2的问题。移动有个短信业务叫做短信回执,也就是以短信的方式告诉你你是否发送成功或失败(还附带广告)。如果开通了这个业务,接受成功广告就没有了,我又头大了。有人会说你可以捕获短信分析内容来判断啊,但是通过分析短信是无法知道是不是你的app发送的还是其他app发送的。
&&&&& 所以到此,我还没有一个通过客户端可以准确统计短信发送接收成功的方法,如有哪位高人有思路,忘不吝指教,谢谢
&&&&&& 第四,分析下短信保存
这个比较简单,通过操作数据库完成,直接上代码
public static void saveSms(Context context, String tel, String msg) {
ContentValues values = new ContentValues();
// 发送时间
values.put(&date&, System.currentTimeMillis());
// 阅读状态
values.put(&read&, 0);
// 1为收 2为发
values.put(&type&, 2);
// 送达号码
values.put(&address&, tel);
// 送达内容
values.put(&body&, msg);
// 插入短信库
context.getContentResolver().insert(Uri.parse(&content://sms/sent&),
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:75210次
积分:1150
积分:1150
排名:千里之外
原创:34篇
转载:30篇
评论:45条
文章:12篇
阅读:24591
(4)(31)(13)(3)(2)(9)(2)91951人阅读
Android(38)
最近做的项目里要监听手机的短消息内容,这个东西好像在最初学的时候都做过,不过现在早忘记了,现在写下来,记住了。
前提--权限:
&uses-permission android:name=&android.permission.RECEIVE_SMS& &
&/uses-permission&
&uses-permission android:name=&android.permission.READ_SMS& &
&/uses-permission&
方式一:通过广播监听短信消息
(注意:这种方式只对新收到的短消息有效,运行代码,并不会读取收件箱中已读或未读的消息,只有当收到新来的短消息时,才会执行onChange方法)
注册一个广播:
&receiver android:name=&com.dbjtech.acbxt.waiqin.SmsReciver& &
&intent-filter android:priority=&999&&
&action android:name=&android.provider.Telephony.SMS_RECEIVED& /&
&/intent-filter&
&/receiver&
SmsReceiver.java
public class SmsReciver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
SmsMessage msg =
if (null != bundle) {
Object[] smsObj = (Object[]) bundle.get(&pdus&);
for (Object object : smsObj) {
msg = SmsMessage.createFromPdu((byte[]) object);
Date date = new Date(msg.getTimestampMillis());//时间
SimpleDateFormat format = new SimpleDateFormat(&yyyy-MM-dd HH:mm:ss&);
String receiveTime = format.format(date);
System.out.println(&number:& + msg.getOriginatingAddress()
body:& + msg.getDisplayMessageBody() + &
+ msg.getTimestampMillis());
//在这里写自己的逻辑
if (msg.getOriginatingAddress().equals(&10086&)) {
系统的这个广播是有序广播,就是当别的程序先获取到了这个广播再传递给你,当然它也可以干掉这个广播,让你接收不到,这样你的程序肯定是接收不到这个广播的了。我们发现,通过设置priority的数值,其实有时是不管用的,现在在一些定制的系统或是有安全软件的情况下,往往短消息都被截取到,并被干掉。
那么,我们只能使用方法二,监听短信数据库的变化,这种方式比方法一稍微复杂一些,不过使用起来也很方便,不受其它程序干扰~
方式二:通过短信数据库获取短信内容
(注意:这种方式可以获取手机上所有的短信,包括已读未读的短信,是不是很赞)
private Uri SMS_INBOX = Uri.parse(&content://sms/&);
public void getSmsFromPhone() {
ContentResolver cr = getContentResolver();
String[] projection = new String[] { &body& };//&_id&, &address&, &person&,, &date&, &type
String where = & address = '' AND date &
+ (System.currentTimeMillis() - 10 * 60 * 1000);
Cursor cur = cr.query(SMS_INBOX, projection, where, null, &date desc&);
if (null == cur)
if (cur.moveToNext()) {
String number = cur.getString(cur.getColumnIndex(&address&));//手机号
String name = cur.getString(cur.getColumnIndex(&person&));//联系人姓名列表
String body = cur.getString(cur.getColumnIndex(&body&));
//这里我是要获取自己短信服务号码中的验证码~~
Pattern pattern = pile(& [a-zA-Z0-9]{10}&);
Matcher matcher = pattern.matcher(body);
if (matcher.find()) {
String res = matcher.group().substring(1, 11);
mobileText.setText(res);
sms主要结构:
  _id:短信序号,如100
  thread_id:对话的序号,如100,与同一个手机号互发的短信,其序号是相同的
  address:发件人地址,即手机号,如+
  person:发件人,如果发件人在通讯录中则为具体姓名,陌生人为null
  date:日期,long型,如,可以对日期显示格式进行设置
  protocol:协议0SMS_RPOTO短信,1MMS_PROTO彩信
  read:是否阅读0未读,1已读
  status:短信状态-1接收,0complete,64pending,128failed
  type:短信类型1是接收到的,2是已发出
  body:短信具体内容
  service_center:短信服务中心号码编号,如+0
通过方式二,我们就能获取手机中所有的短消息了,可是还有一个问题,如果来了新的短消息呢?我们总不能写个线程,每隔多少秒,去读取一下短信数据库吧?其实我们可以把方式二换个方式写:
private SmsObserver smsO
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.app_login);
smsObserver = new SmsObserver(this, smsHandler);
getContentResolver().registerContentObserver(SMS_INBOX, true,
smsObserver);
public Handler smsHandler = new Handler() {
//这里可以进行回调的操作
class SmsObserver extends ContentObserver {
public SmsObserver(Context context, Handler handler) {
super(handler);
public void onChange(boolean selfChange) {
super.onChange(selfChange);
//每当有新短信到来时,使用我们获取短消息的方法
getSmsFromPhone();
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:3886618次
积分:14186
积分:14186
排名:第860名
原创:95篇
转载:24篇
评论:693条
(1)(1)(1)(1)(3)(2)(11)(6)(1)(7)(1)(1)(3)(2)(1)(10)(4)(6)(9)(4)(10)(1)(5)(4)(1)(3)(2)(9)(5)(1)(6)2014年6月 移动开发大版内专家分月排行榜第一2014年3月 移动开发大版内专家分月排行榜第一
2014年11月 移动开发大版内专家分月排行榜第二2014年4月 移动开发大版内专家分月排行榜第二2014年2月 移动开发大版内专家分月排行榜第二
2014年6月 移动开发大版内专家分月排行榜第一2014年3月 移动开发大版内专家分月排行榜第一
2014年11月 移动开发大版内专家分月排行榜第二2014年4月 移动开发大版内专家分月排行榜第二2014年2月 移动开发大版内专家分月排行榜第二
2014年6月 移动开发大版内专家分月排行榜第一2014年3月 移动开发大版内专家分月排行榜第一
2014年11月 移动开发大版内专家分月排行榜第二2014年4月 移动开发大版内专家分月排行榜第二2014年2月 移动开发大版内专家分月排行榜第二
2014年6月 移动开发大版内专家分月排行榜第一2014年3月 移动开发大版内专家分月排行榜第一
2014年11月 移动开发大版内专家分月排行榜第二2014年4月 移动开发大版内专家分月排行榜第二2014年2月 移动开发大版内专家分月排行榜第二
本帖子已过去太久远了,不再提供回复功能。调用系统的发短信怎么判断发送成功:SmsManager sms = SmsManager.getDefault();sms.sendMultipartTextMessage()
该问题被发起重新开启投票
投票剩余时间:
之前被关闭原因:
该问题被发起删除投票
投票剩余时间:
距离悬赏到期还有:
参与关闭投票者:
关闭原因:
该问题已经被锁定
锁定原因:()
保护原因:避免来自新用户不合宜或无意义的致谢、跟帖答案。
该问题已成功删除,仅对您可见,其他人不能够查看。
public final void sendDataMessage (String destinationAddress, String scAddress, short destinationPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent)
通过判断PendingIntent sentIntent的结果PendingIntent sentIntent:当短信发出时,成功的话sendIntent会把其内部的描述的intent广播出去,否则产生错误代码并通过android.app.PendingIntent.OnFinished进行回调,这个参数最好不为空,否则会存在资源浪费的潜在问题;
private void sendSmsMessage(String address,String message)throws Exception
SmsManager smsMgr = SmsManager.getDefault();
Intent sent = new Intent();
sent.setAction("com.send");
PendingIntent sentIntent = PendingIntent.getBroadcast(this, 0, sent, 0);
Intent delivery = new Intent();
delivery.setAction("com.delivery");
PendingIntent deliveryIntent = PendingIntent.getBroadcast(this, 0, delivery , 0);
smsMgr.sendTextMessage(address, null, message, sentIntent, deliveryIntent);
} BroadcastReceiver send = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
if("com.send".equals(intent.getAction()))
Toast.makeText(TelephonyDemo.this, "SMS send
Toast.LENGTH_LONG).show();
BroadcastReceiver delivery = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
if("com.delivery".equals(intent.getAction()))
Toast.makeText(TelephonyDemo.this, "SMS delivery success",
Toast.LENGTH_LONG).show();
不是您所需,查看更多相关问题与答案
德问是一个专业的编程问答社区,请
后再提交答案
关注该问题的人
共被浏览 (7939) 次}

我要回帖

更多关于 android 判断蓝牙状态 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信