Android四大组件之BroadcastReceiver

BroadcastReceiver简介

BroadcastReceiver也就是”广播接收者”的意思, 顾名思义, 它就是用来接收来自系统和应用中的广播.
 在Android系统中, 广播体现在方方面面, 例如当开机完成后系统会产生一条广播,接收到这条广播就能实现开机启动服务的 功能;当网络状态改变时系统会产生一条广播,接收到这条广播就能及时地做出提示和保存数据等橾作;当电池电量改变时,系统会产生一条广播,接收到这条广播就能在电量低时告知用户及时保存进度,等等。
 Android中的广播机制设计的非常出色,很多事情原本需要开发者亲自操作的,现在只需等待广播告知自己就可以了,大大减少了开发的工作量和开发周期。而作为应用开发者,就需要数练掌握Android系统提供的一个开发利器,那就是 BroadcastReceiver

广播接收器的类型

1,Normal broadcasts:默认广播
发送一个默认广播使用Context.sendBroadcast()方法,普通广播对于多个接收者来说是完全异步的,通常每个接收者都无需 等待即可以接收到广播,接收者相互之间不会有影响。对于这种广播,接收者无法终止广播,即无法阻止其他接收者的接收动作。

2, Ordered broadcasts:有序广播
发送一个有序广播使Context.sendOrderedBroadcast()方法,有序广播比较特殊,它每次只发送到优先级较高的接收者那 里,然后由优先级高的接受者再传播到优先级低的接收者那里,优先级高的接收者有能力终止这个广播。

3, Sticky Broadcast:粘牲广播
当处理完之后的Intent,依然存在,直到你把它去掉。

广播接收器的两种注册方法

静态注册

静态注册是在AndroidManifest.xml文件中配置。

创建一个广播接收器
MyReceiver1.java

 * 自定义的广播接收器
 */
public class MyReceiver1 extends BroadcastReceiver {
    public MyReceiver1() {
    }
    //接收的方法
    @Override
    public void onReceive(Context context, Intent intent) {
        String info = intent.getStringExtra("info");
        Toast.makeText(context, info, Toast.LENGTH_SHORT).show();

    }
}

清单文件

  <!--表示该receiver有效, 并且可以在外部访问-->
        <receiver
            android:name=".MyReceiver1"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.lulu.action.MY_BROADCAST"/>

            </intent-filter>

        </receiver>

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    //发送一个普通的广播
    public void sendNormal(View view){
        //发送广播的"动作", 这里的action和接收器过滤器中的action一一对应
        Intent intent = new Intent("com.lulu.action.MY_BROADCAST");
        intent.putExtra("info",  "广播发送示例");
        this.sendBroadcast(intent);
    }

}

xml文件就不给出了, 就是一个button.

下面就是该段代码的演示:
这里写图片描述

动态注册

动态注册需要在代码中动态的指定广播地址并注册,通常我们是在Activity或Service注册一个广播

MyReceiver2.java

public class MyReceiver2 extends BroadcastReceiver {
    public MyReceiver2() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "动态的注册广播接收器", Toast.LENGTH_SHORT).show();
    }
}

MainActivity.java

package com.lulu.lbroadcasereceiver;

import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    private MyReceiver2 receiver2 = new MyReceiver2();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }


    //完成广播注册
    @Override
    protected void onResume() {
        super.onResume();
        IntentFilter filter = new IntentFilter();
        filter.addAction("com.lulu.action.MY_BROADCAST");
        registerReceiver(receiver2, filter);
    }

    //完成解除注册
    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(receiver2);
    }
}

注意:
代码注册中, 收到广播的先后和注明优先级最后的他们的先后 是随机的
如果没有优先级, 代码注册收到的为最先

有序广播

发送有序广播:sendOrderedBroadcast()
  在注册广播中的中使用android:priority属牲。这个属牲的范围在-1000到1000,数值越大,优先级越高。
在广播接收器中使用setResultExtras方法将一个Bundle对象设置为结果集对象,传递到下一个接收者那里,这样优先级低的 接收者可以用getResultExtras获取到最新的经过处理的信息集合。
  使用sendOrderedBroadcast方法发送有序广播时,需要一个权限参数,如果为null表示不要求接收者声明指定的权限,如果不为null,则表示接收者若要接收此广播,需声明指定权限。这样做是从安全角度考虑的,例如系统的短信就是有序 广播的形式,一个应用可能是具有拦截垃圾短信的功能,当短信到来时它可以先接受到短信广播,必要时终止广播传递, 这样的软件就必须声明接收短信的权限。

终止广播传递 abortBroadcast();

