在上篇文章中对四大组件之Activity进行进行总结,这篇文章是对另一个四大组件Broadcast 广播进行总结。

广播类型

广播可以分为两种类型:

  • Normal broadcasts 标准广播:完全异步的,广播发出后,所有的广播接收器几乎都会在同一时刻收到这条广播消息。它的特点是,广播效率高,但是无法被截断。
    NormalBroadcasts.jpg
  • Ordered broadcasts 有序广播:同步执行的,广播发出后,同一时刻只能有一个广播接收器能够收到这条广播消息,只有当该广播接收器的逻辑处理完成后,广播才会继续传递给下一个广播接收器。优先级越高的广播接收器会优先接收到广播消息,另外广播接收器还可以对广播进行截断,这样后面的广播接收器就无法收到该广播消息。
    OrderBroadcasts.jpg

广播接收器类型

创建广播接收器必须直接或间接地集成BroadcastReceiver,重写onReceive方法。

广播接收器根据注册的方式可以分成两类:动态注册、静态注册

动态注册

动态注册:通过代码方式注册广播接收器。动态注册的接收器,一定都要取消注册。

例如下面的代码动态创建广播接收器,在onCreate中创建广播接收器并进行注册,在onDestroy中取消注册:

public class MainActivity extends AppCompatActivity {
    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 {
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(context, "network change", Toast.LENGTH_LONG).show();
        }
   }
}

AndroidManifest.xml中加入权限:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.jyoryo.app.android.study.s0401">

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

</manifest>

静态注册

动态注册可以自由控制广播接收器的注册、注销,但也存在一个缺点:必须要在程序启动并运行后才能接收到广播。如果需要在程序未启动的情况下就能接收到广播,可以使用静态注册广播接收器。
静态注册:在AndroidManifest.xml中注册的广播接收器。

1、创建广播接收器:

/**
 * 开机广播接收器
 */
public class BootCompleteReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "Boot Complete!", Toast.LENGTH_LONG).show();
    }
}

2、在AndroidManifest.xml中注册静态广播接收器:

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

3、根据是否需要相关权限在AndroidManifest.xml申明需要的权限,比如上面的开机广播需要android.permission.RECEIVE_BOOT_COMPLETED权限。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.jyoryo.app.android.study.s0401">

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

</manifest>

发送自定义广播

发送标准广播

发送标准广播:新建一个Intent,然后sendBroadcast(intent)即可。

Intent intent = new Intent("com.jyoryo.app.android.study.MY_BROADCAST");
sendBroadcast(intent);

通过静态注册接收自定义广播。
AndroidManifest.xml注册MyBroadcast广播接收器:

    <receiver
        android:name=".MyBroadcastReceiver"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="com.jyoryo.app.android.study.MY_BROADCAST" />
        </intent-filter>
    </receiver>

广播接收器MyBroadcastReceiver:

/**
 * 接收自定义广播
 */
public class MyBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "receive in MyBroadcastReceiver", Toast.LENGTH_LONG).show();
    }
}

发送有序广播

发送有序广播:新建一个Intent,然后sendOrderedBroadcast(intent, receiverPermission)即可。

Intent intent = new Intent("com.jyoryo.app.android.study.MY_BROADCAST");
sendOrderedBroadcast(intent, null);

给广播接收器指定先后顺序,通过android:priority="100"将该接收器的优先级设置为100。

    <receiver
        android:name=".MyBroadcastReceiver"
        android:enabled="true"
        android:exported="true">
        <intent-filter android:priority="100">
            <action android:name="com.jyoryo.app.android.study.MY_BROADCAST" />
        </intent-filter>
    </receiver>

如果广播接收器处理后,想要截断这条广播,需要在处理完逻辑后调用abortBroadcast()方法。

public class MyBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "receive in MyBroadcastReceiver", Toast.LENGTH_LONG).show();
        abortBroadcast();
    }
}

使用本地广播

上面接收的广播都是属于系统全局广播,即发出的广播可以被其他所有的程序接收到。但有时为了安全,发送的广播携带关键或敏感的数据,我们需要发送的广播只能通过本应用接收。这时可以通过本地广播机制来解决。
本地广播主要使用LocalBroadcastManager对广播进行管理,提供本地广播的注册localBroadcastManager.registerReceiver和注销localBroadcastManager.unregisterReceiver操作。

public class MainActivity extends AppCompatActivity {
    private LocalBroadcastManager localBroadcastManager;
    private IntentFilter intentFilter;
    private LocalReceiver localReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // LocalBroadcastManager
        localBroadcastManager = LocalBroadcastManager.getInstance(this);
        // 注册动态广播接收器
        intentFilter = new IntentFilter();
        intentFilter.addAction("com.jyoryo.app.android.study.LOCAL_BROADCAST");
        localReceiver = new LocalReceiver();
        localBroadcastManager.registerReceiver(localReceiver, intentFilter);

        // 通过按钮测试发送本地广播
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent("com.jyoryo.app.android.study.LOCAL_BROADCAST");
                sendOrderedBroadcast(intent, null);
                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, "receive local broadcast", Toast.LENGTH_LONG).show();
       }
   }
}

本地广播的特点:

  1. 本地广播无法通过静态注册方式来接收。
  2. 本地广播离不开本身的程序,因此不用担心敏感数据泄露。
  3. 本地广播的发送比系统全局广播的发送更高效。

标签: android

添加新评论