Android 实现登录界面和功能实例

来源:互联网 发布:绿地集团知乎 编辑:程序博客网 时间:2024/05/18 00:26

       最近一个android小程序需要登录功能,我简单实现了一下。现在记录下来也当做个笔记,同时也希望可以相互学习。所以,如果我的代码有问题,还各位请提出来。多谢了!


下面,就简述一下此实例的主要内容:

        输入用户名和密码 ,从本地文件userinfo.json中读取users。判断此用户名是否在users中,如果不在则加入users,每次退出Activity都使用AES算法加密users,然后保存到userinfo.json中。用户名下拉菜单是由PopupWindow + ListView 实现。


运行效果图:



主要的代码:

1、用户类User

package com.example.logindemo;import org.json.JSONException;import org.json.JSONObject;import android.util.Log;public class User {private String mId;private String mPwd;private static final String masterPassword = "FORYOU"; // AES加密算法的种子private static final String JSON_ID = "user_id";private static final String JSON_PWD = "user_pwd";private static final String TAG = "User";public User(String id, String pwd) {this.mId = id;this.mPwd = pwd;}public User(JSONObject json) throws Exception {if (json.has(JSON_ID)) {String id = json.getString(JSON_ID);String pwd = json.getString(JSON_PWD);// 解密后存放mId = AESUtils.decrypt(masterPassword, id);mPwd = AESUtils.decrypt(masterPassword, pwd);}}public JSONObject toJSON() throws Exception {// 使用AES加密算法加密后保存String id = AESUtils.encrypt(masterPassword, mId);String pwd = AESUtils.encrypt(masterPassword, mPwd);Log.i(TAG, "加密后:" + id + "  " + pwd);JSONObject json = new JSONObject();try {json.put(JSON_ID, id);json.put(JSON_PWD, pwd);} catch (JSONException e) {e.printStackTrace();}return json;}public String getId() {return mId;}public String getPwd() {return mPwd;}}


2、保存和加载本地User列表

package com.example.logindemo;import java.io.BufferedReader;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.io.Writer;import java.util.ArrayList;import org.json.JSONArray;import org.json.JSONException;import org.json.JSONTokener;import android.content.Context;import android.util.Log;public class Utils {private static final String FILENAME = "userinfo.json"; // 用户保存文件名private static final String TAG = "Utils";/* 保存用户登录信息列表 */public static void saveUserList(Context context, ArrayList<User> users)throws Exception {/* 保存 */Log.i(TAG, "正在保存");Writer writer = null;OutputStream out = null;JSONArray array = new JSONArray();for (User user : users) {array.put(user.toJSON());}try {out = context.openFileOutput(FILENAME, Context.MODE_PRIVATE); // 覆盖writer = new OutputStreamWriter(out);Log.i(TAG, "json的值:" + array.toString());writer.write(array.toString());} finally {if (writer != null)writer.close();}}/* 获取用户登录信息列表 */public static ArrayList<User> getUserList(Context context) {/* 加载 */FileInputStream in = null;ArrayList<User> users = new ArrayList<User>();try {in = context.openFileInput(FILENAME);BufferedReader reader = new BufferedReader(new InputStreamReader(in));StringBuilder jsonString = new StringBuilder();JSONArray jsonArray = new JSONArray();String line;while ((line = reader.readLine()) != null) {jsonString.append(line);}Log.i(TAG, jsonString.toString());jsonArray = (JSONArray) new JSONTokener(jsonString.toString()).nextValue(); // 把字符串转换成JSONArray对象for (int i = 0; i < jsonArray.length(); i++) {User user = new User(jsonArray.getJSONObject(i));users.add(user);}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (JSONException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}return users;}}


3、AES加密/解密

package com.example.logindemo;import java.security.SecureRandom;import javax.crypto.Cipher;import javax.crypto.KeyGenerator;import javax.crypto.SecretKey;import javax.crypto.spec.IvParameterSpec;import javax.crypto.spec.SecretKeySpec;public class AESUtils {public static String encrypt(String seed, String cleartext)throws Exception {byte[] rawKey = getRawKey(seed.getBytes());byte[] result = encrypt(rawKey, cleartext.getBytes());return toHex(result);}public static String decrypt(String seed, String encrypted)throws Exception {byte[] rawKey = getRawKey(seed.getBytes());byte[] enc = toByte(encrypted);byte[] result = decrypt(rawKey, enc);return new String(result);}private static byte[] getRawKey(byte[] seed) throws Exception {KeyGenerator kgen = KeyGenerator.getInstance("AES");SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");sr.setSeed(seed);kgen.init(128, sr);SecretKey skey = kgen.generateKey();byte[] raw = skey.getEncoded();return raw;}private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");Cipher cipher = Cipher.getInstance("AES");cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()]));byte[] encrypted = cipher.doFinal(clear);return encrypted;}private static byte[] decrypt(byte[] raw, byte[] encrypted)throws Exception {SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");Cipher cipher = Cipher.getInstance("AES");cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()]));byte[] decrypted = cipher.doFinal(encrypted);return decrypted;}private static String toHex(String txt) {return toHex(txt.getBytes());}private static String fromHex(String hex) {return new String(toByte(hex));}private static byte[] toByte(String hexString) {int len = hexString.length() / 2;byte[] result = new byte[len];for (int i = 0; i < len; i++)result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2),16).byteValue();return result;}private static String toHex(byte[] buf) {if (buf == null)return "";StringBuffer result = new StringBuffer(2 * buf.length);for (int i = 0; i < buf.length; i++) {appendHex(result, buf[i]);}return result.toString();}private final static String HEX = "0123456789ABCDEF";private static void appendHex(StringBuffer sb, byte b) {sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));}}


4、LoginActivity.java

package com.example.logindemo;import java.util.ArrayList;import android.app.Activity;import android.app.Dialog;import android.graphics.drawable.ColorDrawable;import android.os.Bundle;import android.text.Editable;import android.text.TextWatcher;import android.util.DisplayMetrics;import android.util.Log;import android.view.View;import android.view.ViewGroup;import android.view.Window;import android.view.WindowManager;import android.view.View.OnClickListener;import android.view.ViewGroup.LayoutParams;import android.view.animation.Animation;import android.view.animation.AnimationUtils;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.ArrayAdapter;import android.widget.Button;import android.widget.EditText;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.ListView;import android.widget.PopupWindow;import android.widget.PopupWindow.OnDismissListener;import android.widget.TextView;import android.widget.Toast;public class LoginActivity extends Activity implements OnClickListener,OnItemClickListener, OnDismissListener {protected static final String TAG = "LoginActivity";private LinearLayout mLoginLinearLayout; // 登录内容的容器private LinearLayout mUserIdLinearLayout; // 将下拉弹出窗口在此容器下方显示private Animation mTranslate; // 位移动画private Dialog mLoginingDlg; // 显示正在登录的Dialogprivate EditText mIdEditText; // 登录ID编辑框private EditText mPwdEditText; // 登录密码编辑框private ImageView mMoreUser; // 下拉图标private Button mLoginButton; // 登录按钮private ImageView mLoginMoreUserView; // 弹出下拉弹出窗的按钮private String mIdString;private String mPwdString;private ArrayList<User> mUsers; // 用户列表private ListView mUserIdListView; // 下拉弹出窗显示的ListView对象private MyAapter mAdapter; // ListView的监听器private PopupWindow mPop; // 下拉弹出窗@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_login);initView();setListener();mLoginLinearLayout.startAnimation(mTranslate); // Y轴水平移动/* 获取已经保存好的用户密码 */mUsers = Utils.getUserList(LoginActivity.this);if (mUsers.size() > 0) {/* 将列表中的第一个user显示在编辑框 */mIdEditText.setText(mUsers.get(0).getId());mPwdEditText.setText(mUsers.get(0).getPwd());}LinearLayout parent = (LinearLayout) getLayoutInflater().inflate(R.layout.userifo_listview, null);mUserIdListView = (ListView) parent.findViewById(android.R.id.list);parent.removeView(mUserIdListView); // 必须脱离父子关系,不然会报错mUserIdListView.setOnItemClickListener(this); // 设置点击事mAdapter = new MyAapter(mUsers);mUserIdListView.setAdapter(mAdapter);}/* ListView的适配器 */class MyAapter extends ArrayAdapter<User> {public MyAapter(ArrayList<User> users) {super(LoginActivity.this, 0, users);}public View getView(final int position, View convertView,ViewGroup parent) {if (convertView == null) {convertView = getLayoutInflater().inflate(R.layout.listview_item, null);}TextView userIdText = (TextView) convertView.findViewById(R.id.listview_userid);userIdText.setText(getItem(position).getId());ImageView deleteUser = (ImageView) convertView.findViewById(R.id.login_delete_user);deleteUser.setOnClickListener(new OnClickListener() {// 点击删除deleteUser时,在mUsers中删除选中的元素@Overridepublic void onClick(View v) {if (getItem(position).getId().equals(mIdString)) {// 如果要删除的用户Id和Id编辑框当前值相等,则清空mIdString = "";mPwdString = "";mIdEditText.setText(mIdString);mPwdEditText.setText(mPwdString);}mUsers.remove(getItem(position));mAdapter.notifyDataSetChanged(); // 更新ListView}});return convertView;}}private void setListener() {mIdEditText.addTextChangedListener(new TextWatcher() {public void onTextChanged(CharSequence s, int start, int before,int count) {mIdString = s.toString();}public void beforeTextChanged(CharSequence s, int start, int count,int after) {}public void afterTextChanged(Editable s) {}});mPwdEditText.addTextChangedListener(new TextWatcher() {public void onTextChanged(CharSequence s, int start, int before,int count) {mPwdString = s.toString();}public void beforeTextChanged(CharSequence s, int start, int count,int after) {}public void afterTextChanged(Editable s) {}});mLoginButton.setOnClickListener(this);mLoginMoreUserView.setOnClickListener(this);}private void initView() {mIdEditText = (EditText) findViewById(R.id.login_edtId);mPwdEditText = (EditText) findViewById(R.id.login_edtPwd);mMoreUser = (ImageView) findViewById(R.id.login_more_user);mLoginButton = (Button) findViewById(R.id.login_btnLogin);mLoginMoreUserView = (ImageView) findViewById(R.id.login_more_user);mLoginLinearLayout = (LinearLayout) findViewById(R.id.login_linearLayout);mUserIdLinearLayout = (LinearLayout) findViewById(R.id.userId_LinearLayout);mTranslate = AnimationUtils.loadAnimation(this, R.anim.my_translate); // 初始化动画对象initLoginingDlg();}public void initPop() {int width = mUserIdLinearLayout.getWidth() - 4;int height = LayoutParams.WRAP_CONTENT;mPop = new PopupWindow(mUserIdListView, width, height, true);mPop.setOnDismissListener(this);// 设置弹出窗口消失时监听器// 注意要加这句代码,点击弹出窗口其它区域才会让窗口消失mPop.setBackgroundDrawable(new ColorDrawable(0xffffffff));}/* 初始化正在登录对话框 */private void initLoginingDlg() {mLoginingDlg = new Dialog(this, R.style.loginingDlg);mLoginingDlg.setContentView(R.layout.logining_dlg);Window window = mLoginingDlg.getWindow();WindowManager.LayoutParams params = window.getAttributes();// 获取和mLoginingDlg关联的当前窗口的属性,从而设置它在屏幕中显示的位置// 获取屏幕的高宽DisplayMetrics dm = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(dm);int cxScreen = dm.widthPixels;int cyScreen = dm.heightPixels;int height = (int) getResources().getDimension(R.dimen.loginingdlg_height);// 高42dpint lrMargin = (int) getResources().getDimension(R.dimen.loginingdlg_lr_margin); // 左右边沿10dpint topMargin = (int) getResources().getDimension(R.dimen.loginingdlg_top_margin); // 上沿20dpparams.y = (-(cyScreen - height) / 2) + topMargin; // -199/* 对话框默认位置在屏幕中心,所以x,y表示此控件到"屏幕中心"的偏移量 */params.width = cxScreen;params.height = height;// width,height表示mLoginingDlg的实际大小mLoginingDlg.setCanceledOnTouchOutside(true); // 设置点击Dialog外部任意区域关闭Dialog}/* 显示正在登录对话框 */private void showLoginingDlg() {if (mLoginingDlg != null)mLoginingDlg.show();}/* 关闭正在登录对话框 */private void closeLoginingDlg() {if (mLoginingDlg != null && mLoginingDlg.isShowing())mLoginingDlg.dismiss();}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.login_btnLogin:// 启动登录showLoginingDlg(); // 显示"正在登录"对话框,因为此Demo没有登录到web服务器,所以效果可能看不出.可以结合情况使用Log.i(TAG, mIdString + "  " + mPwdString);if (mIdString == null || mIdString.equals("")) { // 账号为空时Toast.makeText(LoginActivity.this, "请输入账号", Toast.LENGTH_SHORT).show();} else if (mPwdString == null || mPwdString.equals("")) {// 密码为空时Toast.makeText(LoginActivity.this, "请输入密码", Toast.LENGTH_SHORT).show();} else {// 账号和密码都不为空时boolean mIsSave = true;try {Log.i(TAG, "保存用户列表");for (User user : mUsers) { // 判断本地文档是否有此ID用户if (user.getId().equals(mIdString)) {mIsSave = false;break;}}if (mIsSave) { // 将新用户加入usersUser user = new User(mIdString, mPwdString);mUsers.add(user);}} catch (Exception e) {e.printStackTrace();}closeLoginingDlg();// 关闭对话框Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show();finish();}break;case R.id.login_more_user: // 当点击下拉栏if (mPop == null) {initPop();}if (!mPop.isShowing() && mUsers.size() > 0) {// Log.i(TAG, "切换为角向上图标");mMoreUser.setImageResource(R.drawable.login_more_down); // 切换图标mPop.showAsDropDown(mUserIdLinearLayout, 2, 1); // 显示弹出窗口}break;default:break;}}@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position,long id) {mIdEditText.setText(mUsers.get(position).getId());mPwdEditText.setText(mUsers.get(position).getPwd());mPop.dismiss();}/* PopupWindow对象dismiss时的事件 */@Overridepublic void onDismiss() {// Log.i(TAG, "切换为角向下图标");mMoreUser.setImageResource(R.drawable.login_more_up);}/* 退出此Activity时保存users */@Overridepublic void onPause() {super.onPause();try {Utils.saveUserList(LoginActivity.this, mUsers);} catch (Exception e) {e.printStackTrace();}}}


其他一些布局和资源配置我就不详细列出了,想看的可以下载    源码


11 0
原创粉丝点击