`
modabobo
  • 浏览: 506262 次
文章分类
社区版块
存档分类
最新评论

Android的四大组件之Broadcast Receiver

 
阅读更多

BroadcastReceiver(广播接收器)是Android中的四大组件之一。
下面是Android Doc中关于BroadcastReceiver的概述:
①广播接收器是一个专注于接收广播通知信息,并做出对应处理的组件。很多广播是源自于系统代码的──比如,通知时区改变、电池电量低、拍摄了一张照片或者用户改变了语言选项。应用程序也可以进行广播──比如说,通知其它应用程序一些数据下载完成并处于可用状态。
②应用程序可以拥有任意数量的广播接收器以对所有它感兴趣的通知信息予以响应。所有的接收器均继承自BroadcastReceiver基类。
③广播接收器没有用户界面。然而,它们可以启动一个activity来响应它们收到的信息,或者用NotificationManager来通知用户。通知可以用很多种方式来吸引用户的注意力──闪动背灯、震动、播放声音等等。一般来说是在状态栏上放一个持久的图标,用户可以打开它并获取消息。
Android中的广播事件有两种,一种就是系统广播事件,比如:ACTION_BOOT_COMPLETED(系统启动完成后触发),ACTION_TIME_CHANGED(系统时间改变时触发),ACTION_BATTERY_LOW(电量低时触发)等等。另外一种是我们自定义的广播事件。
广播事件的流程
①注册广播事件:注册方式有两种,一种是静态注册,就是在AndroidManifest.xml文件中定义,注册的广播接收器必须要继承BroadcastReceiver;另一种是动态注册,是在程序中使用Context.registerReceiver注册,注册的广播接收器相当于一个匿名类。两种方式都需要IntentFIlter。
②发送广播事件:通过Context.sendBroadcast来发送,由Intent来传递注册时用到的Action。
③接收广播事件:当发送的广播被接收器监听到后,会调用它的onReceive()方法,并将包含消息的Intent对象传给它。onReceive中代码的执行时间不要超过5s,否则Android会弹出超时dialog。

Broadcast Receiver接收系统自带的广播
我们做一个例子,功能是在系统启动时播放一首音乐。
1、建立一个项目Lesson21_BroadcastReceiver,拷贝一首音乐进res/raw目录
2、建立HelloBroadcastReceiver.java 内容如下:

Codepackage android.basic.lesson21;   
  
import android.content.BroadcastReceiver;   
import android.content.Context;   
import android.content.Intent;   
import android.media.MediaPlayer;   
import android.util.Log;   

public class HelloBroadReciever extends BroadcastReceiver {   
  
    //如果接收的事件发生   
    @Override  
    public void onReceive(Context context, Intent intent) {   
        //则输出日志   
        Log.e("HelloBroadReciever", "BOOT_COMPLETED!!!!!!!!!!!!!!!!!!!!!!!!!");   
        Log.e("HelloBroadReciever", ""+intent.getAction());   
  
       //则播放一首音乐   
        MediaPlayer.create(context, R.raw.babayetu).start();   
   }   
}  

3、在AndroidManifest.xml中注册此Receiver :

<?xml version="1.0" encoding="utf-8"?>  
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionname="1.0" android:versioncode="1" package="android.basic.lesson21">  
    <application android:icon="@drawable/icon" android:label="@string/app_name">  
        <activity android:label="@string/app_name" android:name=".MainBroadcastReceiver">  
            <intent -filter="">  
                <action android:name="android.intent.action.MAIN">  
                <category android:name="android.intent.category.LAUNCHER">  
            </category></action></intent>  
        </activity>  
    <!-- 定义Broadcast Receiver 指定监听的Action -->  
    <receiver android:name="HelloBroadReciever">  
            <intent -filter="">  
                <action android:name="android.intent.action.BOOT_COMPLETED">  
            </action></intent>  
    </receiver>  
</application></manifest>  

4、发布程序,启动模拟器,可以在Logcat中看到:

同时能听到音乐播放的声音。说明我们确实接收到了系统启动的广播事件,并做出了响应。

自定义广播
下面我们学习自己制作一个广播。我们接着刚才的例子,继续写下去。
5、在MainBroadcastReceiver.java中填写如下代码:

Codepackage android.basic.lesson21;   
  
import android.app.Activity;   
import android.content.Intent;   
import android.os.Bundle;   
import android.view.View;   
import android.widget.Button;   
  
public class MainBroadcastReceiver extends Activity {   
    /** Called when the activity is first created. */  
    @Override  
    public void onCreate(Bundle savedInstanceState) {   
        super.onCreate(savedInstanceState);   
        setContentView(R.layout.main);   
  
        Button b1 = (Button) findViewById(R.id.Button01);   
  
        b1.setOnClickListener(new View.OnClickListener() {   
  
            @Override  
            public void onClick(View v) {   
                //定义一个intent   
                Intent intent = new Intent().setAction(   
                        "android.basic.lesson21.Hello").putExtra("yaoyao",   
                        "yaoyao is 189 days old ,27 weeks -- 2010-08-10");   
                //广播出去   
                sendBroadcast(intent);   
            }   
        });   
    }   
}  

6、更改 HelloBroadReceiver.java 内容如下:

Codepackage android.basic.lesson21;   
  
import android.content.BroadcastReceiver;   
import android.content.Context;   
import android.content.Intent;   
import android.media.MediaPlayer;   
import android.util.Log;   
  
public class HelloBroadReciever extends BroadcastReceiver {   
  
    //如果接收的事件发生   
    @Override  
    public void onReceive(Context context, Intent intent) {   
        //对比Action决定输出什么信息   
        if(intent.getAction().equals("android.intent.action.BOOT_COMPLETED")){   
            Log.e("HelloBroadReciever", "BOOT_COMPLETED !!!!!!!!!!!!!!!!!!!!!!!!!");   
        }   
  
        if(intent.getAction().equals("android.basic.lesson21.Hello")){   
            Log.e("HelloBroadReciever", "Say Hello to Yaoyao !!!!!!!!!!!!!!!!!!!!!!!!!");   
            Log.e("HelloBroadReciever", intent.getStringExtra("yaoyao"));   
        }   
  
        //播放一首音乐   
        MediaPlayer.create(context, R.raw.babayetu).start();   
    }   
}  

7、更改 AndroidManifest.xml 内容如下:

<?xml version="1.0" encoding="utf-8"?>  
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android.basic.lesson21" android:versionname="1.0" android:versioncode="1">  
    <application android:icon="@drawable/icon" android:label="@string/app_name">  
        <activity android:label="@string/app_name" android:name=".MainBroadcastReceiver">  
            <intent -filter="">  
                <action android:name="android.intent.action.MAIN">  
                <category android:name="android.intent.category.LAUNCHER">  
            </category></action></intent>  
        </activity>  
    <!-- 定义Broadcast Receiver 指定监听的Action 这里我们的接收器,接收了2个Action,一个系统的一个我们自定义的  -->  
    <receiver android:name="HelloBroadReciever">  
            <intent -filter="">  
                <action android:name="android.intent.action.BOOT_COMPLETED">  
            </action></intent>  
            <intent -filter="">  
                <action android:name="android.basic.lesson21.HelloYaoYao">  
            </action></intent>  
  
    </receiver>  
</application>  
<uses -sdk="" android:minsdkversion="8">  
</uses></manifest>

8、运行程序,点击按钮,查看LogCat,听听声音


在使用Broadcast 时我们应该注意到,BroadcastReceiver的子类别都是无状态的类别,每次收到发送广播事件后,BroadcastReceiver都会创建一个新的对象,然后再执行onReceive()函数,当onReceive()函数执行完毕后,就立刻删掉该对象,下一次再收到此广播后,又会创建一个新的对象。所以说Broadcast组建是Android中最轻薄、最短小的组建。我们增加了一个static的变量numStatic ,和num变量 。代码如下:

package com.androidtest.broadcaster;   
    
import android.content.BroadcastReceiver;   
import android.content.Context;   
import android.content.Intent;   
import android.util.Log;   
    
/**  
 * ClassName:Broadcaster  
 * Function: TODO ADD FUNCTION  
 * Reason:   TODO ADD REASON  
 *  
 * @author   Leon  
 * @version  
 * @since    Ver 1.1  
 * @Date     2011-6-9  
 */  
public class Broadcaster extends BroadcastReceiver{   
    
    private  static  final  String TAG = "Broadcaster";   
    private  static  int  numStatic  =100 ;   
    private  int  num =100 ;   
    @Override  
    public void onReceive(Context context, Intent intent) {   
    
        // TODO Auto-generated method stub   
        String string = intent.getAction();   
        numStatic= numStatic+50;   
        num=100+50;   
        Log.v(TAG  , "The action is "+ string + "Static Number is :" + numStatic   
                 + " Object num is :" + num);   
    
    }   
    
}  

多次发送广播,然后输出的结果如下,我们可以看到static Number 每次执行都会增加,而Object Num因为每次都要创建所以一直都是一个固定的值。

上文中提到了BroadcastReceiver是Android中最轻薄、最短小的组件,它的对象生命周期十分短暂,经过傻蛋测试在BroadcastReceiver中让线程睡眠10秒(Activity是5秒钟)的话,Android就会弹出错误(和Activity超时的错误相同),同时需要注意的是Activity、Service和BroadcastReceiver都是运行在本进程的主线程里面的。通过这个测试让傻蛋进一步产生了疑问,如果在Service中处理一个长时间的任务会怎么样?
启动一个Service,然后在Service的onCreate()方法中添加如下代码:

try {   
          Log.v(TAG , "sleep start …..");   
         Thread.sleep(20000);   
         Log.v(TAG,"sleep end …..");   
} catch (InterruptedException e) {   
     
         / / TODO Auto-generated catch block   
         e.printStackTrace();   
}    

很简单就是让Service睡眠20秒钟,我们会发现,sleep start…. 和 sleep end….这两个日志打印出来了,但是后台还会出现如下错误,前台弹出no response超时对话框。

在onCreate()中新启动一个线程来,睡眠时,程序正常。
所以总结一下:无论是 Activity、BroadcastReceiver还是Service,只要是有长时间处理的任务,就需要重新开一个线程来处理,为什么会这样?因为他们都是运行在主线程中的。
在使用BroadcastReceiver时还有一个我们需要注意的:在BroadcastReceiver的onReceive(Context context , Intent intent )这第一个context到底是哪一个context?是Activity还是Application?通过测试发现:
如果你的BroadcastReceiver是通过在Activity中的this.registerReceiver(myBroadcaster, filter); 来注册的话,那么这个context就是这个Activity,而如果是通过AndroidManifest来注册的话,那么这个context就是:android.app.ReceiverRestrictedContext。


BroadcastReceiver是接收从sendBroadcast()发出的intent的基类。你可以通过Context.registerReceiver()方法在代码中动态的注册一个BroadcastReceiver的实例,也可以通过再AndroidManifest.xml文件中用<receiver>标签来静态声明。
注意:如果你实在Activity.onResume()方法中注册的一个receiver,那么你必须在Activity.onPause()方法中进行注销。(当一个activity处于暂停状态是不会接收intents的,并且这样做也可以减小系统不必要的开销)。不要在Activity.onSaveInstanceState()方法中注销receiver,因为activity从栈中恢复的时候并不会调用这个方法了。
可以接收的broadcast主要分为两种类型:
普通的broadcasts(通过Context.sendBroadcast发送)是完全异步的。这个broadcast的receiver以无序的状态运行,经常是在同一时刻运行。这种做法是十分高效的,但是也意味着receiver不能够利用相互处理的结果或者是调用退出的API来退出(因为不知道哪个receiver先接收到intent)。
有序的broadcasts(通过Context.sendOrderedBroadcast发送)一次只发送给一个receiver。每一个receiver是有序的处理这个intent的,前面的receiver可以传递结果给下一个receiver,或者任意一个receiver都可以完全的退出,这样intent就不会传递给其他的receivers.receiver的执行顺序可以通过匹配的intent-filter中的android:priority属性来控制;如果有多个receivers处于同一个优先级,那么这几个receivers将会以任意的顺序来执行。
即使是在广播普通的broadcasts的情况下,系统也有可能在某些情况下转换为一次发送一个broadcast给一个receriver。特别是当receivers需要创建进程时,在同一时刻仅仅一个receiver可以运行,避免系统因为这些新建的进程而过载。
注意:尽管Intent类是用来发送和接受这些broadcasts,这里的Intent broadcast机制和那些通过Context.startActivity()方法来启动activity的intent是完全独立的。一个BroadcastReceiver是没办法观察和捕获一个用于启动activity的intent的;同样的,当你通过intent来发出broadcast时,你也不可能(通过这个intent)找到或者启动一个activity的。这两种操作是完全不同的:通过一个intent来启动一个activity是一个前台操作,会改变用户当前交互的对象;而通过intent来发出broadcast是一个后台操作,用户经常是察觉不到的。
BroadcastReceiver类(通过一个manifest的<receiver>标签作为一个组件启动)是应用程序全局声明周期重要的一部分。

讨论的主题
1、Receiver的生命周期
2、权限
3、进程的生命周期

开发者指南
更详细的关于如何获取和解析一个Intent的内容,请详见Intents and Intent Filters开发者指南

Receiver的生命周期
一个BroadcastReceiver的对象仅仅在调用onReceiver(COntext, Intent)的时间中有效。一旦你的代码从这个函数中返回,那么系统就认为这个对象应该结束了,不能再被激活。
你在onReceive(Context, Intent)中的实现有着非常重要的影响:任何对于异步操作的请求都是不允许的,因为你可能需要从这个函数中返回去处理异步的操作,但是在那种情况下,BroadcastReceiver将不会再被激活,因此系统就会再异步操作之前杀死这个进程。
特别是,你不应该再一个BroadcastReceiver中显示一个对话框或者绑定一个服务。对于前者(显示一个对话框),你应该用NotificationManagerAPI来替代,对于后者(绑定一个服务),你可以使用Context.startService()发送一个命令给那个服务来实现绑定效果。
权限
存取的权限可以通过在发送方的Intent或者接收方的Intent中强制指定。
在发送一个broadcast时强制指定权限,就必须提供一个非空的peemission参数给sendBroadcast(Intent, String)或者是sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handel, int, String, Bundle).只有那些拥有这些权限(通过在ANdroidManifest.xml文件中相应的声明<uses-permission>标签)的receiver能够接收这些broadcast。
在接收一个broadcast时强制指定权限,就必须在注册receiver时提供一个非空的permission参数--无论是在调用registerReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler)或者是通过再AndroidManifest.xml文件中通过<receiver>静态标签来声明。只有那些拥有这些权限(通过在相应的AndroidManifest.xml文件中查询<uses-permission>标签来获知)的发送方将能够给这个receiver发送Intent。
对于安全和权限的详细内容请查看Security and Permission文档。
进程的生命周期
一个正在执行BroadcastReceiver(也就是,正在执行onReceive(COntext, Intent)方法)的进程被认为是一个前台的进程,将会一直运行,除非系统处于内存极度低的情况下。
一旦从OnReceive()方法中返回,这个BroadcastReceiver将不会再被激活,此时它的主进程就和任何其他运行于此应用程序中的组件拥有相同的优先级。这一点非常重要,如果进程仅仅只是拥有BroadReceiver(一个普遍的情况是用户从不或者是最近没有和它进行交互),因此一旦它从onReceive()方法中返回时,系统就会认为进程是空的并且主动的杀死它,以便这些资源可以被其他重要的进程利用。
这意味着对于耗时的操作,可以采用将Service和BroadcastReceiver结合使用以确保执行这个操作的进程在整个执行过程中都保持激活状态。

文章转自:http://www.oschina.net/question/157182_45595







分享到:
评论

相关推荐

    Android四大组件之Broadcast Receiver

    Android四大组件之Broadcast Receiver 作者:白璐 日期:2020/2/23 文章目录Android四大组件之Broadcast Receiver概述广播接收器(Broadcast Receiver)Broadcast Receiver简介Broadcast Receiver的注册一. 静态注册...

    Android开发的四大组件

    文档主要是讲Android开发的四大组件详解,包含 Activity详解 ,Service详解,Broadcast Receiver详解,Content Provider详解 外加一个重要组件 intent的详解。 文章内容来自网络,本文是一个总结性文章。

    Broadcast Receiver Demo

    一个关于Android四大组件Broadcast Receiver的小demo

    android四大组件详解

    android 四大组件初学者必备,activity services等等

    Android开发应用中Broadcast Receiver组件详解

    BroadcastReceiver(广播接收器)是Android中的四大组件之一。下面就具体介绍一下Broadcast Receiver组件的用法。 下面是Android Doc中关于BroadcastReceiver的概述: ①广播接收器是一个专注于接收广播通知信息,...

    Android四大组件之Service

    Android四大组件之ServiceService的生命周期被启动(startService)的服务的生命周期:被绑定(bindService)的服务的生命周期:被启动又被绑定的服务的生命周期:实例布局创建Service类启动ServiceDemo下载 android开发...

    Android系统架构概述PPT

    应用程序层主要就是由四大组件Activity、Service、Broadcast Receiver和Content Provider构成,它们是应用开发的基础。这个PPT从一个通用的应用程序架构开始,概述Android系统的专用驱动、HAL、关键服务、Dalvik、...

    【推荐】超全的移动安全自学资料精编合集(43份).zip

    Android安全开发基础: 四大组件之广播(Broadcast Receiver) Android安全开发基础: 四大组件之内容提供器(Content Provider) Android安全开发基础: 进程间通信机制(IPC) Android安全开发基础: JVM Dalvik ART...

    Android高薪之路:Android程序员面试宝典 李宁

    3 9 2 广播接收器:Broadcast Receiver 3 9 3 服务 Service 3 9 4 内容提供者 Content Provider 第4章 对话框 信息提示和菜单 4 1 对话框 4 2 信息提示 4 2 1 Toast信息框 4 2 2 通知 Notification 4 3 菜单 第5...

    Android BroadcastReceiver实例Demo

    Android四大组件之一,BroadcastReceiver的实例Demo。

    Android BroadcastReceiver实现网络状态实时监听

    本文将介绍使用四大组件之一的BroadcastReceiver实现全局的网络状态监听,使用动态方式注册。 BroadcastReceiver的注册方式: (1)动态注册:即在代码中使用registerReceiver()方法进行注册,动态注册需要在onPause...

    Android初学习之intent-filter意图过滤器

    Intent Filter就是用来注册 Activity 、Service 、 Broadcast、Receiver(四大组件) 具有能在某种数据上执行一个动作的能力。使用 Intent Filter ,应用程序组件告诉 Android ,它们能为其它程序的组件的动作请求...

    移动安全系列教学下载共43份.zip

    Android安全开发基础--4--四大组件之广播(Broadcast Receiver).pdf Android安全开发基础--5--四大组件之内容提供器(Content Provider).pdf Android安全开发基础--6--进程间通信机制(IPC).pdf Android安全开发...

    Android开发权威指南 第二版

    , 《Android开发权威指南(第二版)》全面介绍了Android应用开发的各种技术,主要内容包括Android的四大应用程序组件(Activity、Service、Content Provider和Broadcast Receiver)、布局、菜单、控件、资源和本地化、...

    android学习笔记2--BroadcastReceiver

    介绍了andorid四大组件之一的BroadcastReceiver

    Android开发权威指南

    , 《Android开发权威指南(第二版)》全面介绍了Android应用开发的各种技术,主要内容包括Android的四大应用程序组件(Activity、Service、Content Provider和Broadcast Receiver)、布局、菜单、控件、资源和本地化、...

    BroadcastReceiverDemo.zip

    使用人群:BroadcastReceiver初学者。 里面涉及BroadcastReceiver的静态注册(无序广播)、动态注册(无序广播)、有序广播。 项目对应:https://shuaici.blog.csdn.net/article/details/118337894

    leetcode安卓-0-1Learning:0-1学习,好好学习,天天向上!

    05四大组件——广播接收器broadcast receiver ├── 06UI和控件 ├── 07碎片 ├── 08数据存储 ├── 09多媒体技术 ├── 10网络技术 └── 11Android特色开发 ├── android-framework -- android系统 ├─...

    Android开发艺术探索

    9.4 Broadcast Receiver的工作过程 / 352 9.4.1 广播的注册过程 / 353 9.4.2 广播的发送和接收过程 / 356 9.5 Content Provider的工作过程 / 362 第10章 Android的消息机制 / 372 10.1 Android的消息机制...

    android开发艺术探索高清完整版PDF

    316 9.1 四大组件的运行状态 / 316 9.2 Activity的工作过程 / 318 9.3 Service的工作过程 / 336 9.3.1 Service的启动过程 / 336 9.3.2 Service的绑定过程 / 344 9.4 Broadcast Receiver的工作过程 / 352 9.4.1...

Global site tag (gtag.js) - Google Analytics