BroadcastReceiver

BroadcastReceiver也是安卓的四大组件之一,它负责接受安卓系统或者应用发出的广播。比如安卓自身会在手机电量快耗尽时发出广播,通过BroadcastReceiver,我们就能在应用中检测到电量即将耗尽;再比如想要在一个应用中检测到安卓系统是否处于飞行模式,,那么也可以使用BroadcastReceiver来接受安卓系统在切换飞行模式时候发出的广播,再例如想要实现应用开机自启动,也要靠接收开机时的广播,再比如检测网络状态变化等等。

这一组件的原理很简单:

广播源在特定时刻发出广播,通过静态注册或者动态注册广播源地址,使应用能接收到广播,然后应用通过继承BroadcastReceiver类重写onReceive方法来接收广播,一旦接收到广播,就会执行onReceive方法。

BroadCastReceiver的生命周期很简单,接收到广播时调用onReceive方法,然后结束生命周期。再次接收到广播时,再次调用。。。
使用这一组件同样也要在清单文件中声明:

1
2
3
<receiver
android:name=".MyReceiver">

</receiver>

BroadcastReceiver有两种注册方式:

  • 1.静态注册

静态注册很简单,只需要在清单文件中注册就行了,如下代码:

1
2
3
4
5
6
7
<receiver
android:name=".MyReceiver">

<intent-filter>
<action android:name="android.intent.action.AIRPLANE_MODE"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>

这段代码的第四行就代表了检测飞行模式的一个广播源地址,然后我们只需要新建一个类,继承BroadcastReceiver后重写onReceive方法即可。
MyReceiver.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.example.ahtcfg24.broadcastreceiverdemo;

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

/**
* 由于清单文件中的Receiver注册的广播地址是android.intent.action.AIRPLANE_MODE,
* 因此当手机被调成飞行模式,或者从飞行模式恢复正常模式时,都会执行onReceive方法
*/

public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "收到", Toast.LENGTH_SHORT).show();
Log.i("静态广播", "--->收到消息");
}
}

这样注册的android.intent.action.AIRPLANE_MODE是安卓系统本身发送的广播,与程序的Activity无关,因此不再赘述Activity的代码。

这样写,无论该程序是否处于运行状态,只要已经安装到了手机上,那么这个onReceive方法都能接收到系统的广播

当然,我们也可以让自己的应用发出广播。

首先在清单文件中,我们自定义一个广播地址:android.intent.action.My_Broadcast

1
2
3
4
5
6
7
<receiver
android:name=".MyReceiver">

<intent-filter>
<action android:name="android.intent.action.My_Broadcast"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>

接着在Activity中添加发送广播的按钮和广播地址、广播内容
MainActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.example.ahtcfg24.broadcastreceiverdemo;

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


public class MainActivity extends Activity {
private Button button;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);

button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
send();
}
});

}

public void send() {
Intent intent = new Intent("android.intent.action.My_Broadcast");
intent.putExtra("广播", "发出一条广播");
sendBroadcast(intent);
}

}

然后在Receiver中接收该广播内容

MyReceiver.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.example.ahtcfg24.broadcastreceiverdemo;

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

/**
* 由于清单文件中的Receiver注册的广播地址是android.intent.action.AIRPLANE_MODE,
* 因此当手机被调成飞行模式,或者从飞行模式恢复正常模式时,都会执行onReceive方法
*/

public class MyReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
String msg = intent.getStringExtra("广播");
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
Log.i("静态广播", "--->" + msg);
}
}

布局文件忽略,这样当我们点击发送按钮时,就会弹出一个Toast提示收到广播
如图

查看代码

  • 2.动态注册

动态注册与静态注册相比,最大的区别在于它是非常驻式接收广播,即Receiver的生命周期与应用保持一致。只有在应用被打开时,才能接收到广播。

同样拿安卓系统的飞行模式改变时发出的广播作为例子:

首先,只需要在清单文件中简单注册:

1
2
3
<receiver
android:name=".MyReceiver">

</receiver>

然后在别的地方(Activity或者Service中注册广播地址)

MainActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.example.ahtcfg24.broadcastreceiverdemo2;

import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
private MyReceiver receiver;
private IntentFilter intentFilter;

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

registerMyReceiver();
}

/**
* 在代码中动态注册receiver
*/

public void registerMyReceiver() {
receiver = new MyReceiver();
intentFilter = new IntentFilter();
intentFilter.addAction("android.intent.action.AIRPLANE_MODE");
registerReceiver(receiver, intentFilter);
}

/**
* 当退出程序时如果没有注销Receiver,就会出现异常,因此在onDestroy中进行注销操作
*/

@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}
}

布局文件忽略

MyReceiver.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.example.ahtcfg24.broadcastreceiverdemo2;

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

public class MyReceiver extends BroadcastReceiver {
public MyReceiver() {
}

@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "收到广播", Toast.LENGTH_LONG).show();
Log.i("动态注册", "--->收到广播");
}
}

然后执行程序,发现在程序打开时改变飞行模式才会调用onReceive方法,而程序处于关闭状态则无法执行

查看代码

参考资料

(本文系作者原创,转载请注明出处)