Android第一行代码--广播

广播机制

为了方便进行系统级别的消息通知,Android引用一套广播消息机制。Android中的每个应用程序可以对自己感兴趣的广播进行注册。

  • 标志广播:是一种完全异步执行的广播,广播发出时,所有广播接收器几乎在同一时刻接收到这条广播信息。
  • 有序广播:是一种同步执行的广播,在广播发出时,同一时刻只会有一个广播接收器能够收到这条广播信息,当这个广播接收器逻辑执行完毕后,广播才会继续传递。此时的广播具有优先级,优先级高的广播接收器可以先收到广播信息,并且前面的广播接收器还可以截断正在传递的广播。

接收系统广播

  • 动态注册:在代码中注册
  • 静态注册:AndroidManifest.xml注册

动态注册

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@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();
}
class NetworkChangeReceiver extends BroadcastReceiver{

@Override
public void onReceive(Context context, Intent intent) {
Log.d("onReceive", "onReceive: 11111");
Toast.makeText(context,"network changes",Toast.LENGTH_SHORT).show();
}
}
  • IntentFilter:意图拦截器,用于拦截符合actioncategory的意图,这里需要接收网络修改的广播,因此行为为"android.net.conn.CONNECTIVITY_CHANGE"

  • NetworkChangeReceiver类是继承了广播类并重写了接收到广播的方法

  • registerReceiver()方法用于注册广播接收器

    • 参数一:需要注册的广播接收器
    • 参数二:需要接收广播的行为
  • unregisterReceiver()方法用于取消注册

1
2
3
4
5
6
7
8
9
10
11
12
13
public void onReceive(Context context, Intent intent) {
ConnectivityManager connectivityManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if(networkInfo != null && networkInfo.isAvailable())
{
Toast.makeText(context,"network is available", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(context,"network is unavailable",Toast.LENGTH_SHORT).show();
}

}
  • getSystemService()方法用于获取系统服务类
  • ConnectivityManager类是专门用于管理网络连接
  • getActiveNetworkInfo()方法用于获取网络状态

静态注册

动态注册更灵活但是必须程序运行时才能接收广播,但是静态注册可以在程序未启动的时候接收广播。

1
2
3
4
<receiver
android:name=".BootCompleteReceiver"
android:enabled="true"
android:exported="true"></receiver>
  • android:name用于指定注册的广播接收器
  • android:enabled表示是否启用该广播接收器
  • android:exported表示是否允许这个广播接收器接收本程序以外的广播
1
2
3
4
5
6
7
8
9
10
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
...
<receiver
android:name=".BootCompleteReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>

由于Android系统启动时会发出值为android.intent.action.BOOT_COMPLETED的广播,因此添加相应的action

发送自定义广播

发送标准广播

首先自定义一个广播接收器,<intent-filter>标签内需要拦截的行为为"com.example.mybroadcastreceiver.MY_BROADCAST",接着发送广播的行为也为这个,即可发送和接收广播。

1
2
Intent intent = new Intent("com.example.mybroadcastreceiver.MY_BROADCAST");
sendBroadcast(intent);

发送有序广播

广播可以跨进程通信。

  • sendOrderedBroadcast(intent,null)方法可以发送有序广播
    • 参数一:Intent对象
    • 参数二:与权限相关的字符串
  • android:prority可以自定义广播的优先级
  • abortBroadcast()方法可以拦截广播

本地广播

  • 本地广播是在程序内部的广播,防止接收垃圾广播,或者广播中携带安全数据被恶意劫持。
  • 本地广播无法静止注册
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
public class MainActivity extends AppCompatActivity {
private IntentFilter intentFilter;
private LocalReceiver localReceiver;
private LocalBroadcastManager localBroadcastManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
localBroadcastManager = LocalBroadcastManager.getInstance(this);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.example.mybroadcastreceiver.MY_BROADCAST");
localBroadcastManager.sendBroadcast(intent);
}
});
}

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

class LocalReceiver extends BroadcastReceiver{

@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"received local broadcast",Toast.LENGTH_SHORT).show();
}
}
}

本地广播使用动态注册。

  • LocalBroadcastManager:用于在同一个应用内的不同组件间发送Broadcast

强制下线功能

ActivityConllector

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class ActivityCollector {
public static List<Activity>activities = new ArrayList<>();
public static void addActivity(Activity activity){
activities.add(activity);//增加活动
}
public static void removeActivity(Activity activity){
activities.remove(activity);//删除活动
}
public static void finishAll(){//移除所有活动
for(Activity activity:activities){
if(!activity.isFinishing()){
activity.finish();
}
}
}
}

ForceOfflineReceiver类

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
38
39
.....
//需要在Resume与Pause中重写代码,强制下线的对话框需要在栈顶的活动实例中展现,不需要每个活动实例都弹出对话框。
@Override
protected void onResume() {
super.onResume();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.example.broadcastbestpractice.FORCE_OFFLINE");
receiver = new ForceOfflineReceiver();
registerReceiver(receiver,intentFilter);
}

@Override
protected void onPause() {
super.onPause();
if(receiver!=null){
unregisterReceiver(receiver);
receiver = null;
}
}
.....
class ForceOfflineReceiver extends BroadcastReceiver{

@Override
public void onReceive(final Context context, Intent intent) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);//创建一个对话框
builder.setTitle("Warning");//设置标题
builder.setMessage("You are forced to be offline. Please try to login agin");//设置消息
builder.setCancelable(false);//取消功能必须删除,否则无法强制下线
//点击OK会触发的时间
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ActivityCollector.finishAll();//将所有活动移除
Intent intent = new Intent(context,LoginActivity.class);
context.startActivity(intent);//重新跳转到登陆页面
}
});
builder.show();
}

Android第一行代码--广播
https://h0pe-ay.github.io/Android第一行代码--广播/
作者
hope
发布于
2023年6月27日
许可协议