==
几乎每个app都会有登录注册的功能,可以看看笔者开发的『南方周末新闻阅读器』,登录、手机注册、忘记密码这些入口,这些功能在app中要如何来实现呢?这个模块看似很简单,但要做好就需要考虑很多细节,比如对用户的输入的容错,操作的提示文案的设定,登录成功保存用户信息等等。
业务流程图
=====
业务逻辑描述
======
上一节的流程图已经很清晰的展现了登录注册的流程,这里继续用文字说明一下:
1. 点击进入个人中心或者需要用户登录状态的操作,先判断用户是否已经登录。
2. 如果已经登录,则继续后面的业务,否则,跳转到登录页面进行登录。
3. 如果已经有账号,则可以直接登录,或者可以直接选择第三方平台授权登录。
4. 如果未注册账号,则需要先进行账号注册,注册成功后再登录;也可以不注册账号,通过第三方平台授权进行登录。
5. 如果有账号,但忘记密码,则需要进行重置密码,否则直接登录。
具体实现
====
登录可以使用账号登录,现在的app基本上都是手机号码登录,注册的时候也是一个手机对应一个账号,通过发送验证码进行验证;用户也可以选择第三方平台进行登录,一般会提供微信、QQ、新浪微博这样的主流社交平台进行授权登录,这里笔者使用了友盟的SDK进行实现。
示例代码:LoginActivity.java
package com.devilwwj.loginandregister;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.text.method.HideReturnsTransformationMethod;
import android.text.method.PasswordTransformationMethod;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.TextView;
import android.widget.Toast;
import com.devilwwj.loginandregister.global.AppConstants;
import com.devilwwj.loginandregister.utils.LogUtils;
import com.devilwwj.loginandregister.utils.ProgressDialogUtils;
import com.devilwwj.loginandregister.utils.RegexUtils;
import com.devilwwj.loginandregister.utils.ShareUtils;
import com.devilwwj.loginandregister.utils.SpUtils;
import com.devilwwj.loginandregister.utils.ToastUtils;
import com.devilwwj.loginandregister.utils.Utils;
import com.devilwwj.loginandregister.views.CleanEditText;
import com.umeng.socialize.bean.SHARE_MEDIA;
import com.umeng.socialize.controller.UMServiceFactory;
import com.umeng.socialize.controller.UMSocialService;
import com.umeng.socialize.controller.listener.SocializeListeners.UMAuthListener;
import com.umeng.socialize.controller.listener.SocializeListeners.UMDataListener;
import com.umeng.socialize.exception.SocializeException;
import java.util.Map;
import static android.view.View.OnClickListener;
/**
-
@desc 登录界面
-
Created by devilwwj on 16/1/24.
*/
public class LoginActivity extends Activity implements OnClickListener {
private static final String TAG = “loginActivity”;
private static final int REQUEST_CODE_TO_REGISTER = 0x001;
// 界面控件
private CleanEditText accountEdit;
private CleanEditText passwordEdit;
// 第三方平台获取的访问token,有效时间,uid
private String accessToken;
private String expires_in;
private String uid;
private String sns;
// 整个平台的Controller,负责管理整个SDK的配置、操作等处理
private UMSocialService mController = UMServiceFactory
.getUMSocialService(AppConstants.DESCRIPTOR);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
initViews();
// 配置分享平台
ShareUtils.configPlatforms(this);
}
/**
- 初始化视图
*/
private void initViews() {
accountEdit = (CleanEditText) this.findViewById(R.id.et_email_phone);
accountEdit.setImeOptions(EditorInfo.IME_ACTION_NEXT);
accountEdit.setTransformationMethod(HideReturnsTransformationMethod
.getInstance());
passwordEdit = (CleanEditText) this.findViewById(R.id.et_password);
passwordEdit.setImeOptions(EditorInfo.IME_ACTION_DONE);
passwordEdit.setImeOptions(EditorInfo.IME_ACTION_GO);
passwordEdit.setTransformationMethod(PasswordTransformationMethod
.getInstance());
passwordEdit.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE
|| actionId == EditorInfo.IME_ACTION_GO) {
clickLogin();
}
return false;
}
});
}
private void clickLogin() {
String account = accountEdit.getText().toString();
String password = passwordEdit.getText().toString();
if (checkInput(account, password)) {
// 《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》无偿开源 徽信搜索公众号【编程进阶路】 TODO: 请求服务器登录账号
}
}
/**
-
检查输入
-
@param account
-
@param password
-
@return
*/
public boolean checkInput(String account, String password) {
// 账号为空时提示
if (account == null || account.trim().equals(“”)) {
Toast.makeText(this, R.string.tip_account_empty, Toast.LENGTH_LONG)
.show();
} else {
// 账号不匹配手机号格式(11位数字且以1开头)
if ( !RegexUtils.checkMobile(account)) {
Toast.makeText(this, R.string.tip_account_regex_not_right,
Toast.LENGTH_LONG).show();
} else if (password == null || password.trim().equals(“”)) {
Toast.makeText(this, R.string.tip_password_can_not_be_empty,
Toast.LENGTH_LONG).show();
} else {
return true;
}
}
return false;
}
@Override
public void onClick(View v) {
Intent intent = null;
switch (v.getId()) {
case R.id.iv_cancel:
finish();
break;
case R.id.btn_login:
clickLogin();
break;
case R.id.iv_wechat:
clickLoginWexin();
break;
case R.id.iv_qq:
clickLoginQQ();
break;
case R.id.iv_sina:
loginThirdPlatform(SHARE_MEDIA.SINA);
break;
case R.id.tv_create_account:
enterRegister();
break;
case R.id.tv_forget_password:
enterForgetPwd();
break;
default:
break;
}
}
/**
- 点击使用QQ快速登录
*/
private void clickLoginQQ() {
if (!Utils.isQQClientAvailable(this)) {
ToastUtils.showShort(LoginActivity.this,
getString(R.string.no_install_qq));
} else {
loginThirdPlatform(SHARE_MEDIA.QZONE);
}
}
/**
- 点击使用微信登录
*/
private void clickLoginWexin() {
if (!Utils.isWeixinAvilible(this)) {
ToastUtils.showShort(LoginActivity.this,
getString(R.string.no_install_wechat));
} else {
loginThirdPlatform(SHARE_MEDIA.WEIXIN);
}
}
/**
- 跳转到忘记密码
*/
private void enterForgetPwd() {
Intent intent = new Intent(this, ForgetPasswordActivity.class);
startActivity(intent);
}
/**
- 跳转到注册页面
*/
private void enterRegister() {
Intent intent = new Intent(this, SignUpActivity.class);
startActivityForResult(intent, REQUEST_CODE_TO_REGISTER);
}
/**
-
授权。如果授权成功,则获取用户信息
-
@param platform
*/
private void loginThirdPlatform(final SHARE_MEDIA platform) {
mController.doOauthVerify(LoginActivity.this, platform,
new UMAuthListener() {
@Override
public void onStart(SHARE_MEDIA platform) {
LogUtils.i(TAG, “onStart------”
- Thread.currentThread().getId());
ProgressDialogUtils.getInstance().show(
LoginActivity.this,
getString(R.string.tip_begin_oauth));
}
@Override
public void onError(SocializeException e,
SHARE_MEDIA platform) {
LogUtils.i(TAG, “onError------”
- Thread.currentThread().getId());
ToastUtils.showShort(LoginActivity.this,
getString(R.string.oauth_fail));
ProgressDialogUtils.getInstance().dismiss();
}
@Override
public void onComplete(Bundle value, SHARE_MEDIA platform) {
LogUtils.i(TAG, “onComplete------” + value.toString());
if (platform == SHARE_MEDIA.SINA) {
accessToken = value.getString(“access_key”);
} else {
accessToken = value.getString(“access_token”);
}
expires_in = value.getString(“expires_in”);
// 获取uid
uid = value.getString(AppConstants.UID);
if (value != null && !TextUtils.isEmpty(uid)) {
// uid不为空,获取用户信息
getUserInfo(platform);
} else {
ToastUtils.showShort(LoginActivity.this,
getString(R.string.oauth_fail));
}
}
@Override
public void onCancel(SHARE_MEDIA platform) {
LogUtils.i(TAG, “onCancel------”
- Thread.currentThread().getId());
ToastUtils.showShort(LoginActivity.this,
getString(R.string.oauth_cancle));
ProgressDialogUtils.getInstance().dismiss();
}
});
}
/**
-
获取用户信息
-
@param platform
*/
private void getUserInfo(final SHARE_MEDIA platform) {
mController.getPlatformInfo(LoginActivity.this, platform,
new UMDataListener() {
@Override
public void onStart() {
// 开始获取
LogUtils.i(“getUserInfo”, “onStart------”);
ProgressDialogUtils.getInstance().dismiss();
ProgressDialogUtils.getInstance().show(
LoginActivity.this, “正在请求…”);
}
@Override
public void onComplete(int status, Map<String, Object> info) {
try {
String sns_id = “”;
String sns_avatar = “”;
String sns_loginname = “”;
if (info != null && info.size() != 0) {