提交 e6f29f07 编写于 作者: xuexiangjys's avatar xuexiangjys 😊

增加登录模块

上级 d3ae7bed
......@@ -32,12 +32,17 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activity.MainActivity"
android:configChanges="screenSize|keyboardHidden|orientation|keyboard"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan|stateHidden" />
<activity
android:name=".activity.LoginActivity"
android:configChanges="screenSize|keyboardHidden|orientation|keyboard"
android:launchMode="singleInstance"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan|stateHidden" />
<!--通用浏览器-->
<activity
......
/*
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.xuexiang.templateproject.activity;
import android.os.Bundle;
import android.view.KeyEvent;
import com.xuexiang.templateproject.core.BaseActivity;
import com.xuexiang.templateproject.fragment.LoginFragment;
import com.xuexiang.xui.utils.KeyboardUtils;
import com.xuexiang.xui.utils.StatusBarUtils;
import com.xuexiang.xutil.display.Colors;
/**
* 登录页面
*
* @author xuexiang
* @since 2019-11-17 22:21
*/
public class LoginActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
openPage(LoginFragment.class, getIntent().getExtras());
}
@Override
protected boolean isSupportSlideBack() {
return false;
}
@Override
protected void initStatusBarStyle() {
StatusBarUtils.initStatusBarStyle(this, false, Colors.WHITE);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return KeyboardUtils.onDisableBackKeyDown(keyCode) && super.onKeyDown(keyCode, event);
}
}
......@@ -20,7 +20,8 @@ package com.xuexiang.templateproject.activity;
import android.view.KeyEvent;
import com.xuexiang.templateproject.R;
import com.xuexiang.templateproject.utils.MMKVUtils;
import com.xuexiang.templateproject.utils.SettingUtils;
import com.xuexiang.templateproject.utils.TokenUtils;
import com.xuexiang.templateproject.utils.Utils;
import com.xuexiang.xui.utils.KeyboardUtils;
import com.xuexiang.xui.widget.activity.BaseSplashActivity;
......@@ -56,20 +57,26 @@ public class SplashActivity extends BaseSplashActivity implements CancelAdapt {
*/
@Override
protected void onSplashFinished() {
boolean isAgree = MMKVUtils.getBoolean("key_agree_privacy", false);
if (isAgree) {
ActivityUtils.startActivity(MainActivity.class);
finish();
if (SettingUtils.isAgreePrivacy()) {
loginOrGoMainPage();
} else {
Utils.showPrivacyDialog(this, (dialog, which) -> {
dialog.dismiss();
MMKVUtils.put("key_agree_privacy", true);
ActivityUtils.startActivity(MainActivity.class);
finish();
SettingUtils.setIsAgreePrivacy(true);
loginOrGoMainPage();
});
}
}
private void loginOrGoMainPage() {
if (TokenUtils.hasToken()) {
ActivityUtils.startActivity(MainActivity.class);
} else {
ActivityUtils.startActivity(LoginActivity.class);
}
finish();
}
/**
* 菜单、返回键响应
*/
......
......@@ -25,6 +25,7 @@ import com.xuexiang.xpage.base.XPageFragment;
import com.xuexiang.xpage.core.CoreSwitchBean;
import com.xuexiang.xrouter.facade.service.SerializationService;
import com.xuexiang.xrouter.launcher.XRouter;
import com.xuexiang.xui.utils.ResUtils;
import com.xuexiang.xui.widget.slideback.SlideBack;
import butterknife.ButterKnife;
......@@ -54,25 +55,18 @@ public class BaseActivity extends XPageActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// XUI.initTheme(this);
initStatusBarStyle();
super.onCreate(savedInstanceState);
mUnbinder = ButterKnife.bind(this);
// 侧滑回调
if (isSupportSlideBack()) {
SlideBack.with(this)
.haveScroll(true)
.callBack(this::popPage)
.register();
}
registerSlideBack();
}
/**
* @return 是否支持侧滑返回
* 初始化状态栏的样式
*/
protected boolean isSupportSlideBack() {
CoreSwitchBean page = getIntent().getParcelableExtra(CoreSwitchBean.KEY_SWITCH_BEAN);
return page == null || page.getBundle() == null || page.getBundle().getBoolean(KEY_SUPPORT_SLIDE_BACK, true);
protected void initStatusBarStyle() {
}
/**
......@@ -122,7 +116,38 @@ public class BaseActivity extends XPageActivity {
@Override
protected void onRelease() {
mUnbinder.unbind();
unregisterSlideBack();
super.onRelease();
}
/**
* 注册侧滑回调
*/
protected void registerSlideBack() {
if (isSupportSlideBack()) {
SlideBack.with(this)
.haveScroll(true)
.edgeMode(ResUtils.isRtl() ? SlideBack.EDGE_RIGHT : SlideBack.EDGE_LEFT)
.callBack(this::popPage)
.register();
}
}
/**
* 注销侧滑回调
*/
protected void unregisterSlideBack() {
if (isSupportSlideBack()) {
SlideBack.unregister(this);
}
}
/**
* @return 是否支持侧滑返回
*/
protected boolean isSupportSlideBack() {
CoreSwitchBean page = getIntent().getParcelableExtra(CoreSwitchBean.KEY_SWITCH_BEAN);
return page == null || page.getBundle() == null || page.getBundle().getBoolean(KEY_SUPPORT_SLIDE_BACK, true);
}
}
......@@ -93,7 +93,7 @@ public abstract class BaseFragment extends XPageFragment {
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
public void onConfigurationChanged(@NonNull Configuration newConfig) {
//屏幕旋转时刷新一下title
super.onConfigurationChanged(newConfig);
ViewGroup root = (ViewGroup) getRootView();
......@@ -103,6 +103,14 @@ public abstract class BaseFragment extends XPageFragment {
}
}
@Override
public void onDestroyView() {
if (mIProgressLoader != null) {
mIProgressLoader.dismissLoading();
}
super.onDestroyView();
}
@Override
public void onResume() {
super.onResume();
......
......@@ -61,7 +61,7 @@ public abstract class BaseSimpleListFragment extends XPageSimpleListFragment {
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
public void onConfigurationChanged(@NonNull Configuration newConfig) {
//屏幕旋转时刷新一下title
super.onConfigurationChanged(newConfig);
ViewGroup root = (ViewGroup) getRootView();
......
......@@ -39,11 +39,11 @@ import butterknife.BindView;
@Page(name = "关于")
public class AboutFragment extends BaseFragment {
@BindView(R.id.version)
@BindView(R.id.tv_version)
TextView mVersionTextView;
@BindView(R.id.about_list)
XUIGroupListView mAboutGroupListView;
@BindView(R.id.copyright)
@BindView(R.id.tv_copyright)
TextView mCopyrightTextView;
@Override
......
/*
* Copyright (C) 2020 xuexiangjys(xuexiangjys@163.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.xuexiang.templateproject.fragment;
import android.graphics.Color;
import android.view.View;
import com.xuexiang.templateproject.R;
import com.xuexiang.templateproject.activity.MainActivity;
import com.xuexiang.templateproject.core.BaseFragment;
import com.xuexiang.templateproject.utils.RandomUtils;
import com.xuexiang.templateproject.utils.SettingUtils;
import com.xuexiang.templateproject.utils.TokenUtils;
import com.xuexiang.templateproject.utils.Utils;
import com.xuexiang.templateproject.utils.XToastUtils;
import com.xuexiang.xaop.annotation.SingleClick;
import com.xuexiang.xpage.annotation.Page;
import com.xuexiang.xpage.enums.CoreAnim;
import com.xuexiang.xui.utils.CountDownButtonHelper;
import com.xuexiang.xui.utils.ResUtils;
import com.xuexiang.xui.utils.ThemeUtils;
import com.xuexiang.xui.widget.actionbar.TitleBar;
import com.xuexiang.xui.widget.button.roundbutton.RoundButton;
import com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText;
import com.xuexiang.xutil.app.ActivityUtils;
import butterknife.BindView;
import butterknife.OnClick;
/**
* 登录页面
*
* @author xuexiang
* @since 2019-11-17 22:15
*/
@Page(anim = CoreAnim.none)
public class LoginFragment extends BaseFragment {
@BindView(R.id.et_phone_number)
MaterialEditText etPhoneNumber;
@BindView(R.id.et_verify_code)
MaterialEditText etVerifyCode;
@BindView(R.id.btn_get_verify_code)
RoundButton btnGetVerifyCode;
private CountDownButtonHelper mCountDownHelper;
@Override
protected int getLayoutId() {
return R.layout.fragment_login;
}
@Override
protected TitleBar initTitle() {
TitleBar titleBar = super.initTitle()
.setImmersive(true);
titleBar.setBackgroundColor(Color.TRANSPARENT);
titleBar.setTitle("");
titleBar.setLeftImageDrawable(ResUtils.getVectorDrawable(getContext(), R.drawable.ic_login_close));
titleBar.setActionTextColor(ThemeUtils.resolveColor(getContext(), R.attr.colorAccent));
titleBar.addAction(new TitleBar.TextAction(R.string.title_jump_login) {
@Override
public void performAction(View view) {
onLoginSuccess();
}
});
return titleBar;
}
@Override
protected void initViews() {
mCountDownHelper = new CountDownButtonHelper(btnGetVerifyCode, 60);
//隐私政策弹窗
if (!SettingUtils.isAgreePrivacy()) {
Utils.showPrivacyDialog(getContext(), (dialog, which) -> {
dialog.dismiss();
SettingUtils.setIsAgreePrivacy(true);
});
}
}
@SingleClick
@OnClick({R.id.btn_get_verify_code, R.id.btn_login, R.id.tv_other_login, R.id.tv_forget_password, R.id.tv_user_protocol, R.id.tv_privacy_protocol})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.btn_get_verify_code:
if (etPhoneNumber.validate()) {
getVerifyCode(etPhoneNumber.getEditValue());
}
break;
case R.id.btn_login:
if (etPhoneNumber.validate()) {
if (etVerifyCode.validate()) {
loginByVerifyCode(etPhoneNumber.getEditValue(), etVerifyCode.getEditValue());
}
}
break;
case R.id.tv_other_login:
XToastUtils.info("其他登录方式");
break;
case R.id.tv_forget_password:
XToastUtils.info("忘记密码");
break;
case R.id.tv_user_protocol:
XToastUtils.info("用户协议");
break;
case R.id.tv_privacy_protocol:
XToastUtils.info("隐私政策");
break;
default:
break;
}
}
/**
* 获取验证码
*/
private void getVerifyCode(String phoneNumber) {
// TODO: 2020/8/29 这里只是界面演示而已
XToastUtils.warning("只是演示,验证码请随便输");
mCountDownHelper.start();
}
/**
* 根据验证码登录
*
* @param phoneNumber 手机号
* @param verifyCode 验证码
*/
private void loginByVerifyCode(String phoneNumber, String verifyCode) {
// TODO: 2020/8/29 这里只是界面演示而已
onLoginSuccess();
}
/**
* 登录成功的处理
*/
private void onLoginSuccess() {
String token = RandomUtils.getRandomNumbersAndLetters(16);
if (TokenUtils.handleLoginSuccess(token)) {
popToBack();
ActivityUtils.startActivity(MainActivity.class);
}
}
@Override
public void onDestroyView() {
if (mCountDownHelper != null) {
mCountDownHelper.recycle();
}
super.onDestroyView();
}
}
......@@ -19,10 +19,13 @@ package com.xuexiang.templateproject.fragment;
import com.xuexiang.templateproject.R;
import com.xuexiang.templateproject.core.BaseFragment;
import com.xuexiang.templateproject.utils.TokenUtils;
import com.xuexiang.templateproject.utils.XToastUtils;
import com.xuexiang.xaop.annotation.SingleClick;
import com.xuexiang.xpage.annotation.Page;
import com.xuexiang.xui.widget.dialog.DialogLoader;
import com.xuexiang.xui.widget.textview.supertextview.SuperTextView;
import com.xuexiang.xutil.XUtil;
import butterknife.BindView;
......@@ -64,7 +67,7 @@ public class SettingsFragment extends BaseFragment implements SuperTextView.OnSu
@SingleClick
@Override
public void onClick(SuperTextView superTextView) {
switch(superTextView.getId()) {
switch (superTextView.getId()) {
case R.id.menu_common:
case R.id.menu_privacy:
case R.id.menu_push:
......@@ -72,9 +75,22 @@ public class SettingsFragment extends BaseFragment implements SuperTextView.OnSu
XToastUtils.toast(superTextView.getLeftString());
break;
case R.id.menu_change_account:
case R.id.menu_logout:
XToastUtils.toast(superTextView.getCenterString());
break;
case R.id.menu_logout:
DialogLoader.getInstance().showConfirmDialog(
getContext(),
getString(R.string.lab_logout_confirm),
getString(R.string.lab_yes),
(dialog, which) -> {
dialog.dismiss();
XUtil.getActivityLifecycleHelper().exit();
TokenUtils.handleLogoutSuccess();
},
getString(R.string.lab_no),
(dialog, which) -> dialog.dismiss()
);
break;
default:
break;
}
......
......@@ -248,4 +248,23 @@ public final class MMKVUtils {
}
/**
* 判断键值对是否存在
*
* @param key 键
* @return 键值对是否存在
*/
public static boolean containsKey(String key) {
return getsMMKV().containsKey(key);
}
/**
* 清除指定键值对
*
* @param key 键
*/
public static void remove(String key) {
getsMMKV().remove(key).apply();
}
}
/*
* Copyright (C) 2018 xuexiangjys(xuexiangjys@163.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.xuexiang.templateproject.utils;
import android.graphics.Color;
import android.text.TextUtils;
import java.util.Random;
/**
* <pre>
* desc : Random Utils
* author : xuexiang
* time : 2018/4/28 上午12:41
* </pre>
* <ul>
* Shuffling algorithm
* <li>{@link #shuffle(Object[])} Shuffling algorithm, Randomly permutes the specified array using a default source of
* randomness</li>
* <li>{@link #shuffle(Object[], int)} Shuffling algorithm, Randomly permutes the specified array</li>
* <li>{@link #shuffle(int[])} Shuffling algorithm, Randomly permutes the specified int array using a default source of
* randomness</li>
* <li>{@link #shuffle(int[], int)} Shuffling algorithm, Randomly permutes the specified int array</li>
* </ul>
* <ul>
* get random int
* <li>{@link #getRandom(int)} get random int between 0 and max</li>
* <li>{@link #getRandom(int, int)} get random int between min and max</li>
* </ul>
* <ul>
* get random numbers or letters
* <li>{@link #getRandomCapitalLetters(int)} get a fixed-length random string, its a mixture of uppercase letters</li>
* <li>{@link #getRandomLetters(int)} get a fixed-length random string, its a mixture of uppercase and lowercase letters
* </li>
* <li>{@link #getRandomLowerCaseLetters(int)} get a fixed-length random string, its a mixture of lowercase letters</li>
* <li>{@link #getRandomNumbers(int)} get a fixed-length random string, its a mixture of numbers</li>
* <li>{@link #getRandomNumbersAndLetters(int)} get a fixed-length random string, its a mixture of uppercase, lowercase
* letters and numbers</li>
* <li>{@link #getRandom(String, int)} get a fixed-length random string, its a mixture of chars in source</li>
* <li>{@link #getRandom(char[], int)} get a fixed-length random string, its a mixture of chars in sourceChar</li>
* </ul>
*
*/
public final class RandomUtils {
public static final String NUMBERS_AND_LETTERS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static final String NUMBERS = "0123456789";
public static final String LETTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static final String CAPITAL_LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static final String LOWER_CASE_LETTERS = "abcdefghijklmnopqrstuvwxyz";
/**
* Don't let anyone instantiate this class.
*/
private RandomUtils() {
throw new Error("Do not need instantiate!");
}
/**
* 在数字和英文字母中获取一个定长的随机字符串
*
* @param length 长度
* @return 随机字符串
* @see RandomUtils#getRandom(String source, int length)
*/
public static String getRandomNumbersAndLetters(int length) {
return getRandom(NUMBERS_AND_LETTERS, length);
}
/**
* 在数字中获取一个定长的随机字符串
*
* @param length 长度
* @return 随机数字符串
* @see RandomUtils#getRandom(String source, int length)
*/
public static String getRandomNumbers(int length) {
return getRandom(NUMBERS, length);
}
/**
* 在英文字母中获取一个定长的随机字符串
*
* @param length 长度
* @return 随机字母字符串
* @see RandomUtils#getRandom(String source, int length)
*/
public static String getRandomLetters(int length) {
return getRandom(LETTERS, length);
}
/**
* 在大写英文字母中获取一个定长的随机字符串
*
* @param length 长度
* @return 随机字符串 只包含大写字母
* @see RandomUtils#getRandom(String source, int length)
*/
public static String getRandomCapitalLetters(int length) {
return getRandom(CAPITAL_LETTERS, length);
}
/**
* 在小写英文字母中获取一个定长的随机字符串
*
* @param length 长度
* @return 随机字符串 只包含小写字母
* @see RandomUtils#getRandom(String source, int length)
*/
public static String getRandomLowerCaseLetters(int length) {
return getRandom(LOWER_CASE_LETTERS, length);
}
/**
* 在一个字符数组源中获取一个定长的随机字符串
*
* @param source 源字符串
* @param length 长度
* @return <ul>
* <li>if source is null or empty, return null</li>
* <li>else see {@link RandomUtils#getRandom(char[] sourceChar, int length)}</li>
* </ul>
*/
public static String getRandom(String source, int length) {
return TextUtils.isEmpty(source) ? null : getRandom(source.toCharArray(), length);
}
/**
* 在一个字符数组源中获取一个定长的随机字符串
*
* @param sourceChar 字符数组源
* @param length 长度
* @return <ul>
* <li>if sourceChar is null or empty, return null</li>
* <li>if length less than 0, return null</li>
* </ul>
*/
public static String getRandom(char[] sourceChar, int length) {
if (sourceChar == null || sourceChar.length == 0 || length < 0) {
return null;
}
StringBuilder str = new StringBuilder(length);
Random random = new Random();
for (int i = 0; i < length; i++) {
str.append(sourceChar[random.nextInt(sourceChar.length)]);
}
return str.toString();
}
/**
* get random int between 0 and max
*
* @param max 最大随机数
* @return <ul>
* <li>if max <= 0, return 0</li>
* <li>else return random int between 0 and max</li>
* </ul>
*/
public static int getRandom(int max) {
return getRandom(0, max);
}
/**
* get random int between min and max
*
* @param min 最小随机数
* @param max 最大随机数
* @return <ul>
* <li>if min > max, return 0</li>
* <li>if min == max, return min</li>
* <li>else return random int between min and max</li>
* </ul>
*/
public static int getRandom(int min, int max) {
if (min > max) {
return 0;
}
if (min == max) {
return min;
}
return min + new Random().nextInt(max - min);
}
/**
* 获取随机颜色
*
* @return
*/
public static int getRandomColor() {
Random random = new Random();
int r = random.nextInt(256);
int g = random.nextInt(256);
int b = random.nextInt(256);
return Color.rgb(r, g, b);
}
/**
* 随机打乱数组中的内容
*
* @param objArray
* @return
*/
public static boolean shuffle(Object[] objArray) {
if (objArray == null) {
return false;
}
return shuffle(objArray, getRandom(objArray.length));
}
/**
* 随机打乱数组中的内容
*
* @param objArray
* @param shuffleCount
* @return
*/
public static boolean shuffle(Object[] objArray, int shuffleCount) {
int length;
if (objArray == null || shuffleCount < 0 || (length = objArray.length) < shuffleCount) {
return false;
}
for (int i = 1; i <= shuffleCount; i++) {
int random = getRandom(length - i);
Object temp = objArray[length - i];
objArray[length - i] = objArray[random];
objArray[random] = temp;
}
return true;
}
/**
* 随机打乱数组中的内容
*
* @param intArray
* @return
*/
public static int[] shuffle(int[] intArray) {
if (intArray == null) {
return null;
}
return shuffle(intArray, getRandom(intArray.length));
}
/**
* 随机打乱数组中的内容
*
* @param intArray
* @param shuffleCount
* @return
*/
public static int[] shuffle(int[] intArray, int shuffleCount) {
int length;
if (intArray == null || shuffleCount < 0 || (length = intArray.length) < shuffleCount) {
return null;
}
int[] out = new int[shuffleCount];
for (int i = 1; i <= shuffleCount; i++) {
int random = getRandom(length - i);
out[i - 1] = intArray[random];
int temp = intArray[length - i];
intArray[length - i] = intArray[random];
intArray[random] = temp;
}
return out;
}
}
package com.xuexiang.templateproject.utils;
/**
* SharedPreferences管理工具基类
*
* @author xuexiang
* @since 2018/11/27 下午5:16
*/
public final class SettingUtils {
private SettingUtils() {
throw new UnsupportedOperationException("u can't instantiate me...");
}
private static final String IS_FIRST_OPEN_KEY = "is_first_open_key";
private static final String IS_AGREE_PRIVACY_KEY = "is_agree_privacy_key";
/**
* 是否是第一次启动
*/
public static boolean isFirstOpen() {
return MMKVUtils.getBoolean(IS_FIRST_OPEN_KEY, true);
}
/**
* 设置是否是第一次启动
*/
public static void setIsFirstOpen(boolean isFirstOpen) {
MMKVUtils.put(IS_FIRST_OPEN_KEY, isFirstOpen);
}
/**
* @return 是否同意隐私政策
*/
public static boolean isAgreePrivacy() {
return MMKVUtils.getBoolean(IS_AGREE_PRIVACY_KEY, false);
}
public static void setIsAgreePrivacy(boolean isAgreePrivacy) {
MMKVUtils.put(IS_AGREE_PRIVACY_KEY, isAgreePrivacy);
}
}
/*
* Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.xuexiang.templateproject.utils;
import android.content.Context;
import com.umeng.analytics.MobclickAgent;
import com.xuexiang.templateproject.activity.LoginActivity;
import com.xuexiang.xutil.app.ActivityUtils;
import com.xuexiang.xutil.common.StringUtils;
/**
* Token管理工具
*
* @author xuexiang
* @since 2019-11-17 22:37
*/
public final class TokenUtils {
private static String sToken;
private static final String KEY_TOKEN = "com.xuexiang.templateproject.utils.KEY_TOKEN";
private TokenUtils() {
throw new UnsupportedOperationException("u can't instantiate me...");
}
private static final String KEY_PROFILE_CHANNEL = "github";
/**
* 初始化Token信息
*/
public static void init(Context context) {
MMKVUtils.init(context);
sToken = MMKVUtils.getString(KEY_TOKEN, "");
}
public static void setToken(String token) {
sToken = token;
MMKVUtils.put(KEY_TOKEN, token);
}
public static void clearToken() {
sToken = null;
MMKVUtils.remove(KEY_TOKEN);
}
public static String getToken() {
return sToken;
}
public static boolean hasToken() {
return MMKVUtils.containsKey(KEY_TOKEN);
}
/**
* 处理登录成功的事件
*
* @param token 账户信息
*/
public static boolean handleLoginSuccess(String token) {
if (!StringUtils.isEmpty(token)) {
XToastUtils.success("登录成功!");
MobclickAgent.onProfileSignIn(KEY_PROFILE_CHANNEL, token);
setToken(token);
return true;
} else {
XToastUtils.error("登录失败!");
return false;
}
}
/**
* 处理登出的事件
*/
public static void handleLogoutSuccess() {
MobclickAgent.onProfileSignOff();
//登出时,清除账号信息
clearToken();
XToastUtils.success("登出成功!");
//跳转到登录页
ActivityUtils.startActivity(LoginActivity.class);
}
}
......@@ -21,7 +21,7 @@ import android.app.Application;
import com.xuexiang.templateproject.MyApp;
import com.xuexiang.templateproject.core.BaseActivity;
import com.xuexiang.templateproject.utils.MMKVUtils;
import com.xuexiang.templateproject.utils.TokenUtils;
import com.xuexiang.templateproject.utils.XToastUtils;
import com.xuexiang.xaop.XAOP;
import com.xuexiang.xhttp2.XHttpSDK;
......@@ -72,7 +72,7 @@ public final class XBasicLibInit {
*/
private static void initXUtil(Application application) {
XUtil.debug(MyApp.isDebug());
MMKVUtils.init(application);
TokenUtils.init(application);
}
/**
......
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
~
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="?attr/colorAccent" />
<item android:state_selected="true" android:color="?attr/colorAccent" />
<item android:state_enabled="false" android:color="@color/xui_btn_disable_color" />
<item android:color="?attr/colorAccent" />
</selector>
\ No newline at end of file
<!--
~ Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
~
-->
<vector android:height="24dp" android:viewportHeight="1024"
android:viewportWidth="1024" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#299ee3" android:pathData="M597.8,511.49 L813.56,295.72c23.83,-23.83 23.83,-62.47 0,-86.31 -23.83,-23.83 -62.47,-23.83 -86.31,0L511.49,425.18 295.72,209.41c-23.83,-23.83 -62.48,-23.83 -86.31,0 -23.83,23.83 -23.83,62.47 0,86.31l215.77,215.77L209.41,727.26c-23.83,23.83 -23.83,62.47 0,86.31 23.83,23.83 62.47,23.83 86.31,0l215.77,-215.77 215.77,215.77c23.83,23.83 62.48,23.83 86.31,0 23.83,-23.83 23.83,-62.47 0,-86.31L597.8,511.49z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M869.03,393.85a54.14,54.14 0,0 1,54.14 54.14v467.74a54.14,54.14 0,0 1,-54.14 54.14H154.97a54.14,54.14 0,0 1,-54.14 -54.14V447.98a54.14,54.14 0,0 1,54.14 -54.14h714.07m0,-54.14H154.97a108.27,108.27 0,0 0,-108.27 108.27v467.74a108.27,108.27 0,0 0,108.27 108.27h714.07a108.27,108.27 0,0 0,108.27 -108.27V447.98a108.27,108.27 0,0 0,-108.27 -108.27z"
android:fillColor="#000000"/>
<path
android:pathData="M817.87,362.72h-54.14v-56.84a251.74,251.74 0,1 0,-503.47 0v56.84h-54.14v-56.84a305.87,305.87 0,1 1,611.75 0z"
android:fillColor="#000000"/>
<path
android:pathData="M438.64,520.53m71.46,0l3.79,0q71.46,0 71.46,71.46l0,3.79q0,71.46 -71.46,71.46l-3.79,0q-71.46,0 -71.46,-71.46l0,-3.79q0,-71.46 71.46,-71.46Z"
android:fillColor="#000000"/>
<path
android:pathData="M483.04,567.63m28.15,0l1.35,0q28.15,0 28.15,28.15l0,204.37q0,28.15 -28.15,28.15l-1.35,0q-28.15,0 -28.15,-28.15l0,-204.37q0,-28.15 28.15,-28.15Z"
android:fillColor="#000000"/>
</vector>
<vector android:height="24dp" android:viewportHeight="1024"
android:viewportWidth="1024" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#000000" android:pathData="M640,542.72c76.8,-44.8 128,-128 128,-217.6 0,-140.8 -115.2,-256 -256,-256s-256,108.8 -256,249.6c0,96 51.2,172.8 128,217.6 -166.4,51.2 -281.6,204.8 -288,384 0,25.6 12.8,38.4 32,38.4s32,-12.8 32,-32c6.4,-192 160,-345.6 352,-345.6s345.6,153.6 352,345.6c0,19.2 12.8,32 32,32s32,-12.8 32,-32c-6.4,-179.2 -121.6,-332.8 -288,-384zM320,318.72c0,-108.8 83.2,-192 192,-192s192,83.2 192,192 -83.2,192 -192,192 -192,-83.2 -192,-192z"/>
</vector>
......@@ -40,7 +40,15 @@
app:srcCompat="@drawable/ic_logo_app" />
<TextView
android:id="@+id/version"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:text="@string/app_name"
android:textColor="@color/xui_config_color_gray_3"
android:textSize="16sp" />
<TextView
android:id="@+id/tv_version"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
......@@ -59,7 +67,7 @@
android:layout_weight="1" />
<TextView
android:id="@+id/copyright"
android:id="@+id/tv_copyright"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="25dp"
......
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
~
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_gravity="center_horizontal"
app:srcCompat="@mipmap/ic_launcher" />
<TextView
style="@style/TextStyle.Title"
android:layout_width="match_parent"
android:layout_marginTop="10dp"
android:text="登 录"
android:textSize="30sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="24dp"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
android:tint="?attr/colorAccent"
app:srcCompat="@drawable/ic_phone" />
<com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
android:id="@+id/et_phone_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="36dp"
android:hint="@string/tip_please_input_phone_number"
android:inputType="number"
app:met_clearButton="true"
app:met_errorMessage="@string/tip_phone_number_error"
app:met_floatingLabel="normal"
app:met_floatingLabelText="@string/title_phone_number"
app:met_regexp="@string/regex_phone_number" />
</FrameLayout>
<FrameLayout
android:id="@+id/fl_verify_code"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
android:tint="?attr/colorAccent"
app:srcCompat="@drawable/ic_password" />
<com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
android:id="@+id/et_verify_code"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="36dp"
android:hint="@string/hint_please_input_verify_code"
android:inputType="number"
app:met_clearButton="false"
app:met_errorMessage="@string/tip_verify_code_error"
app:met_floatingLabel="normal"
app:met_floatingLabelText="@string/lab_verify_code"
app:met_maxCharacters="4"
app:met_regexp="@string/regex_verify_code" />
<com.xuexiang.xui.widget.button.roundbutton.RoundButton
android:id="@+id/btn_get_verify_code"
style="@style/RoundButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:paddingStart="10dp"
android:paddingTop="3dp"
android:paddingEnd="10dp"
android:paddingBottom="3dp"
android:text="@string/action_get_verify_code"
android:textColor="@color/selector_round_button_main_theme_color"
android:textSize="13sp"
app:rb_borderColor="@color/selector_round_button_main_theme_color"
app:rb_borderWidth="1.5dp"
app:rb_radius="15dp" />
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.xuexiang.xui.widget.alpha.XUIAlphaTextView
android:id="@+id/tv_other_login"
style="@style/TextStyle.Explain"
android:layout_gravity="start"
android:paddingStart="10dp"
android:paddingTop="5dp"
android:paddingEnd="10dp"
android:paddingBottom="5dp"
android:text="其他登录方式"
android:textColor="@color/xui_config_color_primary_text" />
<com.xuexiang.xui.widget.alpha.XUIAlphaTextView
android:id="@+id/tv_forget_password"
style="@style/TextStyle.Explain"
android:layout_gravity="end"
android:paddingStart="10dp"
android:paddingTop="5dp"
android:paddingEnd="10dp"
android:paddingBottom="5dp"
android:text="忘记密码"
android:textColor="@color/xui_config_color_primary_text" />
</FrameLayout>
</LinearLayout>
<com.xuexiang.xui.widget.textview.supertextview.SuperButton
android:id="@+id/btn_login"
style="@style/SuperButton.Primary.Login"
android:layout_marginTop="16dp"
android:text="@string/title_login_register" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginBottom="20dp"
android:gravity="center_horizontal"
android:orientation="horizontal">
<TextView
style="@style/TextStyle.Explain"
android:layout_width="wrap_content"
android:text="登陆/注册代表您已阅读并同意"
android:textColor="@color/xui_config_color_primary_text" />
<com.xuexiang.xui.widget.alpha.XUIAlphaTextView
android:id="@+id/tv_user_protocol"
style="@style/TextStyle.Explain"
android:layout_width="wrap_content"
android:text="用户协议"
android:textColor="?attr/colorAccent" />
<TextView
style="@style/TextStyle.Explain"
android:layout_width="wrap_content"
android:text="和"
android:textColor="@color/xui_config_color_primary_text" />
<com.xuexiang.xui.widget.alpha.XUIAlphaTextView
android:id="@+id/tv_privacy_protocol"
style="@style/TextStyle.Explain"
android:layout_width="wrap_content"
android:text="隐私政策"
android:textColor="?attr/colorAccent" />
</LinearLayout>
</FrameLayout>
</LinearLayout>
\ No newline at end of file
......@@ -41,4 +41,32 @@
<string name="content_privacy_explain_again">我们非常重视对你个人信息的保护,承诺严格按照《%s隐私权政策》保护及处理你的信息。如果你不同意该政策,很遗憾我们将无法为你提供服务</string>
<string name="lab_privacy_name">《%s隐私权政策》</string>
<!-- 登录 -->
<string name="title_login_register">登录/注册</string>
<string name="action_get_verify_code">获取验证码</string>
<string name="title_login">登录</string>
<string name="title_login_by_verify_code">验证码登录</string>
<string name="title_register">注册</string>
<string name="lab_forget_password">忘记密码?</string>
<string name="lab_login_by_verify_code">验证码登录</string>
<string name="lab_login_by_password">密码登录</string>
<string name="tip_please_input_phone_number">请输入手机号码</string>
<string name="title_phone_number">手机号码</string>
<string name="title_password">密码</string>
<string name="title_old_password">旧密码</string>
<string name="hint_please_input_verify_code">请输入验证码</string>
<string name="lab_verify_code">验证码</string>
<string name="tip_password_error">密码必须是8~18位字母和数字的组合!</string>
<string name="tip_new_password_error">新密码必须是8~18位字母和数字的组合!</string>
<string name="tip_phone_number_error">无效的手机号!</string>
<string name="regex_phone_number">^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(16[6])|(17[0,1,3,5-8])|(18[0-9])|(19[8,9]))\\d{8}$</string>
<string name="tip_verify_code_error">请输入4位数验证码</string>
<string name="regex_verify_code">^\\d{4}$</string>
<string name="regex_password">^(?:(?=.*[a-zA-Z])(?=.*[0-9])).{8,18}$</string>
<string name="title_forget_password">重置密码</string>
<string name="lab_register_account">点击注册即表示同意</string>
<string name="lab_service_protocol"><![CDATA[<用户协议>]]></string>
<string name="lab_logout_confirm">是否确认退出账号?</string>
<string name="title_jump_login">跳过</string>
</resources>
......@@ -83,4 +83,15 @@
<item name="android:overScrollMode">never</item>
</style>
<style name="SuperButton.Primary.Login">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">40dp</item>
<item name="android:layout_marginStart">50dp</item>
<item name="android:layout_marginEnd">50dp</item>
<item name="sCornersRadius">20dp</item>
<item name="sSelectorNormalColor">?attr/colorAccent</item>
<item name="sSelectorPressedColor">?attr/colorAccent</item>
<item name="android:textColor">@color/xui_config_color_white</item>
</style>
</resources>
\ No newline at end of file
......@@ -240,13 +240,13 @@ ext.isRelease = this.&isRelease
//默认添加代码仓库路径
static def addRepos(RepositoryHandler handler) {
handler.google()
handler.jcenter()
handler.mavenCentral()
//Add the aliyun repository
handler.maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
//Add the JitPack repository
handler.maven { url "https://jitpack.io" }
handler.jcenter()
handler.mavenCentral()
handler.maven { url "https://dl.bintray.com/umsdk/release" }
//Add the aliyun repository
handler.maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
handler.maven{ url 'https://oss.sonatype.org/content/repositories/public'}
//Add the Local repository
handler.maven{ url 'LocalRepository'}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册