Android_Broadcast

简介

Broadcast Receiver用于接收并处理广播通知(broadcastannouncements)。

多数的广播是系统发起的,如地域变换、电量不足、来电来信等。

程序可以有任意数量的Broadcast Receivers来响应它觉得重要的通知。

Broadcast Receiver可以通过多种方式通知用户:启动activity、使用NotificationManager、开启背景灯、振动设备、播放声音等,最典型的是在状态栏显示一个图标,这样用户就可以点它打开看通知内容。

通常我们的某个应用或系统本身在某些事件(电池电量不足、来电来短信)来临时会广播一个Intent出去,我们可以利用注册一个Broadcast Receiver来监听到这些Intent并获取Intent中的数据。


在程序中接受系统发的广播

我们举一个例子说明,一个接受系统Date改变的广播的例子。

先新建一个HelloBroadcastReceiver.java类,继承自BroadcastReceiver并复写它的onReceive方法。这样就创建了一个专门用来接收广播的类。

package com.tianjf;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class HelloBroadcastReceiver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {
		Log.d("debug", "Date has been changed!");        
		Log.d("debug", ""+intent.getAction()); 
	}
}
但是上面的Broadcast Receiver没有指定接收哪个广播,我们要指定某个Receiver接收哪个广播,必须在AndroidManifest.xml中注册此Receiver
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.tianjf"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="4" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".BroadcastDemoActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!-- 定义Broadcast Receiver指定监听的Action(系统Date改变action) -->
        <receiver android:name="HelloBroadcastReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.DATE_CHANGED" />
            </intent-filter>
        </receiver>
    </application>

</manifest>

OK,运行之后,更改系统Date看看,果然打印了两行Log。(着两行Log有时候打得出来,有时候打不出来,不知道神马原因)


接收自己发的广播

直接上代码

BroadcastDemoActivity.java

package com.tianjf;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class BroadcastDemoActivity extends Activity implements OnClickListener {

	private Button button;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		button = (Button) findViewById(R.id.button);
		button.setOnClickListener(this);
	}

	@Override
	public void onClick(View v) {
		// 定义一个intent
		Intent intent = new Intent();
		intent.setAction("MY_BROADCAST_ACTION");
		intent.putExtra("yaoyao",
				"yaoyao is 189 days old ,27 weeks -- 2010-08-10");
		// 广播出去
		sendBroadcast(intent);
	}
}
HelloBroadcastReceiver.java
package com.tianjf;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class HelloBroadcastReceiver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {
		Log.d("debug", "" + intent.getAction());
		if (intent.getAction().equals("android.intent.action.DATE_CHANGED")) {
			Log.d("debug", "Date has been changed!");
			Log.d("debug", "" + intent.getAction());
		} else if (intent.getAction().equals("MY_BROADCAST_ACTION")) {
			Log.d("debug", "Say Hello to Yaoyao!");
			Log.d("debug", intent.getStringExtra("yaoyao"));
		}
	}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.tianjf"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="4" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".BroadcastDemoActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!-- 定义Broadcast Receiver指定监听的Action(系统Date改变action和自动义的广播) -->
        <receiver android:name="HelloBroadcastReceiver" >
            <intent-filter>
                <action android:name="MY_BROADCAST_ACTION" />
                <action android:name="android.intent.action.DATE_CHANGED" />
            </intent-filter>
        </receiver>
    </application>

</manifest>

注册广播的2种方式

BroadcastReceiver在没有注册广播地址之前是使用不了的。没有注册广播地址的BroadcastReceiver就像一个缺少选台按钮的收音机,虽然功能俱备,但也无法收到电台的信号。有两种注册方法:

  1. 静态注册。在AndroidManifest.xml文件中配置(上文两个例子已经介绍了)
  2. 动态注册。要在代码中动态的指定广播地址并注册,通常我们是在Activity或Service注册一个广播

静态注册的方法参照以上两个例子。

至于动态注册的方法,我们看以下例子:

将以上的BroadcastDemoActivity做如下修改

package com.tianjf;

import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class BroadcastDemoActivity extends Activity implements OnClickListener {

	private Button button;
	HelloBroadcastReceiver receiver;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		button = (Button) findViewById(R.id.button);
		button.setOnClickListener(this);

		receiver = new HelloBroadcastReceiver();
		IntentFilter filter = new IntentFilter();
		filter.addAction("android.intent.action.DATE_CHANGED");
		filter.addAction("MY_BROADCAST_ACTION");
		registerReceiver(receiver, filter);
	}

	@Override
	public void onClick(View v) {
		// 定义一个intent
		Intent intent = new Intent();
		intent.setAction("MY_BROADCAST_ACTION");
		intent.putExtra("yaoyao",
				"yaoyao is 189 days old ,27 weeks -- 2010-08-10");
		// 广播出去
		sendBroadcast(intent);
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		unregisterReceiver(receiver);
	}
}
注意:动态注册广播的方法必须在onDestory方法里面注销,如果不注销的话,系统会报一个异常(如下)
12-19 07:16:04.186: E/ActivityThread(23244): Activity com.tianjf.BroadcastDemoActivity has leaked IntentReceiver com.tianjf.HelloBroadcastReceiver@40cef150 that was originally registered here. Are you missing a call to unregisterReceiver()?
异常也提示了要注销广播。

