Android客户端实现session会话过期的功能

前言:

项目需要实现session会话过期的功能,经过不断地调试,实现了该功能。下面我简单总结一下在客户端实现session会话过期的功能,希望对大家有所帮助!

需求:

Session会话过期,即5分钟会话到期时,用户退出应用程序。
以下四种情况需要弹出对话框提示:
1.App应用程序锁定 ; 
2.从其他应用程序活动又回到App设备 ; 
3.App应用程序不活动 ; 
4.Refresh_token过期(在拦截器处理,这里不做介绍)。
对话框有一个“OK”按钮的样式,单击“OK”用户将返回到登录页面。

思路:

1.在BaseActivity基类实现该功能,其他Activity继承BaseActivity即可。
2.在App应用程序初始化的时候,用CountTimer来处理。
3.当App应用程序锁定或者从其他应用程序活动又回到App设备,用BroadcastReceiver来处理。
4.App应用程序不活动时,重写dispatchTouchEvent,并处理。
5.弹出对话框提示用AlertDialog。

实现步骤:

1.App应用程序初始化的时候,添加CountTimer计时器。

...
private CountTimer countTimerView;

@Override
protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
        ...
        //设置5分钟后会话过期 
        countTimerView = new CountTimer(5 * 60 * 1000, 1000, BaseActivity.this);
      }
      ...
}

@Override
protected void onResume() {
     super.onResume();
     timeStart();//开始计时
}

@Override
protected void onPause() {
     super.onPause();
     if (countTimerView != null) {
         countTimerView.cancel();//当暂停的时候,要取消计时器
     }
}

private void timeStart() {
     new Handler(getMainLooper()).post(new Runnable() { //重新开一条线程
     @Override
     public void run() {
          if (countTimerView != null)
               countTimerView.start();//开始
          }
    });
}

2.当App应用程序锁定或者从其他应用程序活动又回到App设备,用BroadcastReceiver来处理。

@Override
protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      ...
      //注册广播接收者
      registerReceiver(myReceiver, new IntentFilter(Intent.ACTION_SCREEN_ON));
      registerReceiver(myReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
      registerReceiver(myReceiver, new IntentFilter(Intent.ACTION_USER_PRESENT));
      ... 
}

@Override
protected void onStart() {
     showLockScreenDialog();//调用onStart方法时,展示锁屏的dialog
     super.onStart();
}

@Override
protected void onStop() {
     count--;
     if (count == 0) {
         timeStart = new Date().getTime(); //调用onStop方法时,开始计时
    }
     super.onStop();
}


private BroadcastReceiver myReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) {//屏幕亮起来
            
            }
            if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) { //锁屏
          
            }
            if (Intent.ACTION_USER_PRESENT.equals(intent.getAction()) && isDialogClose == 0) {//解锁
                showLockScreenDialog();
            }
        }
};

private void showLockScreenDialog() {
       if (count == 0) {
            long timeEnd = new Date().getTime();
            if (timeStart != 0 && timeEnd - timeStart >= 5 * 60 * 1000) { //5分钟会话过期,弹出对话框
                  if (countTimerView != null) {
                      countTimerView.showSessionDialog();//Show session dialog
                  }         
            }
        }
        count++;
}

3.App应用程序不活动时,重写dispatchTouchEvent,并处理。

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {     
            case MotionEvent.ACTION_UP://弹起
                if (countTimerView != null)
                    countTimerView.start();//开始计时
                break;
            case MotionEvent.ACTION_DOWN://按下
                View v = getCurrentFocus();
                if (isShouldHideInput(v, ev)) {
                    hideSoftInput(v.getWindowToken());
                }
                if (countTimerView != null)
                    countTimerView.cancel();//取消计时器
                break;

            default:
                if (countTimerView != null)
                    countTimerView.cancel();//取消计时器
                break;
        }
        return super.dispatchTouchEvent(ev);
}

4.在BaseActivity实现的完整代码。

