android开发之短信监听拦截_BroadcastReceiver的使用

1.广播被分为两种不同的类型:“普通广播(Normal broadcasts)”和“有序广播(Ordered broadcasts)”。     普通广播是完全异步的,可以在同一时刻(逻辑上)被所有接收者接收到,消息传递的效率比较高, 但缺点是:接收者不能将处理结果传递给下一个接收者,并且无法终止广播Intent的传播。          有序广播是按照接收者声明的优先级别,被

大家好,又见面了,我是全栈君。

1.广播被分为两种不同的类型:“普通广播(Normal broadcasts)”和“有序广播(Ordered broadcasts)”。 
    

普通广播是完全异步的,可以在同一时刻(逻辑上)被所有接收者接收到,消息传递的效率比较高, 
但缺点是:接收者不能将处理结果传递给下一个接收者,并且无法终止广播Intent的传播。      
    

有序广播是按照接收者声明的优先级别,被接收者依次接收广播。如:A的级别高于B,B的级别高于C,那么,广播先传给A,再传给B,最后传给C 。 
优先级别声明在 intent-filter 元素的 android:priority 属性中,数越大优先级别越高,取值范围:-1000到1000,优先级别也可以调用IntentFilter对象的setPriority()进行设置。 
有序广播的接收者可以终止广播Intent的传播,广播Intent的传播一旦终止,后面的接收者就无法接收到广播。 
另外,有序广播的接收者可以将数据传递给下一个接收者,如:A得到广播后,可以往它的结果对象中存入数据,当广播传给B时,B可以从A的结果对象中得到A存入的数据。

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

Context.sendOrderedBroadcast() 
发送的是有序广播,系统会根据接收者声明的优先级别按顺序逐个执行接收者, 前面的接收者有权终止广播(BroadcastReceiver.abortBroadcast()),如果广播被前面的接收者终止,后面的接收者就再也无法获取到广播。 
对于有序广播,前面的接收者可以将数据通过setResultExtras(Bundle)方法存放进结果对象,然后传给下一个接收者,下一个接收者通过代码:Bundle bundle = getResultExtras(true))可以获取上一个接收者存入在结果对象中的数据。 

 

 

2. 广播接收者(BroadcastReceiver)用于接收广播 Intent,广播 Intent 的发送是通过调用 Context.sendBroadcast()、Context.sendOrderedBroadcast() 来实现的。        
    

通常一个广播 Intent 可以被订阅了此 Intent 的多个广播接收者所接收。

要实现一个广播接收者方法如下: 
              

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

public class IncomingSMSReceiver extends BroadcastReceiver { 
@Override 
public void onReceive(Context context, Intent intent) { 
//操作..
   }            
}

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

              第一种:使用代码进行订阅 

IntentFilter filter = new IntentFilte("android.provider.Telephony.SMS_RECEIVED");
  IncomingSMSReceiver receiver = new IncomingSMSReceiver(); 
  registerReceiver(receiver, filter); 

 第二种:在AndroidManifest.xml文件中的<application>节点中进行订阅:

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

 

3.在Android中,每次广播消息到来时都会创建BroadcastReceiver实例并执行onReceive() 方法, 

onReceive() 方法执行完后,BroadcastReceiver 的实例就会被销毁。

当onReceive() 方法在10秒内没有执行完毕,Android会认为该程序无响应。        

所以在BroadcastReceiver里不能做一些比较耗时的操作,否侧会弹出ANR(Application No Response)的对话框。 
 如果需要完成一项比较耗时的工作,应该通过发送Intent给Service,由Service来完成。 
这里不能使用子线程来解决,因为 BroadcastReceiver 的生命周期很短,子线程可能还没有结束BroadcastReceiver就先结束了。 
BroadcastReceiver一旦结束,此时BroadcastReceiver所在的进程很容易在系统需要内存时被优先杀死,因为它属于空进程(没有任何活动组件的进程)。 
如果它的宿主进程被杀死,那么正在工作的子线程也会被杀死。所以采用子线程来解决是不可靠的。 

 

 

4. 其它广播Intent 
除了短信到来广播Intent,Android还有很多广播Intent,如:开机启动、电池电量变化、时间已经改变等广播Intent。

接收电池电量变化广播Intent ,在AndroidManifest.xml文件中的<application>节点里订阅此Intent: 

<receiver android:name=".IncomingSMSReceiver">
<intent-filter>
<action android:name="android.intent.action.BATTERY_CHANGED"/>
</intent-filter>
</receiver>

 

 接收开机启动广播Intent,在AndroidManifest.xml文件中的<application>节点里订阅此Intent: 

<receiver android:name=".IncomingSMSReceiver"> 
<intent-filter> 
 <action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>

 

