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();
}
} }
其它一些布局和资源配置我就不具体列出了,想看的能够下载 源代码
Android 实现登录界面和功能实例的更多相关文章
- C#WinForm 实现登录界面验证码功能(区分大小写+不区分大小写)
原文:C#WinForm 实现登录界面验证码功能(区分大小写+不区分大小写) 文章来自:https://blog.csdn.net/IT_xiao_guang_guang/article/detail ...
- Android studio登录界面
打开Android studio,你需要建立两个类LoginMainAcitivity.java和SuccessMainActivity.java,和与之相对应的xml布局文件login_main.x ...
- Android 用户登录界面
本篇博客主要给大家演示怎样一步一步地创建一个类似于下图展示的这么一个UI界面: 一.准备图片资源 记住:因为Demo其中用到的图片资源都是直接从上面图片截取的,所以图片质量上面会差一些,只是.不影响我 ...
- 删除CSDN点击“阅读更多”按钮跳转到登录界面的功能
manifest.json { "manifest_version": 2, "name": "Helper2", "versio ...
- 基于easyUI实现登录界面
此文章是基于 EasyUI+Knockout实现经典表单的查看.编辑 一. 准备工作 1. 点击此下载相关文件,并把文件放到 ims 工程对应的文件夹下 二. 相关文件介绍 1. login.jsp: ...
- [转]Android:布局实例之模仿QQ登录界面
Android:布局实例之模仿QQ登录界面 预览图: 准备: 1.找到模仿对象 QQ登陆界面UI下载>>>>> 2.导入工程 3.查看布局结构和使用控件 其对应效果图分布 ...
- Android:布局实例之模仿QQ登录界面
预览图: 准备: 1.找到模仿对象 QQ登陆界面UI下载>>>>> 2.导入工程 3.查看布局结构和使用控件 其对应效果图分布为 4.分析样式选择器 下拉箭头2种样式:点 ...
- Android:布局实例之模仿京东登录界面
预览图及布局结构参考: 布局: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout ...
- Android开发实例之miniTwitter登录界面的实现
原文: http://www.jizhuomi.com/android/example/134.html 本文要演示的Android开发实例是如何完成一个Android中的miniTwitter登录界 ...
随机推荐
- 关于XML的简单整理
- scrapy安装
1.scrapy的安装 -前提,最好用virtualenv 创建的虚拟环境安装 -windows -官方推荐用anaconda -自定已安装 -1.https://www.lfd.uci.edu/~g ...
- SQL-内连接、外连接(左、右)、交叉连接
本文测试基于以下两个表,student(左) \ teacher(右),使用数据库MariaDB,图形化界面HeidiSQL. 连接查询的概念:根据两个表或多个表的列之间的关系,从这些表中查询数据,即 ...
- Stm32基础
Stm32基础 目录 常用功能函数 跑马灯实验 蜂鸣器实验 按键实验 端口复用与重映射 常用功能函数 初始化gpio函数 作用:初始化一个或者多个io口(同一组)的工作方式和速度该函数主要是操作GPI ...
- VBA调用DOS程序两种方法
Set wsh = VBA.CreateObject("WScript.Shell") 'wsh.Run strExePath & " g", vbHi ...
- curl获取结果乱码的解决方法之CURLOPT_ENCODING(curl/Post请求)
//php脚本开始 /*POST请求远程内容函数*/ function ppost($url,$data,$ref){ // 模拟提交数据函数 $curl = curl_init( ...
- php回话控制 cookie
<?php class CustomCookie{ static private $_instance = null; private function __construct(array $o ...
- [JOISC2014]バス通学
[JOISC2014]バス通学 题目大意: 有\(n(n\le10^5)\)个点和\(m(m\le3\times10^5)\)条交通线路.第\(i\)条交通线路可以让你在时间\(x_i\)从\(a_i ...
- ubuntu下使用nvm安装nodejs
sudo apt-get install curl curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.6/install. ...
- (转)nginx uwsgi wsgi django 这些东西究竟是什么关系
有太多的文章告诉我们nginx uwsgi django 这些东西怎么用了,太多的人知道这些东西的怎么使用,怎么配置,怎么优化,但是还是有一部分人比如我这种水货不知道这些东西到底是啥,为啥一个项目的发 ...