`
Jonathan樊
  • 浏览: 77347 次
  • 性别: Icon_minigender_2
  • 来自: 上海
社区版块
存档分类
最新评论

Android开发——Broadcast Receiver

阅读更多

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

       资料来源:最牛网,《官方解读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 内容如下:

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变量 。代码如下:

/**
 * Broadcaster.java
 * com.androidtest.broadcaster
 *
 * Function: TODO
 *
 *   ver     date      		author
 * ──────────────────────────────────
 *   		 2011-6-9 		Leon
 *
 * Copyright (c) 2011, TNT All Rights Reserved.
*/
 
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

另外一篇具有参考价值的文章:http://blog.csdn.net/zuolongsnail/article/details/6450156

  • 大小: 41.2 KB
  • 大小: 311.3 KB
  • 大小: 168.4 KB
  • 大小: 8.2 KB
  • 大小: 20.6 KB
分享到:
评论

相关推荐

    安卓Android源码——broadcast1.rar

    当我们谈论“安卓Android源码——broadcast1.rar”时,很可能是涉及到安卓系统中广播接收器(Broadcast Receiver)的实现细节、广播生命周期、注册方式以及如何自定义广播等相关知识点。 首先,广播接收器是安卓...

    Android源码——broadcast电池电量显示源码.zip

    当我们谈论"Android源码——broadcast电池电量显示源码"时,我们关注的是如何通过广播接收器(BroadcastReceiver)监听并处理系统广播,尤其是与电池电量相关的事件。Android系统会发送特定的广播Intent来通知应用...

    安卓Android源码——broadcast电池电量显示源码.zip

    在安卓(Android)系统中,Broadcast(广播接收者)是一种重要的组件,用于在应用程序之间传递消息,特别是系统级别的事件,如电池电量变化。本压缩包包含的源码着重展示了如何利用BroadcastReceiver监听并显示电池...

    安卓Android源码——应用开发揭秘源码.zip

    《安卓Android源码——应用开发揭秘》是一本深入解析Android应用开发源码的教程,它为开发者揭示了Android操作系统背后的神秘面纱。这份压缩包包含了该书的主要代码示例,帮助读者更好地理解和实践书中讲解的知识点...

    安卓Android源码——KickKick.zip

    通过研究"安卓Android源码——KickKick.zip",开发者不仅能学习到Android的基本架构和工作原理,还能了解到特定项目的技术实现,这对于提升个人的Android开发技能和解决实际问题具有很大的价值。不过,由于具体源码...

    安卓Android源码——应用程序间的通信介绍.zip

    Intent在Android中扮演着消息传递的角色,它是一种轻量级的通信机制,用于启动一个活动(Activity)、服务(Service)或者广播接收器(Broadcast Receiver)。Intent分为显式Intent和隐式Intent。显式Intent通过指定...

    安卓Android源码——Ressource1.rar

    4. **Android Framework**:这部分包括了Android应用程序框架,如Activity Manager、Content Provider、Intent、Broadcast Receiver等,它们构成了Android应用开发的基础。 5. **Libraries**:一系列的C/C++库,如...

    安卓Android源码——MyAndorid002.rar

    5. **应用程序框架**:Android的应用程序框架提供了大量的服务和API,比如Activity Manager负责应用程序生命周期管理,Content Provider用于数据共享,Broadcast Receiver处理广播事件,Intent则用于组件间通信。...

    Android源码——生活手册源码.zip

    4. **Android组件**:Android系统由四大组件构成:活动(Activity)、服务(Service)、广播接收器(Broadcast Receiver)和内容提供者(Content Provider)。理解它们的用途和交互方式是Android开发的基础。 5. **...

    Android源码——网易客户端源码.zip

    3. 应用框架:提供了多种服务,如Activity Manager、Content Provider、Broadcast Receiver等。 4. 库和工具:如SQLite数据库、OpenSSL库等。 5. 应用程序:包括系统预装应用和第三方应用,如网易新闻客户端。 二、...

    安卓Android源码——MyWorkText.zip

    应用程序框架层是Android系统的灵魂,它包括了Activity Manager、Content Provider、Broadcast Receiver、Service等关键组件。开发者可以扩展这些组件来实现跨应用的数据共享、系统级事件监听等功能。"MyWorkText...

    安卓Android源码——upload1.rar

    5. **框架层服务**:如Activity Manager、Content Provider、Broadcast Receiver、Service等,构成了Android应用开发的核心组件。 6. **应用程序**:预装和用户安装的应用程序,通常由Java或Kotlin编写。 7. **...

    安卓Android源码——jamendo.rar

    3. **广播接收器(Broadcast Receiver)**:jamendo应用可能会监听系统广播事件,如耳机插入或网络状态改变,以便根据这些事件做出相应操作,如暂停或恢复播放。 4. **活动(Activity)**:jamendo应用的用户界面...

    安卓Android源码——RenRen.zip

    4. **系统服务**:Android系统服务如Activity Manager、Content Provider、Broadcast Receiver等,是应用间通信的基础。RenRen应用会注册并响应系统广播,实现动态更新、后台服务等功能。 5. **框架API**:开发者...

    Android系统级深入开发——移植与调试

    10. **Android框架层**:深入学习AOSP中的Activity Manager、Content Provider、Intent、Broadcast Receiver等关键组件的工作原理,以及如何通过反射和注解进行框架层的扩展和定制。 通过以上知识点的学习,开发者...

    安卓Android源码——MusicBox.rar

    4. **Broadcast Receiver**:监听系统广播事件,例如当耳机插入或拔出时,MusicBox可以自动暂停或恢复播放。 5. **MediaPlayer**:Android提供的原生音频播放组件,MusicBox可能使用它来处理音频流,控制播放、暂停...

    安卓Android源码——Freegemas.zip

    1. **Android框架**:Android系统基于Linux内核,但其上层框架是由Java编写,包括Activity Manager、Content Provider、Broadcast Receiver、Service等组件,以及Intent、Intent Filter、View等概念。Freegemas项目...

    安卓Android源码——(堆房子).zip

    7. **广播接收者(Broadcast Receiver)**:监听并响应系统或应用广播事件。 8. **权限管理**:Android的安全模型,控制应用对系统资源和数据的访问。 9. **JNI与Native代码**:Java Native Interface允许Java代码...

    安卓Android源码——源码捏苍蝇.zip

    3. **框架服务**:Android框架层包含了众多服务,如Activity Manager、Content Provider、Broadcast Receiver、Service等,这些都是应用开发的基础。理解这些服务的工作原理有助于解决权限问题、性能优化等。 4. **...

Global site tag (gtag.js) - Google Analytics