FC_5 广播机制

广播的注册方式:

  • 动态注册
  • 静态注册

广播的发送方式:

  • 普通广播
  • 有序广播
  • 本地广播

特殊说明

  • 不要在onreceive中添加过多的逻辑或超时操作
  • 本地广播无法通过静态注册方式来接受

关于动态注册&关于静态注册

一种是在活动里通过代码动态注册,另一种在配置文件里静态注册。动态注册的接收器必须要在程序启动之后才能接收到广播,而静态注册的接收器即便程序未启动也能接收到广播,比如想接收到手机开机完成后系统发出的广播就只能用静态注册了。

//动态注册
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实例,,
         * 添加了android.net.conn.CONNECTIVITY_CHANGE的action,当系统发出这个广播时,我们就能收到
         * 创建了NetworkchangeReceiver实例,
         * 调用registerReceiver对广播进行动态注册
         */
        intentFilter = new IntentFilter();
        intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
        networkchangeReceiver = new NetworkchangeReceiver();
        registerReceiver(networkchangeReceiver, intentFilter);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        //动态注册的广播必须取消注册。在onDestroy调用unregisterReceiver方法
        unregisterReceiver(networkchangeReceiver);
    }
    /**
     * 定义内部类,NetworkchangeReceiver,
     * 继承BroadcastReceiver,重写父类的onReceive方法
     * 每当网络状态发生变化时,就会执行,这里简单toast。
     */
    private class NetworkchangeReceiver extends BroadcastReceiver {
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(context, "network changes", Toast.LENGTH_SHORT).show();
        }
    }
}
//静态注册
//1、new other broadcast Receiver,创建广播器MyReceiver,重写onReceive方法
//2、在配置文件中添加<intent-filter>
//3、添加网络权限  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>


public class MyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "network changes", Toast.LENGTH_SHORT).show();
    }
}


//AndroidManifest的配置文件里
      <receiver
            android:name=".MyReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
            </intent-filter>
      </receiver>

关于普通广播

也就是标准广播,普通广播是一种完全异步执行的广播,在广播发出之后,所有的广播接收器几乎都会在同一时刻接收到这条广播消息,因此它们接收的先后是随机的。另外,接收器不能截断普通广播。

  1. 创建广播接收器
  2. AndroidManifest进行静态注册,添加对应的权限
  3. 界面添加按钮,mainactivity里对按钮添加单击事件,发送广播。
public class MyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "received BroadcastReceiver", Toast.LENGTH_SHORT).show();
    }
}
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
        <receiver
            android:name=".MyReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
        </receiver>
 public void onclick(View view) {
        Intent intent = new Intent("firstcode.zs.com.fc_5.MyReceiver");
        sendBroadcast(intent);
    }

关于有序广播

它是一种同步执行的广播,在广播发出之后,同一时刻只会有一个广播接收器能够收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传递,所以此时的广播接收器是有先后顺序的,且优先级(priority)高的广播接收器会先收到广播消息。有序广播可以被接收器截断使得后面的接收器无法收到它。

  1. 发送一个有序广播和普通广播的方法有细微的区别,只需要将sendBroadcast()方法改成sendOrderedBroadcast()方法, 它接收两个参数,第一个参数仍是Intent,第二个参数是一个与权限相关的字符串,这里传入 null就行。
  2. 只要在注册的时候设定它的优先级android:priority为100,数值越大优先级就越高,现在就能保证它一定会在MyReceiver之前收到广播。
  3. 如果在AnotherReceiver的onReceive()方法中调用了abortBroadcast()方法,表示将这条广播截断,后面的广播接收器将无法再接收到这条广播。现在重新运行程序,并点击一下按钮,然后会发现,只有AnotherReceiver中的Toast信息弹出,说明这条广播经过AnotherReceiver之后确实是终止传递了。

关于本地广播

使用本地广播,自己在之前用过,参考这篇文章

前面学到的的广播都属于系统全局广播,即发出的广播可被其他应用程序接收到,且我们也可接收到其他任何应用程序发送的广播。为了能够简单地解决全局广播可能带来的安全性问题,Android引入了一套本地广播机制,使用这个机制发出的广播只能够在应用程序的内部进行传递,并且广播接收器也只能接收本应用程序发出的广播。

实现本地广播的发送和接收也很简单,主要使用了一个LocalBroadcastManager来对广播进行管理,并提供了相应的发送广播和注册广播接收器的方法。

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("firstcode.zs.com.fc_5.LOCAL_BROADCAST");
                localBroadcastManager.sendBroadcast(intent); // 发送本地广播
            }
        });
        intentFilter = new IntentFilter();
        intentFilter.addAction("firstcode.zs.com.fc_5.LOCAL_BROADCAST");
        localReceiver = new LocalReceiver();
        localBroadcastManager.registerReceiver(localReceiver, intentFilter); // 注册本地广播监听器
    }

    @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();
        }
    }
}

关于不要在onreceive中添加过多的逻辑或超时操作:

广播接收器不允许开启线程。当onreceive方法运行了较长时间没有结束时,程序就会报错。

关于本地广播无法通过静态注册方式来接收

静态注册主要是为了让程序在未启动的情况下也能收到广播,而发送本地广播是我们的程序肯定已经启动了,完全不需要静态注册。

FC系列文章,均参考郭神的《第一行代码》,所以这里的文章均为转载

猜你喜欢

转载自blog.csdn.net/easy_purple/article/details/84146474
今日推荐