第11回 我猜小曹不会用Broadcast

刘关张听完孔明的讲解之后,恍然大悟,深感Service的博大精深。

孔明喝了口茶,道:“唉,这说的我口干舌燥,还好我智商够高,嘴皮够快,心肠够好,不然怎么教会你们呀。”

张飞接道:“军师的脸皮也够厚……”

还没等张飞说完,刘备随手拿起一个花盆就糊到张飞脸上!“三弟,不许侮辱军师!”

张飞扒掉脸上的土,抱怨道:“大哥,你咋对我脸意见这么大……”

刘备语重心长道:“唉,我这也是为你好呀,只有成为大牛才能赢得大家的尊重哇。”

孔明赶紧道:“翼德也是心直口快,没关系,对了,面试官都问了你啥?”

张飞歪了歪嘴,说:“别提了!一进去就看一壮汉翘个二郎腿在那嗑瓜子,爷爷我哪里还能看得下去,进去就是一招猴子偷桃攻他下盘,他一招仙人指路点我胸口。就这么我一招偷桃,他一招指路,我一招偷桃,他一招指路,打得好不欢乐。直到后来大哥叫我我这才走的,他还约我有时间再来打过,好像叫‘许猪’什么的。”

刘备、关羽、孔明三人听张飞说完,琢磨了好一会儿,也没能理解张飞是怎么个思想感情,为啥看人嗑瓜子就不爽了。

关羽摇了摇头道:“言归正传,我们还是太年轻了,还是应该多学学再去嚣张啊!这下倒好,尊严全无啊,以后还怎么在道上混啊。”

孔明说:“怕什么,这世上又不止曹操那一家的,而且你们的志向不是做出自己的产品吗?原来的骨气都哪去了?”

刘备说:“是呀!我们一定要做出比小曹还牛的产品,到时候威震四方,让小曹羡慕嫉妒恨去吧!”

孔明说:“我决定先对你们进行一个系统的集训,好好补一下Android的基本知识。嗯……首先就从Broadcast开始!”

1.1. BroadcastBroadcastReceiver的关系

第九回提到了Intent在Broadcast中的作用,究竟什么是广播Broadcast?什么是广播接收器BroadcastReceiver?它们之间又是什么关系呢?本回将对Broadcast和BroadcastReceiver进行详细讲解。

           在Andoird中Broadcast是应用程序间传输消息的一种机制,通过Broadcast可以通知其他组件某个事件已经发生了,比如电量不足、wifi连接等,许多应用程序都可以接收Broadcast消息。Android的Broadcast机制主要由以下三部分组成:

l  Broadcast:用于发送广播,即说明某件事情发生了,提醒相关的组件。

l  BraodcastReceiver:用于接收广播,并进行相应处理。

l  Intent:用于保存广播的相关信息(包括事件内容与用于过滤的信息)。

Broadcast的具体工作方式是这样的:在需要发送信息的地方,将需要发送的信息和用于过滤的信息(action、category等)装入一个Intent对象,然后调用Context.sendBroadcast()方法,将Intent对象发送出去。当Intent发送出去之后所有已经注册的BroadcastReceiver组件都会检测注册的intent-filter是否与该Intent相匹配,如果匹配则调用BroadcastReceiver的onReceive()方法,对Intent进行处理。

张飞:从上面的描述可以看出BroadcastReceiver也是一个卖烤串的,会对Broadcast发送的消息进行过滤,只关心能烤鸡翅什么的。

孔明:什么和什么,完全不能理解你的逻辑。

张飞:军师,我不明白Broadcast机制和前几回讲的Intent有什么区别?

孔明:你这个问题问得很好,其实……这根本就是两个东西!Broadcast是应用程序之间传递消息的一种机制,而Intent是消息的媒介。

 

 

 

 

 

 


1.2. Broadcast

在Android中Broadcast大体可以分为两类:普通广播和有序广播。普通广播是完全异步的,可以在同一时刻被所有接收者收到,消息传递的效率比较高,但缺点是接收者不能将处理结果传递给下一个接收者,且无法终止Intent的传播。有序广播则是按照接收者声明的优先级别,依次接收广播。例如,A的级别高于B,B的级别高于C,这时广播先传给A,再传给B,最后传给C。优先级别在intent-filter元素的priority属性中声明,取值范围是-1000到1000,数值越大级别越高。普通广播可使用Context.sendBroadcast()方法发送,有序广播可使用Context.sendOrederedBroadcast()方法进行发送。下面将要详细讲解Broadcast如何使用。

1.2.1.发送Broadcast

军师,你看看下面我小飞飞写的Broadcast代码,那是典型的Broadcast示例代码:

发送Broadcast代码清单11-2-1:

