android——broadcastreceiver广播机制(自定义广播)(代码片段)

叫我金城武也行 叫我金城武也行     2023-02-21     577

关键词:

普通广播可见: Android——广播

1. 概述

Android广播分为两个方面:广播发送者和广播接收者,通常情况下,BroadcastReceiver指的就是广播接收者(广播接收器)。
广播作为Android组件间的通信方式,可以使用的场景如下:

  • 1.同一app内部的同一组件内的消息通信(单个或多个线程之间);
  • 2.同一app内部的不同组件之间的消息通信(单个进程);
  • 3.同一app具有多个进程的不同组件之间的消息通信;
  • 4.不同app之间的组件之间消息通信;
  • 5.Android系统在特定情况下与App之间的消息通信。

从实现原理看上,Android中的广播使用了观察者模式,基于消息的发布/订阅事件模型。
从实现的角度来看,Android中的广播将广播的发送者和接受者极大程度上解耦,使得系统能够方便集成,更易扩展。

适用场景:

  • 第一种情形:同一app内部的同一组件内的消息通信(单个或多个线程之间),实际应用中肯定是不会用到广播机制的(虽然可以用),无论是使用扩展变量作用域、基于接口的回调还是Handler-post/Handler-Message等方式,都可以直接处理此类问题;
  • 第二种情形:同一app内部的不同组件之间的消息通信(单个进程),对于此类需求,在有些教复杂的情况下单纯的依靠基于接口的回调等方式不好处理,此时可以直接使用EventBus等,相对而言,EventBus由于是针对统一进程,用于处理此类需求非常适合,且轻松解耦。
  • 第三、四、五情形:由于涉及不同进程间的消息通信,此时根据实际业务使用广播机制会显得非常适宜。

实现流程:

  • 1.广播接收者BroadcastReceiver通过Binder机制向AMS(Activity Manager Service)进行注册;
  • 2.广播发送者通过binder机制向AMS发送广播;
  • 3.AMS查找符合相应条件(IntentFilter/Permission等)的BroadcastReceiver,将广播发送到BroadcastReceiver(一般情况下是Activity)相应的消息循环队列中;
  • 4.消息循环执行拿到此广播,回调BroadcastReceiver中的onReceive()方法。

由此看来,广播发送者和广播接收者分别属于观察者模式中的消息发布和订阅两端,AMS属于中间的处理中心。
广播发送者和广播接收者的执行是异步的,发出去的广播不会关心有无接收者接收,也不确定接收者到底是何时才能接收到。

2. BroadcastReceiver (自定义广播)

自定义广播接收器需要继承基类BroadcastReceivre,并实现抽象方法onReceive(context, intent)方法。广播接收器接收到相应广播后,会自动回到onReceive(…)方法。

默认情况下,广播接收器也是运行在UI线程,因此,onReceive方法中不能执行太耗时的操作。否则将因此ANR。

一般情况下,根据实际业务需求,onReceive方法中都会涉及到与其他组件之间的交互,如发送Notification、启动service等。

1. 静态注册

直接在AndroidManifest.xml文件中进行注册,规则如下:

<receiver android:enabled=["true" | "false"]
android:exported=["true" | "false"]
android:icon="drawable resource"
android:label="string resource"
android:name="string"
android:permission="string"
android:process="string" >
. . .
</receiver> 

需要注意的属性

  • android:exported ——此broadcastReceiver能否接收其他App的发出的广播,这个属性默认值有点意思,其默认值是由receiver中有无intent-filter决定的,如果有intent-filter,默认值为true,否则为false。
    同样的,activity/service中的此属性默认值一样遵循此规则)同时,需要注意的是,这个值的设定是以application或者application user id为界的,而非进程为界(一个应用中可能含有多个进程);
  • android:name —— 此broadcastReceiver类名;
  • android:permission ——如果设置,具有相应权限的广播发送方发送的广播才能被此broadcastReceiver所接收;
  • android:process ——broadcastReceiver运行所处的进程。默认为app的进程。可以指定独立的进程(Android四大基本组件都可以通过此属性指定自己的独立进程)

常见的注册形式有:

<receiver android:name=".MyBroadcastReceiver" >
  <intent-filter>
    <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
  </intent-filter>
  <intent-filter>
    <action android:name="android.intent.action.BOOT_COMPLETED" />
  </intent-filter>
