时隔半年再次敲动键盘,发现时间过得真心快。原本自己该干的事情被琐碎事情给耽搁了,现在想想该重新振奋起来好好努力。闲话到此,今天给大家带来的教程是常规化也是常见的登录注册上传头像等操作,本篇也是从项目中挑出部分,项目是真实测试的,完全能实现如上操作,所以各位不用担心,由于时间原因,就不连接服务器测试了,本篇文章也只是演示下过程。包括了客户端和服务器的部分程序,当然了该篇博客仅限学习,下面进入正文。下面是项目的注册登录部分在模拟器上的演示:

在开始讲解咱们的项目之前咱们先整理下思路。在学习本篇文章前请了解并学习下列相关知识:
- okhttp网络请求库最新版本的使用方法(建议去github下载相应的okhttp工具类)
- Mysql数据库进行数据存储
- servlet相关知识(请参考 超详细servlet+jdbc+html+css实现后台管理登陆)
- Base64图片编码
- Tomcat服务器实现虚拟映射路径设置(在本篇文章中将图片保存在服务器的虚拟映射路径中)
注意:本篇文章可能不能完全把代码完全注释讲解,所以敬请大家有点耐心。
客户端:
- 编写注册界面的xml布局文件
- 实现注册界面的逻辑实现
- 编写登录界面的XML布局文件
- 实现登录界面的逻辑实现
首先我们看到客户端的整体的结构图:
注册界面布局:wyt_register.xml
效果如下:
登录界面布局wyt_login.xml:
登录界面效果如下:
接下来是我们的注册界面的逻辑代码:
RegisterAty.java
- package com.mero.wyt_register.activity;
-
- import android.app.ProgressDialog;
- import android.content.Intent;
- import android.database.Cursor;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.net.Uri;
- import android.os.Handler;
- import android.os.Message;
- import android.provider.MediaStore;
- import android.text.TextUtils;
- import android.view.Gravity;
- import android.view.View;
- import android.view.animation.AnimationSet;
- import android.view.animation.TranslateAnimation;
- import android.widget.EditText;
- import android.widget.ImageView;
- import android.widget.Toast;
-
- import com.mero.wyt_register.Base.BaseSwipeBackLayout;
- import com.mero.wyt_register.Config;
- import com.mero.wyt_register.R;
- import com.mero.wyt_register.net.RegisterAction;
- import com.mero.wyt_register.utils.AppUtils;
- import com.mero.wyt_register.utils.Base64Utils;
- import com.mero.wyt_register.utils.SDCardUtils;
- import com.mero.wyt_register.widget.RoundButton;
- import com.mero.wyt_register.widget.SelectPicPopupWindow;
-
- /**
- * Created by chenlei on 2016/11/17.
- */
-
- public class RegisterAty extends BaseSwipeBackLayout implements View.OnClickListener {
- private ImageView img_upload;
- private EditText edt_account = null;
- private EditText edt_pwd = null;
- private RoundButton btn_register = null;
- private static final int RESULT_OPEN_IMAGE = 1;
- private Bitmap bitmap ;//存放裁剪后的头像
- private String fileName;//头像名称
- private String picturePath;//头像路径
- private ProgressDialog pd;//进度条
- private static final int DISMISS = 1000;//进度条消失
- private SelectPicPopupWindow selectPicPopupWindow;
- @Override
- public void initView() {
- img_upload = (ImageView) findViewById(R.id.img_upload_img);
- edt_account = (EditText) findViewById(R.id.edt_register_account);
- edt_pwd = (EditText) findViewById(R.id.edt_register_pwd);
- img_upload.setOnClickListener(this);
- btn_register = (RoundButton) findViewById(R.id.btn_to_register);
- btn_register.setOnClickListener(this);
- }
- @Override
- public void initData() {
-
- }
- private final Handler handler = new Handler(){
- @Override
- public void handleMessage(Message msg) {
- if(msg.what == DISMISS){
- pd.dismiss();
- }
- }
- };
- @Override
- public int getLayoutResourceId() {
- return R.layout.wyt_register;
- }
-
- @Override
- public int getDialogIcon() {
- return 0;
- }
-
- @Override
- public int setStatusBarColor() {
- return 0;
- }
-
- private static final int CAMERA_REQUEST_CODE = 1;//拍照返回码
- private static final int GALLERY_REQUEST_CODE = 2;//相册返回码
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- //如果是拍照返回
- if(requestCode==CAMERA_REQUEST_CODE&&resultCode==RESULT_OK&&data!=null) {
- Uri uri = data.getData();
- if (uri != null) {
- Cursor cursor = this.getContentResolver().query(uri, null, null, null, null);
- if (cursor.moveToFirst()) {
- picturePath = cursor.getString(cursor.getColumnIndex("_data"));
- fileName = getBitmapName(picturePath);
- bitmap = AppUtils.toRoundBitmap(BitmapFactory.decodeFile(picturePath));
- //进行裁剪
- img_upload.setImageBitmap(bitmap);
- }
- } else {
- Toast.makeText(this,"保存照片失败",Toast.LENGTH_SHORT).show();
- return;
- }
- }
-
-
- //如果是相册返回
- if(requestCode==GALLERY_REQUEST_CODE&&resultCode==RESULT_OK&&null!=data){
- Uri selectedImage = data.getData();
- String[] filePathColumn = {MediaStore.Images.Media.DATA};
-
- Cursor cursor = getContentResolver().query(selectedImage,
- filePathColumn, null, null, null);
- cursor.moveToFirst();
- int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
- picturePath = cursor.getString(columnIndex);
- fileName = getBitmapName(picturePath);
- cursor.close();
- //裁剪为圆形头像
- if(SDCardUtils.isSDCardEnable()){
- bitmap = AppUtils.toRoundBitmap(BitmapFactory.decodeFile(picturePath));
- img_upload.setImageBitmap(bitmap);//设置到图片
- }else {
- return;
- }
- }else {
- return;
- }
- }
- //获取图片的名称
- public String getBitmapName(String picPath){
- String bitmapName="";
- String[] s = picPath.split("/");
- bitmapName = s[s.length-1];
- return bitmapName;
- }
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.img_upload_img:
- //判断是否从相册或者调用相机实现
- selectPicPopupWindow = new SelectPicPopupWindow(RegisterAty.this, new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- selectPicPopupWindow.dismiss();
- switch (v.getId()){
- case R.id.btn_select_camera:
- //从相机拍照
- Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
- startActivityForResult(i,1);
- break;
- case R.id.btn_select_pic_photo_lib:
- //从图库选择照片
- Intent ii = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
- startActivityForResult(ii, RESULT_OPEN_IMAGE);
- break;
- }
- }
- });
- View view = RegisterAty.this.findViewById(R.id.register);
- selectPicPopupWindow.showAtLocation(view, Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL,0,0);
- AnimationSet animationSet = new AnimationSet(true);
- TranslateAnimation translateAnimation = new TranslateAnimation(1,0,1,0);
- translateAnimation.setDuration(1000);
- animationSet.addAnimation(translateAnimation);
- view.startAnimation(translateAnimation);
- break;
- case R.id.btn_to_register:
- //点击的是注册按钮
- final String wyt_account = edt_account.getText().toString();//获取账号
- final String wyt_pwd = edt_pwd.getText().toString();//获取密码
- if(TextUtils.isEmpty(wyt_account)){
- Toast.makeText(RegisterAty.this,"账号不能为空",Toast.LENGTH_SHORT).show();
- return;
- }
- if(TextUtils.isEmpty(wyt_pwd)){
- Toast.makeText(RegisterAty.this,"密码不能为空",Toast.LENGTH_SHORT).show();
- return;
- }
- if(wyt_account.length()>20){
- Toast.makeText(RegisterAty.this,"您输入的账号过长",Toast.LENGTH_SHORT).show();
- return;
- }
- if(wyt_pwd.length()>20){
- Toast.makeText(RegisterAty.this,"您输入的密码过长",Toast.LENGTH_SHORT).show();
- return;
- }
- pd = ProgressDialog.show(this,"温馨提示","正在注册...",false,true);
- if(null!=bitmap){
- //截取图片后缀
-
- String base64img = Base64Utils.bitmaptoString(bitmap);
- //进行用户注册
- new RegisterAction(Config.URL, Config.KEY_REGISTER, wyt_account, wyt_pwd, base64img, new RegisterAction.ISuccessCallback() {
- @Override
- public void onSuccess(String response, int id) {
- pd.setMessage("注册成功");
- handler.sendEmptyMessageDelayed(DISMISS,1000);
- showActivity(RegisterAty.this,LoginAty.class);
- }
- }, new RegisterAction.IFailCallback() {
- @Override
- public void onFail(String failMsg) {
- pd.setMessage("注册失败"+failMsg);
- handler.sendEmptyMessageDelayed(DISMISS,1000);
- }
- });
- }
-
- break;
- default:
- break;
- }
- }
- private String getPicType(String picName){
- String[] s = picName.split(".");
- //数组长度
- return s[s.length-1];
- }
-
- }
然后对注册界面的网络请求进行封装:
RegisterAction.java
- package com.mero.wyt_register.net;
-
- import android.util.Log;
-
- import com.mero.wyt_register.Config;
- import com.zhy.http.okhttp.OkHttpUtils;
- import com.zhy.http.okhttp.callback.StringCallback;
-
- import org.json.JSONException;
- import org.json.JSONObject;
-
- import java.io.File;
- import java.util.HashMap;
- import java.util.Map;
-
- import okhttp3.Call;
-
- import static android.R.attr.action;
- import static com.google.android.gms.internal.zzs.TAG;
- import static com.mero.wyt_register.R.drawable.account;
- import static com.zhy.http.okhttp.OkHttpUtils.post;
-
- /**
- * Created by chenlei on 2016/11/17.
- */
-
- public class RegisterAction {
- /*
- * 注册
- * */
- public RegisterAction(String url, String action, String account, String pwd, String picBase64, final ISuccessCallback successCallback, final IFailCallback failCallback){
- OkHttpUtils
- .post()
- .url(url)
- .addParams(Config.KEY_ACTION,action)
- .addParams(Config.KEY_ACCOUNT,account)
- .addParams(Config.KEY_PWD,pwd)
- .addParams(Config.KEY_USER_ICON,picBase64)
- .build()
- .execute(new StringCallback() {
- @Override
- public void onError(Call call, Exception e, int id) {
- if(null!=failCallback){
- Log.e(TAG,"注册失败"+e.getMessage());
- failCallback.onFail(e.getMessage());
- }
- }
-
- @Override
- public void onResponse(String response, int id) {
- try {
- JSONObject jsonObject = new JSONObject(response);
- int status = jsonObject.getInt(Config.KEY_STATUS);
- int errCode = jsonObject.getInt(Config.KEY_ERR_CODE);
- if(status==1){
- successCallback.onSuccess(response,id);
- }else if(status==0){
- failCallback.onFail(response);
- }
- } catch (JSONException e) {
- e.printStackTrace();
- }
-
- }
- });
- }
- public interface ISuccessCallback{
- void onSuccess(String response,int id);
- };
- public interface IFailCallback{
- void onFail(String errCause);
- }
- }
接下来上登录界面逻辑代码:
LoginAty.java
- package com.mero.wyt_register.activity;
-
- import android.app.ProgressDialog;
- import android.content.Context;
- import android.content.SharedPreferences;
- import android.graphics.Bitmap;
- import android.os.Handler;
- import android.os.Message;
- import android.text.TextUtils;
- import android.util.Log;
- import android.view.View;
- import android.widget.EditText;
- import android.widget.TextView;
- import android.widget.Toast;
-
- import com.mero.wyt_register.Base.BaseSwipeBackLayout;
- import com.mero.wyt_register.Config;
- import com.mero.wyt_register.MyApplication;
- import com.mero.wyt_register.R;
- import com.mero.wyt_register.bean.User;
- import com.mero.wyt_register.db.DbHelper;
- import com.mero.wyt_register.net.LoginAction;
- import com.mero.wyt_register.utils.Base64Utils;
- import com.mero.wyt_register.widget.RoundButton;
-
- /**
- * Created by chenlei on 2016/11/16.
- */
-
- public class LoginAty extends BaseSwipeBackLayout implements View.OnClickListener{
- private static final String TAG = "LoginAty";
- private EditText edt_account = null;
- private EditText edt_pwd = null;
- private RoundButton btn_login_click_to_login;
- private TextView tx_register;
- private ProgressDialog pd;//进度条
- private static final int DISMISS = 0 ;
- private User user ;
-
-
-
-
- @Override
- public void initData() {
- }
-
- @Override
- public void initView() {
- edt_account = (EditText) findViewById(R.id.edt_login_account);
- edt_pwd = (EditText) findViewById(R.id.edt_login_pwd);
- tx_register = (TextView) findViewById(R.id.tx_login_click_to_register);
- btn_login_click_to_login = (RoundButton) findViewById(R.id.btn_login_click_to_login);
- btn_login_click_to_login.setOnClickListener(this);
- tx_register.setOnClickListener(this);
- }
- private final Handler handler = new Handler(){
- @Override
- public void handleMessage(Message msg) {
- if(msg.what==DISMISS){
- pd.dismiss();
- }
- }
- };
- @Override
- public int getLayoutResourceId() {
- return R.layout.wyt_login;
- }
-
- @Override
- public int getDialogIcon() {
- return 0;
- }
-
- @Override
- public int setStatusBarColor() {
- return 0;
- }
-
- @Override
- public void onClick(View v) {
- switch (v.getId()){
- case R.id.btn_login_click_to_login:
- //点击的是登录按钮
- final String wyt_account = edt_account.getText().toString();//获取账号
- final String wyt_pwd = edt_pwd.getText().toString();//获取密码
- if(TextUtils.isEmpty(wyt_account)){
- Toast.makeText(LoginAty.this,"账号不能为空",Toast.LENGTH_SHORT).show();
- return;
- }
- if(TextUtils.isEmpty(wyt_pwd)){
- Toast.makeText(LoginAty.this,"密码不能为空",Toast.LENGTH_SHORT).show();
- return;
- }
- if(wyt_account.length()>20){
- Toast.makeText(LoginAty.this,"您输入的账号过长",Toast.LENGTH_SHORT).show();
- return;
- }
- if(wyt_pwd.length()>20){
- Toast.makeText(LoginAty.this,"您输入的密码过长",Toast.LENGTH_SHORT).show();
- return;
- }
-
- String token = Config.getTokenFromPreferences(this);
- Log.e(TAG,"token的值"+token);
- //显示进度对话框
- pd = ProgressDialog.show(this,"温馨提示","正在登录",false,true);
- new LoginAction(Config.URL, Config.KEY_LOGIN, wyt_account, wyt_pwd, "", new LoginAction.ISuccessCallback() {
- @Override
- public void onSuccess(String s, String token) {
- pd.setMessage("登录成功");
- //把token保存起来
- SharedPreferences sharedPreferences = MyApplication.getMyApplication().getSharedPreferences(Config.ID, Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = sharedPreferences.edit();
- editor.putString(Config.KEY_TOKEN,token);
- editor.commit();
- //获取头像
- Bitmap bitmap = Base64Utils.stringtoBitmap(s);
- user = new User();
- user.setWyt_account(wyt_account);
- user.setWyt_pwd(wyt_pwd);
- user.setUser_icon(bitmap);
- //保存该用户到数据库中
- new DbHelper(LoginAty.this).insert(user,"user_wyt","person");
- pd.dismiss();
- showActivity(LoginAty.this,MainActivity.class);
- }
- }, new LoginAction.IFailCallback() {
- @Override
- public void onFail(String s) {
- pd.setMessage("登录失败");
- handler.sendEmptyMessageDelayed(DISMISS,1000);
- }
- });
-
- // }
-
- break;
- case R.id.tx_login_click_to_register:
- showActivity(LoginAty.this,RegisterAty.class);
- break;
- }
-
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- }
- }
下面是登录网络逻辑的封装代码:
LoginAction.java
- package com.mero.wyt_register.net;
-
- import android.graphics.Bitmap;
- import android.text.TextUtils;
- import android.util.Log;
-
- import com.mero.wyt_register.Config;
- import com.mero.wyt_register.utils.Base64Utils;
- import com.zhy.http.okhttp.OkHttpUtils;
- import com.zhy.http.okhttp.callback.StringCallback;
-
- import org.json.JSONException;
- import org.json.JSONObject;
-
- import okhttp3.Call;
-
- /**
- * Creaed by chenlei on 2016/11/15.
- */
-
- public class LoginAction {
- private static final String TAG = "loginService";
- //登录账号密码
- public LoginAction(String url, String action, String account, String pwd, String token, final ISuccessCallback successCallback, final IFailCallback failCallback){
- OkHttpUtils.post()
- .url(url)
- .addParams(Config.KEY_ACTION,action)
- .addParams(Config.KEY_ACCOUNT,account)
- .addParams(Config.KEY_PWD,pwd)
- .addParams(Config.KEY_TOKEN,token)
- .build().execute(new StringCallback() {
- @Override
- public void onError(Call call, Exception e, int id) {
- if(failCallback!=null){
- failCallback.onFail(e.getMessage());
- }
- }
-
- @Override
- public void onResponse(String response, int id) {
- try {
- JSONObject jsonObject =new JSONObject(response);
- int status = jsonObject.getInt("status");
- String iconStrBase64 = jsonObject.getString("user_icon");
- String token = jsonObject.getString("token");
- if(status==1){
- if(null!=successCallback){
- successCallback.onSuccess(iconStrBase64,token);
- }
- }else if(status==0){
- if(null!=failCallback){
- failCallback.onFail(response);
- }
- }
- } catch (JSONException e) {
- e.printStackTrace();
- }
- }
- });
-
- }
- public interface ISuccessCallback{
- void onSuccess(String s,String token);
- }
- public interface IFailCallback{
- void onFail(String s);
- }
- }
服务器端:
通过servlet实现对Action的处理,本实例仅采用了唯一的一个OnlyServlet。如果对servlet的使用不太会的话建议看下我的这篇关于servlet处理网页客户端的请求。本篇文章中不再累赘。首先我们来看看服务器的简单结构。服务器端仅仅对注册和登录,头像保存部分。
先上最关键的核心处理部分,本文中的登录注册等Action都在该servlet中处理。
OnlyServlet.java
- package com.wyt_register;
-
- import java.io.IOException;
- import java.io.PrintWriter;
- import java.sql.ResultSet;
- import java.sql.SQLException;
-
- import javax.servlet.ServletException;
- import javax.servlet.annotation.WebServlet;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
-
- import org.json.JSONException;
- import org.json.JSONStringer;
-
- import com.wyt_register.db.UserDao;
- import com.wyt_register.md5Tool.Base64Utils;
- import com.wyt_register.md5Tool.Md5Utils;
-
- /**
- * Servlet implementation class OnlyServlet
- */
- @WebServlet("/OnlyServlet")
- public class OnlyServlet extends HttpServlet {
- private static final long serialVersionUID = 1L;
-
- /**
- * @see HttpServlet#HttpServlet()
- */
- public OnlyServlet() {
- super();
- // TODO Auto-generated constructor stub
- }
-
- /**
- * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
- */
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- // TODO Auto-generated method stub
- String action = null;//根据请求的行为进行相应的操作
- if((action=request.getParameter(Config.KEY_ACTION))!=null){
- switch(action){
- // 如果是注册
- case Config.KEY_REGISTER:
- System.out.println("正在请求注册");
- // 用户注册的账号
- String account_register = request.getParameter(Config.KEY_USER_ACCOUNT);
- System.out.println(account_register);
- // 用户注册的密码
- String pwd_register = request.getParameter(Config.KEY_USER_PWD);
- System.out.println(pwd_register);
- // 用户上传的头像
- String icon = request.getParameter(Config.KEY_USER_ICON);
- if((null!=account_register)&&(null!=pwd_register)&&(null!=icon)){
- //开启注册事务
- //把唯一的账号名的md5值作为图片的名字
- StringBuilder sb0 = new StringBuilder("");
- //保存到数据库中的头像图片路径
- sb0.append("/image/").append(Md5Utils.encode(account_register)).append(".png");
- String icon_addr = sb0.toString();
- System.out.println("头像图片地址:"+icon_addr);
- StringBuilder sb1 = new StringBuilder("");
- //写入到本地的头像图片路径
- sb1.append(Config.ADDR_ICON).append(Md5Utils.encode(account_register)).append(".png");
- String local_icon_addr = sb1.toString();
- System.out.println("保存到本地的地址"+local_icon_addr);
- PrintWriter writer =response.getWriter();
- //查询用户是否已经注册过
- try {
- ResultSet set = UserDao.query(account_register);
- //没注册过,需要注册
- if(!set.next()){
- //保存上传的头像至本地
- boolean isSuccessToSaveImageToLocal = Base64Utils.getPicFormatBASE64(icon,local_icon_addr );
- if(isSuccessToSaveImageToLocal){
- //头像上传成功后然后再插入账号密码到数据库
- boolean isSuccessToRegister = UserDao.insert(new Object[]{Config.KEY_ID,Config.KEY_USER_ACCOUNT,Config.KEY_USER_PWD,Config.KEY_USER_ICON_ADDR},new Object[]{null,account_register,pwd_register,icon_addr});
- if(isSuccessToRegister){
- //注册成功
- writer.print("{\"status\":1,\"errCode\":0x00000000}");
- }else{
- //注册失败
- writer.print("{\"status\":0,\"errCode\":0x00000001}");
- }
- }
- }else{
- //注册过了
- writer.print("{\"status\":0,\"errCode\":0x00000010}");
- }
- } }
- }
- }else{
- //注册过了
- writer.print("{\"status\":0,\"errCode\":0x00000010}");
- }
- } catch (SQLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- }
- break;
- // 如果是登录
- case