/**

* @author 刘备至张飞短信:“呵呵,干嘛呢?”

*/

           publicclass SendBroadCastListener implements OnClickListener{

      @Override

      public void onClick(View arg0){

                        // intent就是我们要发送的内容

          Intent intent = new Intent(); 

          intent.putExtra("data", "broadcast”));

          //设置你这个广播的action,

//BroadcastReciever的intent-filter会与action进行匹配,确定是否接收

intent.setAction(action);  

//发送广播 

sendBroadcast(intent);  

              }

}

1.2.2.Broadcast的action

在Android 中定义了许多action用于设置Broadcast,常用的action如表11-1所示:

表11-1 Broadcast action

常量名

说明

ACTION_BOOT_COMPLETED   

在系统启动后,这个动作被广播一次(只有一次)。

ACTION_DATE_CHANGED

日期被改变。

ACTION_PACKAGE_ADDED 

设备上安装了一个新的应用程序包。

ACTION_ SIG_STR

信号强度已改变。

1.3. BroadcastReciever介绍

上一节介绍了Broadcast是如何发送的,本节将介绍BroadcastReceiver如何接收Broadcast。

1.3.1.BroadcastReciever的实现

BroadcastReciever可以接收Broadcast的Intent。当特定的Broadcast发生是,就会触发BroadcastReceiver的onReceive()方法。

//军师,我懂了,你再看看我小飞飞写的BroadcastReceiver实现,如何?

public class MyReceiverextends BroadcastReceiver {

@Override

//收到broadcast时会执行onReceive函数

public void onReceive(Context context, Intent intent) {

//显示出Toast

Toast.makeText(context,“The receiver of broadcast1 is started.. “).show();

}

}

1.3.2.BroadcastReciever的注册方式

BroadcastReceiver有两种注册方式:静态注册和动态注册。两种注册方式的区别是:动态注册的BroadcastReceiver不是常驻型的广播,BroadcastReceiver会随Activtiy的退出而注销;静态注册的BroadcastReceiver是常驻型的广播,当应用程序关闭后,如果有相应的Broadcast到来,程序也会被系统调用。下面详细讲解这两种注册方法:

 

静态注册

在manifest中用<receiver>标签进行声明,并使用<intent-filter>标签注册过滤器,代码如下所示:

<receiverandroid:name=".SMSReceiver">

<intent-filter>

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

</intent-filter>

</receiver>

 

动态注册

动态注册在代码中先定义并设置好一个IntentFilter对象,然后使用Context.registerReceiver()方法进行注册,如果BroadcastReceiver需要注销则调用Context.unregisterReceiver()方法,代码如下所示:

BroadcastReceiver的实现方法代码清单11-3-2:

/**

* @author 刘备至张飞短信:“呵呵,刚才在干嘛呢?”

*/

public class MyBroadcastReceiverextends Activity {   

private BroadcastReceiver receiver;   

//在Activity启动时注册一个BroadcastReceiver

@Override

       protected void onStart() {

        super.onStart();

                                //MyReceiver是一个自定义Receiver

        receiver = new MyReceiver ();

                                //注册Receiver,并创建相应的IntentFilter对象

        registerReceiver(receiver,

new IntentFilter("android.intent.action.PHONE_STATE"));

       }

                     //在Activity停止时进行注销

       @Override        

       protected void onStop() {

                     //注销

        unregisterReceiver(receiver);

        super.onStop();

       }

}

孔明:需要特别注意的是,在退出程序前要记得调用Context.unregisterReceiver()方法。BroadcastReceiver一般在Activity的onStart()方法里进行注册,onStop()方法里进行注销。如果在Activity.onResume()方法里注册了BroadcastReceiver,就必须在Activity.onPause()方法里注销。

 

 

 

 


1.3.3.BroadcastReciever的生存周期

一个BroadcastReciever对象只有在调用onReceive(Context,Intent)方法后会进入活动状态,当从该方法返回后,进入失活状态。当BroadcastReciever处于活动状态时会被保护起来,而不会被杀死;当BroadcastReciever处于失活时,会在其他进程需要它所占有内存时随时被杀掉。如果响应一个广播信息需要较长的时间,为保证用户交互的流畅,可以将响应广播的操作放在一个线程中完成,而不是在主线程中完成。

孔明:在onReceiver()中不应做非常耗时的操作,比如准备SD卡、上传图片、读取数据库等。一个基本的规则就是:快速响应,然后返回。

 

 

 

 


1.4. Broadcast的使用

张飞最近被刘备的蹭饭短信骚扰的无可奈何。这几天听说Android中是以广播的形式接收短信的,他决定写一个程序彻底改善自己的生活。他编写了一个Activity类,命名为SmsShield,代码如下所示:

SmsShield代码清单11-4-0:

           /**

* 动态注册BroadcastReceiver

*            ­­­——大哥,不要再来骚扰我

* @author张飞:我发现我和大哥在一块,不是故事,就是事故。

*/

public classSmsShield extends Activity {

                      Button beginButton;

   Button stopButton;

                      //SmsReceiver

   SmsReceiver receiver = null;

                      //是否注册的标志位

                     boolean isRegisted = false;

                      //接收短信的action

                      staticfinal String ACTION = "android.provider.Telephony.SMS_RECEIVED";

                     @Override

                      public void onCreate(BundlesavedInstanceState) {

                                super.onCreate(savedInstanceState);

                                setContentView(R.layout.main);

                                beginButton =(Button)findViewById(R.id.beginButton);

                                stopButton =(Button)findViewById(R.id.stopButton);

                                beginButton.setEnabled(true);

                                stopButton.setEnabled(false);

                                // 开始拦截短信

        beginButton.setOnClickListener(newOnClickListener() {

                                 @Override

                                publicvoid onClick(View arg0) {

                                           regist();

                                           beginButton.setEnabled(false);

            stopButton.setEnabled(true);

                                           }

                                });

                                // 停止拦截短信

                                stopButton.setOnClickListener(newOnClickListener() {

                                           @Override

                                           public voidonClick(View arg0) {

                                                     unRegist();

                                           }

                                });

                      }

    // 在销毁的时候也要注销receiver

                      @Override

    protected void onDestroy() {

        super.onDestroy();

                                 if (receiver != null &&isRegisted) {

            unregisterReceiver(receiver);

            isRegisted = false;

        }

    }

                      // 注册receiver

    public void regist() {

                      IntentFilter filter = newIntentFilter(ACTION);

                                // 设置优先级最大

        filter.setPriority(1000);

                                 receiver = new SmsReceiver();

                                registerReceiver(receiver,filter);

        isRegisted = true;

                      }

                      // 注销receiver

    public void unRegist() {                        

                                if (receiver != null&& isRegisted) {

                                           unregisterReceiver(receiver);

            isRegisted = false;

                                 }

                      }

}

           在Android中短信是用有序广播的方式进行通知的,可以通过intent.setPriority(1000)将该程序设为最大优先级,先于其他程序获得短信广播。接收Broadcast的BroadcastReciever代码如下所示:

SmsReceiver代码清单11-4:

/**

* @author刘备至张飞短信:“呵呵,现在在干嘛呀?”

张飞:人在江湖飘,“呵呵”是把刀,有些“呵呵”的短信就是不能回。

*/

public class SmsReceiver extends BroadcastReceiver {

    @Override

    public voidonReceive(Context context, Intent intent) {

        // 获得短信的内容

        Object[] pdus =(Object[])intent.getExtras().get("pdus");

        if (pdus != null&& pdus.length > 0) {

            SmsMessage[] messages= new SmsMessage[pdus.length];

            for (int i = 0; i< pdus.length; i++) {

                byte[] pdu =(byte[])pdus[i];

                messages[i] =SmsMessage.createFromPdu(pdu);

            }

            // 遍历新短信

            for (SmsMessagemessage : messages) {

                // 得到发信息的号码

                String sender= message.getOriginatingAddress();

                if(sender.equals("123456")) {

                   Toast.makeText(context, "讨厌,大哥又来骚扰我", 0).show();

                    // 中止发送

                   abortBroadcast();

                }

            }

        }

    }

}

上述代码通过调用abortBroadcast()方法终止有序广播的传播,使其他程序无法收到该广播。需要注意的是接收短信需要在manifest中加入android.permission.RECEIVE_SMS权限。

运行程序,结果如图11-1所示:

图片11-1 SmsShield界面

           如果要使用静态注册Receiver则需要在manfiest中添加intent-filter,代码如下所示:

           <receiverandroid:name=".SmsRecevier">

                     <!--将优先级设到最大 -->

                     <intent-filterandroid:priority="1000">

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

                     </intent-filter>

           </receiver>

1.5. 玄德有话说

刘备:孔明啊,一个Receiver是否可以接收多个Broadcast?

孔明:一个Receiver也可以有多个intent-filter,那样就需要在onReceive()方法里对intent.getAction(action name)进行相应的判断。

刘备:如果两个Reciever的优先级一样时,顺序会怎样?

孔明:随机的。

刘备:原来如此!

 

关羽:军师,如何判断收到的广播是有序广播?

孔明:在Receiver中使用isOrderedBroadcast ()方法进行判断。

 

张飞:StickyBroadcast是什么

孔明:哇,真的假的,飞飞你这个问题问得好深邃啊!sendStickyBroadcast是Broadcast的一种发送方式。该Broadcast的最后一个Intent会被保留,当下次Recevier处于活动状态时,又会接收到保留的Intent。可以通过sendStickyBroadcast()方法进行发送,不过这时需要设置BROADCAST_STICKY权限才行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值