示例代码:
广播发送

  //发送一个有序广播
    public void sendOrderClick(View view){
        Intent intent = new Intent("com.lulu.action.MY_BROADCAST2");
        //参数: intent, 接收权限
        this.sendOrderedBroadcast(intent, null);
    }

下面是两个Receiver


public class MyReceiver3 extends BroadcastReceiver {
    public MyReceiver3() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {


        Bundle data = getResultExtras(false);
        String info = data.getString("info");
        Toast.makeText(context, "有序广播-1" + info, Toast.LENGTH_SHORT).show();

    }

}
public class MyReceiver4 extends BroadcastReceiver {
    public MyReceiver4() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "有序广播-2", Toast.LENGTH_SHORT).show();

        Bundle data = new Bundle();
        data.putString("info", "钓鱼岛是中国的");
        this.setResultExtras(data);

        //中断有序广播
//        this.abortBroadcast();
    }
}

清单文件

    <receiver
            android:name=".MyReceiver3"
            android:enabled="true"
            android:exported="true" >
            <intent-filter android:priority="100">
                <action android:name="com.lulu.action.MY_BROADCAST2"/>
            </intent-filter>
        </receiver>
        <receiver
            android:name=".MyReceiver4"
            android:enabled="true"
            android:exported="true">
            <intent-filter android:priority="200">
                <action android:name="com.lulu.action.MY_BROADCAST2"/>
            </intent-filter>
        </receiver>

优先级顺序:
代码注册(有优先级) -> 静态注册(有优先级) -> 代码注册-> 静态注册

粘性广播

发送粘性广播使用:sendStickyBroadcast(intent);
发这个广播需要权限

去掉是用这个方法removeStickyBroadcast(intent);
sendStickyOrderedBroadcast():这个方法具有有序广播的特性也有粘性广播的特性;
在这个方法发来的广播中,代码注册方式中,收到广播先后次序为:注明优先级的、代码注册的、没有优先级的;如果都没 有优先级,代码注册收到为最先。

粘性广播在API23中已经过时

接收系统广播

开机启动

我们经常会有这样的应用场合,比如消息推送服务,需要实现开机启动的功能。要实现这个功能,我们就可以订阅系统“启动 完成”这条广播,接收到这条广播后我们就可以启动自己的服务了。

<intent-filter>
<!-注册开机广播地址-->
<actionandroid:name="android.intent.action.BOOT_COMPLETED"/>
<categoryandroid:name="android.intent.category.DEFAULT"/>
</intent-filter>

这个开机广播地址,从安全角度考虑,系统要求必须声明接收开机启动广播的权限

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

网络检测

比如用户浏览网络信息时,网络突然断开,我们要及时地提醒用户网络已断开。要实现这个功能,我们可以接收网络状态改变这样一条广播,当由连接状态变为断开状态时,系统就会发送一条广播,我们接收到之后,再通过网络的状态做出相 应的操作。

清单文件配置

<receiver
            android:name=".MyReceiver5"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
            </intent-filter>
</receiver>

问网络状态权限:

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

MyReceiver5.java

public class MyReceiver5 extends BroadcastReceiver {
    public MyReceiver5() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info  = cm.getActiveNetworkInfo();
        if(info != null){
            String name = info.getTypeName();
            Toast.makeText(context, name, Toast.LENGTH_SHORT).show();
        }
    }
}

接收电量的变化

如果我们在使用阅读软件,可能是全屏阅读,这个时候用户就看不到剩余的电量,我们就可以为他们提供电量的信息。要想 做到这一点,我们需要接收一条电量变化的广播,然后获取百分比信息。

当系统的电量发生变化时, 该接收器会触发

/**
 * 检测电量变化的广播接收器
 */
public class MyReceiver6 extends BroadcastReceiver {
    public MyReceiver6() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        //当前电量
        int curr = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
        //总电量
        int total = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 1);

        int percent = curr*100/total;
        Toast.makeText(context, "当前电量为" + percent + "%", Toast.LENGTH_SHORT).show();
    }
}

下面的方法会立即获取当前的电量

     Intent batteryIntent = registerReceiver(null, intentFilter);
        //当前电量
        int curr = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
        //总电量
        int total = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, 1);

        int percent = curr*100/total;
        Toast.makeText(this, "当前电量为" + percent + "%", Toast.LENGTH_SHORT).show();

最后提醒 :
When it runs on the main thread you should never perform long-running operations in it (there is a timeout of 10 seconds that the system allows before considering the receiver to be blocked and a candidate to be killed). You cannot launch a popup dialog in your implementation of onReceive().

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值