一.基本概念

  强制下线功能功能应该算是比较常见的了,很多应用程序都具备这个功能,比如你的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. sqlServer:convert()函数

    在oracle中对于时间格式的转换用到的比较多,相对也比较了解,现在换了新的项目组,使用sqlserver数据库,需要对这个数据库的一些常用函数进行重新学习和熟悉,现在根据w3c及网上博文对conve ...

  2. GetModuleFileNameW

    GetModuleFileNameW( HMODULE hModule, //模块句柄 或应用程序的实例句柄 若参数为NULL,则返回该应用程序全路径 __out_ecount(nSize) LPWS ...

  3. TypeScript完全解读(26课时)_4.TypeScript完全解读-接口

    4.TypeScript完全解读-接口 初始化tslint tslint --init:初始化完成后会生成tslint.json的文件 如果我们涉及到一些规则都会在这个rules里面进行配置 安装ts ...

  4. 极客时间_Vue开发实战_05.Vue组件的核心概念(1):属性

    05.Vue组件的核心概念(1):属性 代码地址: https://github.com/tangjinzhou/geektime-vue-1/blob/master/%E6%BC%94%E7%A4% ...

  5. Flutter实战视频-移动电商-37.路由_Fluro引入和商品详细页建立

    37.路由_Fluro引入和商品详细页建立 https://github.com/theyakka/fluro pages/details_page.dart新建页面 使用路由 先添加路由插件的引用 ...

  6. API网络接口

    1.天气 文章:http://segmentfault.com/a/1190000002607883 地址:http://api.lib360.net/open/weather.json?city=北 ...

  7. Multi-University板块

    力争补完所有 Multi-University 的"水题",任重而道远. HDU2819[二分匹配与矩阵性质] HDU2844[背包问题(二进制优化)] HDU2824[欧拉函数] ...

  8. 传统JDBC操作数据库

    package com.jdbc.example; import java.sql.Connection; import java.sql.Date; import java.sql.DriverMa ...

  9. XCode5 编译ffmpeg流程

    今天想在Mac10.9 XCode5的环境下把ffmpeg编译出来,本来以为很好搞定,结果版本一升级,以前的命令行不通了,出各种错误.折腾了三四个小时,最后终于成功了. 编译流程: 1.ffmpeg官 ...

  10. [coci2015-2016 coii] dijamant【图论】

    传送门:http://www.hsin.hr/coci/archive/2015_2016/ 进去之后的最下面的国家赛.顺便说一句,dijamant是克罗地亚语的“钻石”的意思. 官方题解是说压位的暴 ...