并且要进行权限声明:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

 

 5.接受系统的短信广播,操作短信内容。

AndroidManifest.xml

<uses-permission android:name="android.permission.SEND_SMS"></uses-permission>

<uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>

 

<!-- Receiver -->

<receiver android:name=".sms.SMSReceiver">

<intent-filter>

    <action android:name="android.provider.Telephony.SMS_RECEIVED" />

</intent-filter>

</receiver>

java:

package org.anymobile.demo.sms;

 

import android.content.BroadcastReceiver;

import android.content.Context;

import android.content.Intent;

import android.telephony.gsm.SmsMessage;

import android.util.Log;

 

public class SMSReceiver extends BroadcastReceiver

{

    public static final String TAG = "ImiChatSMSReceiver";

    //android.provider.Telephony.Sms.Intents

    public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";

   

    @Override

    public void onReceive(Context context, Intent intent)

    {

       if (intent.getAction().equals(SMS_RECEIVED_ACTION))

       {

           SmsMessage[] messages = getMessagesFromIntent(intent);

           for (SmsMessage message : messages)

           {

              Log.i(TAG, message.getOriginatingAddress() + " : " +

                  message.getDisplayOriginatingAddress() + " : " +

                  message.getDisplayMessageBody() + " : " +

                  message.getTimestampMillis());

           }

       }

    }

   

    public final SmsMessage[] getMessagesFromIntent(Intent intent)

    {

        Object[] messages = (Object[]) intent.getSerializableExtra("pdus");

        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;

    }

 

}

作者:jason0539

微博:http://weibo.com/2553717707

博客:http://blog.csdn.net/jason0539(转载请说明出处)

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/121396.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Osip2和eXosip协议栈的简析[通俗易懂]

    Osip2和eXosip协议栈的简析[通俗易懂]Osip2和eXosip协议栈的简析

    2022年6月22日
    25
  • IMG镜像写盘工具physdiskwrite,用于MikroTik RouterOS的安装(Windows)

    IMG镜像写盘工具physdiskwrite,用于MikroTik RouterOS的安装(Windows)常用img的备份:1、linux下使用dd,Windows下使用WinImage2、或者还有很多,比如再生龙等等。img还原:1、Win32DiskImager2、physdiskwritephysdiskwrite的简单使用:physdiskwrite.exe-uusb.img出现如下提示:千万不要选错了盘。软件参数:…

    2025年6月29日
    0
  • C语言自定义函数如何返回数组

    C语言自定义函数如何返回数组C语言自定义函数如何返回数组 C语言研究中心 CTO  9个月前(01-28)  4759次浏览  5个评论最近看到一些同学问题,有提到说:如何在一个函数中返回数组呢?能否直接在自定义函数中,写成char*类型返回值,直接返回呢?,代码如下:   直接返回str数组名(注意不需要加&,还有好多同学犯这个错)但事实上,运行结果并非正常,我们尝试在

    2022年6月16日
    38
  • java拦截器放行_java拦截器放行某些请求

    java拦截器放行_java拦截器放行某些请求在java开发中,拦截器使用是很普遍的,最常用的就是登陆拦截了,然后并不是所有的请求我们都需要拦截,比如index页面的请求我们是不拦截的.通常情况下我们有两种方式:先贴出来springboot使用拦截器的case:1.自定义拦截器,实现HandlerInterceptor,也可以采用继承的方式(HandlerInterceptorAdapter),内容不重要,看过程publicclassL…

    2022年6月7日
    155
  • 实验十(课程资源)-DNS服务器配置与管理[通俗易懂]

    实验十(课程资源)-DNS服务器配置与管理[通俗易懂]课程实验报告:一、实验目的:1、了解DNS工作原理及域名解析过程2、掌握DNS服务器的安装、配置与管理二、实验目的:在windows2003上搭建DNS服务器,并进行相关配置与功能测试三、实验原理:DNS:是域名系统(DomainNameSystem)的缩写,指在Internet中使用的分配名字和地址的机制。域名系统允许用户使用友好的名字而不是难以记忆的数字——IP

    2022年6月3日
    43
  • Ubuntu18.04显卡驱动及CUDA卸载

    Ubuntu18.04显卡驱动及CUDA卸载背景故事上文提到显卡驱动和CUDA的安装,你们真的因为一切这么流畅么?当然不是,不然我也不会说是“踩坑”之旅了,因为驱动下错了,就搞了半天,这里记录一下如何卸载驱动和CUDA。卸载步骤卸载显卡驱动$sudoapt-get–purgeremovenvidia*$sudoaptautoremove卸载CUDA$sudoapt-get–purgeremove”*cublas*””cuda*”OK完成,可以重装了。ps.此时重启可能导致图形操作界面无法打开。

    2022年9月5日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号