Android Studio —— Broadcast

943 阅读4分钟

第一行代码读书笔记

广播机制

  • 标准广播
    • 完全异步执行的广播
    • 广播发出后,所有广播接收器几乎在同一时刻接收到这条广播消息,没有先后顺序
    • 效率比较高,无法被截断
  • 有序广播
    • 同步执行的广播
    • 同一个时刻只有一个广播接收器能收到消息
      这个广播接收器中的逻辑执行完以后才会继续传递,有先后顺序
    • 优先级高的广播接收器先收到广播消息
    • 前面的广播接收器可以截断正在传递的广播

接收系统广播

  • 广播接收器 Broadcast
  • 注册广播
    • 动态注册:
      在代码中注册
    • 静态注册:
      在AndroidManifest.xml中注册
  • 创建广播接收器:
    继承自Broadcast-receiver并重写父类的onReceive()

动态注册监听网络变化

public class MainActivity extends AppCompatActivity {

    private IntentFilter intentFilter;

    private NetworkChangeReceiver networkChangeRecevier;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        intentFilter = new IntentFilter();
        intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
        networkChangeRecevier = new NetworkChangeReceiver();
        registerReceiver(networkChangeRecevier, intentFilter);
    }

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

    class NetworkChangeReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(context, "network changes", Toast.LENGTH_SHORT).show();
        }
    }
}
  • 网络状态发生变化时,系统发出一条值为android.net.conn.CONNECTIVITY_CHANGE的广播
  • addAction():监听什么广播
  • registerReceiver()注册广播接收器
  • 最后一定要取消注册
  • 提示用户有网络还是没网络
    class NetworkChangeReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            ConnectivityManager connectionManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo networkInfo = connectionManager.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();
            }
        }
    }
    
    • ConnectivityManager:系统服务类,专门用于管理网络连接
    • 如果程序需要进行一些对用户来说比较敏感的操作,必须在配置文件中声明权限才可以
      在AndroidManifest.xml中加入:
      <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
      
  • 缺点:程序启动后才能接收到广播

静态注册实现开机启动

  • com.example.broadcasttest包->New->Ohter->Broadcast Receiver
    • Exported:是否允许这个广播接收器接收本程序意外的广播
    • Enabled:是否启用这个广播接收器
    public class BootCompleteReceiver extentds BroadcastReceiver {
        @Override
        public void onReceveive(Context context, Intent intent) {
            Toast.makeText(context, "Boot Complete", Toast.LENGTH_LONG).show();
        }
    }
    
    • 静态的广播接收器一定要在AndroidManifest.xml中注册才能使用
    • 快捷方式创建的广播接收器自动注册了
      <receiver
          android:name=".BootCompleteReceiver"
          android:enabled="true"
          android:exported="true"
      /receiver>
      
    • 添加权限
      <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
      
      • (未添加权限报错:Missing permissions required by...)

不要在onReceive()方法中添加过多的逻辑或进行耗时操作
广播接收器中不允许开线程
onReceive()运行了较长时间没有结束时,程序会报错
广播接收器更多扮演一种打开程序其他组件的角色

发送自定义广播

发送标准广播

Button button = (Button) findViewById(R.id.button);
button.setOnClickListener((new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent("com.example.broadcasttest.MY_BROADCAST");
        sendBroadcast(intent);
    }
}));
  • 构建Intent对象,并把要发送的广播值传入
  • 调用Context的sendBoradcast()方法将广播发送出去
  • 由于广播是使用Intent传递的,可以在Intent中携带一些数据传递给广播接收器

发送有序广播

Button button = (Button) findViewById(R.id.button);
button.setOnClickListener((new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent("com.example.broadcasttest.MY_BROADCAST");
        sendOrderedBroadcast(intent, null);
    }
}));
  • sendOrderedBroadcast()接收两个参数
    • 第一个参数:Intent
    • 第二个参数:一个与权限相关的字符串
  • 设定先后顺序:在<receiver>标签的<intent-filter>中添加属性
    android:priority="100"
  • 是否允许广播继续传递:在广播接收器的onReceive()中添加 abortBroadcast();

使用本地广播

  • 使用该机制发出的广播只能在应用程序的内部传递,
    且广播接收器也只能接收来自本应用程序发出的广播
  • 使用LocalBroadcastManager对广播进行管理
    并提供了发送广播和注册广播接收器的方法
    (在android.support.v4.content包中)
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 = LoacalBroadcastManager.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.broadcasttest.LOCAL_BROADCAST");
                localBroadcastManager.sendBroadcast(intent);
            }
        }));
        
        intentFilter = new IntentFilter();
        intentFilter.addAction("android.net.conn.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, "receive local broadcast", Toast.LENGTH_SHORT).show();
        }
    }
}
  • 本地广播无法通过静态注册的方式接收
  • 比全局广播更加高效
  • 广播不会离开程序:机密数据不会泄露
    其他程序无法发送广播进来,不会有安全漏洞的隐患