强制下线的功能,是使用安卓四大组件之一---广播来实现的。通过运用广播的知识,实现这一功能·。
首先新建一个ActivityCollector类用于管理所有的活动
package com.example.a14468.broadcastbestpractice;
import android.app.Activity;
import java.util.ArrayList;
import java.util.List;
/**
* Created by 14468 on 2017/3/21.
*/
/**
* 关闭所有活动
* 在活动管理器中,我们通过一个List来暂存活动,然后提供一个addActivity()方法用于向List中添加一个活动,提供了一个removeActivity()方法
* 用于从List中移除活动,最后提供一个finishAll()方法用于将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.example.a14468.broadcastbestpractice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
/**
* Created by 14468 on 2017/3/21.
*/
public class BaseActivity extends AppCompatActivity {
private ForceOffLineReceiver receiver;
@Override
public void onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) {
super.onCreate(savedInstanceState, persistentState);
ActivityCollector.addActivity(this);
}
/*
*销毁活动
*/
@Override
protected void onDestroy() {
super.onDestroy();
ActivityCollector.RemoveActivity(this);
}
}
接着新建一个登陆界面LoginActivity.
xml文件
<?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">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="60dp">
<TextView
android:layout_width="90dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textSize="18sp"
android:text="Account:"/>
<EditText
android:id="@+id/account"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="60dp">
<TextView
android:layout_width="90dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textSize="18sp"
android:text="Password:"/>
<EditText
android:id="@+id/password"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical"
android:inputType="textPassword"/>
</LinearLayout>
<Button
android:id="@+id/login"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="Login" />
</LinearLayout>然后LoginActivity类
package com.example.a14468.broadcastbestpractice;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
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 {
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();
if (account.equals("admin") && password.equals("123456")){
Intent intent = new Intent(LoginActivity.this,MainActivity.class);
startActivity(intent);
finish();
}else {
Toast.makeText(LoginActivity.this, "密码或者用户名输入错误!", Toast.LENGTH_SHORT).show();
}
}
});
}
}
具体的实现就不多说了,如果有些不懂的可以看我发的博客:安卓UI开发那一篇。
最后就是关键的强制下线功能的实现了。进入activity_main.xml文件 添加一个按钮,用于触发强制下线的功能
<?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">
<Button
android:id="@+id/force_offline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="强制下线" />
</LinearLayout>
然后是MainActivity类
package com.example.a14468.broadcastbestpractice;
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 {
@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.FORCE_OFFLINE");
sendBroadcast(intent);
}
});
}
}
我们在按钮点击事件发送了一条广播:"com.example.broadcastbestpractice.FORCE_OFFLINE"
这条广播用于通知程序强制用户下线的。强制用户下线的程序是写在接收这条广播的广播接收器里面的,这样强制下线的功能不会依附于任何的界面,不管是程序的任何地方,只需要发出一条广播,就可以强制下先操作了。
我们需要创建一个广播接收器来接受这条强制下线的广播。创建的地方 需要弹出一个对话框来阻塞用户正常操作,但如果是创建一个静态注册的广播接收器,是没有办法在onReceive方法里弹出对话框这样的UI控件,而且我们也不会在每一个活动中都注册一个动态广播。这是一个关键 因此这就是我们为什么要在最开始要新建一个 BaseActivity类,所有活动都继承这个类!!
修改BaseActivity中的代码,如下所示
package com.example.a14468.broadcastbestpractice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
/**
* Created by 14468 on 2017/3/21.
*/
public class BaseActivity extends AppCompatActivity {
private ForceOffLineReceiver receiver;
@Override
public void onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) {
super.onCreate(savedInstanceState, persistentState);
ActivityCollector.addActivity(this);
}
/*
重写onResume()和onPause()这两个生命周期函数,分别在这两个方法里注册和取消注册了
对于广播有什么疑问或者是有一些地方不懂得可以看一下我发表的关于广播的博客
ForceOffLineReceiver。之前都是在onCreate方法和onDestroy方法里注册和取消注册广播接收器,但是我们始终需要保证只有处于栈顶的活动才能接收到这条强制下线广播,所以在些onResume()和onPause()方法里就可以很好的解决这个问题当活动失去栈顶的位置就会自动取消广播接收器的注册!并且还要在AndroidManifest.xml文件里将主活动设置为LoginActivity,而不是MainActivity里面。确保打开APP的界面是登录界面*/
@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);
}
/*
onReceive()方法里不仅仅是弹出一个Toast,而是加入了人较多的代码
首先使用AlterDialog.Builder来构建一个对话框,注意要调用setCancelable(false)方法,设对话框不可取消,
不设置当用户按一下Back键就可以关闭对话框继续使用然后使用setPositiveButton()方法给对话框注册确定按钮,当用户点击确认用户按钮时,调用ActivityCollector的finishAll方法来销毁所有的活动,并重启LoginActivity这个活动
*/
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 force to be offline. Please try to login again.");
builder.setCancelable(false);//将对话框设置为不可取消,不设置当用户按一下Back键就可以关闭对话框继续使用程序
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ActivityCollector.finishAll();//销毁所有活动
Intent intent = new Intent(context,LoginActivity.class);
context.startActivity(intent);//重新启动LoginActivcity
}
});
builder.show();
}
}
}