两种广播注册方式的区别:

  • 静态注册的方法,不管应用处于什么状态,甚至于退出应用,都能接收广播并作相应的处理。当然,相对来说是比较耗电的
  • 动态注册的方法,因为动态注册必须要注销广播,所以,应用退出也就不接收广播了。所以是省电的


有序广播(Ordered Broadcast)

有序广播比较特殊,它每次只发送到优先级较高的接收者那里,然后由优先级高的接受者再传播到优先级低的接收者那里,优先级高的接收者有能力终止这个广播

为了演示有序广播的流程,我们创建三个接收者的代码,如下:

package com.tianjf;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

public class FirstBroadcastReceiver extends BroadcastReceiver {
	
	private static final String TAG = "TestOrderdBroadcastReceiver";

	@Override
	public void onReceive(Context context, Intent intent) {
		String msg = intent.getStringExtra("msg");
		Log.i(TAG, "FirstBroadcastReceiver: " + msg);

		Bundle bundle = new Bundle();
		bundle.putString("msg", msg + "@FirstBroadcastReceiver");
		setResultExtras(bundle);
	}
}
package com.tianjf;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

public class SecondBroadcastReceiver extends BroadcastReceiver {
	
	private static final String TAG = "TestOrderdBroadcastReceiver";

	@Override
	public void onReceive(Context context, Intent intent) {
		String msg = getResultExtras(true).getString("msg");
		Log.i(TAG, "SecondBroadcastReceiver: " + msg);

		Bundle bundle = new Bundle();
		bundle.putString("msg", msg + "@SecondBroadcastReceiver");
		setResultExtras(bundle);
	}
}
package com.tianjf;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class ThirdBroadcastReceiver extends BroadcastReceiver {
	
	private static final String TAG = "TestOrderdBroadcastReceiver";

	@Override
	public void onReceive(Context context, Intent intent) {
		String msg = getResultExtras(true).getString("msg");
		Log.i(TAG, "ThirdBroadcastReceiver: " + msg);
	}
}
我们注意到,在FirstReceiver和SecondReceiver中最后都使用了setResultExtras方法将一个Bundle对象设置为结果集对象,传递到下一个接收者那里,这样以来,优先级低的接收者可以用getResultExtras获取到最新的经过处理的信息集合。

之后,我们需要为三个接收者注册广播地址,我们修改一下AndroidMainfest.xml文件:

        <receiver android:name=".FirstBroadcastReceiver" >
            <intent-filter android:priority="1000" >
                <action android:name="android.intent.action.MY_BROADCAST" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>
        <receiver android:name=".SecondBroadcastReceiver" >
            <intent-filter android:priority="999" >
                <action android:name="android.intent.action.MY_BROADCAST" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>
        <receiver android:name=".ThirdBroadcastReceiver" >
            <intent-filter android:priority="998" >
                <action android:name="android.intent.action.MY_BROADCAST" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>
我们看到,现在这三个接收者的<intent-filter>多了一个android:priority属性,并且依次减小。这个属性的范围在-1000到1000,数值越大,优先级越高。

现在,我们需要写一下发送广播的代码,如下:

			Intent intent = new Intent("android.intent.action.MY_BROADCAST");  
		    intent.putExtra("msg", "hello receiver.");  
		    sendOrderedBroadcast(intent, "myAndroid.permission.MY_BROADCAST_PERMISSION");
注意,使用sendOrderedBroadcast方法发送有序广播时,需要一个权限参数,如果为null则表示不要求接收者声明指定的权限,如果不为null,则表示接收者若要接收此广播,需声明指定权限。这样做是从安全角度考虑的,例如系统的短信就是有序广播的形式,一个应用可能是具有拦截垃圾短信的功能,当短信到来时它可以先接受到短信广播,必要时终止广播传递,这样的软件就必须声明接收短信的权限。

所以我们在AndroidMainfest.xml中定义一个权限:

    <permission
        android:name="myAndroid.permission.MY_BROADCAST_PERMISSION"
        android:protectionLevel="normal" />
