《第一行代码Android》学习总结第五章 详解广播机制

一、广播机制简介

        Android提供了一系列API,允许程序自由的发送和接收广播,同时每个程序都可以对自己感兴趣的广播进行注册,该程序便可以只接受来自于系统或其他应用程序的自己关心的广播内容。

标准广播:

        一种完全异步执行的广播,在广播发出后,所有广播接收器会在同一时间接收到该广播消息。它们之间没有任何先后顺序,因此这种广播的效率很高,但无法被截断。

有序广播:

        一种同步执行的广播,广播发出后,同一时间只会有一个广播接收器接收到该广播,当这个广播接收器执行的逻辑完毕后才会继续传递。它们之间是有先后顺序的,优先级高的广播接收器先收到广播,同时前面的广播接收器还可以截断正在传递的广播。

广播接收器(Broadcast Receiver):

       广播接收器可以自由的对感兴趣的广播进行注册,这样当有相应的广播发出时,广播接收器就能够收到该广播,并在内部处理响应的逻辑。注册广播接收器只需新建一个类,继承自BroadcastReceiver类,并重写父类的onReceive()方法。当有广播来时,onReceive()方法会自动执行。

二、接收系统广播

        Android内置了许多系统级的广播,我们可以通过监听系统广播来得到各种系统的状态变化。

1)动态注册——实现监听网络变化

        动态注册主要是在java代码中注册。

1、修改MainActivity中代码注册广播,并在MainActivity中定义内部类NetworkChangeReceiver继承自BroadcastReceiver类,并重写父类的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实例,并将需要那种广播的action添加进来
        intentFilter = new IntentFilter();
//当系统网络变化时发出的广播
        intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
//创建NetworkChangeReceiver实例,并注册广播
        networkChangeReceiver = new NetworkChangeReceiver();
        registerReceiver(networkChangeReceiver,intentFilter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
//动态注册的广播一定要注销
        unregisterReceiver(networkChangeReceiver);
    }

class NetworkChangeReceiver extends BroadcastReceiver{
//每当网络状态发生变化时都会执行onReceive()方法
        @Override
        public void onReceive(Context context, Intent intent) {
//系统服务类,用于专门管理网络连接
            ConnectivityManager connectivityManager = (ConnectivityManager) 
getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
//判断当前是否有网络,对用户进行Toast提示是否有网络
            if(networkInfo != null && networkInfo.isAvailable()){
                Toast.makeText(context,"network is available",Toast.LENGTH_SHORT).show();
            }
            else{
                Toast.makeText(context,"network is not 
available",Toast.LENGTH_SHORT).show();
            }
        }
   }
}

2、在AndroidManifest.xml中添加网络相关权限

        如果程序中需要进行一些对用户来说比较敏感的操作时,就必须在配置文件中声明权限才行,否则程序会直接崩溃。

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

2)静态注册——实现监听开机启动

        静态注册主要是通过AndroidManifest.xml注册。

        动态注册的广播接收器可以自由的控制注册和注销,有很大的灵活性,但存在一个缺点,必须在程序启动时才能接收到广播。而静态注册可以让程序在未启动的情况下接收到广播。

1、使用AndroidStudio提供的快捷方式创建广播接收器,右击com.launcher.broadcasttest包→New→Other→Broadcast Receiver。

        设置广播接收器名为 BootCompleteMyReceiver,

Exported属性表示是否允许这个广播接收器接受本程序以外的广播。

Enabled属性表示是否启用这个广播接收器。

2、修改BootCompleteMyReceiver中onReceive()方法。

public class BootCompleteMyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context,"boot complete",Toast.LENGTH_LONG).show();
    }
}

3、静态的广播接收器只有在AndroidManifest.xml中注册才能使用,创建时这步AndroidStudio已经帮我们做好了。

<receiver
     android:name=".BootCompleteMyReceiver"
     android:enabled="true"
     android:exported="true">
</receiver>

4、<receiver>标签中添加<intent-filter>标签,并在其中设置相应的action。

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

5、在AndroidManifest.xml中添加开机相关权限。

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

注意:不要在onReceive()方法中添加过多逻辑或进行任何耗时操作,因为广播接收器中是不允许开启线程的,当onReceive()方法运行较长时间并没有结束时,程序就会报错。

三、使用本地广播

        系统全局广播中发出的广播可以被其他任何应用程序接收到,也可以收到来自其他任何应用程序的广播。会存在安全性问题。

        本地广播机制,这个机制发出的广播只能在应用程序内部进行传递,而且广播接收器也只能接受来自于本应用程序发出的广播,可以一定程度上解决安全性问题。

        本地广播主要使用了一个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);
// getInstance()方法获取LocalBroadcastManager实例
        localBroadcastManager = LocalBroadcastManager.getInstance(this);
        intentFilter = new IntentFilter();
        intentFilter.addAction("com.launcher.localbroadcasttest.LOCAL_BROADCAST");
        localReceiver = new LocalReceiver();
// localBroadcastManager的registerReceiver()方法注册本地广播
        localBroadcastManager.registerReceiver(localReceiver,intentFilter);
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
            Intent intent = new Intent("com.launcher.localbroadcasttest.LOCAL_BROADCAST");
//localBroadcastManager的sendBroadcast()方法发送本地广播
            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,"LocalBroadcastTest",Toast.LENGTH_SHORT).show();
        }
    }
}

        本地广播无法通过静态注册的方式来接受。

四、广播相关设置与使用

        广播是一种跨进程的通信方式,因此一个应用程序中发出的广播在其他应用程序中通过action包名识别也可以接受。

1)发送自定义广播

1、新建MyBroadcastReceiver类,定义一个广播接收器。

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

2、在AndroidManifest.xml中修改接受自定义广播action,这里为静态注册广播接收器。

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

3、修改activity_main,定义一个Button作为广播的触发点。

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
  >
    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Send Broadcast"/>
</LinearLayout>

4、修改MainActivity,建立并发送自定义广播。

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent();
                intent.setAction("com.launcher.broadcasttest.MY_BROADCAST");
//发送自定义广播,所有监听com.launcher.broadcasttest.MY_BROADCAST广播的广播接收器都会收到消息。
                sendBroadcast(intent);
            }
        });
    }
}

2)发送有序广播

       Intent intent = new Intent("com.launcher.broadcasttest.MY_BROADCAST");
       sendOrderBroadcast(intent,null);

第一个参数为Intent。

第二个参数为一个与权限相关的字符串,一般为null。

3)设置广播优先级

<intent-filter android:priority=”100”>
       <action android:name="com.launcher.broadcasttest.MY_BROADCAST"/>
</intent-filter>

4)将广播截断

abortBroadcast();

        将广播截断后,后面的广播接收器将无法再收到这条广播。

猜你喜欢

转载自blog.csdn.net/LBW9368/article/details/84134158