首先,复习一下,什么是广播呢?

顾名思义,广播就像我们上学的时候每个班级里的喇叭一样,这些喇叭都是接入到学校的总的一个地方,比如说广播室啊什么的。一旦有什么通知,就会播放一条让全校师生都知道的广播。类似的工作机制其实很多,比如就像计算机的网络通信。

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

在Android中,每个应用都可以对自己感兴趣的广播进行注册,这样程序就只会收到自己所关注的广播,这些内容可能来自于系统,也有可能来自于别的app。Android也有一套完整的api,允许应用自由的发送和接收广播,发送广播所采用的就是Intent,而接收广播所采用的就是广播接收器。(Broadcast Receiver)

广播的类型分为 标准广播有序广播

标准广播:

是一种完全异步执行的广播,在广播发出之后,所有的广播接收器都会在同一时间接收到这条广播消息,因此他们之间没有任何先后顺序可言。这种广播的效率会比较高,但同时也意味着它是无法被截断的。


有序广播:

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


这里你可能会疑问了,说了这么多,那怎么创建一个广播接收器呢?

其实只需要创建一个类,让他继承Broadcast-Receiver,并重写onReceive()方法即可。当有广播到来时,onReceive方法就会执行。具体的逻辑就可以在这个方法中处理。广播的详细使用请参阅这里

本文通过一个强制下线的例子来简单说明广播的使用。

强制下线很多程序都具备这个功能,比如QQ号再别处登陆了,就会将你强制挤下线。强制下线的功能思路也比较简单,只需要在界面上弹出一个地画框,让用户无法进行其他操作,必须要点击对话中的确定按钮,然后回到登录界面即可。借助于广播,我们就可以轻松实现这个功能。而不必在每个页面都编写一个弹出对话框的逻辑,因为你不知道用户此时在哪里。

强制下线的功能需要关闭所有活动,然后回到登录界面。关于这个方法,我们先简单说一下:

我们只需要创建一个专门的集合类对所有的活动进行管理就可以了,下面我们就来实现以下。

首先,新建一个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 finish(){for(Activity activity:activities){if (!activity.isFinishing()){activity.finish();}}activities.clear();}
}

在活动管理器中,我们通过一个List来暂存活动,然后提供了一个 addActivity() 方法用于向 List 中添加一个活动,提供了一个 removeActivity() 方法用于从 List 中移除活动,最后提供了一个 finish() 方法用于将 List 中存储的活动全部销毁掉。


然后创建BaseActity类作为所有活动的父类,代码如下

