短信的收发及在android模拟器之间实践(3)

系统 1638 0

6、温故知新之Intent

此系列前面简单地接受过意图(Intent),这里再次简单介绍一下,在短信接收程序和使用Intent发送SMS中我们要用到。android应用程序的三大组件——Activities、Services、Broadcast Receiver,通过消息触发,这个消息就称作意图(Intent)。下面以Acitvity为例,介绍一下Intent。Android用Intent这个特殊的类实现在Activity与Activity之间的切换。 Intent类用于描述应用的功能。在Intent的描述结构中,有两个最重要的部分:动作和动作对应的数据。 典型的动作类型有MAIN、VIEW、PICK、EDIT等,我们在短信接收程序中就用到从广播意图中提取动作类型并判断是否是" android.provider.Telephony.SMS_RECEIVED ",进而作深一步的处理。而动作对应的数据则以URI的形式表示。例如,要查看一个人的联系方式,需要创建一个动作为VIEW的Intent,以及表示这个人的URI。

通过解析各种Intent,从一个屏幕导航到另一个屏幕是很简单的。当向前导航时,Activity将会调用 startActivity("指定一个Intent") 方法。然后,系统会在所有已安装的应用程序中定义的IntentFilter中查找,找到最匹配的Intent对应的Activity。新的Activity接收到指定的Intent的通知后,开始运行。当 startActivity() 方法被调用时,将触发解析指定Intent的动作,该机制提供了两个关键的好处:

  • Activity能够重复利用从其他组件中以Intent形式产生的请求。
  • Activity可以在任何时候被具有相同IntentFilter的新的Activity取代。

7、准备工作:SmsMessage类

顾名思义,SmsMessage类是一个表示短信的类,为了更好地了解Android的短信机制及以后更好地编写短信相关程序,这里介绍一下该类的公有方法和常量,及嵌套枚举、类成员。

