Android广播

一:什么是广播?

中学时代,学校有什么重要通知,一般就会通过广播告知全校师生。

为了便于进行系统级别的消息通知,Android也引入了一套类似于广播的消息机制

结尾有几个注意问题

广播大致分为两类:

1.标准广播:

这是一种完全异步的广播,在广播发出之后,所有的广播接收器,几乎会在同一时间接收到这条消息,因此它们之间没有一种先后顺序。

异步:指的是程序运行时,某个操作可以不阻塞主程序执行的情况下进行。异步操作中,程序可以继续执行其他任务,而无需等待。异步是一种编程方式。

 

2.有序广播:

这是一种同步执行的广播,在广播发出之后,同一时刻,只会有一个广播接收器能够接收到这条广播消息,当这个广播接收器中的而逻辑执行完毕之后,广播才会继续传递,并且前面的广播还可以截断正在传递的广播,这样后面的广播无法接收到广播的信息了。

同步:指的是程序运行时,执行完某个操作后,才能执行另一个操作,严格按照执行顺序执行。同步操作是可以预测的。

二:为什么需要广播?

安卓(Android)系统中引入广播(Broadcast)机制的主要目的是为了实现应用程序间的通信、事件传递和事件通知,以及在应用程序内部实现模块之间的松散耦合。以下是安卓需要广播的一些主要原因:

  1. 应用程序通信: 在安卓系统中,不同的应用程序可能需要相互通信,共享信息或进行协作。广播机制允许应用程序发送广播消息,其他应用程序可以注册接收者并在事件发生时做出响应。这种通信方式可以帮助应用程序之间实现协同工作和信息交换。

  2. 系统事件通知: 安卓系统本身会产生一系列事件,如设备启动、网络状态变化、屏幕解锁、电量变化等。这些事件可能对多个应用程序具有影响。通过广播机制,系统可以在事件发生时发送广播消息,使得应用程序能够监听并做出相应的操作。

  3. 松散耦合: 广播机制实现了发送者和接收者之间的松散耦合。发送者无需知道接收者的详细信息,反之亦然。这使得应用程序能够独立开发,而不需要紧密耦合在一起。这在大型应用程序和模块化开发中尤其有用。

  4. 事件传递: 应用程序内部的不同模块可能需要进行事件传递,而不直接依赖于函数调用或变量共享。广播机制提供了一种异步事件传递的方式,允许一个模块发送事件,而其他模块可以注册接收者并对事件进行响应。

  5. 系统扩展: 安卓系统的各个部分可能会在不同的时间点进行更新和扩展。通过使用广播,新的功能可以通过发送广播消息来通知其他模块,而不需要直接修改现有代码。

三:广播的如何使用?

关于广播的使用我么们分为两大部分:

1.接收广播:

接收系统广播,使用意图过滤器,写明接收哪一个系统应用的通知:

无论是接收系统广播还是接收自己发送的自定义广播,我们都需要注册一个广播接收器

如何注册广播接收器?

>动态注册:

使用java代码注册:

此处的例子是使用了一个检测网络状态的广播接收器

package com.example.activitytest;

import androidx.appcompat.app.AppCompatActivity;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity2 extends AppCompatActivity {

    private NetworkChangeReceive networkChangeReceive;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity2);
        //创建意图过滤器
        IntentFilter intentFilter = new IntentFilter();
        //此处是接收网络变化信息
        intentFilter.addAction("android.net.com.CONNECTIVITY_CHANGE");
        //上一行代码就相当于,在Manifest文件里面的
/*
<intent-filter>
    <action android:...
<intent-filter>
*/
        networkChangeReceive = new NetworkChangeReceive();
        registerReceiver(networkChangeReceive, intentFilter);
    }

    class NetworkChangeReceive extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            //只要网络状态发生变化,就会执行onReceive方法
            Toast.makeText(MainActivity2.this, "network changed", Toast.LENGTH_SHORT).show();
        }
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        //记得关闭广播,不然,只要进程在运行就会,一直通知
        unregisterReceiver(networkChangeReceive);
    }
}

①创建意图过滤器。

②创建一个类继承BroadcastReceiver类,实现onReceive方法。创建该类的实例

③注册一个Receiver,需要两个参数:第一个:继承BroadcastReceiver类的实例,第二个意图过滤器。

注意:

        其中意图过滤器中addAction方法是选择想要接收的信息,意思就是说,你想要接收什么信息,就在这里写,就可以了

为什么要使用意图过滤器:

