時隔半年再次敲動鍵盤,發現時間過得真心快。原本自己該乾的事情被瑣碎事情給耽擱了,現在想想該重新振奮起來好好努力。閒話到此,今天給大家帶來的教程是常規化也是常見的登錄註冊上傳頭像等操作,本篇也是從項目中挑出部分,項目是真實測試的,完全能實現如上操作,所以各位不用擔心,由於時間原因,就不連接服務器測試了,本篇文章也只是演示下過程。包括了客戶端和服務器的部分程序,當然了該篇博客僅限學習,下面進入正文。下面是項目的註冊登錄部分在模擬器上的演示:
在開始講解咱們的項目之前咱們先整理下思路。在學習本篇文章前請了解並學習下列相關知識:
- 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