利用广播接受者监听用户短信

来源:互联网 发布:比较好的php框架 编辑:程序博客网 时间:2024/05/21 09:16

标签: androidservicedateobjectstringsms
 2906人阅读 评论(2) 收藏 举报

初识广播接受者:

广播接受者用于异步接受广播intent,广播intent的发送主要有三种方式:

1.Context.sendboardcast()(发送的是普通广播,所有订阅者都有机会获得并进行处理。

2.context.sendorderedbroadcast()(发送的是有序广播,系统会根据接收者声明的优先级别按顺序逐个执行接收者,前面的接收者有权终止广播,如果广播被前面的接收者终止,后面的接收者就再也无法获取到广播。对于有序广播,前面的接收者可以将处理结果存放进广播Intent,然后传给下一个接收者。

3.Context.sendStickyBroadcast()

实现一个广播接收者的主要步骤分为如下几步:

1.第一步:继承BroadcastReceiver,并重写onReceive()方法。

public class IncomingSMSReceiver extends BroadcastReceiver {

@Override public void onReceive(Context context, Intent intent) { <!--广播的发送端的发送数据就被封装在intent中-->

}

}

2.第二步:订阅感兴趣的广播Intent,订阅方法有两种:

第一种:在AndroidManifest.xml文件中的节点里进行订阅:

[java] view plain copy
  1. <span style="font-size:12px;"><receiver android:name=".IncomingSMSReceiver">  
  2.     <intent-filter>  
  3.          <action android:name="android.provider.Telephony.SMS_RECEIVED"/>  
  4.     </intent-filter>  
  5. </receiver> </span>  
第二种:在代码中进行注册
[java] view plain copy
  1. <span style="font-size:12px;">IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");//或者<span>filter.addAction(<span class="string">"android.intent.action.MY_BROADCAST"</span><span>);  </span></span>  
  2.  filter.setPriority(1000);  
  3. context.registerReceiver(new SmsBoradCastReciver(), filter);  
  4. </span>  
广播接受者的两种类型:有序广播和无序广播(也称普通广播)。

首先对于普通广播而言,它是完全异步的(关于同步和异步小插一曲:同步指的是你的程序在执行一个操作时,一直要等到这个程序执行完,异步就是说程序在执行某一个操作时,只是发出开始的指令;由另外的并行程序执行这段代码,当完成时再通知调用者。)

普通广播:可以在同一时刻(逻辑上)被所有接收者接收到,消息传递的效率比较高,但缺点是:接收者不能传递处理结果给下一个接收者,并且无法终止广播Intent的传播。这些接受者之间并没有太大的关系,并且都能收到广播。

有序广播:逐个执行接收者——系统会按照接收者声明的优先级别(声明在intent-filter元素的Android:priority属性中,数越大优先级别越高,取值范围:-1000到1000。也可以调用IntentFilter对象的setPriority()进行设置),按顺序逐次执行。,前后之间有很大的影响。先收到广播的接受者可以终止广播,同时也能改变广播发送的内容。后续会通过实例代码的方式对这种方式进行进一步的相关解释。

关于广播接受者需要注意的是:

在Android系统中,程序的响应收到ActivityManager以及windowManager的监听。当BroadcastReceiver在10秒内没有执行完毕,Android会认为该程序无响应。所以在BroadcastReceiver里不能做一些比较耗时的操作,否侧会弹出ANR(Application No Response)的对话框。如果需要完成一项比较耗时的工作,应该通过发送Intent给Service,由Service来完成。当BroadcastReceiver在10秒内没有执行完毕,Android会认为该程序无响应。而不是使用子线程的方法来解决,因为BroadcastReceiver的生命周期很短子线程可能还没有结束它就先结束了。当然如果BroadcastReceiver结束了,它的宿主进程还在运行,子线程还会继续执行。但宿主进程此时很容易在系统需要内存时被优先杀死,因为它属于空进程(没有任何活动组件的进程)。 

如果我在一个广播接收器中要处理多个动作呢?那要如何去处理?
registerReceiver在Android 的接收器中onReceive 以经为我们想到的,同样的你必须在Intent-filter 里面注册该动作,可以是系统的广播动作也可以是自己需要的广播,之后你之需要在onReceive 方法中,通过intent.getAction()判断传进来的动作即可做出不同的处理,不同的动作。
同时如果我们要想要特定的广播接受者来接受广播,对于有序广播的情况,可以使用自定义的权限。就类似系统中声明的各种权限一样,用户也可以为自己的广播发送端声明权限。接受者和发送方有相同的权限,此时就可以接受广播了。

关于静态注册和动态注册:
所谓的静态注册就是在清单文件中注册,动态注册就是在代码中使用registerReciver()的方式进行注册。关于第二种注册方法需要特别注意的是;就是当用来注册的 Activity 关掉后,广播也就失效了。同时反映了静态注册的一个优势,就是无需担忧广播接收器是否被关闭,只要设备是开启状态,广播接收器就是打开着的。
关于动态注册还有需要注意的就是:
registerReceiver是android.content.ContextWrapper类中的方法,Activity和Service都继承了ContextWrapper,所以可以直接调用。在实际应用中,我们在Activity或Service中注册了一个BroadcastReceiver,当这个Activity或Service被销毁时如果没有解除注册,系统会报一个异常,提示我们是否忘记解除注册了。所以,记得在特定的地方执行解除注册操作:

[java] view plain copy
  1. package com.luochuang.sms;  
  2.   
  3. import java.text.SimpleDateFormat;  
  4. import java.util.Date;  
  5.   
  6. import android.content.BroadcastReceiver;  
  7. import android.content.Context;  
  8. import android.content.Intent;  
  9. import android.telephony.SmsMessage;  
  10.   
  11. public class SmsBoradCastReciver extends BroadcastReceiver {  
  12.   
  13.     @Override  
  14.     public void onReceive(Context context, Intent intent) {  
  15.         // 通过查看源码可知,短信的发送意图为pdus  
  16.         Object[] objs = (Object[]) intent.getExtras().get("pdu");  
  17.         for (Object obj : objs) {  
  18.             // 通过此方法可以把原始的 Pdu数据格式转换成我们可以阅读的数据格式  
  19.             byte[] sms = (byte[]) obj;  
  20.             SmsMessage message = SmsMessage.createFromPdu(sms);  
  21.             // 短信内容  
  22.             String content = message.getMessageBody();  
  23.             // 发送人号码  
  24.             String number = message.getOriginatingAddress();  
  25.             // 发送时间  
  26.             Date date = new Date(message.getTimestampMillis());  
  27.   
  28.             String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")  
  29.                     .format(date);  
  30.   
  31.             System.out.println(content + number + time);  
  32.             // 短信发送的广播是系统的有序广播,有序广播可以通过abortBroadcast()的方法来结束广播  
  33.             abortBroadcast();  
  34.         }  
  35.     }  

因为该操作侵犯到了用户权限, 所以要在清单文件中注册相关的权限。

小节:

  • 在Android 中如果要发送一个广播必须使用sendBroadCast 向系统发送对其感兴趣的广播接收器中。
  • 使用广播必须要有一个intent 对象必设置其action动作对象
  • 使用广播必须在配置文件中显式的指明该广播对象
  • 每次接收广播都会重新生成一个接收广播的对象
  • 在BroadCast 中尽量不要处理太多逻辑问题,建议复杂的逻辑交给Activity 或者 Service 去处理

我的例子比较杂,这有一篇很好的文章,能帮助初学者准确的理解广播接受者:

0 0
原创粉丝点击