您的位置:首页 > 移动开发 > Android开发

Android--Android中使用广播BroadcastReceiver进行用户强制下线功能

2017-03-16 20:14 239 查看

利用广播BroadcastReceiver实现登录强制下线功能

在这里面登录界面里面的用户名和密码为默认的“admin””123456” 可以在LoginActivity里面进行修改,该例子只是简单的说明怎么样BroadcastReceiver进行强制性的下线。

原理

在应用程序中经常会遇到强制下线的情况,比如qq在别处登录,本机的你就被强制下线了。其实强制下线的原理很简单,就是弹出一个对话框让你没办法进行去他的操作,只能点击对话框的“确定”按钮进行重新登录验证身份,但是我们被通知需要强制下线的时候可能处于任何一个界面,肯定不能在没一个界面都写一个对话框。此时就用到了广播。在本例中点击button后触发广播,然后提交给ForceOfflineReceiver类进行接受广播,进行销毁所有的活动,完成用户强制性下线

1、首先创建一个Activity管理类“ActivityCollector”

在这里面进行Activity的添加 删除 和销毁所有,能够在后面强制下线时,销毁所有的Activity,只显示一个对话框

package com.example.chencong.broadcastbestpractive;

import android.app.Activity;

import java.util.ArrayList;
import java.util.List;

/**
* Created by chencong on 2017/3/16.
*/
public class ActivityCollector {
/**
* 创建一个Activity类来管理所有的活动
*/

public static List<Activity> activities = new ArrayList<Activity>();

/**
* 定义泛型数组activities 添加activity活动的方法addActivity
* @param activity
*/
public static void addActivity(Activity activity){
activities.add(activity);
}

/**
* 移除activity活动的方法removeActivity
* @param activity
*/
public static void removeActivity(Activity activity){
activities.remove(activity);
}

/**
* 遍历所有活动将其停止完成
*/
public static void findAll(){
for (Activity activity: activities) {
if (!activity.isFinishing()){
activity.finish();
}
}
}

}


2、然后创建一个基类BaseActivity

之所以创建这个基类,是为了方便对所有的Activity进行管理(添加 删除 销毁所有),因为在后面创建的Activity是继承此Activity的,能够保证在创建的时候就已添加到ActivityCollector中。

package com.example.chencong.broadcastbestpractive;

import android.app.Activity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

/**
* 定义父类BaseActivity
*/
public class BaseActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

//创建活动时,将其加入管理器中
ActivityCollector.addActivity(this);
}

@Override
protected void onDestroy() {
super.onDestroy();
//销毁活动时,将其从管理器中移除
ActivityCollector.removeActivity(this);
}
}


3、一个简单的登录界面

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">

<EditText
android:id="@+id/account"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="输入账户"/>
<EditText
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:hint="输入密码"/>
<Button
android:id="@+id/login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="登录"/>

</LinearLayout>


4、为
login.xml
编写活动

创建一个Activity继承BaseActivity,命名为LoginActivity.java,在这里使用的账号和密码为默认的“admin”“123456”

package com.example.chencong.broadcastbestpractive;

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 accountEdit;
private EditText passwordEdit;
private Button loginButton;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login);

//初始化 注册控件
accountEdit = (EditText)findViewById(R.id.account);
passwordEdit = (EditText)findViewById(R.id.password);
loginButton = (Button)findViewById(R.id.login);

//登录按钮的点击事件
loginButton.setOnClickListener(this);
}

@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")){
//登录成功后 进入MainActivity  并且在这里面提供强制下线的功能
Intent intent = new Intent(LoginActivity.this,MainActivity.class);
startActivity(intent);
finish();
}else {
Toast.makeText(LoginActivity.this,"账户和密码不匹配",Toast.LENGTH_SHORT).show();
}
}
}


当从LoginActivity.java中登录进去后会进入到MainActivity中,在这里页面中只有一个Button,当然登录进去之后,想实现怎样的功能由你自己去实现了。