</receiver> 

其中,intent-filter由于指定此广播接收器将用于接收特定的广播类型。本示例中给出的是用于接收网络状态改变或开启启动时系统自身所发出的广播。当此App首次启动时,系统会自动实例化MyBroadcastReceiver,并注册到系统中。

一个简单的静态注册广播:

  • (1)新建一个广播接收器用于来接收自定义的广播:
public class MyReceiver extends BroadcastReceiver 
    public MyReceiver() 
    

    @Override
    public void onReceive(Context context, Intent intent) 
        Toast.makeText(context,"接收到自定义的广播",Toast.LENGTH_SHORT).show();
    

  • (2)修改 AndroidManifest.xml 文件,注册要监听的自定义广播
<receiver
    android:name=".MyReceiver"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
        <action android:name="net.deniro.android.MY_BROADCAST"/>
    </intent-filter>

</receiver>
  • (3)在主布局文件中,添加一个按钮作为发送广播的触发点:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="net.deniro.android.mybroadcastreceiver.MainActivity">

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="发送广播"></Button>
</RelativeLayout>

  • (4)最后修改主活动的代码
//这里通过 sendBroadcast() 方法来发送广播,这样所有监听这个广播的接收器就会收到消息。
public class MainActivity extends AppCompatActivity 

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

        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                sendBroadcast(new Intent("net.deniro.android.MY_BROADCAST"));
            
        );
    

2. 动态注册:

动态注册时,无须在AndroidManifest中注册组件。直接在代码中通过调用Context的registerReceiver函数,可以在程序中动态注册BroadcastReceiver。registerReceiver的定义形式如下:

registerReceiver(BroadcastReceiver receiver, IntentFilter filter)

registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler)

典型的写法示例如下:

public class MainActivity extends Activity 
  public static final String BROADCAST_ACTION = "com.example.corn";
  private BroadcastReceiver mBroadcastReceiver;

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

    mBroadcastReceiver = new MyBroadcastReceiver();
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(BROADCAST_ACTION);
    registerReceiver(mBroadcastReceiver, intentFilter);
  
  
  @Override
  protected void onDestroy() 
    super.onDestroy();
    unregisterReceiver(mBroadcastReceiver);
  

注:Android中所有与观察者模式有关的设计中,一旦涉及到register,必定在相应的时机需要unregister。因此,上例在onDestroy()回到中需要unregisterReceiver(mBroadcastReceiver)。

当此Activity实例化时,会动态将MyBroadcastReceiver注册到系统中。当此Activity销毁时,动态注册的MyBroadcastReceiver将不再接收到相应的广播。

3. 不同注册方式的广播接收器回调onReceive(context, intent)中的context具体类型

  • 1).对于静态注册的ContextReceiver,回调onReceive(context, intent)中的context具体指的是ReceiverRestrictedContext;
  • 2).对于全局广播的动态注册的ContextReceiver,回调onReceive(context, intent)中的context具体指的是Activity Context;
  • 3).对于通过LocalBroadcastManager动态注册的ContextReceiver,回调onReceive(context, intent)中的context具体指的是Application Context。

注:对于LocalBroadcastManager方式发送的应用内广播,只能通过LocalBroadcastManager动态注册的ContextReceiver才有可能接收到(静态注册或其他方式动态注册的ContextReceiver是接收不到的)。

Android 广播 - 使用权限发送和接收

...【发布时间】:2017-12-2212:07:43【问题描述】:我尝试实现BroadcastReceiver的权限方式。在sender类中,我尝试发送普通广播Intentintent=newIntent();intent.setAction("com.vn.BroadcastRec 查看详情

android游戏开发大全的目录

...本组件 393.1.1 activity组件 393.1.2 service组件 413.1.3 broadcastrec 查看详情

android面试题解析美团/抖音/batandroid四大组件是什么

(1)Activity(2)service(3)BroadcastReceive(4)ContentProvider网上学习Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技... 查看详情

android获取当前电量信息(broadcastreceiver的使用)

...面主要介绍一下动态注册广播获取当前电量信息,从BroadcastReceive中获取电量信息,并传递给activity,显示在textview中xml文件中只有一个textview<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools&#... 查看详情

android获取当前电量信息(broadcastreceiver的使用)

...面主要介绍一下动态注册广播获取当前电量信息,从BroadcastReceive中获取电量信息,并传递给activity,显示在textview中xml文件中只有一个textview<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools&#... 查看详情

android四大组件详解

...容提供器)介绍作用系统的ContentProvider自定义ContentProviderBroadcastReceiver广播概述广播的作用广播接收者的创建广播接收者的类型注册广播的两种方式静态注册和动态注册的区别有序广播和无序广播的区别有序广播接收者们的优先级... 查看详情

