Android 之 sms 短信

概述

SMS(Short Messaging Service), 即我们经常使用的短信服务。它是一种存储和转发服务。也就是说,短消息并不是直接从发送人发送到接收人,而始终通过 SMS 中心进行转发的。如果接收人处于未连接状态(可能电话已关闭),则消息将在接收人再次连接时发送。

短信长度一般为140个字节,70个字符。既然我们经常使用短信,那么今天我们就来分析一下短信的实现。

说明:本文主要根据android应用层的sms代码来进行分析的,并结合了SMSpopup.有不到位的地方欢迎指正并补充

短信结构

_id//短消息序号

thread_id//对话的序号

address//收件人

person//

date//日期

protocol//协议

read//是否阅读

status//状态

type//类型 (收发)

reply_path_present//

subject//主题

body//短消息内容

service_center//服务中心

相关类图


上面几个类是涉及到sms的部分类的类图,其中涉及到键盘锁定状态、指示灯提示、通话状态等的判断,从而决定短信来的时候该怎么样去处理和提示。

短信接收

先来看看短信的接收,在android中,短信的接收需要在manifest.xml中配置广播接收器,如下:

   <receiver android:name=".SmsReceiver">
        <intent-filter>
            <action android:name="android.provider.Telephony.SMS_RECEIVED" />
        </intent-filter>
   </receiver>

来看下时序图:

    /**
       *  接收到短信的处理放在该service中去进行处理
       */
  public static void beginStartingService(Context context, Intent intent) {
    synchronized (mStartingServiceSync) {
      if (Log.DEBUG) Log.v("SMSReceiverService: beginStartingService()");
      if (mStartingService == null) {
          //电源管理,决定是否亮指示灯、键盘、屏幕等
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        mStartingService = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
            Log.LOGTAG+".SmsReceiverService");
        mStartingService.setReferenceCounted(false);
      }
      mStartingService.acquire();
      context.startService(intent);
    }
  }

在接收到短信的时候,需要有一些提示,比如指示灯点亮、屏幕点亮、键盘点亮等。这个主要通过PowerManager来控制。关于PowerManager,可以参看我之间写的一篇文章:http://blog.csdn.net/xieqibao/article/details/6562256

ServiceHandler的handleMessage方法中处理消息,判断消息的类型是mms、sms,在handleSmsReceived中处理接收到的sms短信

/**
   * 处理接收到的短信息
   */
  private void handleSmsReceived(Intent intent) {
    Bundle bundle = intent.getExtras();
    if (bundle != null) {
     //获得消息
      SmsMessage[] messages = SmsPopupUtils.getMessagesFromIntent(intent);
      if (messages != null) {
           notifyMessageReceived(new SmsMmsMessage(context, messages,System.currentTimeMillis()));
      }
    }
  }

下面方法中主要是从pdu中获取信息,关于pdu的详细信息可以参考:http://wenku.baidu.com/view/d0d0093e0912a216147929b1.html

/**
   * 从包装了SMS_RECEIVED_ACTION的intent中获取pdu信息
   */
  public static final SmsMessage[] getMessagesFromIntent(Intent intent) {
    Object[] messages = (Object[]) intent.getSerializableExtra("pdus");
    if (messages == null) {
      return null;
    }
    if (messages.length == 0) {
      return null;
    }
    byte[][] pduObjs = new byte[messages.length][];
    for (int i = 0; i < messages.length; i++) {
      pduObjs[i] = (byte[]) messages[i];
    }
    byte[][] pdus = new byte[pduObjs.length][];
    int pduCount = pdus.length;
    SmsMessage[] msgs = new SmsMessage[pduCount];
    for (int i = 0; i < pduCount; i++) {
      pdus[i] = pduObjs[i];
      msgs[i] = SmsMessage.createFromPdu(pdus[i]);
    }
    return msgs;
  }

最终获取到短信息后决定该怎么去进行展示,在smspopup中,是通过弹窗的形式,把短信息显示在activity中

/**
   * 获取短信息并加入到view上
   */
  private void setupMessages(Bundle b, boolean newIntent) {
    // Store bundle
    bundle = b;
    // 从bundle中获取短消息
    SmsMmsMessage message = new SmsMmsMessage(getApplicationContext(), bundle);
    mSmsPopups.addMessage(message);
    if (!newIntent) {
      // TODO: move off UI thread
      mSmsPopups.addMessages(
          SmsPopupUtils.getUnreadMessages(this, message.getMessageId()));
    }
    mSmsPopups.refreshPrivacy();
  }

短信发送

/**
   * 回复短信息
   *
   */
  public boolean replyToMessage(StringquickReply) {
      //首先要标记短信为已读
    setMessageRead();
    // 发送新的短信息
    SmsMessageSender sender =
      new SmsMessageSender(context, newString[] {fromAddress}, quickReply, getThreadId());
    return sender.sendMessage();
  }
  /**
   * 发送短信息入口
   * @return
   */
  @SuppressWarnings("deprecation")
  public boolean sendMessage() {
    if (!(mThreadId > 0)) {
      return false;
    }
    //如果消息文本为空,那就不发消息了
    if ((mMessageText == null) ||(mNumberOfDests == 0)) {
      return false;
    }
    //获得短信管理器
    SmsManager smsManager =SmsManager.getDefault();
    for (int i = 0; i < mNumberOfDests; i++){
        //按照短信息允许的最大字数来拆分短信
      ArrayList<String> messages =smsManager.divideMessage(mMessageText);
      int messageCount = messages.size();
      ArrayList<PendingIntent>deliveryIntents = new ArrayList<PendingIntent>(messageCount);
      ArrayList<PendingIntent>sentIntents = new ArrayList<PendingIntent>(messageCount);
      // 140个字节,70字符。
      if (splitMessage) {
        for (int j = 0; j < messageCount;j++) {
          Uri uri = null;
          try 
            //把短信息加入到provider中
            uri =addMessage(mContext.getContentResolver(), mDests[i], messages.get(j),
                  null, mTimestamp,requestDeliveryReport, mThreadId);
          } catch (SQLiteException e) {
            // TODO: show error here
            //SqliteWrapper.checkSQLiteException(mContext, e);
          }
          PendingIntent deliveryReportIntent =null;
          if (requestDeliveryReport) {
            deliveryReportIntent =
             PendingIntent.getBroadcast(mContext, 0,
                  newIntent(MESSAGING_STATUS_RECEIVED_ACTION, uri)
             .setClassName(MESSAGING_PACKAGE_NAME, MESSAGING_STATUS_CLASS_NAME), 0);
          }
          PendingIntent sentIntent =
           PendingIntent.getBroadcast(mContext, 0,
                newIntent(SmsReceiverService.MESSAGE_SENT_ACTION, uri)
            .setClass(mContext,SmsReceiver.class), 0);
          smsManager.sendTextMessage(
              mDests[i], mServiceCenter,messages.get(j), sentIntent, deliveryReportIntent);
        }
      }
    return false;
  }

总结
1. sms短信主要涉及到短信的发送、接收、提示,以及短信的本地保存等,涉及到的点相对还是比较多的。了解下还是很有必要的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值