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

来源:互联网 发布:吉他推荐 知乎 编辑:程序博客网 时间:2024/05/01 14:39

很多网页或者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下载地址:点击打开

1 0
原创粉丝点击