网站首页 编程语言 正文
目录
- 广播机制简介
- 接收系统广播
- 动态注册监听网络变化
- 静态注册实现开机启动
- 发送自定义广播
- 发送标准广播
- 发送有序广播
- 使用本地广播
- 使用广播实现强制下线功能
广播机制简介
- 标准广播:完全异步执行,广播发出后,所有广播接收器几乎都同一时刻收到这条广播(无法被截断)
- 有序广播:同步执行,广播发出后同一时刻只会有一个广播接收器能收到这条广播消息,前面的接收器可以截断正在传递的广播
接收系统广播
广播接收器可在代码中注册和AndroidManifest.xml中注册,前者为动态注册,后者被称为静态注册。
动态注册监听网络变化
示例代码:
public class MainActivity extends AppCompatActivity {
private IntentFilter intentFilter;
private NetworkChangeReceiver networkChangeReceiver;
@Override
protected 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);
}
@Override
protected void onDestroy(){
super.onDestroy();
unregisterReceiver(networkChangeReceiver);
}
class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public 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();
}
}
}
静态注册实现开机启动
<receiver android:name=".BootCompleteReceiver" android:enabled="true" android:exported="true"></receiver>
Export属性表示是否允许这个广播接收器接收本程序以外的广播,enable表示是否使用这个广播接收器。
<receiver android:name=".BootCompleteReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver>
添加了filter就可以过滤了
可以通过左键新建-》其它来新建静态注册广播
广播接收器中不允许开线程,当onReceive方法运行较长时间而没结束时,程序就会报错,所以其中不能添加过多的逻辑或任何耗时操作。
发送自定义广播
发送标准广播
@Override
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(){
@Override
public void onClick(View v){
Intent intent = new Intent("com.example.broadcasttest.MY_BROADCAST");
sendBroadcast(intent);
}
});
}
通过点击按钮发送广播
public class myBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "receiverd in myBroadcastReceiver", Toast.LENGTH_SHORT).show();
}
}
这里是自定义的接收器
<receiver android:name=".myBroadcastReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="com.example.broadcasttest.MY_BROADCAST"/> </intent-filter> </receiver>
在xml中定义过滤的广播类型
发送有序广播
广播是一种跨进程的通信方式
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(){
@Override
public void onClick(View v){
Intent intent = new Intent("com.example.broadcasttest.MY_BROADCAST");
sendOrderedBroadcast(intent, null);
}
});
}
只需要修改一行代码 sendOrederedBroadcast即可发送有序广播,同时在接收器的xml文件中可以设置优先级
<receiver android: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();
}
使用本地广播
前面我们发送和接收的广播全部属于系统全局广播,即发出的广播可以被其他任何应用程序接收到,并且我们也可以接收来自于其他任何应用程序的广播。这样就很容易引起安全性的问题,比如说我们发送的一些携带关键性数据的广播有可能被其他的应用程序截获,或者其他的程序不停地向我们的广播接收器里发送各种垃圾广播。
使用本地广播则发出的广播只能在应用程序内部传递,并且接收器也只能接收来自本应用程序发出的广播。
public class MainActivity extends AppCompatActivity {
private IntentFilter intentFilter;
private LocalReceiver localReceiver;
private LocalBroadcastManager localBroadcastManger;
@Override
protected 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() {
@Override
public 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); //注册本地广播监听器
}
@Override
protected void onDestroy(){
super.onDestroy();
localBroadcastManger.unregisterReceiver(localReceiver);
}
class LocalReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent){
Toast.makeText(context, "received local broadcast", Toast.LENGTH_SHORT).show();
}
}
}
代码的不同主要在于需要首先获取实例,然后还要有注册。
需要注意的是,本地广播无法通过静态注册来接收。
使用广播实现强制下线功能
强制下线功能首先需要实现下关闭所有的活动的功能,新建一个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;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
ActivityCollector.addActivity(this);
}
@Override
protected void onResume(){
super.onResume();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.example.broadcastbestpractice.FORCE_OFFLINE");
receiver = new ForceOfflineReceiver();
registerReceiver(receiver, intentFilter);
}
@Override
protected void onPause(){
super.onPause();
if(receiver != null){
unregisterReceiver(receiver);
receiver = null;
}
}
@Override
protected void onDestroy(){
super.onDestroy();
ActivityCollector.removeActivity(this);
}
class ForceOfflineReceiver extends BroadcastReceiver{
@Override
public 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() {
@Override
public 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"> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="60dp" tools:ignore="MissingConstraints"> <TextView android:layout_width="90dp" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:textSize="18sp" android:text="Account:"/> <EditText android:layout_width="0dp" android:layout_height="wrap_content" android:id="@+id/account" android:layout_weight="1" android:layout_gravity="center_horizontal"/> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="60dp" tools:ignore="MissingConstraints"> <TextView android:layout_width="90dp" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:textSize="18sp" android:text="password:"/> <EditText android:layout_width="0dp" android:layout_height="wrap_content" android:id="@+id/password" android:layout_weight="1" android:layout_gravity="center_horizontal"/> </LinearLayout> <Button android: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;
@Override
protected 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() {
@Override
public 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 {
@Override
protected 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() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.example.broadcastbestpractice.FROCE_OFFLINE");
sendBroadcast(intent);
}
});
}
}
这样逻辑就差不多了,下面去AndroidManifest.xml中修改下程序入口即可:
原文链接:https://blog.csdn.net/qq_35481726/article/details/129113783
- 上一篇:没有了
- 下一篇:没有了
相关推荐
- 2022-06-20 Android Flutter实现点赞效果的示例代码_Android
- 2023-01-18 Android Admob接入原理及完整教程示例_Android
- 2022-05-20 子查询关键字-ALL、ANY、SOME、IN、EXISTS
- 2022-03-29 C++中的拷贝构造详解_C 语言
- 2022-04-30 C#操作DataGridView获取或设置当前单元格的内容_C#教程
- 2022-06-14 ASP.NET Core MVC中的局部视图用法_基础应用
- 2022-07-25 SQL Server系统函数介绍_MsSql
- 2022-10-09 基于Redission的分布式锁实战_Redis
- 栏目分类
-
- 最近更新
-
- window11 系统安装 yarn
- 超详细win安装深度学习环境2025年最新版(
- Linux 中运行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存储小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基础操作-- 运算符,流程控制 Flo
- 1. Int 和Integer 的区别,Jav
- spring @retryable不生效的一种
- Spring Security之认证信息的处理
- Spring Security之认证过滤器
- Spring Security概述快速入门
- Spring Security之配置体系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置权
- redisson分布式锁中waittime的设
- maven:解决release错误:Artif
- restTemplate使用总结
- Spring Security之安全异常处理
- MybatisPlus优雅实现加密?
- Spring ioc容器与Bean的生命周期。
- 【探索SpringCloud】服务发现-Nac
- Spring Security之基于HttpR
- Redis 底层数据结构-简单动态字符串(SD
- arthas操作spring被代理目标对象命令
- Spring中的单例模式应用详解
- 聊聊消息队列,发送消息的4种方式
- bootspring第三方资源配置管理
- GIT同步修改后的远程分支