public abstract class BaseActivity extends AppCompatActivity
        implements IUIOperation, BaseView {
    private ProgressDialog mPDialog;
    private CountTimer countTimerView;
    private AlertDialog dialog;
    private AlertDialog dialog2;
    public int count = 0;
    private long timeStart;
    private int isDialogClose = 0;

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ...
        //5分钟会话过期   
        countTimerView = new CountTimer(5 * 60 * 1000, 1000, BaseActivity.this);
 
        //注册广播接收者
        registerReceiver(myReceiver, new IntentFilter(Intent.ACTION_SCREEN_ON));
        registerReceiver(myReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
        registerReceiver(myReceiver, new IntentFilter(Intent.ACTION_USER_PRESENT));
        ...

    }

    @Override
    protected void onStart() {
        showLockScreenDialog();//调用onStart方式时,弹出对话框
        super.onStart();
    }

    @Override
    protected void onResume() {
        super.onResume();
        timeStart();//开始计时
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (countTimerView != null) {
            countTimerView.cancel();//取消计时器
        }
    }

    @Override
    protected void onStop() {
        count--;
        if (count == 0) {
            timeStart = new Date().getTime();//调用onStop方法时,开始计时
        }
        if (isDialogClose == 1) {
            if (mPDialog != null) {
                mPDialog.dismiss();
                mPDialog = null;
            }
            if (dialog != null) {
                dialog.dismiss();
                dialog = null;
            }
            if (dialog2 != null) {
                dialog2.dismiss();
                dialog2 = null;
            }
        }

        super.onStop();
    }

    
    private void timeStart() {
        new Handler(getMainLooper()).post(new Runnable() {//新开一条线程
            @Override
            public void run() {
                if (countTimerView != null)
                    countTimerView.start();//开始计时
            }
        });
    }

  
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_UP: //弹起
                if (countTimerView != null)
                    countTimerView.start(); //开始计时
                break;
            case MotionEvent.ACTION_DOWN: //按下
                View v = getCurrentFocus();
                if (isShouldHideInput(v, ev)) {
                    hideSoftInput(v.getWindowToken());
                }
                if (countTimerView != null)
                    countTimerView.cancel(); //取消计时
                break;

            default:
                if (countTimerView != null)
                    countTimerView.cancel(); //取消计时
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

  
    private boolean isShouldHideInput(View v, MotionEvent event) {
        if (v != null && (v instanceof EditText)) {
            int[] l = {0, 0};
            v.getLocationInWindow(l);
            int left = l[0], top = l[1], bottom = top + v.getHeight(), right = left
                    + v.getWidth();
            if (event.getX() > left && event.getX() < right
                    && event.getY() > top && event.getY() < bottom) {
                // Click on the EditText event and ignore it.
                return false;
            } else {
                return true;
            }
        }
        return false;
    }

    
    private void hideSoftInput(IBinder token) {
        if (token != null) {
            InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            im.hideSoftInputFromWindow(token,
                    InputMethodManager.HIDE_NOT_ALWAYS);
        }
    }

    //计时器的类
    class CountTimer extends CountDownTimer {
        private Context context;

        public CountTimer(long millisInFuture, long countDownInterval, Context context) {
            super(millisInFuture, countDownInterval);
            this.context = context;
        }

        @Override
        public void onFinish() {
            showSessionDialog();//弹出对话框
        }

        @Override
        public void onTick(long millisUntilFinished) {
        }
        //自定义对话框
        private void showSessionDialog() {
            AlertDialog.Builder builder = new AlertDialog.Builder(context);
            View view = LayoutInflater.from(context).inflate(R.layout.common_session_dialog, null);
            try {
                builder.setView(view);
                TextView tvContent = (TextView) view.findViewById(R.id.tv_content);
                Button btnOk = (Button) view.findViewById(R.id.btn_ok);
                //Introducing a custom font style.
                tvContent.setTypeface(Const.font300);
                btnOk.setTypeface(Const.font700);
                builder.setCancelable(false);
                dialog = builder.create();
                dialog.setCanceledOnTouchOutside(false);
                dialog2 = builder.show();
                btnOk.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        GotoLoginActivity(context); //会话过期,要求用户直接登录
                        isDialogClose = 1;
                    }
                });

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        private void GotoLoginActivity(Context context) {
            Intent intent = new Intent(context, LoginActivity.class);
            context.startActivity(intent);//返回登录页面
            AppManager.getInstance().finishOthersActivity(LoginActivity.class);        
        }
 
    }


    private BroadcastReceiver myReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) {//屏幕亮起来

            }
            if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {//锁屏

            }
            if (Intent.ACTION_USER_PRESENT.equals(intent.getAction()) && isDialogClose == 0) {//解锁
                showLockScreenDialog();//弹出对话框
            }
        }
    };

   
    private void showLockScreenDialog() {
        if (count == 0) {
            long timeEnd = new Date().getTime();
            if (timeStart != 0 && timeEnd - timeStart >= 5 * 60 * 1000) {//5分钟会话过期               
                    if (countTimerView != null) {
                        countTimerView.showSessionDialog();//弹出对话框
                    }                
            }
        }
        count++;
    }

     ...

}

5.总结:在项目中已经实现了session会话过期四种场景的需求。欢迎大家围观,多多指教!

猜你喜欢

转载自my.oschina.net/u/3286162/blog/1800421