Android读书笔记之广播Broadcast
一.BroadcastReveiver简介
本质就是一个全局监听器,用于监听系统全局的广播消息。可以方便地实现系统中不同组件之间的通信。例如,我们希望客户端程序与startService方法启动的Service之间通信,就可以借助于BroadcastReceiver来实现。
程序启动BroadcastReceiver就需要两步:
a.创建需要启动的BroadcastReceiver的Intent;
b.调用Context的sendBroadcast()或sendOrderedBroadcast()方法来启动指定的BroadcastReceiver。
实现BroadcastReceiver的方法也十分简单,只要重写BroadcastReceiver的onReceive(Context conext, Intent intent)方法即可。
指定该BroadcastReveiver能匹配的Intent,此时有两种方式:
BroadcastReceiver的生命周期:
每次系统Broadcast事件发生后,系统就会创建对应的BroadcastReceiver实例,并自动触发它的onReceive方法,onReceive方法执行后,BroadcastReceiver实例就会被销毁。
如果BroadcastReceiver的onReceive方法不能在10s内执行完成,Android会认为该程序无响应。所以不要在BroadcastReceiver的onReceive方法里执行一些耗时的操作;否则会弹出ANR对话框。
如果需要耗时操作,可以考虑通过Intent启动一个Service来完成该操作,不应该考虑使用新线程去完成耗时的操作,因为broadcastReceiver本身的生命周期很短,可能出现子线程可能还没结束,BroadcastReceiver就已经退出了。
二.发送广播
定义了如何发送Broadcast,使用BroadcastReceiver接受广播。
MainActivity.java
public class MainActivity extends Activity
{
Button send;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取程序界面中的按钮
send = (Button) findViewById(R.id.send);
send.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
// 创建Intent对象
Intent intent = new Intent();
// 设置Intent的Action属性
intent.setAction("org.crazyit.action.CRAZY_BROADCAST");
intent.putExtra("msg", "简单的消息");
// 发送广播
sendBroadcast(intent);
}
});
}
}
MyReceiver.java
public class MyReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
Toast.makeText(context,
"接收到的Intent的Action为:" + intent.getAction()
+ "\n消息内容是:" + intent.getStringExtra("msg")
, Toast.LENGTH_LONG).show();
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.crazyit.broadcast" >
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".MyReceiver">
<intent-filter>
<!-- 指定该BroadcastReceiver所响应的Intent的Action -->
<action android:name="org.crazyit.action.CRAZY_BROADCAST" />
</intent-filter>
</receiver>
</application>
</manifest>
三.有序广播
接下来介绍一个发送有序广播的示例,该程序的Activity界面上只有一个普通按钮,用户发送有序广播。
MainActivity.java
public class MainActivity extends Activity
{
Button send;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取程序中的send按钮
send = (Button) findViewById(R.id.send);
send.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
// 创建Intent对象
Intent intent = new Intent();
intent.setAction("org.crazyit.action.CRAZY_BROADCAST");
intent.putExtra("msg", "简单的消息");
// 发送有序广播
sendOrderedBroadcast(intent, null);
}
});
}
}
MyReceiver.java
public class MyReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
Toast.makeText(context, "接收到的Intent的Action为:"
+ intent.getAction() + "\n消息内容是:"
+ intent.getStringExtra("msg")
, Toast.LENGTH_LONG).show();
// 创建一个Bundle对象,并存入数据
Bundle bundle = new Bundle();
bundle.putString("first", "第一个BroadcastReceiver存入的消息");
// 将bundle放入结果中
setResultExtras(bundle);
// 取消Broadcast的继续传播,如果保持这条代码生效,那么优先级比MyReveiver低的
//BroadcastReceiver都将不会触发。
abortBroadcast(); // ①
}
}
上面的BroadcastReceiver不仅处理了它所接收到的消息,而且向处理结果中存入为first的消息,这个消息将可以被第二个BroadcastReceiver解析出来。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.crazyit.broadcast" >
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".MyReceiver">
<intent-filter android:priority="20">
<action android:name="org.crazyit.action.CRAZY_BROADCAST" />
</intent-filter>
</receiver>
<receiver android:name=".MyReceiver2">
<intent-filter android:priority="0">
<action android:name="org.crazyit.action.CRAZY_BROADCAST" />
</intent-filter>
</receiver>
</application>
</manifest>
MyReceiver2.java
public class MyReceiver2 extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
Bundle bundle = getResultExtras(true);
// 解析前一个BroadcastReceiver所存入的key为first的消息
String first = bundle.getString("first");
Toast.makeText(context, "第一个Broadcast存入的消息为:"
+ first, Toast.LENGTH_LONG).show();
}
}
四.接收系统广播消息
如果应用需要在系统特定时刻执行某些操作,就可以通过监听系统广播来实现,Android的大量系统事件都会对外发送标准广播。
下面是Android常见的广播Action常量:
通过使用BroadcastReceiver来监听特殊的广播,即可让应用随系统执行特定的操作。
实例 开机自动运行的Service
有些应用下需要开机自动运行的Service,如监听用户来电,监听用户短信,拦截黑名单电话,为了让Service随系统启动自动运行,可以让BroadcastReceiver监听Action为ACTION_BOOT_COMPLETED常量的Intent。然后在BroadcastReciver中启动特定Service即可。
LaunchReceiver.java
package org.crazyit.broadcast;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class LaunchReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
Intent tIntent = new Intent(context
, LaunchService.class);
// 启动指定Service
context.startService(tIntent);
}
}
同时需要在AndroidManifest.xml中配置该BroadcastReceiver:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.crazyit.broadcast" >
<application
android:allowBackup="true"
android:theme="@style/AppTheme" >
<service android:name=".LaunchService">
</service>
<!-- 定义一个BroadcastReceiver,监听系统开机广播 -->
<receiver android:name=".LaunchReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
<!-- 授予应用程序访问系统开机事件的权限 -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
</manifest>
还可以用于短信提醒和手机电量提示等信息。