因为安卓系统在运行过程中会一直产生各种事件和消息,例如设备启动,网络变化,电量变化,屏幕解锁等,这些事情可能对应用程序产生影响,因此安卓系统通过广播机制发送这些消息。

 对于这个例子:如果想要告诉用户,网络到底是连接了还是没有连接,可以使用以下方法:

通过getSystemService();得到一个系统服务类ConnectivityManager的实例,通过这个实例的静态方法getActiveNetworkInfo();如果networkInfo不为空则,可以给一条Toast说明网络并没有问题

将onReceive方法修改之后:

 //只要网络状态发生变化,就会执行onReceive方法
ConnectivityManager systemService = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = systemService.getActiveNetworkInfo();
if (networkInfo != null) {
    Toast.makeText(context, "network available", Toast.LENGTH_SHORT).show();
} else {
                Toast.makeText(context, "network unavailable", Toast.LENGTH_SHORT).show();
}

>静态注册:

因为广播是安卓四大组件之一,所以可以在Manifeast.xml文件里面直接注册,也就是在代码执行之前就完成了注册

既然已经有了动态注册为什么需要静态注册呢?

因为在系统开机的时候,也需要广播使整个手机知道手机已经开机,开始工作,所有必须有一个当程序还没有运行的时候给程序消息提醒,让其开始运行。

 ①直接创建一个广播

 ②在Manifest文件里面做一些修改,说明广播接收器,接收的是什么信息。

 此处是开机广播,将手机开机,此程序就会收到开机广播,当然,如果你想要进行一些操作,就可以在创建的接收器里面的onReceive方法里面进行操作。

2.发送广播:

使用意图发送自定义的广播消息:

前面我们说了,广播分为两种,分别是标准广播和有序广播,所有这里也分两类:

>标准广播:

这里我们定义一个按钮作为广播的发送键,并使用静态注册的方法:

在xml中:

<receiver
       android:name=".MyReceiver"
       android:enabled="true"
       android:exported="true">
       <intent-filter>
           action android:name="com.example.activitytest.MyReceiver"/>
       </intent-filter>
</receiver>

 在 广播接收器中:

package com.example.activitytest;

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) {
        Toast.makeText(context, "things gonna be all right", Toast.LENGTH_SHORT).show();
    }
}

 在活动中:

package com.example.activitytest;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button btn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);
        btn = findViewById(R.id.button_1);
        btn.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        //使用意图发送广播
        Intent intent = new Intent("com.example.activitytest.MyReceiver");
        sendBroadcast(intent);
    }
}

 >有序广播

发送有序广播其实很简单,只需要简单改动活动中的代码;

package com.example.activitytest;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button btn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);
        btn = findViewById(R.id.button_1);
        btn.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        //使用意图发送广播
        Intent intent = new Intent("com.example.activitytest.MyReceiver");
        //修改过后
        sendOrderedBroadcast(intent,null);
    }
}

 只需要将此行修改为有序即可

如何截断有序广播?

只需要在onReceive方法后面加上一句

abortBroadcast()即可

 如何设置广播的优先级?

在xml文件中修改为

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

补充:3.使用本地广播:

注意此处有一个类叫做LocalBroadcastManager类,不过已经被弃用了,只需要将xml

文件中的exported属性修改为false即可

对自定义广播的理解:

我们通过某个行为的发生,发送广播,在意图的构造器中写上一个包名,当作自己按钮的上的标签,如果有监听此包名的广播接收器,就会收到消息,具体是什么消息,由于使用意图,所以消息数据等由你决定,如果没有,那么就是默认,也就是啥都没有,接收器只感觉自己被戳了一下,就开始执行onReceive方法了。

如何传输数据?

使用bundle,添加到intent中,然后send出去

关于文中“标签的具体含义”:

在Android中发送广播时,通过Intent对象指定的"action"字符串(通常是包含包名的字符串)并不代表实际的应用包名,而是一个广播的标识符或动作名。这样的字符串命名常用于区分和标识广播的类型或动作。

使用包名前缀的好处是,它确保广播动作是全局唯一的,避免与其他应用或系统广播冲突。考虑到Android平台上有成千上万的应用,使用包名前缀是一种确保唯一性的普遍做法。

举个例子,如果你的应用的包名是com.example.myapp,你可能为某个自定义广播定义一个动作字符串,如com.example.myapp.CUSTOM_ACTION。这里的com.example.myapp.CUSTOM_ACTION只是一个字符串,用于标识你的广播动作,它不表示应用的包名或其他内容。

当其他组件或应用想要接收这个广播时,它们需要使用相同的字符串(com.example.myapp.CUSTOM_ACTION)来注册广播接收器。

总的来说,广播中的这种字符串(通常建议使用包名前缀)主要用于确保广播动作的唯一性,避免混淆和冲突。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值