个推技术分享:android12更新详解及适配指南(代码片段)

...;Activity)、服务(Service)、广播接收器(BroadcastReceive)和内容提供器(Conte 查看详情

broadcastreceiver

BroadcastReceiver的概念  BroadcastReceiver的作用主要是用来监听系统或者应用发出的广播信息,然后根据广播信息作为相应的逻辑处理;说通俗点其实上就是一种全局监听器,要来实现系统中不同组件之间的通信。有时候也会用来... 查看详情

app和sdk开发必看|个推分享android12适配指南(代码片段)

...;Activity)、服务(Service)、广播接收器(BroadcastReceive)和内容提供器(ContentProvider)。A 查看详情

ACTION_CAMERA_BUTTON 的广播接收器永远不会被调用

...N_CAMERA_BUTTON的广播接收器永远不会被调用【英文标题】:broadcastreceiverforACTION_CAMERA_BUTTONnevergetscalled【发布时间】:2011-08-2413:39:52【问题描述】:我在android中有一个应用程序,我想在按下相机的物理硬件按钮时拍照。我为这种类... 查看详情

使用 MethodChanneel 检测 Flutter 上的电话

...始我试图实现它只是为了展示一个烤面包机classCallReceiver:BroadcastRec 查看详情

使用 ClusterManager 时如何更新 Map 上的标记

...rManager)map(-在我看来,我只能在ClusterManager中添加。我有BroadcastRec 查看详情

android版本api对应表

Android版本ApiAndroid13.0(T)32Android12.0(S)31Android11.0(R)30Android10.0(Q)29Android9.0(Pie)28Android8.1(Oreo)27Android8.0(Oreo)26Android7.1(Nougat)25Android7.0(Nougat)24Android6.0(Marshmallow)23Android5.1(Lollipop)22Android5.0(Lollipop)21Android4.4W(KitKatWear)20Android4.4(KitKat)19Android4.3(Je... 查看详情

android逆向android权限(android逆向中使用的android.permission权限|android系统中的linux用户权限)

文章目录一、Android逆向中使用的android.permission权限二、Android系统中的Linux用户权限一、Android逆向中使用的android.permission权限Android逆向中使用的权限:android.permission.SET_DEBUG_APP:调试程序,应用有该权限后,可以指定调试相关的程序;an... 查看详情

android逆向android权限(android逆向中使用的android.permission权限|android系统中的linux用户权限)

文章目录一、Android逆向中使用的android.permission权限二、Android系统中的Linux用户权限一、Android逆向中使用的android.permission权限Android逆向中使用的权限:android.permission.SET_DEBUG_APP:调试程序,应用有该权限后,可以指定调试相关的程序;an... 查看详情

android工程师的概述

参考技术A主要包括:Android应用软件开发工程师、Android游戏程序员、Android网络游戏程序员、Android软件移植工程师、Android嵌入式设备软件开发工程师、Android游戏开发工程师、Android网络游戏开发工程师等。1、熟悉java开发,有丰... 查看详情

android面试题android高级/资深面试题

Android面试题(一)Java基础Android面试题(二)Android基础Android面试题(三)Java虚拟机Android面试题(四)设计模式Android面试题(五)数据结构/算法Android面试题(六)网络基础Activity/Fragment的生命周期(参考 查看详情

android:backgroundTint 不工作 - Android

】android:backgroundTint不工作-Android【英文标题】:android:backgroundTintisn\'tworking-Android【发布时间】:2021-12-0705:59:09【问题描述】:有人可以帮我弄清楚为什么按钮的backgroundTint不起作用吗?我使用android:background作为背景颜色,使用and... 查看详情