公有方法:

  • public   static   int []  calculateLength  (CharSequence  msgBody,  boolean  use7bitOnly)
    参数
    msgBody -要封装的消息、 use7bitOnly -如果为TRUE,不是广播特定7-比特编码的部分字符被认为是单个空字符;如果为FALSE,且 msgBody 包含非7-比特可编码字符,长度计算使用16-比特编码。
    返回值
    返回一个4个元素的int数组,int[0]表示要求使用的SMS数量、int[1]表示编码单元已使用的数量、int[2]表示剩余到下个消息的编码单元数量、int[3]表示编码单元大小的指示器。
  • public   static   int []  calculateLength  (String  messageBody,  boolean  use7bitOnly)
    参数 返回值 跟上面类似
  • public   static  SmsMessage   createFromPdu  ( byte [] pdu)
    从原始的PDU(protocol description units)创建一个SmsMessage。这个方法很重要,在我们编写短信接收程序要用到,它从我们接收到的广播意图中获取的字节创建SmsMessage。
  • public  String  getDisplayMessageBody()
    返回短信消息的主体,或者Email消息主体(如果这个消息来自一个Email网关)。如果消息主体不可用,返回null。这个方法也很重要,在我们编写短信接收程序也要用到。
  • public  String   getDisplayOriginatingAddress  ()
    返回信息来源地址,或Email地址(如果消息来自Email网关)。如果消息主体不可用,返回null。这个方法在来电显示,短信接收程序中经常用到。
  • public  String   getEmailBody  ()
    如果isEmail为TRUE,即是邮件,返回通过网关发送Email的地址,否则返回null。
  • public   int   getIndexOnIcc  ()
    返回消息记录在ICC上的索引(从1开始的)
  • public  String   getMessageBody  ()
    以一个String返回消息的主体,如果它存在且是基于文本的。
  • public  SmsMessage.MessageClass   getMessageClass  ()
    返回消息的类。
  • public  String   getOriginatingAddress  ()
    以String返回SMS信息的来电地址,或不可用时为null。
  • public   byte []  getPdu  ()
    返回消息的原始PDU数据。
  • public   int   getProtocolIdentifier  ()
    获取协议标识符。
  • public  String   getPseudoSubject  ()
  • public  String   getServiceCenterAddress  ()
    返回转播消息SMS服务中心的地址,如果没有的话为null。
  • public   int   getStatus  ()
    GSM:为一个SMS-STATUS-REPORT消息,它返回状态报告的status字段。这个字段表示之前提交的SMS消息的状态。
    CDMA:为不影响来自GSM的状态码,值移动到31-16比特。这个值由一个error类(25-16比特)和一个状态码(23-16比特)组成。
    如果是0,表示之前发送的消息已经被收到。
  • public   int   getStatusOnIcc  ()
    返回消息在ICC上的状态(已读、未读、已发送、未发送)。有下面的几个值:SmsManager.STATUS_ON_ICC_FREE、SmsManager.STATUS_ON_ICC_READ、SmsManager.STATUS_ON_ICC_UNREAD、SmsManager.STATUS_ON_ICC_SEND、SmsManager.STATUS_ON_ICC_UNSENT这几个值在 上篇 的SmsManager类介绍有讲到。
  • public   static  SmsMessage.SubmitPdu   getSubmitPdu  (
           String  scAddress, String  destinationAddress, 
            short  destinationPort,  byte [] data, 
            boolean  statusReportRequested)
    参数 scAddress  - 服务中心的地址(Sercvice Centre address,为null即使用默认的)、 destinationAddress  - 消息的目的地址、 destinationPort - 发送消息到目的的端口号、 data  - 消息数据。
    返回值 :一个包含编码了的SC地址(如果指定了的话)和消息内容的SubmitPdu,否则返回null,如果编码错误。
  • public   static  SmsMessage.SubmitPdu   getSubmitPdu  (
           String  scAddress, String  destinationAddress,
           String  message,  boolean  statusReportRequested)
    和上面类似。
  • public   static   int   getTPLayerLengthForPDU  (String  pdu)
    返回指定SMS-SUBMIT PDU的TP-Layer-Length,长度单位是字节而不是十六进字符。
  • public   long   getTimestampMillis  ()
    以currentTimeMillis()格式返回服务中心时间戳。
  • public   byte []  getUserData  ()
    返回用户数据减去用户数据头部(如果有的话)
  • public   boolean   isCphsMwiMessage  ()
    判断是否是CPHS MWI消息
  • public   boolean   isEmail  ()
    判断是否是Email,如果消息来自一个Email网关且Email发送者(sender)、主题(subject)、解析主体(parsed body)可用,则返回TRUE。
  • public   boolean   isMWIClearMessage  ()
    判断消息是否是一个CPHS 语音邮件或消息等待MWI清除(clear)消息。
  • public   boolean   isMWISetMessage  ()
    判断消息是否是一个CPHS 语音邮件或消息等待MWI设置(set)消息。
  • public   boolean   isMwiDontStore  ()
    如果消息是一个“Message Waiting Indication Group:Discard Message”通知且不应该保存,则返回TRUE,否则返回FALSE。
  • public   boolean   isReplace  ()
    判断是否是一个“replace short message”SMS
  • public   boolean   isReplyPathPresent  ()
    判断消息的TP-Reply-Path位是否在消息中设置了。
  • public   boolean   isStatusReportMessage  ()
    判断是否是一个SMS-STATUS-REPORT消息。

常量值:

  • public   static   final   int   ENCODING_16BIT :值为3(0x00000003)
  • public   static   final   int   ENCODING_8BIT :值为2 (0x00000002)
  • public   static   final   int   ENCODING_UNKNOWN :值为0 (0x00000000) ,用户数据编码单元的大小。
  • public   static   final   int   MAX_USER_DATA_BYTES :值为140 (0x0000008c),表示每个消息的最大负载字节数。
  • public   static   final   int   MAX_USER_DATA_BYTES_WITH_HEADER :134 (0x00000086),如果一个用户数据有头部,该值表示它的最大负载字节数,该值假定头部仅包含CONCATENATED_8_BIT_REFENENCE元素。
  • public   static   final   int   MAX_USER_DATA_SEPTETS :值为160 (0x000000a0) ,表示每个消息的最大负载septets数。
  • public   static   final   int   MAX_USER_DATA_SEPTETS_WITH_HEADER :值为153 (0x00000099),如果存在用户数据头部,则该值表示最大负载septets数该值假定头部仅包含CONCATENATED_8_BIT_REFENENCE元素。

嵌套枚举成员SmsMessage.MessageClass的枚举值:

  • public   static   final  SmsMessage.MessageClass   CLASS_0
  • public   static   final  SmsMessage.MessageClass   CLASS_1
  • public   static   final  SmsMessage.MessageClass   CLASS_2
  • public   static   final  SmsMessage.MessageClass   CLASS_3
  • public   static   final  SmsMessage.MessageClass   CLASS_UNKNOWN

