android广播


广播简述

广播作为四大组件之一,它的作用不可或缺。既然称之为广播,那么肯定有发送者sender和接收者receiver。

广播分类

普通广播

该广播会不care receiver的优先级,该广播的所有接收者都能接收到该广播。任何接收者都不可终止该广播。

发送方法

context.sendBroadcasr(intent);
复制代码

有序广播

见名知意,该广播首先会发送给优先级较高的receiver,然后再由优先级较高的receiver发送给优先级较低的receiver,在这个过程中,有序广播可以随时被优先级价高的receiver中断,中断之后该广播就停止向下传递。

发送方式

context.sendOrderedBroadcast(intent, receiverPermission);
复制代码

可以看到,发送有序广播时多了一个字段receiverPermission,该字段指出receiver要接受有序广播所需的权限。也就是说如果发送有序广播时指定了该字段,那么receiver必须拥有这个权限才可以接收到该广播。如果该字段为null,则不做权限校验。举例如下:

Intent intent  = new Intent("cn.codemperor.sample.ordered");
activity.sendOrderedBroadcast(intent, "cn.codemperor.sample.orderedbroadcast_permission");
复制代码

然后我们在注册广播时需要指定"cn.codemperor.sample.orderedbroadcast_permission"权限,否则我们将无法收到消息。

<receiver android:name="cn.codemperor.sample.OrderedBroadcastPermissionTest"
    android:enabled="true"
    android:exported="false"
    android:permission="cn.codemperor.sample.orderedbroadcast_permission">
    <intent-filter android:priority="1000">
            <action android:name="cn.codemperor.sample.ordered" />
    </intent-filter>
</receiver>
复制代码

可以看到我们在intent-filter中指定了android:priority为1000,正如我们前面提到的优先级(android中指定priority的范围为-1000~1000,数字越大优先级越高)越高的receiver越先接收到有序广播,而且可以中断该广播向下传递,也可以在向下传递时添加一些额外信息给优先级较低的receiver。

中断广播

只需要在优先级较高的BroadcastReceiver中的onReceive(Context context, Intent intent)中调用abortBroadcast()就可以中断广播向下传递。

 @Override
public void onReceive(Context context, Intent intent) {
    ...
    abortBroadcast();
}
复制代码

粘性广播(StickBroadcastReceiver?)

该广播在发送之后不会消失,换句话说,如果发送该广播时,某个接收者处于dead状态,那么当该接收者起送之后仍然可以接收到该广播。

只要粘性广播的发送者还存在,粘性广播就持续存在,也就是说只要粘性广播发送者还存在,任何该广播的接收者在注册之后都会受到该广播

使用粘性广播需要添加下面的权限:

<uses-permission android:name="android.permission.BROADCAST_STICKY"/>
复制代码

粘性广播的用法主要有

/**
 * 发送粘性广播
 **/
Intent intent = new Intent("cn.codemperor.sample.stickybroadcast");
context.sendStickyBroadcast(intent);

/**
 * 发送有序粘性广播
 **/ 
context.sendOrderedStickyBroadcast(intent);
复制代码

广播接收者的注册方式

静态注册

静态注册仅需要在androidManifest注册就可以,在此不再展示

动态注册

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

MyReceiver receiver = new MyReceiver();
receiver.setAction("cn.codemperor.sample.register_broadcastreceiver");
receiver.putExtra("msg", "一些额外信息");
context.sendBroadcast(intent);
复制代码

动态注册的广播接收者依赖于启动它的组件,那么当该组件销毁时,需要将动态注册的广播解除注册。解除注册的方式十分简单:

context.unregisterReceiver(receiver);
复制代码

注意 如果receiver优先级相同,那么动态注册的receiver先收到广播;如果优先级不同,则为随机。

注意 在onReceive(...)中执行操作的事件不可超过10秒,否则ANR。

接收系统广播

1、 开机启动广播 使用开机启动广播需要添加权限:

<uses-permission android:name="android:permission.RECEIVE_BOOT_COMPLETED" />
复制代码

然后在相应的receiver的intent中添加以下action

<intent-filter>
    <action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
复制代码

这样你就可以在receiver中接收到开机广播了~_~

2、 网络状态变化 监听网络状态变化的广播需要添加权限:

<uses-permission android:name="android:permission.ACCESS_NETWORK_STATE" />
复制代码

然后在相应的receiver的intent中添加以下action

<intent-filter>
    <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
复制代码

这样我们就可以在相应的receiver中接收到该广播了,然后就可以在onReceive中查看当前的网络状态并给予用户提示。

ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo ni = cm.getActiveNetworkInfo();
if (ni != null) {
    String currentNi = ni.getTypeName() + "";
    Log.i(TAG, currentNi);
} else {
    Log.i(TAG, "当前无网络");
}
复制代码

3、 电量变化广播 电量变化广播一般情况下会一分钟左右发送一次。 使用开机启动广播在相应的receiver的intent中添加以下action

<intent-filter>
    <action android:name="android.intent.action.BATTERY_CHANGED" />
</intent-filter>
复制代码

这样你就可以在receiver中通知用户电量变化了~_~

int currentBatteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);//当前电量
int totalLevel = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 1);//总电量
double percent = currentBatteryLevel * 100.0 / totalLevel;
复制代码

当然还有一种立即获取电量的办法哟!!

Intent intent = getApplicationContext().registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));

int currentBatteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);//当前电量
int totalLevel = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 1);//总电量
double percent = currentBatteryLevel * 100.0 / totalLevel;

复制代码

本地广播

前面我们发送和接收的广播都属于系统全局广播,即发送的广播可以被其他任何应用程序收到,并且我们可以接受来自其他应用程序的广播。这样便很容易引起安全线问题,比如其他应用程序可以不断的向我们发送垃圾广播,导致应用程序效率低下。

为了解决这个问题,android引入了本地广播的概念。发出的本地广播只可以在本应用程序内部传播,广播接收者也只可以接受本应用程序内部的广播。具体用法如下:

//定义本地广播接收者
public class LocalBroadcastReceiver extends BroadcastReceiver {

    public static final String TAG = "MyReceiver";

    public LocalBroadcastReceiver() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i(TAG, "onReceive: " + intent.hashCode());
    }
}
复制代码
public class MainActivity extends AppCompatActivity {

    private LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
    private LocalBroadcastReceiver receiver = new LocalBroadcastReceiver();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sticky);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    }

    /**
     * 注册本地广播
     */
    @Override
    protected void onResume() {
        super.onResume();
        IntentFilter filter = new IntentFilter("cn.codemperor.sample.local_broadcast");
        lbm.registerReceiver(receiver, filter);
    }

    /**
     * 发送本地广播
     * @param view
     */
    public void sendStickyBroadcast(View view ){
        Intent intent = new Intent("cn.codemperor.summary.sticky");
       // sendStickyBroadcast(intent);

        sendOrderedBroadcast(intent, null);
    }

    /**
     * 移除本地广播注册
     */
    @Override
    protected void onPause() {
        super.onPause();
        lbm.unregisterReceiver(receiver);
    }
}
复制代码

**注:**本地广播只可以使用代码注册

转载于:https://juejin.im/post/5a3d2afff265da4328410e3b

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值