Android组件之BroadcastReceiver

广播BroadcastReceiver

1.分类

标准广播:异步,所有广播接收器同时接收到,效率高但不可截断

有序广播:同步,同一时刻只有一个接收器接收到,优先级高的先收到,可截断

2.注册方式

在代码中注册(动态注册),灵活性好,但只能程序启动之后才能进行

在AndroidManifest.xml中注册(静态注册)

动态注册监听网络

新建一个类,继承BroadcastReceiver,重写onReceive方法。通过getSystemService()方法获取ConnectivityManager的一个实例,这是一个系统服务器类,专门管理网络连接的,然后调用他的 getActiveNetworkInfo()方法获取 NetworkInfo 的实例,接着调用 NetworkInfo 的isAvailable()方法判断是否联网

package com.example.tingyu.broadcasttest;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

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");
        //android.net.conn.CONNECTIVITY_CHANGE专门用来判断网络变化,想监听什么广播,添加对应的action
        networkChangeReceiver=new NetworkChangeReceiver();
        registerReceiver(networkChangeReceiver,intentFilter);
    }

    @Override
    //动态注册的广播接收器一定要取消注册
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(networkChangeReceiver);
    }
     class NetworkChangeReceiver extends BroadcastReceiver{
        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();
            }
        }
    }
}

在网络发生改变的时候toast提醒用户

静态注册开机启动

程序未启动情况下就能接收到广播

首先在MainActivity目录下新建一个类new->other->Broadcast Receiver,勾选Export和Enable按钮,在接下来的注册文件中也会自动生成这两项

https://i.loli.net/2018/08/10/5b6cfeb7d345e.png
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.tingyu.broadcasttest">

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
//监视系统开机广播的权限
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver
            android:name=".MyReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
    </application>

</manifest>
package com.example.tingyu.broadcasttest;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO: This method is called when the BroadcastReceiver is receiving
        // an Intent broadcast.
        Toast.makeText(context, "Boot Complete", Toast.LENGTH_LONG).show();
        //throw new UnsupportedOperationException("Not yet implemented");
    }
}

注册文件有了receiver和activity用法差不多,intent-filter里添加想要的广播即可。然后重启模拟器,就可以开机时看到广播了

3.发送自定义广播

发送系统全局广播

发送标准广播

(1)首先需要定义一个广播接收器接收广播,其实在之前静态注册的时候我们定义的那个类就是广播接收器。同样的,我们注册一个MyBroadcastReceiver继承自BroadcastReceiver

(2)然后再在AndroidMabifest.xml中进行注册。

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

这里接受一个值为com.example.broadcasttest.MY_BROADCAST得 广播,接下来我们将传送一个这样的广播

(3)修改布局文件activity_main.xml,定义一个按钮,作为广播触发点

(4)再修改MainActivity中代码

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

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.broadcastbutton);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent=new Intent("com.example.broadcasttest.MY_BROADCAST");
                sendBroadcast(intent);
            }
        });
    }
}

构造一个Intent对象,在其中传入一条广播,再调用Context的sendBroadcast方法将广播发出去

最终效果如下:

[![1533886284743.png](https://i.loli.net/2018/08/10/5b6d40f759cd7.png)](https://i.loli.net/2018/08/10/5b6d40f759cd7.png)

发送有序广播

(1)新建一个名为BroadcastTest2的项目new->new project

(2)新建广播接收器类,使得它接收到的广播与BroadcastTest保持一致,也就是注册类里AndroidManifest.xml中这里保持一致

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

(3)sendBroadcast(intent);是发送标准广播,sendOrderedBroadcast(intent,null);是发送有序广播,差别不大,第二个null参数是一个与权限有关的字符串。在MainActivity中修改

package com.example.tingyu.broadcasttest;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

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.broadcastbutton);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent=new Intent("com.example.broadcasttest.MY_BROADCAST");
                sendOrderedBroadcast(intent,null);
                //差别在这里
            }
        });
    }
}

也可以拦截广播,在广播接收器类中进行修改

package com.example.tingyu.broadcasttest;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class MyBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO: This method is called when the BroadcastReceiver is receiving
        // an Intent broadcast.
        //throw new UnsupportedOperationException("Not yet implemented");
        Toast.makeText(context, "receive in MyBroadcastReceiver", Toast.LENGTH_LONG).show();
        abortBroadcast();//将广播拦截,不再继续传递

    }
}

(4)在注册地方修改如下,这样就有了优先级

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

最后点击按钮后只弹出MyBroadcastReceiver收到消息,第二个接收器没有弹出,有序广播带拦截功能发送成功

发送局部广播

系统全局广播安全性不高,数据乱传,局部广播只针对一个应用内部传播数据

实现思想就是用一个LocalBroadcastManager对广播进行管理,并提供发送广播和注册广播接收器的方法

package com.example.tingyu.broadcasttest;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

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.broadcastbutton);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent("com.example.broadcasttest.LOCAL_BROADCAST");
                localBroadcastManager.sendBroadcast(intent);
            }
        });
        intentFilter = new IntentFilter();
        intentFilter.addAction("com.example.broadcasttest.LOCAL_BROADCAST");
        localReceiver = new LocalReceiver();
        localBroadcastManager.registerReceiver(localReceiver, intentFilter);
    }
        //注册本地广播监听器
        protected void onDestroy()
        {
            super.onDestroy();
            localBroadcastManager.unregisterReceiver(localReceiver);
        }
        class LocalReceiver extends BroadcastReceiver{
            public void onReceive(Context context,Intent intent){
                Toast.makeText(context,"receved local broadcast",Toast.LENGTH_SHORT).show();
            }
        }
    }

与动态注册代码相同,只是通过LocalBroadcastManager的getInstance()方法来获取实例,注册的时候使用它的registerReceiver方法,发送广播时调用sendBroadcast方法

参考书籍:郭霖《第一行代码》

猜你喜欢

转载自blog.csdn.net/ytingyu/article/details/81572021