嵌套枚举成员SmsMessage.MessageClass的公有方法:

  • public   static  SmsMessage.MessageClass valueOf (String name):返回值的字符串的值
  • public   static   final  MessageClass[]   values  ():返回MessageClass的值数组

嵌套类成员SmsMessage.SubmitPdu的字段:

  • public   byte []  encodedMessage :编码了的消息
  • public   byte []  encodedScAddress :编码的服务中心地址

嵌套类成员SmsMessage.SubmitPdu的公有方法:

  • public  String   toString  ()
    返回一个包含简单的、可读的这个对象的描述字符串。鼓励子类去重写这个方法,并提供实现对象的类型和数据。默认实现简单地连接类名、@、十六进制表示的对象哈希码,即下面的形式: getClass().getName() + '@' + Integer.toHexString(hashCode())

8、SMS接收程序

当一个SMS消息被接收时,一个新的广播意图由android.provider.Telepony.SMS_RECEIVED动作触发。注意:这个一个字符串字面量(string  literal),但是SDK当前并没有包括这个字符串的引用,因此当要在应用程序中使用它时必须自己显示的指定它。现在我们就开始构建一个SMS接收程序:

1)、跟SMS发送程序类似,要在清单文件 AndroidManifest.xml 中指定权限允许接收SMS: < uses - permission   android : name = "android.permission.RECEIVER_SMS" />

为了能够回发短信,还应该加上发送的权限。

2)、应用程序监听SMS意图广播,SMS广播意图包含了到来的SMS细节。我们要从其中提取出 SmsMessage 对象,这样就要用到 pdu 键提取一个SMS PDUs数组(protocol description units—封装了一个SMS消息和它的元数据),每个元素表示一个SMS消息。为了将每个PDU byte数组转化为一个SMS消息对象,需要调用 SmsMessage.createFromPdu

每个 SmsMessage 包含SMS消息的详细信息,包括起始地址(电话号码)、时间戳、消息体。下面编写一个接收短信的类SmsReceiver代码如下:

 

      
      
        
          package
        
         skynet.com.conblogs.www;


        
          import
        
         android.content.BroadcastReceiver;

        
          import
        
         android.content.Context;

        
          import
        
         android.content.Intent;

        
          import
        
         android.os.Bundle;

        
          import
        
         android.telephony.SmsManager;

        
          import
        
         android.telephony.SmsMessage;

        
          import
        
         android.widget.Toast;


        
          public
        
        
          class
        
         SmsReceiver 
        
          extends
        
         BroadcastReceiver {
 @Override
 
        
          public
        
        
          void
        
         onReceive(Context _context, Intent _intent) {
  
        
          if
        
         (_intent.getAction().equals(SMS_RECEIVER)) {
   SmsManager sms = SmsManager.getDefault();

   Bundle bundle = _intent.getExtras();
   
        
          if
        
         (bundle != 
        
          null
        
        ) {
    Object[] pdus = (Object[]) bundle.get("
        
          pdus
        
        ");
    SmsMessage[] messages = 
        
          new
        
         SmsMessage[pdus.length];
    
        
          for
        
         (
        
          int
        
         i = 0; i < pdus.length; i++)
     messages[i] = SmsMessage.createFromPdu((
        
          byte
        
        []) pdus[i]);
    
        
          for
        
         (SmsMessage message : messages) {
     String msg = message.getMessageBody();
     String to = message.getOriginatingAddress();
     
        
          if
        
         (msg.toLowerCase().startsWith(queryString)) {
      String out = msg.substring(queryString.length());
      sms.sendTextMessage(to, 
        
          null
        
        , out, 
        
          null
        
        , 
        
          null
        
        );

      Toast.makeText(_context, "
        
          success
        
        ", 
        Toast.LENGTH_LONG).show();
     }
    }
   }
  }
 }
    
 
        
          private
        
        
          static
        
        
          final
        
         String queryString="
        
          @echo
        
        ";
 
        
          private
        
        
          static
        
        
          final
        
         String SMS_RECEIVER=
  "
        
          android.provider.Telephony.SMS_RECEIVED
        
        ";
}
      
    

 

上面代码的功能是从接收到的广播意图中提取来电号码、短信内容,然后将短信加上@echo头部回发给来电号码,并在屏幕上显示一个Toast消息提示成功。

短信的收发及在android模拟器之间实践(3)


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论