一.基本概念

  强制下线功能功能应该算是比较常见的了,很多应用程序都具备这个功能,比如你的QQ号或者微信号在别处登录了,就会将你强制挤下线。只需要在界面上弹出一个对话框,让用户无法进行任何其他的操作,必须要点击对话框中的确定按钮,然后回到登录界面即可。可是这样就存在着一个问题,因为我们被通知需要强制下线时可能正处于任何一个界面,难道需要在每一个界面都编写一个弹出对话框的逻辑吗?如果真的是这样想那么思维就偏远了,我们完全可以借助所学的广播知识来实现这一个功能。

二.代码之旅

  强制下线功能需要先关闭所有的活动,然后回到登录界面,代码如下所示:

package com.nyl.nativebroadcast;

import android.app.Activity;

import java.util.ArrayList;
import java.util.List; 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类作为所有活动的父类,代码如下所示:

package com.nyl.nativebroadcast;

import android.app.Activity;
import android.os.Bundle; public class BaseActivity extends Activity{ @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityCollector.addActivity(this);
} @Override
protected void onDestroy() {
super.onDestroy();
ActivityCollector.removeActivity(this);
}
}

  创建一个登录界面的布局,代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<TableLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_login"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:stretchColumns="1"> <TableRow> <TextView
android:layout_height="wrap_content"
android:text="账号:"/> <EditText
android:id="@+id/etAccount"
android:layout_height="wrap_content"
android:hint="请输入账号"/>
</TableRow> <TableRow> <TextView
android:layout_height="wrap_content"
android:text="密码:"/> <EditText
android:id="@+id/etPassword"
android:layout_height="wrap_content"
android:inputType="textPassword"/>
</TableRow> <TableRow>
<Button
android:id="@+id/btnLogin"
android:layout_height="wrap_content"
android:layout_span="2"
android:text="登录"/>
</TableRow> </TableLayout>

  新建一个LoginActivity继承BaseActivity,代码如下所示:

package com.nyl.nativebroadcast;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast; public class LoginActivity extends BaseActivity implements View.OnClickListener { private EditText etAccount;
private EditText etPassword;
private Button btnLogin; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
initView(); //初始化布局
} private void initView() {
etAccount = (EditText) findViewById(R.id.etAccount);
etPassword = (EditText) findViewById(R.id.etPassword);
btnLogin = (Button) findViewById(R.id.btnLogin); btnLogin.setOnClickListener(this);
} @Override
public void onClick(View view) {
//获取用户输入的账号,密码的数据
String account = etAccount.getText().toString();
String password = etPassword.getText().toString();
//如果账号是123且密码是123,就登录成功
if (account.equals("123") && password.equals("123")){
Intent intent = new Intent(LoginActivity.this,MainActivity.class);
startActivity(intent);
finish();
}else {
Toast.makeText(LoginActivity.this,"账号或密码是无效的",Toast.LENGTH_SHORT).show();
}
}
}

  同样在MainActivity继承BaseActivity,一个非常简单的MainActivity,不过多解释,代码如下所示:

package com.nyl.nativebroadcast;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button; public class MainActivity extends BaseActivity implements View.OnClickListener { private Button btnOffline; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnOffline = (Button) findViewById(R.id.btnOffline); btnOffline.setOnClickListener(this);
} @Override
public void onClick(View view) {
Intent intent = new Intent("com.nyl.nativebroadcast.ForceOfflineReceiver");
sendBroadcast(intent);
}
}

  创建一个广播接收器,代码如下所示:

package com.nyl.nativebroadcast;

import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.view.WindowManager; public class ForceOfflineReceiver extends BroadcastReceiver{ @Override
public void onReceive(final Context context, Intent intent) {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
dialogBuilder.setTitle("警告");
dialogBuilder.setMessage("你被迫离线,请重新登录!");
dialogBuilder.setCancelable(false);
dialogBuilder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
/**
* 调用ActivityCollector的finishAll()方法来销毁掉所有的活动,
* 并重新启动LoginActivity这个活动
*/
ActivityCollector.finishAll();//销毁所以活动
Intent intent = new Intent(context,LoginActivity.class);
/**
* 在广播接收器里启动活动,因此一定要给Intent加入FLAG_ACTIVITY_NEW_TASK这个标准
*/
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
});
AlertDialog alertDialog = dialogBuilder.create();
//需要设置AlertDialog的类型,保证在广播接收器中可以正常弹出
alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
alertDialog.show();
}
}

  最后不要忘记在AndroidManifest.xml文件进行配置,代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.nyl.nativebroadcast"> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".LoginActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MainActivity"></activity> <receiver android:name=".ForceOfflineReceiver">
