Android通讯之短信功能实现:

使用android.telephony.SmsManager对象,可以发送短信和彩信。
// 构造回调函数,短信发送结束后,会发出对应的Intent请求
Intent intent = new Intent("com.sample.sms_sent");
intent.putExtra("sms_id",GenerateSmsId());
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,0,intent,0);

// 发送文本短信
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(phone_number, null, text_content, pendingIntent,null);

其中,pendingIntent 对象是一个异步的Intent请求,当短信发送完成后,会触发预设在其中的广播事件;通过监听该广播事件,可以获知短信发送的结果:
// 在对应的触发器组件中,监听并处理短信发送的结果
@Override
protected void onHandleIntent(Intent intent){
if("com.sample.sms_sent".equals(intent.getAction())){
long sms_id = intent.getLongExtra("sms_id",0);
int result = intent.getIntExtra("result",0);
// 处理不同的发送结果
if(result == Activity.RESULT_OK){
// 发送成功
......
} else{
// 发送失败
......
}
}
}
通过该方式发送短信,无法与系统的短信数据库整合起来,也就是说通过这种发送出去的短信,无法在其他短信应用中查看,也无法通过其他短信应用来管理其状态。
在很多场景下,开发者如果不是期望在后台发送短信,可以通过发送Intent请求,调用第三方短信应用的界面组件来实现短信的发送。在这种方式下,用户可以对准备发送的短信进行确认和修改,并自行进行发送:
/* 构造短信发送的Intent对象,如果使用Action为Intent.ACTION_SENDTO的方式,可以包含目标地址;如果使用Action为Intent.ACTION_SEND的方式,可以预设短信内容等。*/
final Uri sms = Uri.parse("smsto:1234567");
Intent intent = new Intent(Intent.ACTION_SENDTO,sms);
startActivity(intent);

调用第三方短信界面组件发送短信,不仅能节约开发编辑短信界面的成本,还可以申请短信发送权限,只要场景合适,应该优先使用该方式。但基于第三方组件发送短信的方式,需要用户再次确认,并且无法确认最终的发送结果,在有些场景下并不适合。这时候,就要考虑将短信插入到系统短信数据库的待发送队列来进行短信发送。通过这样的方式,将短信的发送整合到系统短信数据库中,可以通过其他短信应用查看,也可以实现后台的发送和控制。
// 构造需要发送的短信,在对应的数据列上插入对应的值
ContentValues values = new ContentValues();
values.put("address",TARGET_ADDRESS); // 短信地址
values.put("body",SMS_CONTENT); // 短信内容
values.put("type",6); // 短信的类型,6代表待发送短信
values.put("date",CurrentDate()); // 短信发送时间
......
// 将短信插入到数据源
Uri insertUri = getContentResolver().insert("content://sms",values);
// 从插入的地址信息中解析出短信id,通过这个id值,随时可以在数据源中查看短信的状态、内容等信息
long sms_id = Long.valuesOf(insertUri.getLastPathSegment());
......

基于该方式进行的短信发送,可能还存在一定得兼容性隐患。短信数据源属于系统隐藏的数据源组件,其接口和数据库接口的稳定性都不给予保证。一旦在未来某个版本中,短信数据源的地址或数据库结构进行了变更,基于该方式进行的短信发送就可能会失效。

当Android系统从通信底层获取到新的短信信息后,会发出Action为android.provider.Telephony.SMS_RECEIVED的广播事件,通过监听该事件可以读取到新短信的短信内容:
@Override
protected void onHandleIntent(Intent intent){
// 从化名为pdus的Extra域中,读取新短信的内容
Object[] pdus = (object[]) bundle.get("pdus");
// 把所有数据块中的内容抽取出来,拼接成完整的短信内容
String sms_content;
SmsMessage[] messages = new SmsMessage[pdus.length];
for( int i=0;i<messages.length;i++){
messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
sms_content += messages[i].getDisplayMessageBody();
}
// 其余信息,均可以从第一个短信数据块中抽取出来
SmsMessage first_message = messages[0];
String address = first_message.getDisplayOriginatingAddress();
int status = first_message.getStatus();
......
}

在实际开发中,需要特别留意该触发器组件的优先级。因为该广播事件是一个有序的事件广播,系统会按照触发器组件的优先级,从高到低依次进行通知。

Androidmanifest中添加发送短信的权限:
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />

示例代码下载链接:http://www.apkbus.com/android-137411-1-1.html
参考文章链接:

更多相关文章

  1. Android——Pull方式解析XML数据
  2. Android获取CPU使用率的几种方式
  3. Andrioid SystemProperties和Settings.System介绍,不同应用间传递
  4. 10天学通Android开发(7)-数据存储
  5. Android客户端向服务器端发送数据的流程(1)
  6. android 退出activity 的方式总结
  7. Android系统中的广播(Broadcast)机制注册注销发送原理总结
  8. Android的简介
  9. android IPC 通讯机制

随机推荐

  1. 每日前端夜话(0x04):2018年JavaScript状态
  2. LeetCode #27 移除元素
  3. 以B站C语言视频为基础的课后总结(一)
  4. LeetCode #26 删除排序数组中的重复项
  5. 排序算法 #5 归并排序
  6. 来自Kenneth Reitz大神的建议:避免不必要
  7. 满满的一篇,全是复杂度分析核心知识点
  8. LeetCode #80 删除排序数组中的重复项II
  9. 再聊聊Python中文社区的翻译
  10. Python对象的身份迷思:从全体公民到万物皆