账号二次登陆,强制当前账号下线

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/abc6368765/article/details/51784561

很多网页或者APP都是通过SessionID(会话ID)或者Token(令牌)和服务器进行交互,以保证交互过程,客户端的唯一性。那么如果账号出现了二次登陆,应该如何处理呢?本文模拟服务器消息,然后简单实现了强制当前账号下线的功能。

一、大概说一下思路,客户端和服务器保持着通讯连接,当服务器检测到同一账号在另一个地方登陆的时候,会给当前账号发送消息,当APP监听到账号二次登陆的消息之后(本地要先实现对用户登陆状态的监听功能),会发送一个本地广播,然后让用户选择关闭或者重新登陆。
效果图:
这里写图片描述

二、具体实现代码:

  • MyBaseActivity.java
 * 
 * @author SHI 
 * 所有Activity的父类
 * 2016-2-1 11:41:42
 *
 */
public abstract class MyBaseActivity extends AppCompatActivity {
    /**当前Activity对象**/
    public FragmentActivity mContext;
    /**当前设备宽度**/
    public int displayDeviceWidth;
    /**当前设备高度**/
    public int displayDeviceHeight;
    /**初始化布局文件**/
    public abstract void initView();
    /**初始化页面数据**/
    public abstract void initData();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        ActivityCollector.addActivity(this);
        mContext = this;
        displayDeviceWidth = getResources().getDisplayMetrics().widthPixels;
        displayDeviceHeight = getResources().getDisplayMetrics().heightPixels;
        initView();
        initData();
    }

    @Override
    protected void onDestroy() {
        ActivityCollector.removeActivity(this);
        super.onDestroy();
    }

}
  • ActivityCollector.java
/***
 * activity管理工具类,方便同时操作所有Activity
 * @author SHI
 * 2016-6-29 17:04:01
 */
public class ActivityCollector {

    public static List<Activity> activities = new ArrayList<Activity>();
    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();
            }
        }
    }
}
  • LoginActivity.java代码
/**
 * 2016年6月29日 16:45:25
 * SHI
 * 登陆界面
 */
public class LoginActivity extends MyBaseActivity{

    private EditText mEmailView;
    private EditText mPasswordView;
    public final static String regExpEmailNumber = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";


    @Override
    public void initView() {
        setContentView(R.layout.activity_login);
        mEmailView = (EditText) findViewById(R.id.email);
        mPasswordView = (EditText) findViewById(R.id.password);
        Button login = (Button) findViewById(R.id.login);
        Button press_logout = (Button) findViewById(R.id.press_logout);

        login.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                login();
            }
        });



    }

    @Override
    public void initData() {

    }

    private void login() {

        mEmailView.setError(null);
        mPasswordView.setError(null);

        String email = mEmailView.getText().toString();
        String password = mPasswordView.getText().toString();
        View focusView = null;

        if (TextUtils.isEmpty(password) || !isPasswordValid(password)) 
        {
            mPasswordView.setError("输入的密码太短了");
            focusView = mPasswordView;
        }
        if (TextUtils.isEmpty(email)) {
                mEmailView.setError(getString(R.string.error_field_required));
            focusView = mEmailView;
        } else if (!isEmailValid(email)) {
            mEmailView.setError(getString(R.string.error_invalid_email));
            focusView = mEmailView;
        }

        if (focusView !=null) {
            focusView.requestFocus();
        } else {
            Intent intent = new Intent(this,MainActivity.class);
            startActivity(intent);
            finish();
        }
    }

    //是否是合法邮箱
    private boolean isEmailValid(String email) {
        if(TextUtils.isEmpty(email)){
            return false;
        }
        return email.matches(regExpEmailNumber);
    }

    //密码是否合法
    private boolean isPasswordValid(String password) {
        return password.length() > 4;
    }
}
  • activity_login.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"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    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.shi.androidstudy.presslogout.LoginActivity">

    <ScrollView
        android:id="@+id/login_form"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:id="@+id/email_login_form"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <android.support.design.widget.TextInputLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <EditText
                    android:id="@+id/email"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="邮箱"
                    android:inputType="textEmailAddress"
                    android:maxLines="1"
                    android:singleLine="true" />

            </android.support.design.widget.TextInputLayout>

            <android.support.design.widget.TextInputLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <EditText
                    android:id="@+id/password"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="密码"
                    android:inputType="textPassword"
                    android:maxLines="1"
                    android:singleLine="true" />

            </android.support.design.widget.TextInputLayout>

            <Button
                android:id="@+id/login"
                style="?android:textAppearanceSmall"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="16dp"
                android:text="登陆"
                android:textStyle="normal" />

        </LinearLayout>
    </ScrollView>
</LinearLayout>
  • MainActivity.java代码
/**
 * 2016年6月29日 16:45:38
 * SHI
 * 登陆成功进入的主界面,在这个界面模拟9秒之后收到服务器返回的当前用户二次登
 * 陆消息,然后发送强制用户下线广播
 */
public class MainActivity extends MyBaseActivity {

    private int numDelay = 9;
    private Button press_logout;


    private Handler handler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            if(numDelay > 1){
                numDelay--;
                press_logout.setText(numDelay+"秒后强制下线");
                handler.sendEmptyMessageDelayed(0,1000);
                return false;
            }
            press_logout.setText("强制下线");
            Intent intent = new Intent("com.shi.androidstudy.PRESS_LOGOUT");
            sendBroadcast(intent);
            return true;
        }
    });

    @Override
    public void initView() {
        setContentView(R.layout.activity_main);
        press_logout = (Button) findViewById(R.id.press_logout);
        handler.sendEmptyMessageDelayed(0,1000);
    }

    @Override
    public void initData() {

    }
    @Override
    protected void onDestroy() {
        handler.removeCallbacksAndMessages(null);
        super.onDestroy();
    }
}
  • activity_main.xml 登陆成功主界面对应的布局文件
<?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.shi.androidstudy.presslogout.MainActivity">
    <Button
        android:id="@+id/press_logout"
        style="?android:textAppearanceSmall"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="9秒后强制下线"
        android:textStyle="normal" />
</RelativeLayout>
  • 强制用户下线广播接受者

接收到强制用户下线广播之后,弹出AlertDialog,让用户选择
重新登陆(关闭当前所有Activity重新打开登陆界面) 还是 确定(关闭应用程序),不过谷歌官方不推荐使用AlertDialog,所以,所以也可以打开一个新的Activity去展示提示信息,强制用户下线。

/**
 * 广播接受者
 * 2016年6月29日 16:46:12
 * SHI
 */
public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(final Context context, Intent intent) {
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setTitle("下线通知");
        String line = System.getProperties().getProperty("line.separator");
        builder.setMessage("账号在别处登陆,您被迫下线。"+line+"若非本人操作,请尽快修改密码。");
        builder.setCancelable(false);
        builder.setPositiveButton("重新登陆", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                ActivityCollector.finishAll();
                Intent intent = new Intent(context,LoginActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(intent);
            }
        });
        builder.setNegativeButton("确定",new DialogInterface.OnClickListener(){

            @Override
            public void onClick(DialogInterface dialog, int which) {
                ActivityCollector.finishAll();
            }
        });

        AlertDialog alertDialog = builder.create();
        alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);//点击
        alertDialog.show();
    }
}

好了,到这里基本就实现了强制当前账号下线的功能了,代码很简单。
最后附上demo下载地址:点击打开

阅读更多

没有更多推荐了,返回首页