【安卓开发】安卓广播机制
读书笔记系列(第一行代码)
5.1 广播机制简介
- 标准广播:完全异步执行,广播发出后,所有广播接收器几乎都同一时刻收到这条广播(无法被截断)
- 有序广播:同步执行,广播发出后同一时刻只会有一个广播接收器能收到这条广播消息,前面的接收器可以截断正在传递的广播

5.2 接收系统广播
广播接收器可在代码中注册和AndroidManifest.xml中注册,前者为动态注册,后者被称为静态注册。
5.2.1 动态注册监听网络变化
示例代码:
public class MainActivity extends AppCompatActivity {private IntentFilter intentFilter;private NetworkChangeReceiver networkChangeReceiver;@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView((R.layout.activity_main));intentFilter= new IntentFilter();intentFilter.addAction("android.net.conn.CONNECTIVITY_VHANGE");networkChangeReceiver = new NetworkChangeReceiver();registerReceiver(networkChangeReceiver, intentFilter);}@Overrideprotected void onDestroy(){super.onDestroy();unregisterReceiver(networkChangeReceiver);}class NetworkChangeReceiver extends BroadcastReceiver {@Overridepublic 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.makeText(context, "network changes", Toast.LENGTH_SHORT).show();}}
}
静态注册实现开机启动
<receiverandroid:name=".BootCompleteReceiver"android:enabled="true"android:exported="true"></receiver>
Export属性表示是否允许这个广播接收器接收本程序以外的广播,enable表示是否使用这个广播接收器。
<receiverandroid:name=".BootCompleteReceiver"android:enabled="true"android:exported="true"><intent-filter><action android:name="android.intent.action.BOOT_COMPLETED"/></intent-filter></receiver>
添加了filter就可以过滤了
可以通过左键新建-》其它来新建静态注册广播
广播接收器中不允许开线程,当onReceive方法运行较长时间而没结束时,程序就会报错,所以其中不能添加过多的逻辑或任何耗时操作。
5.3 发送自定义广播
5.3.1 发送标准广播
@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView((R.layout.activity_main));Button button = (Button)findViewById(R.id.button);button.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View v){Intent intent = new Intent("com.example.broadcasttest.MY_BROADCAST");sendBroadcast(intent);}});}
通过点击按钮发送广播
public class myBroadcastReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Toast.makeText(context, "receiverd in myBroadcastReceiver", Toast.LENGTH_SHORT).show();}
}
这里是自定义的接收器
<receiverandroid:name=".myBroadcastReceiver"android:enabled="true"android:exported="true"><intent-filter><action android:name="com.example.broadcasttest.MY_BROADCAST"/></intent-filter></receiver>
在xml中定义过滤的广播类型
5.3.2 发送有序广播
广播是一种跨进程的通信方式
protected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView((R.layout.activity_main));Button button = (Button)findViewById(R.id.button);button.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View v){Intent intent = new Intent("com.example.broadcasttest.MY_BROADCAST");sendOrderedBroadcast(intent, null);}});}
只需要修改一行代码 sendOrederedBroadcast即可发送有序广播,同时在接收器的xml文件中可以设置优先级
<receiverandroid:name=".myBroadcastReceiver"android:enabled="true"android:exported="true">
<!-- 在这里设置优先级--><intent-filter android:priority="100"><action android:name="com.example.broadcasttest.MY_BROADCAST"/></intent-filter></receiver>
如果想要在接收到广播之后就让广播停止继续传递呢,修改onReceive的代码即可
public void onReceive(Context context, Intent intent) {Toast.makeText(context, "receiverd in myBroadcastReceiver", Toast.LENGTH_SHORT).show();
// 停止继续传递abortBroadcast();}
5.4 使用本地广播
前面我们发送和接收的广播全部属于系统全局广播,即发出的广播可以被其他任何应用程序接收到,并且我们也可以接收来自于其他任何应用程序的广播。这样就很容易引起安全性的问题,比如说我们发送的一些携带关键性数据的广播有可能被其他的应用程序截获,或者其他的程序不停地向我们的广播接收器里发送各种垃圾广播。
使用本地广播则发出的广播只能在应用程序内部传递,并且接收器也只能接收来自本应用程序发出的广播。
public class MainActivity extends AppCompatActivity {private IntentFilter intentFilter;private LocalReceiver localReceiver;private LocalBroadcastManager localBroadcastManger;@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView((R.layout.activity_main));localBroadcastManger = LocalBroadcastManager.getInstance(this); //获取实例Button button = (Button) findViewById(R.id.button);button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Intent intent = new Intent("com.example.broadcasttest.LOCAL_BROADCAST");localBroadcastManger.sendBroadcast(intent); //发送本地广播}});intentFilter = new IntentFilter();intentFilter.addAction("com.example.broadcasttest.LOCAL_BROADCAST");localReceiver = new LocalReceiver();localBroadcastManger.registerReceiver(localReceiver, intentFilter); //注册本地广播监听器}@Overrideprotected void onDestroy(){super.onDestroy();localBroadcastManger.unregisterReceiver(localReceiver);}class LocalReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent){Toast.makeText(context, "received local broadcast", Toast.LENGTH_SHORT).show();}}
}
代码的不同主要在于需要首先获取实例,然后还要有注册。
需要注意的是,本地广播无法通过静态注册来接收。
5.5 使用广播实现强制下线功能
强制下线功能首先需要实现下关闭所有的活动的功能,新建一个ActivityCollector类管理所有的活动
public class ActivityCollector {public static List<Activity> activities = new ArrayList<>();public static void addActivity(Activity activity){activities.add(activity);}public static void removeActivity(Activity activity){activities.remove(activity);}public static void finishAll(){for(Activity activity:activities){if(!activity.isFinishing()){activity.finish();}}}
}
然后创建baseActivity类作为活动的父类,代码如下:
public class BaseActivity extends AppCompatActivity {private ForceOfflineReceiver receiver;@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);ActivityCollector.addActivity(this);}@Overrideprotected void onResume(){super.onResume();IntentFilter intentFilter = new IntentFilter();intentFilter.addAction("com.example.broadcastbestpractice.FORCE_OFFLINE");receiver = new ForceOfflineReceiver();registerReceiver(receiver, intentFilter);}@Overrideprotected void onPause(){super.onPause();if(receiver != null){unregisterReceiver(receiver);receiver = null;}}@Overrideprotected void onDestroy(){super.onDestroy();ActivityCollector.removeActivity(this);}class ForceOfflineReceiver extends BroadcastReceiver{@Overridepublic void onReceive(final Context context, Intent intent){AlertDialog.Builder builder = new AlertDialog.Builder(context);builder.setTitle("warning");builder.setMessage("You are forced to be offline");builder.setCancelable(false);builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int which) {ActivityCollector.finishAll(); //销毁所有活动Intent intent = new Intent(context, LoginActivity.class);context.startActivity(intent); //重新启动loginActivity}});builder.show();}}
}
我们可以注意到,之前编写注册和销毁接收器的时候是在onCreate和onDestroy这两个函数里的,但是上面代码中却写在了onResume和onPause里面,这是因为我们每次都只需要在栈顶的活动接收广播,非栈顶活动没必要接收这条广播。
除此之外,我们创建一个登陆的活动,在活动页面上放置输入框,并编写登录逻辑
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/container"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingBottom="@dimen/activity_vertical_margin"tools:context=".ui.login.LoginActivity"><LinearLayoutandroid:orientation="horizontal"android:layout_width="match_parent"android:layout_height="60dp"tools:ignore="MissingConstraints"><TextViewandroid:layout_width="90dp"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:textSize="18sp"android:text="Account:"/><EditTextandroid:layout_width="0dp"android:layout_height="wrap_content"android:id="@+id/account"android:layout_weight="1"android:layout_gravity="center_horizontal"/></LinearLayout><LinearLayoutandroid:orientation="horizontal"android:layout_width="match_parent"android:layout_height="60dp"tools:ignore="MissingConstraints"><TextViewandroid:layout_width="90dp"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:textSize="18sp"android:text="password:"/><EditTextandroid:layout_width="0dp"android:layout_height="wrap_content"android:id="@+id/password"android:layout_weight="1"android:layout_gravity="center_horizontal"/></LinearLayout><Buttonandroid:layout_width="match_parent"android:layout_height="60dp"android:id="@+id/login"android:text="Login"tools:ignore="MissingConstraints"></Button></androidx.constraintlayout.widget.ConstraintLayout>
public class LoginActivity extends AppCompatActivity {private EditText accountEdit;private EditText passwordEdit;private Button login;@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_login);accountEdit = (EditText) findViewById(R.id.account);passwordEdit = (EditText) findViewById(R.id.password);login = (Button) findViewById(R.id.login);login.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {String account = accountEdit.getText().toString();String password = passwordEdit.getText().toString();//如果账号是admin 且密码是123456则登录成功if(account.equals("admin") && password.equals("123456")){Intent intent = new Intent(LoginActivity.this, MainActivity.class);startActivity(intent);finish();}else {Toast.makeText(LoginActivity.this, "account is invalid", Toast.LENGTH_SHORT).show();}}});}
}
这样就模拟了登录的窗口,然后在mainActivity中加入触发强制下线的代码
public class MainActivity extends BaseActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button forceOffline = (Button) findViewById(R.id.force_offline);forceOffline.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent("com.example.broadcastbestpractice.FROCE_OFFLINE");sendBroadcast(intent);}});}
}
这样逻辑就差不多了,下面去AndroidManifest.xml中修改下程序入口即可:
相关文章:
【安卓开发】安卓广播机制
读书笔记系列(第一行代码) 5.1 广播机制简介 标准广播:完全异步执行,广播发出后,所有广播接收器几乎都同一时刻收到这条广播(无法被截断)有序广播:同步执行,广播发出后…...
移动WEB开发四、rem布局
零、文章目录 文章地址 个人博客-CSDN地址:https://blog.csdn.net/liyou123456789个人博客-GiteePages:https://bluecusliyou.gitee.io/techlearn 代码仓库地址 Gitee:https://gitee.com/bluecusliyou/TechLearnGithub:https:…...
request.getURL()和request.getURI() 以及通过request获得路径相关大全
request.getURL()和request.getURI() 如果我的请求是:http://localhost:8080/ServletTest/servlet/Hello request.getRequestURI() 返回值类似:/ServletTest/servlet/Hello request.getRequestURL() 返回值类似:http://localhost:8080/Servle…...
java网络编程-nio学习:阻塞和非阻塞
一、阻塞 阻塞模式下,相关方法都会导致线程暂停 ServerSocketChannel.accept 会在没有连接建立时让线程暂停 SocketChannel.read 会在没有数据可读时让线程暂停 阻塞的表现其实就是线程暂停了,暂停期间不会占用 cpu,但线程相当于闲置 单线…...
JVM-JMM内存模型(happens-before、volatile)
前言 由于计算机的存储设备与处理器的运算速度有几个数量级的差距所以现代计算机系统都不得不加入一层读写速度尽可能接近处理器运算速度的高速缓存(Cache)来作为内存与处理器之间的缓冲。 将运算需要使用到的数据复制到缓存中,让运算能快速进行,当运算…...
算法leetcode|37. 解数独(rust重拳出击)
文章目录37. 解数独:样例 1:提示:分析:题解:rustgoccpythonjava37. 解数独: 编写一个程序,通过填充空格来解决数独问题。 数独的解法需 遵循如下规则: 数字 1-9 在每一行只能出现…...
SpringBoot整合Dubbo
目录1、dubbo简介2、dubbo解决了什么问题3、环境准备4、项目搭建5、总结springboot整合feign可参考我另外一篇文章SpringBoot集成Feign 1、dubbo简介 Apache Dubbo 最初在 2008 年由 Alibaba 捐献开源,很快成为了国内开源服务框架选型的事实标准框架 ,…...
[软件工程导论(第六版)]第9章 面向对象方法学引论(课后习题详解)
文章目录1. 什么是面向对象方法学?它有哪些优点?2. 什么是“对象”?它与传统的数据有何异同?3. 什么是“类”?4. 什么是“继承”?5. 什么是模型?开发软件为何要建模?6. 什么是对象模…...
光学分辨率光声显微镜中基于深度学习的运动校正算法
在这项研究中,我们提出了一种基于深度学习的方法来校正光学分辨率光声显微镜 (OR-PAM) 中的运动伪影。该方法是一种卷积神经网络,它从具有运动伪影的输入原始数据建立端到端映射,以输出校正后的图像。首先,我们进行了仿真研究&…...
浅谈UG二次开发中使用的FindObject
一般我们在业务逻辑里想查找一个Object的时候,会调用FindObject、GetObject、NxObjectManager.Get,不管是上述哪种实现,都是在内存中找东西,找到了就返回对象,否则返回null,但不会触发加载。 这里我分别从建…...
贪心原理及刷题
更新中 概念 使用贪心需要满足,上一步的局部最优解能推出这一步的局部最优解,直到得到全局最优解 而dp这一步的局部最优,不一定来源上一步的局部最优,而可能与更早的解有关,同时dp转移方程的推导也比较复杂 122. 买卖股票的最佳时机 II - 力扣(LeetCode) 这道题是典…...
2023赏金计划:Coremail SRC漏洞征集与样本奖励火热进行中
赏金活动一:Coremail SRC漏洞奖励计划 01 活动背景 2023年1月,Coremail安全应急响应中心(Coremail SRC)正式上线启用,面向公众收集安全漏洞信息与安全情报。Coremail SRC旨在联合众多安全专家、白帽子研究员共同发现…...
简记:清理指定后缀名文件的 powerhsell 小脚本
清理指定后缀名文件的 powerhsell 小脚本jcLee95:https://blog.csdn.net/qq_28550263?spm1001.2101.3001.5343 邮箱 :291148484163.com 本文地址:https://blog.csdn.net/qq_28550263/article/details/129121074 1.介绍 相关工具代码 2.目…...
问题记录:mac系统偏好设置不展示mysql
Mac新系统升级(10.14.5)后未从appstore下载的软件在安装时会提示安装包已损坏之类的东东,这是因为没有打开“设置”—“安全与隐私”中的“任何来源”造成的,可是升级后的10.14.5却没有这个选项。 那么macOS 10.14.5以上允许任何…...
网络计划--时间参数的计算和优化
根据网络图的基本概念和原则绘制出网络图之后,我们可以计算网络图中有关的时间参数,主要目的是找出关键路线,为网络计划的优化、调整和执行提供明确的时间概念。如下图中从始点①到终点⑧共有4条路线,可以分别计算出每条路线所需的…...
1.2.7存储结构-磁盘管理:磁盘移臂调度算法、先来先服务(FCFS)、最短寻道时间优先(SSTF)、扫描算法(SCAN)、循环扫描(CSCAN)
1.2.7存储结构-磁盘管理:磁盘移臂调度算法、先来先服务(FCFS)、最短寻道时间优先(SSTF)、扫描算法(SCAN)、循环扫描(CSCAN)先来先服务(FCFS)最短寻…...
2022年AI顶级论文 —生成模型之年(上)
CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 过去十年来,人工智能技术在持续提高和飞速发展,并不断冲击着人类的认知。 2012年,在ImageNet图像识别挑战赛中,一种神经网络模型(AlexNet&…...
Linux下程序调试的方法【GDB】GDB相关命令和基础操作(命令收藏)
目录 1、编译 2、启动gdb调试 2.1 直接运行 2.2 运行gdb后使用run命令 2.3 调试已运行的程序 3、图形界面提示 4、调试命令 1、查看源码 2、运⾏程序/查看运⾏信息 3、设置断点 5、单步/跳步执⾏ 6、分割窗口 7、其他命令 8、相关参数 1、编译 在编译时要加上-g选…...
使用frp配置内网机器访问
frp简介 frp 是一个开源、简洁易用、高性能的内网穿透和反向代理软件,支持 tcp, udp, http, https等协议。frp 项目官网是 https://github.com/fatedier/frp,软件下载地址为https://github.com/fatedier/frp/releases frp工作原理 服务端运行…...
简述7个流行的强化学习算法及代码实现!
目前流行的强化学习算法包括 Q-learning、SARSA、DDPG、A2C、PPO、DQN 和 TRPO。这些算法已被用于在游戏、机器人和决策制定等各种应用中,并且这些流行的算法还在不断发展和改进,本文我们将对其做一个简单的介绍。1、Q-learningQ-learning:Q-…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...
深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...
Unity中的transform.up
2025年6月8日,周日下午 在Unity中,transform.up是Transform组件的一个属性,表示游戏对象在世界空间中的“上”方向(Y轴正方向),且会随对象旋转动态变化。以下是关键点解析: 基本定义 transfor…...
上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式
简介 在我的 QT/C 开发工作中,合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式:工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...
Pydantic + Function Calling的结合
1、Pydantic Pydantic 是一个 Python 库,用于数据验证和设置管理,通过 Python 类型注解强制执行数据类型。它广泛用于 API 开发(如 FastAPI)、配置管理和数据解析,核心功能包括: 数据验证:通过…...