5、在MainActivity中进行强制下线

package com.example.chencong.broadcastbestpractive;

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 AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

Button forceOffline = (Button)findViewById(R.id.force_offline);
/**点击按钮 发送一个"com.example.chencong.broadcastbestpractive.FORCE_OFFLINE"
*强制下线的广播 然后在接受这条广播的类(接收器)中进行强制下线的功能
* 在这里新建一个广播接收器 ForceOfflineReceiver 类 来继承 BroadcastReceiver
*/
forceOffline.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.example.chencong.broadcastbestpractive.FORCE_OFFLINE");
sendBroadcast(intent);
}
});
}
}


布局很简单啦,就一个Button就行了

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.chencong.broadcastbestpractive.MainActivity">

<!--<TextView-->
<!--android:layout_width="wrap_content"-->
<!--android:layout_height="wrap_content"-->
<!--android:text="Hello World!" />-->

<!--提供强制下线的功能-->
<Button
android:id="@+id/force_offline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="强制下线账户"/>
</RelativeLayout>


不过这里有个重点,在Button的点击事件中,发送了一条广播,广播值为
com.example.chencong.broadcastbestpractive.FORCE_OFFLINE
,这条广播就是用于通知程序,将用户强制下线的。

也就是说强制用户下线的功能并不是写在MainActivity中的,而是写在这条广播的广播接收器中,这样强制下线就不会依赖任何界面,不管是在程序的任何地方,只要一发出这样的一条广播,就可以完成强制下线了。

对,现在就来创建一个广播的接收器,新建一个ForceOfflineReceiver类继承BroadcastReceiver

6、新建一个ForceOfflineReceiver类继承BroadcastReceiver

package com.example.chencong.broadcastbestpractive;

import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.view.WindowManager;

/**
* Created by chencong on 2017/3/16.
*/
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 dialog, int which) {
ActivityCollector.findAll();  //销毁所有活动
Intent i = new Intent(context,LoginActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);   //在广播接收器中启动活动 因此需要加上这个标志
context.startActivity(i);  //重新启动登录界面
}
});

AlertDialog alertDialog = dialogBuilder.create();
//设置AlertDialog 的类型 保证广播接收器中可以正常的弹出

//系统级别的对话框 因此需要在AndroidManifest中进行声明
alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
alertDialog.show();
}
}


在onReceiver()方法中,首先使用AlertDialog.Builder构建一个对话框,并且调用setCancelable()方法将对话框设置为不可取消,否则用户按一下返回键就能够关闭对话框就能够继续使用程序了,然后用setPositiveButton()方法为对话框注册确定按钮,并且当用户点击确定按钮时候就调用之前我们创建的ActivityCollector这个类的finishAll()方法类销毁所有的Activity,并且重新启动LoginActivity进行登录。

并且在广播接收器中启动活动时候,一定要给Intent的对象加入FLAG_ACTIVITY_NEW_TASK这个标志,最后将对话框的类型设置为系统级别,否在无法在广播接收器中进行弹出。

7、最后的配置

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.chencong.broadcastbestpractive">

<!--进行权限配置-->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"

android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".LoginActivity"
android:label="@string/app_login">
<intent-filter
android:label="@string/app_name">
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".BaseActivity" />
<activity android:name=".MainActivity"
android:label="@string/app_mian"/>

<receiver android:name=".ForceOfflineReceiver">
<intent-filter>
<action android:name="com.example.chencong.broadcastbestpractive.FORCE_OFFLINE"/>
</intent-filter>
</receiver>

</application>

</manifest>


前面将对话框设置为系统级别的,因此在这里需要进行声明。然后对广播进行注册,并且指定为哪一个广播。

8、运行看看效果啦

登录界面,输入账户 密码



登录进去后 进行点击下线



9、最后附上源码

项目地址:github传送门

apk下载:github传送门

喜欢就去做,想到就去做!做自己喜欢的事情

----by chencong
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 对话框 密码