public class BaseActivity extends AppCompatActivity {protected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);ActivityCollector.addActivity(this);}@Overrideprotected void onDestroy() {super.onDestroy();ActivityCollector.removeActivity(this);     //取消广播}}

接着,创建一个登录界面的活动,新建LoginActivity,并让Android stdio自动帮我们生成相应的布局文件。然后编辑布局文件 activity_login.xml,代码如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:orientation="horizontal"android:layout_width="match_parent"android:layout_height="60dp"><TextViewandroid:layout_width="90dp"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:textSize="18sp"android:text="Account"/><EditTextandroid:id="@+id/account"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:layout_gravity="center_vertical"/></LinearLayout><LinearLayoutandroid:orientation="horizontal"android:layout_width="match_parent"android:layout_height="60dp"><TextViewandroid:layout_width="90dp"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:textSize="18sp"android:text="password"/><EditTextandroid:id="@+id/password"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:layout_weight="1"android:inputType="textPassword"/></LinearLayout><Buttonandroid:id="@+id/login"android:layout_width="match_parent"android:layout_height="60dp"android:text="Login"/>
</LinearLayout>

这里我们使用LinearLayout编写出了一个登录布局,布局的样式这里不难理解吧。


接下来修改LoginActivity中的代码,如下所示:

public class LoginActivity extends BaseActivity {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();  //获取密码输入框的信息if(account.equals("admin")&&password.equals("password")){     //判断输入是否正确Intent intent=new Intent(LoginActivity.this,MainActivity.class);startActivity(intent);finish();}else{Toast.makeText(LoginActivity.this, "输入有误,请重新输入", Toast.LENGTH_SHORT).show();}}});}
}

这里我们模拟登录时的界面,首先将  LoginActivity  的继承结构改为继承自  BaseActivity  ,然后调用了  findViewById()  方法分别获取到输入框中的信息,然后再登录按钮里使用了一个简单的if判断,这里并没有用到数据库等知识。

因此,你就可以将MainActivity理解成登录成功后进入的程序主界面了。这里我们并不需要在主界面添加什么花哨的功能,只需要加入强制下线即可。


修改activity_main.xml文件中的代码。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><Buttonandroid:id="@+id/force_offline"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="强制下线按钮"/></LinearLayout>

非常简单,只有一个按钮而已,用于出发强制下线功能。然后修改MainActivity中的代码。

public class MainActivity extends BaseActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button button=(Button) findViewById(R.id.force_offline);button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Intent intent=new Intent("com.example.xiaxian");sendBroadcast(intent);      //发送广播}});}

同样也很简单,这里我们给按钮注册了个监听事件,并且在点击事件里发送了一条广播,广播的值为com.example.xiaxian,这条广播就是通知程序强制用户下线的。也就是说,强制下线的功能并不是写在MainActivity里的,而是应该写在接收这条广播的广播接收器里面,这样强制用户下线的功能就不会依附于任何界面,不管是在程序的任何地方,只需要发出这样一条广播,可以完成强制下线的操作了。

那么接下来的操作,毫无疑问就是需要创建一个广播接收器来接收这条强制下线广播,唯一的问题就是,应该在哪里创建呢?由于广播接收器需要弹出一个对话框来阻塞用户的正常操作,但如果创建的是一个静态注册的广播接收器,是没有办法在  onReceive() 方法里弹出对话框的这样的UI操作的,而我没问显然也不可能在每个活动中都去注册一个动态的广播接收器。

解决办法就是,只需要在BaseActivity中动态注册一个广播接收器就可以了,因为所有的活动都是继承自BaseActivity的。


修改BaseActivity中的代码,如下所示:

public class BaseActivity extends AppCompatActivity {private ForceOfflineReceiver receiver;protected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);ActivityCollector.addActivity(this);}protected void onResume(){super.onResume();IntentFilter intentFilter=new IntentFilter();intentFilter.addAction("com.example.xiaxian");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. Please try to login agaun");      //内容builder.setCancelable(false);       //不可取消活动(即无法通过返回键取消活动)builder.setPositiveButton("OK",new DialogInterface.OnClickListener(){   //对话框注册确定按钮@Overridepublic void onClick(DialogInterface dialog, int which) {ActivityCollector.finish(); //强制下线,即销毁所有活动Intent intent=new Intent(context,LoginActivity.class);context.startActivity(intent);      //重新启动LoginActivity}});builder.show();}}
}

先看一下ForceOfflineReceiver中的代码吧,这次,我们先用 AlertDialog.Builder来构建了一个对话框,注意这一定要调用 setCancelable() 方法将对话框设置为不可取消,否则用户点一下返回键就可以关闭对话框并据需使用程序了。然后使用setPositiveButton()方法来给用户对话框注册确定按钮,当用户点击了确定按钮时,就调用强制下线功能来销毁所有活动,并重新启动登录界面。

再来看一下我们是怎么注册ForeOfflineReceiver这个广播接收器,可以看到,这里重写了onResume()和 onPause() 这两个活动得生命周期函数,然后分别在这两个方法里面注册和取消注册了 ForeOfflineReceiver。

为什么要这样写呢?

因为我们要始终保证只有处于栈顶的活动才能接受到这条强制下线广播,非栈顶的活动没必要去接受这条广播,所以写 onRemove 和 onPause() 方法里就可以很好的解决这个问题,当一个活动失去栈顶位置是就会自动取消广播接收器的注册。


这样的话,所有强制下线的逻辑就已经完成了,接下来我们换需要对AndroidManifest.xml文件进行修改,代码如下所示。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.a15094.broadcastbestpractice"><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme"><activity android:name=".MainActivity"></activity><activity android:name=".LoginActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application>

好了,现在我们来试一下吧。

初学Android,互相学习啦。。

