`

android基础知识05:四大组件之Broadcast Receiver

 
阅读更多

  本文介绍Broadcast Receiver,包括几部分内容:Broadcast Receiver概述及实例、自定义Broadcast Receiver、Broadcast Receiver的实现细节、生命周期等。

       csdn貌似今天出问题了,无法上传图片。

        资料来源:最牛网,《官方解读BroadcastReceiver》《Android中Broadcast Receiver组件详解》《(转)第二十一讲: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 内容如下:

 

  1. Codepackage android.basic.lesson21;  
  2.   
  3. import android.content.BroadcastReceiver;  
  4. import android.content.Context;  
  5. import android.content.Intent;  
  6. import android.media.MediaPlayer;  
  7. import android.util.Log;  
  8.   
  9. public class HelloBroadReciever extends BroadcastReceiver {  
  10.   
  11.     //如果接收的事件发生  
  12.     @Override  
  13.     public void onReceive(Context context, Intent intent) {  
  14.         //则输出日志  
  15.         Log.e("HelloBroadReciever""BOOT_COMPLETED!!!!!!!!!!!!!!!!!!!!!!!!!");  
  16.         Log.e("HelloBroadReciever"""+intent.getAction());  
  17.   
  18.         //则播放一首音乐  
  19.         MediaPlayer.create(context, R.raw.babayetu).start();  
  20.     }  
  21. }  

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

 

 

  1. Code<?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionname="1.0" android:versioncode="1" package="android.basic.lesson21">  
  3.     <application android:icon="@drawable/icon" android:label="@string/app_name">  
  4.         <activity android:label="@string/app_name" android:name=".MainBroadcastReceiver">  
  5.             <intent -filter="">  
  6.                 <action android:name="android.intent.action.MAIN">  
  7.                 <category android:name="android.intent.category.LAUNCHER">  
  8.             </category></action></intent>  
  9.         </activity>  
  10.     <!-- 定义Broadcast Receiver 指定监听的Action -->  
  11.     <receiver android:name="HelloBroadReciever">  
  12.             <intent -filter="">  
  13.                 <action android:name="android.intent.action.BOOT_COMPLETED">  
  14.             </action></intent>  
  15.     </receiver>  
  16. </application></manifest>  

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

 


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


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

 

  1. Codepackage android.basic.lesson21;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.Intent;  
  5. import android.os.Bundle;  
  6. import android.view.View;  
  7. import android.widget.Button;  
  8.   
  9. public class MainBroadcastReceiver extends Activity {  
  10.     /** Called when the activity is first created. */  
  11.     @Override  
  12.     public void onCreate(Bundle savedInstanceState) {  
  13.         super.onCreate(savedInstanceState);  
  14.         setContentView(R.layout.main);  
  15.   
  16.         Button b1 = (Button) findViewById(R.id.Button01);  
  17.   
  18.         b1.setOnClickListener(new View.OnClickListener() {  
  19.   
  20.             @Override  
  21.             public void onClick(View v) {  
  22.                 //定义一个intent  
  23.                 Intent intent = new Intent().setAction(  
  24.                         "android.basic.lesson21.Hello").putExtra("yaoyao",  
  25.                         "yaoyao is 189 days old ,27 weeks -- 2010-08-10");  
  26.                 //广播出去  
  27.                 sendBroadcast(intent);  
  28.             }  
  29.         });  
  30.     }  
  31. }  

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

 

 

  1. Codepackage android.basic.lesson21;  
  2.   
  3. import android.content.BroadcastReceiver;  
  4. import android.content.Context;  
  5. import android.content.Intent;  
  6. import android.media.MediaPlayer;  
  7. import android.util.Log;  
  8.   
  9. public class HelloBroadReciever extends BroadcastReceiver {  
  10.   
  11.     //如果接收的事件发生  
  12.     @Override  
  13.     public void onReceive(Context context, Intent intent) {  
  14.         //对比Action决定输出什么信息  
  15.         if(intent.getAction().equals("android.intent.action.BOOT_COMPLETED")){  
  16.             Log.e("HelloBroadReciever""BOOT_COMPLETED !!!!!!!!!!!!!!!!!!!!!!!!!");  
  17.         }  
  18.   
  19.         if(intent.getAction().equals("android.basic.lesson21.Hello")){  
  20.             Log.e("HelloBroadReciever""Say Hello to Yaoyao !!!!!!!!!!!!!!!!!!!!!!!!!");  
  21.             Log.e("HelloBroadReciever", intent.getStringExtra("yaoyao"));  
  22.         }  
  23.   
  24.         //播放一首音乐  
  25.         MediaPlayer.create(context, R.raw.babayetu).start();  
  26.     }  
  27. }  

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

 

 

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

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

 


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

 

  1. /** 
  2.  * Broadcaster.java 
  3.  * com.androidtest.broadcaster 
  4.  * 
  5.  * Function: TODO 
  6.  * 
  7.  *   ver     date           author 
  8.  * ────────────────────────────────── 
  9.  *           2011-6-9       Leon 
  10.  * 
  11.  * Copyright (c) 2011, TNT All Rights Reserved. 
  12. */  
  13.    
  14. package com.androidtest.broadcaster;  
  15.    
  16. import android.content.BroadcastReceiver;  
  17. import android.content.Context;  
  18. import android.content.Intent;  
  19. import android.util.Log;  
  20.    
  21. /** 
  22.  * ClassName:Broadcaster 
  23.  * Function: TODO ADD FUNCTION 
  24.  * Reason:   TODO ADD REASON 
  25.  * 
  26.  * @author   Leon 
  27.  * @version 
  28.  * @since    Ver 1.1 
  29.  * @Date     2011-6-9 
  30.  */  
  31. public class Broadcaster extends BroadcastReceiver{  
  32.    
  33.     private  static  final  String TAG = "Broadcaster";  
  34.     private  static  int  numStatic  =100 ;  
  35.     private  int  num =100 ;  
  36.     @Override  
  37.     public void onReceive(Context context, Intent intent) {  
  38.    
  39.         // TODO Auto-generated method stub  
  40.         String string = intent.getAction();  
  41.         numStatic= numStatic+50;  
  42.         num=100+50;  
  43.         Log.v(TAG  , "The action is "+ string + "Static Number is :" + numStatic  
  44.                  + " Object num is :" + num);  
  45.    
  46.     }  
  47.    
  48. }  

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

 


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

 

  1. try {  
  2.           Log.v(TAG , "sleep start …..");  
  3.          Thread.sleep(20000);  
  4.          Log.v(TAG,"sleep end …..");  
  5. catch (InterruptedException e) {  
  6.    
  7.          / / TODO Auto-generated catch block  
  8.          e.printStackTrace();  
  9. }  

        很简单就是让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结合使用以确保执行这个操作的进程在整个执行过程中都保持激活状态。

分享到:
评论

相关推荐

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

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

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

    6 1 SQLite基础知识 6 2 SQLite 函数 6 2 1 核心函数 6 2 2 日期和时间函数 6 2 3 聚合函数 6 3 在Android中使用SQLite 6 4 面向对象数据库:db4o 第7章 网络与加密 7 1 客户端Socket 7 2 服务端Socket 7 3 非阻塞I ...

    Android基础知识

    Android基础知识是移动应用开发领域的重要组成部分,它是学习如何构建安卓应用程序的基础。Android系统是由Google公司主导开发的开源操作系统,广泛应用于智能手机、平板电脑以及其他智能设备。掌握Android基础知识...

    Android宝典(第二版)

    ### Android宝典(第二版):Android最实用的技术 #### 前言 《Android宝典(第二版)》是一本全面介绍Android开发技术的书籍,涵盖了从...希望通过对这些基础知识的学习,读者能够在实际项目中更加灵活地运用这些技术。

    Android四大组件

    Android四大组件是Android操作系统的核心构建块,它们是应用程序框架的关键组成部分,用于实现应用程序的各种功能和服务。这四个组件包括:活动(Activity)、服务(Service)、广播接收器(Broadcast Receiver)和...

    Android组件与数据存储安全分析及实战

    首先,Android四大组件包括Activity、Broadcast Receiver、Service和Content Provider,它们是构建Android应用程序的基础。每一个组件都有可能成为安全漏洞的入口点。因此,理解并安全地使用这些组件是每个Android...

    android程序员简历02.doc

    1. Android 移动开发: Android 是 Google 的开源移动手机平台,了解 Android 的基本知识,懂得四大组件 Activity、Service、Broadcast Receiver 和 Content Provider。 2. 软件测试网络环境配置:熟悉 WEB 服务...

    Android Programming: The Big Nerd Ranch Guide(第三版,完美文字pdf)

    3. 基本组件:涵盖Activity、Service、Broadcast Receiver和Content Provider等Android四大组件的介绍和应用。 4. Android中的数据存储:包括使用SQLite数据库进行本地数据存储、文件系统操作,以及使用...

    android应用程序开发作业流程要点.doc

    Android 应用程序开发作业流程要点包括 Java 基础知识、Android 应用程序开发环境搭建、Android 应用程序目录结构、新建一个 Android 应用、Android 四大组件及界面 UI 元素、Android 应用程序工作机制、Android ...

    Android 高级开发面试题以及答案 整理

    四大组件是 Android 应用的基础组件,包括 Activity、Service、Broadcast Receiver 和 Content Provider 等。数据存储是 Android 应用的重要组件,用于存储应用程序的数据。网络编程是 Android 应用的重要组件,用于...

    Android程序设计:第2版

    2. **Android架构与组件**:Android应用程序由四大组件构成:活动(Activity)、服务(Service)、广播接收器(Broadcast Receiver)和内容提供者(Content Provider)。理解它们的工作原理和交互方式是Android开发...

    Android基础教程 第4版

    接下来,你会学习Android的四大组件:活动(Activity)、服务(Service)、广播接收器(Broadcast Receiver)和内容提供者(Content Provider)。活动是用户界面的基本单元,负责处理用户交互。服务则在后台运行,...

    Android 基础教程 第三版 PDF 含源码

    书中深入探讨了Android应用程序的四大组件:活动(Activity)、服务(Service)、广播接收器(Broadcast Receiver)和内容提供者(Content Provider)。活动是用户界面的核心,服务则在后台运行,不与用户交互。广播...

    Android 系统知识总结+培训课程+笔记

    Android应用由四大组件构成:活动(Activity)、服务(Service)、广播接收器(Broadcast Receiver)和内容提供者(Content Provider)。理解每个组件的作用以及它们之间的交互方式对于开发复杂的Android应用至关...

    Android期末复习选择题100道

    Android是谷歌主导的移动操作系统,其核心特性之一就是四大组件,包括Activity、Service、BroadcastReceiver和ContentProvider。这些组件构成了Android应用程序的基础架构。 1. **Activity**:Activity是用户界面的...

    Eclipse开发android教程

    应用程序基础是指Android应用程序的基本结构和组成部分,包括Activity、Service、Broadcast Receiver和Content Provider四大组件。这些组件都是Android应用程序的基本单元,每个组件都有其特定的功能和作用域。 ...

    超爽android中文教程

    4. **Android程序架构**:Android应用基于组件模型,主要包含四大组件:Activity(活动)、Service(服务)、Broadcast Receiver(广播接收器)和Content Provider(内容提供者)。Activity是用户交互的主要界面,...

    android 教程

    通过《Android应用框架原理与程序设计》这本书,读者不仅可以学习到Android开发的基础知识,还能深入探究Android系统的工作原理,从而提升应用的性能和用户体验。无论你是初学者还是经验丰富的开发者,这本书都将是...

    android经典书籍-Professional Android 4 Application Development【pdf+代码】

    2. **Android架构和组件**:深入讲解了Android系统的架构,包括四大组件:Activity、Service、Broadcast Receiver和Content Provider。这些组件是构建任何Android应用的基础。 3. **UI设计**:介绍如何使用XML布局...

Global site tag (gtag.js) - Google Analytics