然后声明使用了此权限:
<uses-permission android:name="myAndroid.permission.MY_BROADCAST_PERMISSION" />

然后我们点击发送按钮发送一条广播,控制台打印如下:

12-20 08:13:45.978: I/TestOrderdBroadcastReceiver(29914): FirstBroadcastReceiver: hello receiver.
12-20 08:13:46.088: I/TestOrderdBroadcastReceiver(29914): SecondBroadcastReceiver: hello receiver.@FirstBroadcastReceiver
12-20 08:13:46.138: I/TestOrderdBroadcastReceiver(29914): ThirdBroadcastReceiver: hello receiver.@FirstBroadcastReceiver@SecondBroadcastReceiver

我们看到接收是按照顺序的,第一个和第二个都在结果集中加入了自己的标记,并且向优先级低的接收者传递下去。

既然是顺序传递,试着终止这种传递,看一看效果如何,我们修改FirstReceiver的代码,在onReceive的最后一行添加以下代码:

abortBroadcast();
然后再次运行程序,控制台打印如下:
12-20 08:13:45.978: I/TestOrderdBroadcastReceiver(29914): FirstBroadcastReceiver: hello receiver.
此次,只有第一个接收者执行了,其它两个都没能执行,因为广播被第一个接收者终止了。

注:只有有序广播可以用abortBroadcast();来终止,其他广播是没有效果的。


BroadcastReceiver的生命周期

BroadcastReceiver的生命周期很短,也就是onReceive的执行时间,onReceive执行结束,BroadcastReceiver的实例就被销毁(不管那种注册方法)


Broadcast Action 大全

android.intent.action.BATTERY_CHANGED
充电状态,或者电池的电量发生变化

android.intent.action.BOOT_COMPLETED
在系统启动后,这个动作被广播一次(只有一次)

android.intent.action.CFF
语音电话的呼叫转移状态已经改变

android.intent.action.CONFIGURATION_CHANGED
设备的配置信息已经改变,参见 Resources.Configuration

android.intent.action.DATA_ACTIVITY
电话的数据活动(data activity)状态(即收发数据的状态)已经改变

android.intent.action.DATA_STATE
电话的数据连接状态已经改变

android.intent.action.DATE_CHANGED
日期被改变

android.server.checkin.FOTA_CANCEL
取消所有被挂起的 (pending) 更新下载

android.server.checkin.FOTA_INSTALL
更新已经被确认,马上就要开始安装

android.server.checkin.FOTA_READY
更新已经被下载,可以开始安装

android.server.checkin.FOTA_RESTART
恢复已经停止的更新下载

android.server.checkin.FOTA_UPDATE
通过 OTA 下载并安装操作系统更新

android.intent.action.MEDIABUTTON
用户按下了"Media Button"

android.intent.action.MEDIA_BAD_REMOVAL
扩展介质(扩展卡)已经从 SD 卡插槽拔出,但是挂载点 (mount point) 还没解除 (unmount)

android.intent.action.MEDIA_EJECT
用户想要移除扩展介质(拔掉扩展卡)

android.intent.action.MEDIA_MOUNTED
扩展介质被插入,而且已经被挂载

android.intent.action.MEDIA_REMOVED
扩展介质被移除

android.intent.action.MEDIA_SCANNER_FINISHED
已经扫描完介质的一个目录

android.intent.action.MEDIA_SCANNER_STARTED
开始扫描介质的一个目录

android.intent.action.MEDIA_SHARED
扩展介质的挂载被解除 (unmount),因为它已经作为 USB 大容量存储被共享

android.intent.action.MEDIA_UNMOUNTED
扩展介质存在,但是还没有被挂载 (mount)

android.intent.action.MWI
电话的消息等待(语音邮件)状态已经改变

android.intent.action.NETWORK_TICKLE_RECEIVED
设备收到了新的网络 "tickle" 通知

android.intent.action.PACKAGE_ADDED
设备上新安装了一个应用程序包

android.intent.action.PACKAGE_REMOVED
设备上删除了一个应用程序包

android.intent.action.PHONE_STATE
电话状态已经改变

android.intent.action.PROVIDER_CHANGED
更新将要(真正)被安装

android.intent.action.PROVISIONING_CHECK
要求 polling of provisioning service 下载最新的设置

android.intent.action.SCREEN_OFF
屏幕被关闭

android.intent.action.SCREEN_ON
屏幕已经被打开

android.intent.action.SERVICE_STATE
电话服务的状态已经改变

android.intent.action.SIG_STR
电话的信号强度已经改变

android.intent.action.STATISTICS_REPORT
要求 receivers 报告自己的统计信息

android.intent.action.STATISTICS_STATE_CHANGED
统计信息服务的状态已经改变

android.intent.action.TIMEZONE_CHANGED
时区已经改变