Android-浅谈广播机制,实现强制下线功能相关推荐

  1. 广播,实现强制下线功能(项目文件已上传GitHub)

    项目文件GitHub地址: https://github.com/Skymqq/BroadcastBestPractice.git 新建BoradcastBestPractice项目. 首先我们需要制 ...

  2. android 强制下线功能,Android学习之基础知识八—Android广播机制实践(实现强制下线功能)...

    强制下线功能算是比较常见的了,很多的应用程序都具备这个功能,比如你的QQ号在别处登录了,就会将你强制挤下线.实现强制下线功能的思路比较简单,只需要在界面上弹出一个对话框,让用户无法进行任何操作,必须要 ...

  3. Android通过广播实现强制下线功能

    Android通过广播实现强制下线功能 我们首先定义一个activity集合类,在这个类里面主要添加三个方法,分别是 1.添加activity 2.删除activity 3.关闭所有activity ...

  4. Android开发(2) | 广播 Broadcast 的应用——强制下线功能

    文章目录 功能简介 关闭所有活动 登陆界面 发送强制下线的广播 广播接收器 AndroidManifest.xml 运行结果 功能简介 强制下线功能只需要弹出一个对话框,让用户只能点击确定按钮,回到登 ...

  5. android#boardcast#广播实现强制下线功能

    参考自<第一行代码>--郭霖 强制下线功能需要先关闭掉所有的活动(Activity),然后回到登录界面.先创建一个ActivityCollector类用于管理所有的活动,代码如下所示: p ...

  6. Android 浅谈 Activity (下)

    Android 浅谈 Activity(中) 上节讲了数据传递和数据回传,这节讲一讲状态保存以及启动模式. 在使用Bundle传递数据时,要注意,Bundle的大小是有限制的 < 0.5MB,如 ...

  7. android仿qq强制下线服务器,qq强制下线(实现一个类似QQ的强制下线功能)

    qq强制下线(实现一个类似QQ的强制下线功能),哪吒游戏网给大家带来详细的qq强制下线(实现一个类似QQ的强制下线功能)介绍,大家可以阅读一下,希望这篇qq强制下线(实现一个类似QQ的强制下线功能)可 ...

  8. 浅谈Attention机制

    浅谈Attention机制 Attention注意机制现在大热,很多深度学习的框架都带上了注意力机制,而且也取得了很好的性能指标.乘着大热也来水一水文章,发表发表自己的看法.事先说明老哥我在NLP上萌 ...

  9. 浅谈Attention机制的作用

    浅谈注意力机制的作用 前言 什么是注意力机制 空间注意力 对于时间步的注意力机制 1.数据集的制作 2.建立注意力模型 3.建立整体神经网络 4.完整代码 5.实验效果 通道注意力机制 前言 Atte ...

最新文章

  1. javascript乘法和加法_JavaScript大数相加相乘的实现方法实例
  2. 放假看片时,一定要检查域名是不是 HTTPS ,不然……
  3. smart-socket如何实现字符串通信
  4. [置顶] Spring中DI设置器注入
  5. Python编程基础:第三十七节 石头剪刀布游戏Rock, Paper, Scissors Game
  6. gorm查询降序排列
  7. html5布局总结,HTML5网页布局的总结
  8. python爬虫模拟浏览器的两种方法_python爬虫模拟浏览器访问-User-Agent过程解析
  9. 卷积神经网络(CNN)之池化层的实现
  10. WPF in Finance
  11. 20岁黑客发现苹果核心 web 应用中的严重漏洞,获奖$3.6万
  12. mysql workbench企业_甲骨文发布MySQL Workbench 6.0版本
  13. mybatis+mysql分库分表_一种简单易懂的 MyBatis 分库分表方案
  14. nyoj---快速查找素数
  15. Comprehensive learning path – Data Science in Python深度学习路径-用python进行数据学习
  16. 我要悄悄学习 Java 字节码指令,在成为技术大佬的路上一去不复返
  17. 前端安全机制集合(不定期更新) -- 戴向天
  18. ios 判断打开相机权限_ios 判断是否有权限访问相机,相册,定位
  19. mach_absolute_time 高效计算时间差
  20. springcloudAlibaba+dubbo线程拥堵Thread pool is EXHAUSTED

热门文章

  1. Cortana小娜:前世今生
  2. 中国农历1900-2100算法工具类
  3. Chrome 96 版本无法发送跨域请求的问题 解决方案
  4. 计算机网络考试重点【自用】
  5. 支付宝,微信的城市服务 UI
  6. 墙壁绘图机器人盘点,丰富家居生活!
  7. POI实现动态导出功能
  8. google浏览器如何截图?
  9. 安防、监控行业常用英文与中文对照表,iris,lens,cradle
  10. 【SQL事务】事务是如何实现的?