您的位置:首页 > 移动开发 > Android开发

全局大喇叭,详解广播机制

2015-10-11 14:11 507 查看

1. 广播接收器(Broadcast Receiver)

android中的广播有两种类型:标准广播和有序广播

标准广播 :一种完全异步执行的广播,在广播发出之后,所有的广播接受器几乎都会在同一时刻接收到这条广播信息,他们没有先后顺序可言,效率比较高,无法被截断的。



有序广播 :一种通病执行的广播,在广播发出之后,同一时刻只会有一个广播接收器收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传播,所有此时的广播接收器是有先后顺序的,优先级高的广播接收器就可以先收到广播消息,并且前面广播接收器还可以截断正在传递的广播,后面的广播接收器就无法收到广播消息了。



2.接收系统广播

android内置了很多系统级别的广播,比如手机开机完成后发出一条广播,电池的电量发送变化发出一条广播。

广播接收器可以自由的对自己感兴趣的广播进行注册,当有相应的广播发出时,广播接收器就能收到该广播,然后处理相应的逻辑,

注册广播的方式:

在代码中注册(动态注册,动态注册的广播接收器一定要取消注册才行

在AndroidManifest.xml中注册(静态注册)

创建一个广播接收器,很简单只需要继承BroadcastReceiver,重写父类的onReceiver()方法就行了,有广播到来时,onReceiver()方法就会被执行。

动态注册监听网络变化

public class MainActivity extends Activity {

private IntentFilter intentFilter;
private NetworkChangeReceiver networkChangeReceiver;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
networkChangeReceiver = new NetworkChangeReceiver();
//动态注册监听网络变化的广播
registerReceiver(networkChangeReceiver, intentFilter);
}

@Override
protected void onDestroy() {
super.onDestroy();
//取消注册的广播(动态注册的广播接收器一定要取消才行)
unregisterReceiver(networkChangeReceiver);
}

/**
* 监听网络变化的广播接收器
*/
class NetworkChangeReceiver extends BroadcastReceiver {
//当网络状态发生变化时,onReceive方法就会得到执行
@Override
public void onReceive(Context context, Intent intent) {
//用于管理网络连接
ConnectivityManager connManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connManager.getActiveNetworkInfo();
//判断当前是否有网络
if(networkInfo!=null && networkInfo.isAvailable()){
Toast.makeText(context, "连接成功", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(context, "网络在开小差,检查网络是否连接成功", Toast.LENGTH_SHORT).show();
}
}

}

}


加一个权限:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>


如何测试广播接收器是否接收到消息呢?

打开数据流量就能看到,设置里面,流量使用情况



或者打开wifi,移动数据的按钮。

优缺点:动态注册的广播接收器可以自由的控制注册和注销,程序必须启动之后才能接收到广播。(京东手机客户端“网络在开小差检查后后在试吧”,解放号“网络异常,请稍后再试”)

静态注册实现开机启动

优点:可以在程序没有启动的情况下接收广播。

/**
* 开机启动的广播
*
*/
public class BootCompleteReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "开机启动了广播", Toast.LENGTH_SHORT).show();
}

}


在AndroidManifest.xml中注册广播接收者

添加手机重启的权限:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>


注册开机启动的广播接收者

<receiver android:name=".BootCompleteReceiver">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>


强调:不要在onReceive()方法中添加过多的逻辑或者执行任何的耗时的操作,

3.发送自定义广播

3.1 发送标准广播

广播是使用Intent传递数据的,我们可以在Intent中携带一些数据传递给广播接收器

/**
* 自定义广播接收器
* @author jzz
*
*/
public class MyBroadcastReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
String name = intent.getStringExtra("name");
Toast.makeText(context, "发送自定义广播"+name, Toast.LENGTH_SHORT).show();
}

}


Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//发送自定义广播
Intent intent = new Intent("com.example.broadcasttest.MY_BROADCAST");
//可以携带一些数据传递给广播接收器
intent.putExtra("name", "helloworld");
sendBroadcast(intent);
}
});


3.2 发送有序广播

我们应用程序发出的广播,其他的应用程序也能接收到的。

证明:

创建另一个项目:BroadcastTest2. 新建类AnotherBroadcastReceiver 继承BroadcastReceiver.

public class AnotherBroadcastReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
String name = intent.getStringExtra("name");
Toast.makeText(context, "在另一个广播接收器里面接收"+name, Toast.LENGTH_SHORT).show();
}

}


在AndroidManifest.xml 文件里面注册静态广播接收器

<receiver android:name=".AnotherBroadcastReceiver">
<intent-filter >
<action android:name="com.example.broadcasttest.MY_BROADCAST"/>
</intent-filter>
</receiver>


部署BroadcastTest2。

测试BroadcastTest2也能收到BroadcastTest发送的广播。

1.运行BroadcastTest2,按home键,

- 运行BroadcastTest,点击自定义广播发送。

- 会弹出2次提示信息,并且数据BroadcastTest2也是可以接收到BroadcastTest发送的内容的。





发送有序广播

//sendBroadcast(intent);//发送标准广播
sendOrderedBroadcast(intent, null);//发送有序广播


设定广播接收器的先后顺序

<!-- 自定义广播接收器 -->
<receiver android:name=".MyBroadcastReceiver">
<!-- 通过设置优先级来设定广播接收器的先后顺序 -->
<intent-filter android:priority="100">
<action android:name="com.example.broadcasttest.MY_BROADCAST"/>
</intent-filter>
</receiver>


广播的截断

public void onReceive(Context context, Intent intent) {
String name = intent.getStringExtra("name");
Toast.makeText(context, "发送自定义广播"+name, Toast.LENGTH_SHORT).show();
abortBroadcast();//截断广播
}


部署运行BroadcastTest ,点击发送,只有MyBroadcastReceiver的信息弹出来,说明已经截断了广播。

3.3 使用本地广播

点击本地广播发送就进入本地广播发送的界面

/**
* 本地广播接收器
* @author jzz
*
*/
public class MainActivity2 extends Activity{

private IntentFilter intentFilter;
private LocalBroadcastManager localBroadcastManager;
private LocalReceiver localReceiver;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);

intentFilter = new IntentFilter();
localBroadcastManager = LocalBroadcastManager.getInstance(this);
Button button3 = (Button) findViewById(R.id.button3);
button3.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.example.broadcasttest.LOCAL_BROADCAST");
localBroadcastManager.sendBroadcast(intent);
}
});

intentFilter.addAction("com.example.broadcasttest.LOCAL_BROADCAST");
localReceiver = new LocalReceiver();
//注册本地广播监听器
localBroadcastManager.registerReceiver(localReceiver, intentFilter);
}

class LocalReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "本地广播", Toast.LENGTH_SHORT).show();
}

}
}


本地广播比全局系统广播多了个LocalXXX

本地广播的优势:

1.本地广播无法通过静态注册的方式来接收

2.可以明确地知道正在发送的广播不会离开我们的程序,因此不需要担心机密数据泄

漏的问题。

3.其他的程序无法将广播发送到我们程序的内部,因此不需要担心会有安全漏洞的隐



4.发送本地广播比起发送系统全局广播将会更加高效。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android