广播接收器(Broadcast Receiver),是我们接触到的第二个组件。Broadcast(广播)是一种广泛应用在应用程序之间传输信息的机制,而BroadcastReceiver(广播接收器)则是用于接收来自系统和应用的广播对并对其进行响应的组件。Android提供了一套完整的API,允许应用程序自由地发送和接收广播。其中发送广播的方法就是使用Intent,而接收广播就需要使用广播接收器了。
广播的类型
在介绍广播接收器之前,我们先来具体介绍一下广播。Android里面广播就类似于现实生活里面的广播。当我们需要传达一些信息给很多人听的时候,我们就会使用广播,而在程序里面也是同样的道理,除此以外,它不仅能够给自己的程序发送广播,还能够给其他的程序发送广播。
Android中的广播主要可以分为两种类型:标准广播和有序广播。
- 标准广播
标准广播是一种完全异步执行的广播,在广播发出之后,几乎所有的广播接收器都会接受到这个广播,因此标准广播的效率是很高的。
- 有序广播
有序广播是一种同步执行的广播,在广播发出之后,同一时刻只会有一个广播接收器能够收到这条广播,当这个广播接收器中的逻辑执行完毕之后,这条广播才能够被继续传递。所以此时的广播接收器是有先后顺序的。
接收广播的方法
广播接收器就是用来接收广播,它可以对它需要的广播进行注册,这样当有相应的广播发出时,它就能够接收到该广播。注册广播的方式一般有2种:动态注册和静态注册。下面分别来看一看吧。
1.动态注册
动态注册简单来说其实就是在代码中进行使用registerReceiver()方法来为广播接收器进行注册。先创建一个空项目,然后修改主代码:
package com.example.yzbkaka.myapplication;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
IntentFilter intentFilter; //放置广播的“容器”
NetworkChangeReceiver networkChangeReceiver; //广播接收器
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intentFilter = new IntentFilter();
networkChangeReceiver = new NetworkChangeReceiver();
intentFilter.addAction("android.net.com.CONNECTIVITY.CHANGE");
registerReceiver(networkChangeReceiver,intentFilter); //注册广播
}
@Override
protected void onDestroy(){
super.onDestroy();
unregisterReceiver(networkChangeReceiver);
}
class NetworkChangeReceiver extends BroadcastReceiver{ //广播接收器继承自BroadcastReceiver
@Override
public void onReceive(Context context, Intent intent) { //添加逻辑
Toast.makeText(MainActivity.this, "get a broadcast", Toast.LENGTH_SHORT).show();
}
}
}
这里我们首先是要创建一个内部类NetworkChangeReceiver并让它继承BroadcastReceiver 然后我们就在它的onReceive()的方法中来添加逻辑。接着看到上面的主代码,我们先是新建一个IntentFilter的实例,这个实例是用来存放广播的,然后我们对它使用addAction()的方法来添加广播,这里添加的广播是系统自带的广播,主要是用来判断网络变化的。然后我们就使用registerReceiver()的方法来对广播进行注册,这里需要的两个参数就是我们的广播接收器和intentFilter了。
需要注意的是使用动态的方法注册的广播必须要手动取消注册才行,我们在onDestroy()的方法中使用unregisterReceiver()来进行取消注册。
2.静态注册
静态注册的主要思路就是在AndroidManifest.xml中来进行注册。我们先创造一个新的类,修改代码:
package com.example.yzbkaka.myapplication;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class BootCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "this is bootcompletereceiver", Toast.LENGTH_SHORT).show();
}
}
接着我们到AndroidManifest.xml来为接收器进行注册:
我们在android:enable
属性是指是否启用这个接收器,而android:exported
属性是指是否允许这个广播接收器接收本程序以外的广播。
接着我们就需要来为广播接收器添加广播了,还是在AndroidManifest.xml中修改:
因为在Android系统中使用某些比较隐秘的广播时需要我们来声明权限,所以我们先在开头中声明一下权限,使用的是
静态注册的方法看起来是要比动态注册的方法操作要复杂一些,但是它却能够在程序启动之前就能够接收到广播,因为动态注册的方法实在onCreate()中进行的,所以动态注册的广播接收器必须当活动被创建起来之后才能够接收到广播。
发送广播
前面我们使用的例子中接收到的广播都是系统内置的广播,也就是说这些广播能都在某些情况下由系统自动的发送。但是我们也可以自定义广播来进行发送。
1.发送标准广播
前面说过,标准广播就是可以被所有的广播接收器接收。下面我们就来发送标准广播吧。
还是先创建一个空项目,然后新建一个广播接收器:
package com.example.yzbkaka.sendbroadcastpractice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "get a broadcast", Toast.LENGTH_SHORT).show();
}
}
还是比较容易理解的代码,这里就不多说了。接着是注册广播接收器:
在注册的时候我们是自定义了一条叫做com.example.broadcast.MY_BROADCAST
的广播,到时候我们的广播接收器就会接收这样一条广播。然后我们为我们的主活动添加一个按钮,最后修改主代码:
package com.example.yzbkaka.sendbroadcastpractice;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button send = (Button)findViewById(R.id.button1);
final Intent intent = new Intent("com.example.broadcast.MY_BROADCAST");
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
sendBroadcast(intent); //发送广播
}
});
}
}
我们这里先是将广播存放在intent当中,然后就是将intent使用sendBroadcast()方法来进行发送。
运行程序,然我们点击按钮的时候就会发送广播,而在程序的下方就会出现一跳短消息提示语句,说明我们的接收器成功接收到了广播。
2.发送有序广播
知道了如何发送标准广播,下面就来看一看如何发送有序广播吧。
我们直接使用上面的项目,前面的代码都不变,我们直接修改主代码:
package com.example.yzbkaka.sendbroadcastpractice;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button send = (Button)findViewById(R.id.button1);
final Intent intent = new Intent("com.example.broadcast.MY_BROADCAST");
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
sendOrderedBroadcast(intent,null); //有序发送广播的方法
}
});
}
}
这里我们是直接修改发送广播的方法,改成使用sendOrderedBroadcast()方法来进行发送,这个方法需要2个参数:第一个就是存储了广播的intent;第二个就是直接使用默认的null即可。
有序广播的特点是必须要按照广播接收器的优先级来被捕获,即优先级越高的广播接收器,就能够越在前面接收广播。所以我们接下来就来修改广播接收器的优先级,打开AndroidManifest.xml,修改代码:
使用priority的属性来设置广播接收器的优先级,这里我们设置为100。之后如果有多个广播接收器,我们就可以手动的设置它们的优先级来为它们进行排序。
当然,优先级高的广播接收器也可以执行不让广播继续传送的操作,即广播传到它这里以后就不会再传书下去了,我们直接在onCreate()里面添加abortBroadcase()方法就能够阻断广播的传输了。
使用本地广播
我们之前发送的广播(包括系统广播和自定义广播)都是在系统内全局发送的,即所有的程序都能够接收这些广播。但是有些情况下我们不想让其他的程序收到我们的广播时,我们就可以选择发送本地广播。
新建项目,添加一个按钮,然后直接修改主代码:
package com.example.yzbkaka.localbroadcasttest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
IntentFilter intentFilter;
LocalReceiver localReceiver;
LocalBroadcastManager localBroadcastManager; //创建管理器
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Button send = (Button)findViewById(R.id.button1);
localBroadcastManager = LocalBroadcastManager.getInstance(this);
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent("com.example.broadcast.LOCAL_BROADCAST");
localBroadcastManager.sendBroadcast(intent); //发送广播
}
});
intentFilter = new IntentFilter();
intentFilter.addAction("com.example.broadcast.LOCAL_BROADCAST");
localReceiver = new LocalReceiver();
localBroadcastManager.registerReceiver(localReceiver,intentFilter); //注册广播接收器
}
class LocalReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "get local broadcast", Toast.LENGTH_SHORT).show();
}
}
}
这里我们是采用动态注册的方法来实现的,因为我们想要的是发送不让其他程序接收到的广播,如果采用静态的注册方法,则在我们活动创建之前就有了广播,这和我们想要的是不同的。接着我们就是创建一个LocalBroadcastManager的实例,我们发送本地广播主要就是依靠它来完成的。然后就是调用LocalBroadcastManager实例的方法来进行发送和注册。