LoginHelper.java 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. package com.xzjmyk.pm.activity.helper;
  2. import android.content.Context;
  3. import android.content.Intent;
  4. import android.content.IntentFilter;
  5. import android.text.TextUtils;
  6. import com.android.volley.Response;
  7. import com.android.volley.VolleyError;
  8. import com.xzjmyk.pm.activity.AppConfig;
  9. import com.xzjmyk.pm.activity.MyApplication;
  10. import com.xzjmyk.pm.activity.bean.LoginAuto;
  11. import com.xzjmyk.pm.activity.bean.LoginRegisterResult;
  12. import com.xzjmyk.pm.activity.bean.User;
  13. import com.xzjmyk.pm.activity.db.dao.UserDao;
  14. import com.xzjmyk.pm.activity.sp.UserSp;
  15. import com.xzjmyk.pm.activity.ui.MainActivity;
  16. import com.xzjmyk.pm.activity.util.DeviceInfoUtil;
  17. import com.xzjmyk.pm.activity.volley.ObjectResult;
  18. import com.xzjmyk.pm.activity.volley.Result;
  19. import com.xzjmyk.pm.activity.volley.StringJsonObjectRequest;
  20. import java.util.HashMap;
  21. import java.util.Map;
  22. /**
  23. * 当前登陆用户的帮助类
  24. * token
  25. *
  26. */
  27. public class LoginHelper {
  28. public static final String ACTION_LOGIN = AppConfig.sPackageName + ".action.login";// 登陆
  29. public static final String ACTION_LOGOUT = AppConfig.sPackageName + ".action.logout";// 用户手动注销登出
  30. public static final String ACTION_CONFLICT = AppConfig.sPackageName + ".action.conflict";// 登陆冲突(另外一个设备登陆了)
  31. public static final String ACTION_TOKEN= AppConfig.sPackageName + ".action.token";// token异常
  32. // 用户需要重新登陆,更新本地数据(可能是STATUS_USER_TOKEN_OVERDUE,STATUS_USER_NO_UPDATE,STATUS_USER_TOKEN_CHANGE三种状态之一)
  33. public static final String ACTION_NEED_UPDATE = AppConfig.sPackageName + ".action.need_update";
  34. public static final String ACTION_LOGIN_GIVE_UP = AppConfig.sPackageName + ".action.login_give_up";// 在下载资料的时候,没下载完就放弃登陆了
  35. /* 信息完整程度由低到高,从第2级别开始,MyApplication中的mLoginUser是有值得 */
  36. /* 没有用户,即游客(不需要进行其他操作) */
  37. public static final int STATUS_NO_USER = 0;
  38. /* 有用户,但是不完整,只有手机号,可能是之前注销过(不需要进行其他操作) */
  39. public static final int STATUS_USER_SIMPLE_TELPHONE = 1;
  40. /* 有用户,但是本地Token已经过期了(需要弹出对话框提示:本地Token已经过期,重新登陆) */
  41. public static final int STATUS_USER_TOKEN_OVERDUE = 2;
  42. /*
  43. * 有用户,本地Token未过期,但是可能信息不是最新的,即在上次登陆之后,没有更新完数据就退出了app (需要检测Token是否变更,变更即提示登陆,未变更则提示更新资料)
  44. */
  45. public static final int STATUS_USER_NO_UPDATE = 3;
  46. /*
  47. * 用户资料全部完整,但是Token已经变更了,提示重新登陆
  48. */
  49. public static final int STATUS_USER_TOKEN_CHANGE = 4;
  50. /*
  51. * 用户资料全部完整,但是还要检测Token是否变更 (需要检测Token是否变更,变更即提示登陆) 此状态比较特殊,因为有可能Token没有变更,不需要在进行登陆操作。<br/> 在检测Token接口调用失败的情况下,默认为一个不需要重新登陆的用户。
  52. * 在检测Token接口调用成功的情况下,此状态会立即过度到STATUS_USER_VALIDATION状态。
  53. */
  54. public static final int STATUS_USER_FULL = 5;
  55. /*
  56. * 用户资料全部完整,并且已经检测Token没有变更,或者新登录更新完成 (不需要进行其他操作)
  57. */
  58. public static final int STATUS_USER_VALIDATION = 6;//
  59. // 获取登陆和登出的action filter
  60. public static IntentFilter getLogInOutActionFilter() {
  61. IntentFilter intentFilter = new IntentFilter();
  62. intentFilter.addAction(ACTION_LOGIN);
  63. intentFilter.addAction(ACTION_LOGOUT);
  64. intentFilter.addAction(ACTION_CONFLICT);
  65. intentFilter.addAction(ACTION_NEED_UPDATE);
  66. intentFilter.addAction(ACTION_LOGIN_GIVE_UP);
  67. return intentFilter;
  68. }
  69. // 登陆广播,且登陆的用户为MyApplication.getInstance().mLoginUser
  70. public static void broadcastLogin(Context context) {
  71. Intent intent = new Intent(ACTION_LOGIN);
  72. context.sendBroadcast(intent);
  73. }
  74. // 登出广播
  75. public static void broadcastLogout(Context context) {
  76. Intent intent = new Intent(ACTION_LOGOUT);
  77. context.sendBroadcast(intent);
  78. }
  79. // 放弃登陆
  80. public static void broadcastLoginGiveUp(Context context) {
  81. Intent intent = new Intent(ACTION_LOGIN_GIVE_UP);
  82. context.sendBroadcast(intent);
  83. }
  84. // 登陆冲突(另外一个设备登陆了)
  85. public static void broadcastConflict(Context context) {
  86. Intent intent = new Intent(ACTION_CONFLICT);
  87. context.sendBroadcast(intent);
  88. }
  89. // 登陆冲突(另外一个设备登陆了)
  90. public static void broadcastToken(Context context) {
  91. Intent intent = new Intent(ACTION_TOKEN);
  92. context.sendBroadcast(intent);
  93. }
  94. public static void broadcastNeedUpdate(Context context) {
  95. Intent intent = new Intent(ACTION_NEED_UPDATE);
  96. context.sendBroadcast(intent);
  97. }
  98. /* 进入MainActivity,判断当前是游客,还是之前已经登陆过的用户 */
  99. public static int prepareUser(Context context) {
  100. int userStatus = STATUS_NO_USER;
  101. boolean idIsEmpty = TextUtils.isEmpty(UserSp.getInstance(context).getUserId(""));
  102. boolean telephoneIsEmpty = TextUtils.isEmpty(UserSp.getInstance(context).getTelephone(null));
  103. if (!idIsEmpty && !telephoneIsEmpty) {// 用户标识都不为空,那么就能代表一个完整的用户
  104. // 进入之前,加载本地已经存在的数据
  105. String userId = UserSp.getInstance(context).getUserId("");
  106. User user = UserDao.getInstance().getUserByUserId(userId);
  107. if (!LoginHelper.isUserValidation(user)) {// 用户数据错误,那么就认为是一个游客
  108. userStatus = STATUS_NO_USER;
  109. } else {
  110. MyApplication.getInstance().mLoginUser = user;
  111. MyApplication.getInstance().mAccessToken = UserSp.getInstance(context).getAccessToken(null);
  112. MyApplication.getInstance().mExpiresIn = UserSp.getInstance(context).getExpiresIn(0);
  113. if (LoginHelper.isTokenValidation()) {// Token未过期
  114. boolean isUpdate = UserSp.getInstance(context).isUpdate(true);
  115. if (isUpdate) {
  116. userStatus = STATUS_USER_FULL;
  117. } else {
  118. userStatus = STATUS_USER_NO_UPDATE;
  119. }
  120. } else {// Token过期
  121. userStatus = STATUS_USER_TOKEN_OVERDUE;
  122. }
  123. }
  124. } else if (!idIsEmpty) {// (适用于切换账号之后的操作)手机号不为空
  125. userStatus = STATUS_USER_SIMPLE_TELPHONE;
  126. } else {
  127. userStatus = STATUS_NO_USER;
  128. }
  129. MyApplication.getInstance().mUserStatus = userStatus;
  130. return userStatus;
  131. }
  132. // User数据是否能代表一个有效的用户
  133. public static boolean isUserValidation(User user) {
  134. if (user == null) {
  135. return false;
  136. }
  137. if (TextUtils.isEmpty(user.getUserId())) {
  138. return false;
  139. }
  140. if (TextUtils.isEmpty(user.getTelephone())) {
  141. return false;
  142. }
  143. if (TextUtils.isEmpty(user.getPassword())) {
  144. return false;
  145. }
  146. return !TextUtils.isEmpty(user.getNickName());
  147. }
  148. /**
  149. * AccessToken 是否是有效的
  150. *
  151. * @return
  152. */
  153. public static boolean isTokenValidation() {
  154. if (TextUtils.isEmpty(MyApplication.getInstance().mAccessToken)) {
  155. return false;
  156. }
  157. return MyApplication.getInstance().mExpiresIn >= System.currentTimeMillis();
  158. }
  159. /**
  160. * @desc:保存当前登录用户的信息
  161. * @author:Administrator on 2016/1/27 15:13
  162. */
  163. public static boolean setLoginUser(Context context, String telephone, String password, ObjectResult<LoginRegisterResult> result) {
  164. if (result == null) {
  165. return false;
  166. }
  167. if (result.getResultCode() != Result.CODE_SUCCESS) {
  168. return false;
  169. }
  170. if (result.getData() == null) {
  171. return false;
  172. }
  173. // 保存当前登陆的用户信息和Token信息作为全局变量,方便调用
  174. User user = MyApplication.getInstance().mLoginUser;
  175. user.setTelephone(telephone);
  176. user.setPassword(password);
  177. user.setUserId(result.getData().getUserId());
  178. user.setNickName(result.getData().getNickName());
  179. // user.setCompanyId(result.getData().getCompanyId());
  180. if (!LoginHelper.isUserValidation(user)) {// 请求下来的用户数据不完整有错误
  181. return false;
  182. }
  183. MyApplication.getInstance().mAccessToken = result.getData().getAccess_token();
  184. long expires_in = result.getData().getExpires_in() * 1000L + System.currentTimeMillis();
  185. // long expires_in = 60 * 1000L + System.currentTimeMillis();// 测试 1分钟就过期的Token
  186. MyApplication.getInstance().mExpiresIn = expires_in;
  187. if (result.getData().getLogin() != null) {
  188. user.setOfflineTime(result.getData().getLogin().getOfflineTime());
  189. }
  190. // 保存基本信息到数据库
  191. boolean saveAble = UserDao.getInstance().saveUserLogin(user);
  192. if (!saveAble) {
  193. return false;
  194. }
  195. // 保存最后一次登录的用户信息到Sp,用于免登陆
  196. UserSp.getInstance(MyApplication.getInstance()).setUserId(result.getData().getUserId());
  197. UserSp.getInstance(MyApplication.getInstance()).setTelephone(telephone);
  198. UserSp.getInstance(MyApplication.getInstance()).setAccessToken(result.getData().getAccess_token());
  199. UserSp.getInstance(MyApplication.getInstance()).setExpiresIn(expires_in);
  200. MyApplication.getInstance().mUserStatusChecked = true;
  201. MyApplication.getInstance().mUserStatus = STATUS_USER_VALIDATION;
  202. return true;
  203. }
  204. /**
  205. * 检测Status,是否要弹出更新用户状态的对话框
  206. *
  207. * @param activity
  208. * 是否弹出对话框有本方法内部逻辑决定。<br/>
  209. * 是否继续循环检测(检测未成功的情况下),<br/>
  210. * 由 MyApplication.getInstance().mUserStatusChecked值决定,( 因为方法内部有异步操作,不能直接返回值来判断) 在MainActivity中进行重复检测的判定
  211. */
  212. public static void checkStatusForUpdate(final MainActivity activity, final OnCheckedFailedListener listener) {
  213. if (MyApplication.getInstance().mUserStatusChecked) {
  214. return;
  215. }
  216. final int status = MyApplication.getInstance().mUserStatus;
  217. if (status == STATUS_NO_USER || status == STATUS_USER_SIMPLE_TELPHONE) {
  218. MyApplication.getInstance().mUserStatusChecked = true;
  219. return;
  220. }
  221. final User user = MyApplication.getInstance().mLoginUser;
  222. if (!isUserValidation(user)) {// 如果是用户数据不完整,那么就可能是数据错误,将状态变为STATUS_NO_USER和STATUS_USER_SIMPLE_TELPHONE
  223. boolean telephoneIsEmpty = TextUtils.isEmpty(UserSp.getInstance(activity).getTelephone(null));
  224. if (telephoneIsEmpty) {
  225. MyApplication.getInstance().mUserStatus = STATUS_NO_USER;
  226. } else {
  227. MyApplication.getInstance().mUserStatus = STATUS_USER_SIMPLE_TELPHONE;
  228. }
  229. return;
  230. }
  231. if (status == STATUS_USER_VALIDATION) {
  232. MyApplication.getInstance().mUserStatusChecked = true;
  233. broadcastLogin(activity);
  234. return;
  235. }
  236. if (status == STATUS_USER_TOKEN_CHANGE) {// Token已经变更,直接提示,不需要再检测Token是否变更
  237. MyApplication.getInstance().mUserStatusChecked = true;
  238. broadcastNeedUpdate(activity);
  239. return;
  240. }
  241. /**
  242. * 能往下执行的只有三种状态 <br/>
  243. * public static final int STATUS_USER_TOKEN_OVERDUE = 2;<br/>
  244. * public static final int STATUS_USER_NO_UPDATE = 3;<br/>
  245. * public static final int STATUS_USER_FULL = 5;<br/>
  246. */
  247. Map<String, String> params = new HashMap<String, String>();
  248. params.put("access_token", MyApplication.getInstance().mAccessToken);
  249. params.put("userId", user.getUserId());
  250. params.put("serial", DeviceInfoUtil.getDeviceId(activity));
  251. // 地址信息
  252. double latitude = MyApplication.getInstance().getBdLocationHelper().getLatitude();
  253. double longitude = MyApplication.getInstance().getBdLocationHelper().getLongitude();
  254. if (latitude != 0)
  255. params.put("latitude", String.valueOf(latitude));
  256. if (longitude != 0)
  257. params.put("longitude", String.valueOf(longitude));
  258. StringJsonObjectRequest<LoginAuto> request = new StringJsonObjectRequest<LoginAuto>(MyApplication.getInstance().getConfig().USER_LOGIN_AUTO,
  259. new Response.ErrorListener() {
  260. @Override
  261. public void onErrorResponse(VolleyError arg0) {
  262. if (listener != null) {
  263. listener.onCheckFailed();
  264. }
  265. }
  266. }, new StringJsonObjectRequest.Listener<LoginAuto>() {
  267. @Override
  268. public void onResponse(ObjectResult<LoginAuto> result) {
  269. boolean success = Result.defaultParser(activity, result, false);
  270. if (success && result.getData() != null) {
  271. MyApplication.getInstance().mUserStatusChecked = true;// 检测Token成功
  272. int tokenExists = result.getData().getTokenExists();// 1=令牌存在、0=令牌不存在
  273. int serialStatus = result.getData().getSerialStatus();// 1=没有设备号、2=设备号一致、3=设备号不一致
  274. if (serialStatus == 2) {// 设备号一致,说明没有切换过设备
  275. if (tokenExists == 1) {// Token也存在,说明不用登陆了
  276. if (status == STATUS_USER_FULL) {// 本地数据完整,那么就免登陆使用
  277. MyApplication.getInstance().mUserStatus = STATUS_USER_VALIDATION;
  278. } else {
  279. // do no thing 依然保持其他的状态
  280. }
  281. } else {// Token 不存在
  282. if (status == STATUS_USER_FULL) {// 数据也完整,那么就是Token过期
  283. MyApplication.getInstance().mUserStatus = STATUS_USER_TOKEN_OVERDUE;
  284. } else {
  285. // do no thing 依然保持其他的状态
  286. }
  287. }
  288. } else {// 设备号不一致,那么就是切换过手机
  289. // MyApplication.getInstance().mUserStatus = STATUS_USER_TOKEN_CHANGE;
  290. //TODO 可能存在异常提示账号在另一设备登陆情况
  291. }
  292. // 最后判断是否要跳转弹出对话框
  293. if (MyApplication.getInstance().mUserStatus != STATUS_USER_VALIDATION) {
  294. broadcastNeedUpdate(activity);
  295. } else {// 如果是用户已经完整验证,那么发出用户登录的广播
  296. broadcastLogin(activity);
  297. }
  298. } else {
  299. if (listener != null) {
  300. listener.onCheckFailed();
  301. }
  302. }
  303. }
  304. }, LoginAuto.class, params);
  305. request.setTag("checkStatus");
  306. activity.addDefaultRequest(request);
  307. }
  308. public interface OnCheckedFailedListener {// 检查Token失败才回调,然后外部在继续下一次检测
  309. void onCheckFailed();
  310. }
  311. }