android.intent.action.TIME_SET
时间已经改变(重新设置)

android.intent.action.TIME_TICK
当前时间已经变化(正常的时间流逝)

android.intent.action.UMS_CONNECTED
设备进入 USB 大容量存储模式。

android.intent.action.UMS_DISCONNECTED
设备从 USB 大容量存储模式退出

android.intent.action.WALLPAPER_CHANGED
系统的墙纸已经改变

android.intent.action.XMPP_CONNECTED
XMPP 连接已经被建立

android.intent.action.XMPP_DI  
XMPP 连接已经被断开

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: android_udpbroadcast_demo 是一个 Android 平台上的示例程序,用于展示如何使用UDP广播进行网络通信。 首先需要明确的是,UDP(User Datagram Protocol)是一种面向无连接的网络传输协议,它不保证数据的可靠性和顺序,但是具有速度快的特点。而广播则是一种将数据包发送给网络上所有设备的通信方式。 在 android_udpbroadcast_demo 中,主要包括以下几个部分的功能: 1. 发送广播:通过UDP协议,将数据包发送给本地局域网内的所有设备。示例程序中提供了发送和停止发送广播的功能。 2. 接收广播:监听网络上的UDP数据包,获取其他设备发送的数据。示例程序中展示了如何设置UDP监听器,并在接收到数据包时进行处理。 3. 显示接收的广播数据:将接收到的数据显示在界面上,让用户可以直观地查看广播内容。 通过 android_udpbroadcast_demo,开发者可以学习如何在 Android 平台上实现UDP广播的功能,可以用于实现局域网内的设备间通信、发现和数据传输等功能。例如,可以用于创建多人游戏、局域网聊天应用等。 总之,android_udpbroadcast_demo 是一个帮助开发者了解和学习如何使用UDP广播进行网络通信的示例程序,通过该示例程序,开发者可以掌握如何在Android平台上实现UDP广播的功能。 ### 回答2: android_udpbroadcast_demo是一个用于在Android设备上进行UDP广播通信的示例程序。UDP (User Datagram Protocol) 是一种无连接的传输协议,它可以提供高效的数据传输。在该示例程序中,通过UDP广播,可以实现Android设备之间的快速通信。 Android设备通过使用DatagramSocket和DatagramPacket类来创建一个UDP套接字并发送和接收数据包。在示例程序中,首先创建一个用于接收数据的DatagramSocket,并设置一个固定的广播端口。然后使用一个线程来循环接收来自其他设备的广播消息,并对接收到的消息进行处理。 接下来,在发送广播消息之前,需要创建一个新的DatagramSocket和一个DatagramPacket。在发送消息时,将相应的数据封装到DatagramPacket中,并通过UDP广播发送给其他设备。 示例程序还包括了需要添加的权限,例如INTERNET权限和ACCESS_NETWORK_STATE权限,以便可以进行网络通信,并检查设备的网络状态。 通过运行该示例程序,可以在多个Android设备上实现UDP广播通信。例如,可以将一台设备设置为发送广播消息的服务器,其他设备可以接收并处理这些广播消息。这个示例程序可以用于各种场景,例如实时在线聊天、设备之间的实时数据同步等。 总之,android_udpbroadcast_demo是一个完整的示例程序,展示了如何在Android设备上使用UDP广播进行快速通信。使用该示例程序,可以轻松实现Android设备之间的通信,为各种应用场景提供了很大的灵活性和可扩展性。 ### 回答3: android_udpbroadcast_demo是一个使用UDP协议进行广播的Android应用程序示例。 UDP(User Datagram Protocol)是一种无连接的传输协议,它提供了面向数据报的简单传输服务。广播是一种网络通信方式,可以将数据包同时发送给同一局域网中的多个接收者。 在android_udpbroadcast_demo中,首先需要创建一个UDP广播发送器和接收器。发送器负责将数据打包成数据包,并通过UDP广播发送给局域网中的接收器。接收器则负责接收传输过来的数据包,并进行解析处理。 在示例中,可以通过点击按钮或在文本框中输入信息来触发发送广播。发送器将信息封装成数据包,并通过UDP广播发送。接收器侦听局域网中的UDP广播,一旦接收到数据包,就会解析其中的信息,并在界面上显示出来。这样,就实现了同一局域网中多台设备之间的信息交流。 android_udpbroadcast_demo可以用于开发各种需要广播通信功能的Android应用程序。例如,可以用于多人游戏中的消息广播、局域网内设备的发现与连接、实时通信应用的消息推送等场景。 总之,android_udpbroadcast_demo是一个使用UDP协议进行广播的Android应用程序示例,能够实现同一局域网中多台设备之间的消息传递。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值