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


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


    以下。就简述一下此实例的主要内容:

            输入username和password 。从本地文件userinfo.json中读取users。推断此username是否在users中,假设不在则增加users,每次退出Activity都使用AES算法加密users。然后保存到userinfo.json中。username下拉菜单是由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; // 显示正在登录的Dialog
    	private EditText mIdEditText; // 登录ID编辑框
    	private EditText mPwdEditText; // 登录password编辑框
    	private ImageView mMoreUser; // 下拉图标
    	private Button mLoginButton; // 登录button
    	private ImageView mLoginMoreUserView; // 弹出下拉弹出窗的button
    	private String mIdString;
    	private String mPwdString;
    	private ArrayList<User> mUsers; // 用户列表
    	private ListView mUserIdListView; // 下拉弹出窗显示的ListView对象
    	private MyAapter mAdapter; // ListView的监听器
    	private PopupWindow mPop; // 下拉弹出窗
    
    	@Override
    	public void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_login);
    		initView();
    		setListener();
    		mLoginLinearLayout.startAnimation(mTranslate); // Y轴水平移动
    
    		/* 获取已经保存好的用户password */
    		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中删除选中的元素
    				@Override
    				public 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);// 高42dp
    		int lrMargin = (int) getResources().getDimension(
    				R.dimen.loginingdlg_lr_margin); // 左右边沿10dp
    		int topMargin = (int) getResources().getDimension(
    				R.dimen.loginingdlg_top_margin); // 上沿20dp
    
    		params.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();
    	}
    
    	@Override
    	public void onClick(View v) {
    		switch (v.getId()) {
    		case R.id.login_btnLogin:
    			// 启动登录
    			showLoginingDlg(); // 显示"正在登录"对话框,由于此Demo没有登录到webserver,所以效果可能看不出.能够结合情况使用
    			Log.i(TAG, mIdString + "  " + mPwdString);
    			if (mIdString == null || mIdString.equals("")) { // 账号为空时
    				Toast.makeText(LoginActivity.this, "请输入账号", Toast.LENGTH_SHORT)
    						.show();
    			} else if (mPwdString == null || mPwdString.equals("")) {// password为空时
    				Toast.makeText(LoginActivity.this, "请输入password", Toast.LENGTH_SHORT)
    						.show();
    			} else {// 账号和password都不为空时
    				boolean mIsSave = true;
    				try {
    					Log.i(TAG, "保存用户列表");
    					for (User user : mUsers) { // 推断本地文档是否有此ID用户
    						if (user.getId().equals(mIdString)) {
    							mIsSave = false;
    							break;
    						}
    					}
    					if (mIsSave) { // 将新用户增加users
    						User 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;
    		}
    
    	}
    
    	@Override
    	public 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时的事件 */
    	@Override
    	public void onDismiss() {
    		// Log.i(TAG, "切换为角向下图标");
    		mMoreUser.setImageResource(R.drawable.login_more_up);
    	}
    
    	/* 退出此Activity时保存users */
    	@Override
    	public void onPause() {
    		super.onPause();
    		try {
    			Utils.saveUserList(LoginActivity.this, mUsers);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    
    }
    


    其它一些布局和资源配置我就不具体列出了,想看的能够下载    源代码


  • 相关阅读:
    使用CDN后,PHP如何获取用户的真是IP?
    git常用命令整理
    svn常用命令
    Ansible 运维自动化(一)
    grep 简单笔记
    sed 笔记
    awk命令笔记
    无限极分类(一)获得树结构
    php自定义函数求取平方根
    class path resource [config.xml] cannot be opened because it does not exist
  • 原文地址:https://www.cnblogs.com/mthoutai/p/7402431.html
Copyright © 2020-2023  润新知