<intent-filter>
<action android:name="com.nyl.nativebroadcast.ForceOfflineReceiver"/>
</intent-filter>
</receiver>
</application> </manifest>

  好了,现在尝试运行一下程序吧,首先进入到登录界面,并可以在这里输入账号和密码,如下图:

  

  如果输入的账号是:123,密码是123,点击登录按钮就会进入到程序的主界面,如下图:

  

  这时点击一下发送强制用户下线的广播按钮,就会发出一条强制下线的广播,ForceOfflineReceiver里收到这条广播后会弹出一个对话框提示用户已被强制下线,如下图所示:

  

  这时用户将无法再对界面的任何元素进行操作,只能点击OK按钮,然后回重新回到登录界面。这样,强制下线功能就已经完整的实现了。

Android学习总结(八)———— 广播的最佳实践(实现强制下线功能)的更多相关文章

  1. Android学习笔记(十五)——实战:强制下线

    //此系列博文是<第一行Android代码>的学习笔记,如有错漏,欢迎指正! 实现强制下线功能的思路也比较简单,只需要在界面上弹出一个对话框, 让用户无法进行任何其他操作, 必须要点击对话 ...

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

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

  3. 九、Android学习第八天——广播机制与WIFI网络操作(转)

    (转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 九.Android学习第八天——广播机制与WIFI网络操作 今天熟悉了An ...

  4. Android学习总结——强制下线功能(广播)

    最近一口气买了好几本书,其中Android的<第一行代码>觉得真心不错,学到这个内容,顺便做个总结,加深印象. 强制下线的基本思想就是在界面上弹出一个对话框,让用户必须点击确定按钮跳转到登 ...

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

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

  6. Android广播时间——实现强制下线功能

    目录 思路:强制下线功能需要先关闭掉所有的活动,然后回到登录界面. 步骤 1.关闭所有活动 2.创建BaseActivity类作为所有活动的父类,因为需要用ActivityCollector管理所有活 ...

  7. android: 实现强制下线功能

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

  8. 《深入理解Android:Telephon原理剖析与最佳实践》学习笔记(系统框架)

        Android智能手机的系统结构: 智能手机的硬件基本结构大多采用双处理器架构:主处理器和从处理器,主处理器主要运行开放式操作系统以及操作系统之上的应用,负责整个系统的控制,称之为AP,从处理 ...

  9. Android 学习笔记 BroadcastReceiver广播...

    PS:不断提升自己,是件好事... 学习内容: 1.BroadcastReceiver的使用.. 2.通过BroadcastReceiver去启动Service... 1.BroadcastRecei ...

随机推荐

  1. 比利牛斯獒犬 flask web

    1. 使用 session.get('name') 直接从会话中读取 name 参数的值.和普通的字典一样,这里使用 get() 获取字典中键对应的值以避免未找到键的异常情况,因为对于不存在的键, g ...

  2. Python的中文处理

    一.使用中文字符 在python源码中如果使用了中文字符,运行时会有错误,解决的办法是在源码的开头部分加入字符编码的声明,下面是一个例子: #!/usr/bin/env python # -*- co ...

  3. 高级java工程师面试题-随笔

    最近打算要换工作,也面试了几家,因为不是自己喜欢的所以拒了一些(当然也有人家不要我的.....).在面试的过程中发现对java高级程序员的考察基本上围绕知识面,知识深度两个方面来考察.下面是在面试过程 ...

  4. WebService完成文件上传下载

    由于开发需要使用webservice,第一个接触的工具叫axis2.项目开发相关jar下载. service端: 启动类: import java.net.InetAddress; import ja ...

  5. A - Mike and Cellphone

    While swimming at the beach, Mike has accidentally dropped his cellphone into the water. There was n ...

  6. 4 pyspark学习---RDD

    开始新的东西,其实很多操作在第二篇的时候就有所介绍啦.在这里继续学习一遍加深一下印象. 1关于RDD (1) RDD-----Resilient Distributed Dataset,弹性分布式数据 ...

  7. 13.详解oauth2授权码流程

    13.详解oauth2授权码流程 把登陆系统单独独立出来,可以给自己写的微服务用,也可以给第三方的系统调用我们的服务 显式的和隐式的,两种方式,

  8. E20190404-hm

    prepend vt. 预先考虑,预先计划,预谋;

  9. Event事件的三个阶段

    转自www.w3school.com.cn/htmldom/event_bubbles.asp 在 2 级 DOM标准中,事件传播分为三个阶段: 第一,捕获阶段.事件从 Document 对象沿着文档 ...

  10. 第一篇 HTML5打包APP之VMware15安装MAC(MAC OS 10.13)(OS X 10.14)原版可升级最新可解锁macOS Unlocker3.0(OS X 10.13)

    1.1.2安装环境: 1.1.3所需资源: 1.1.4 Unlocker 3.0解锁 1.1.5 配置环境 1.1.6开始安装 1.1.7开启虚拟机进入MAC安装界面 1.1.8 macOS 10.1 ...