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

来源:互联网 发布:学校图书馆wind数据库 编辑:程序博客网 时间:2024/05/21 14:02

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

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


运行效果图:



主要的代码:

1、用户类User

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.example.logindemo;  
  2.   
  3. import org.json.JSONException;  
  4. import org.json.JSONObject;  
  5. import android.util.Log;  
  6.   
  7. public class User {  
  8.     private String mId;  
  9.     private String mPwd;  
  10.     private static final String masterPassword = "FORYOU"// AES加密算法的种子  
  11.     private static final String JSON_ID = "user_id";  
  12.     private static final String JSON_PWD = "user_pwd";  
  13.     private static final String TAG = "User";  
  14.   
  15.     public User(String id, String pwd) {  
  16.         this.mId = id;  
  17.         this.mPwd = pwd;  
  18.     }  
  19.   
  20.     public User(JSONObject json) throws Exception {  
  21.         if (json.has(JSON_ID)) {  
  22.             String id = json.getString(JSON_ID);  
  23.             String pwd = json.getString(JSON_PWD);  
  24.             // 解密后存放  
  25.             mId = AESUtils.decrypt(masterPassword, id);  
  26.             mPwd = AESUtils.decrypt(masterPassword, pwd);  
  27.         }  
  28.     }  
  29.   
  30.     public JSONObject toJSON() throws Exception {  
  31.         // 使用AES加密算法加密后保存  
  32.         String id = AESUtils.encrypt(masterPassword, mId);  
  33.         String pwd = AESUtils.encrypt(masterPassword, mPwd);  
  34.         Log.i(TAG, "加密后:" + id + "  " + pwd);  
  35.         JSONObject json = new JSONObject();  
  36.         try {  
  37.             json.put(JSON_ID, id);  
  38.             json.put(JSON_PWD, pwd);  
  39.         } catch (JSONException e) {  
  40.             e.printStackTrace();  
  41.         }  
  42.         return json;  
  43.     }  
  44.   
  45.     public String getId() {  
  46.         return mId;  
  47.     }  
  48.   
  49.     public String getPwd() {  
  50.         return mPwd;  
  51.     }  
  52. }  


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

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.example.logindemo;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.FileInputStream;  
  5. import java.io.FileNotFoundException;  
  6. import java.io.IOException;  
  7. import java.io.InputStreamReader;  
  8. import java.io.OutputStream;  
  9. import java.io.OutputStreamWriter;  
  10. import java.io.Writer;  
  11. import java.util.ArrayList;  
  12. import org.json.JSONArray;  
  13. import org.json.JSONException;  
  14. import org.json.JSONTokener;  
  15.   
  16. import android.content.Context;  
  17. import android.util.Log;  
  18.   
  19. public class Utils {  
  20.   
  21.     private static final String FILENAME = "userinfo.json"// 用户保存文件名  
  22.     private static final String TAG = "Utils";  
  23.   
  24.     /* 保存用户登录信息列表 */  
  25.     public static void saveUserList(Context context, ArrayList<User> users)  
  26.             throws Exception {  
  27.         /* 保存 */  
  28.         Log.i(TAG, "正在保存");  
  29.         Writer writer = null;  
  30.         OutputStream out = null;  
  31.         JSONArray array = new JSONArray();  
  32.         for (User user : users) {  
  33.             array.put(user.toJSON());  
  34.         }  
  35.         try {  
  36.             out = context.openFileOutput(FILENAME, Context.MODE_PRIVATE); // 覆盖  
  37.             writer = new OutputStreamWriter(out);  
  38.             Log.i(TAG, "json的值:" + array.toString());  
  39.             writer.write(array.toString());  
  40.         } finally {  
  41.             if (writer != null)  
  42.                 writer.close();  
  43.         }  
  44.   
  45.     }  
  46.   
  47.     /* 获取用户登录信息列表 */  
  48.     public static ArrayList<User> getUserList(Context context) {  
  49.         /* 加载 */  
  50.         FileInputStream in = null;  
  51.         ArrayList<User> users = new ArrayList<User>();  
  52.         try {  
  53.   
  54.             in = context.openFileInput(FILENAME);  
  55.             BufferedReader reader = new BufferedReader(  
  56.                     new InputStreamReader(in));  
  57.             StringBuilder jsonString = new StringBuilder();  
  58.             JSONArray jsonArray = new JSONArray();  
  59.             String line;  
  60.             while ((line = reader.readLine()) != null) {  
  61.                 jsonString.append(line);  
  62.             }  
  63.             Log.i(TAG, jsonString.toString());  
  64.             jsonArray = (JSONArray) new JSONTokener(jsonString.toString())  
  65.                     .nextValue(); // 把字符串转换成JSONArray对象  
  66.             for (int i = 0; i < jsonArray.length(); i++) {  
  67.                 User user = new User(jsonArray.getJSONObject(i));  
  68.                 users.add(user);  
  69.             }  
  70.   
  71.         } catch (FileNotFoundException e) {  
  72.             e.printStackTrace();  
  73.         } catch (IOException e) {  
  74.             e.printStackTrace();  
  75.         } catch (JSONException e) {  
  76.             e.printStackTrace();  
  77.         } catch (Exception e) {  
  78.             e.printStackTrace();  
  79.         }  
  80.   
  81.         return users;  
  82.     }  
  83. }  


3、AES加密/解密

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.example.logindemo;  
  2.   
  3.   
  4. import java.security.SecureRandom;  
  5.   
  6. import javax.crypto.Cipher;  
  7. import javax.crypto.KeyGenerator;  
  8. import javax.crypto.SecretKey;  
  9. import javax.crypto.spec.IvParameterSpec;  
  10. import javax.crypto.spec.SecretKeySpec;  
  11.   
  12. public class AESUtils {  
  13.     public static String encrypt(String seed, String cleartext)  
  14.             throws Exception {  
  15.         byte[] rawKey = getRawKey(seed.getBytes());  
  16.         byte[] result = encrypt(rawKey, cleartext.getBytes());  
  17.         return toHex(result);  
  18.     }  
  19.   
  20.     public static String decrypt(String seed, String encrypted)  
  21.             throws Exception {  
  22.         byte[] rawKey = getRawKey(seed.getBytes());  
  23.         byte[] enc = toByte(encrypted);  
  24.         byte[] result = decrypt(rawKey, enc);  
  25.         return new String(result);  
  26.     }  
  27.   
  28.     private static byte[] getRawKey(byte[] seed) throws Exception {  
  29.         KeyGenerator kgen = KeyGenerator.getInstance("AES");  
  30.         SecureRandom sr = SecureRandom.getInstance("SHA1PRNG""Crypto");  
  31.         sr.setSeed(seed);  
  32.         kgen.init(128, sr);  
  33.         SecretKey skey = kgen.generateKey();  
  34.         byte[] raw = skey.getEncoded();  
  35.         return raw;  
  36.     }  
  37.   
  38.     private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {  
  39.         SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");  
  40.         Cipher cipher = Cipher.getInstance("AES");  
  41.         cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(  
  42.                 new byte[cipher.getBlockSize()]));  
  43.         byte[] encrypted = cipher.doFinal(clear);  
  44.         return encrypted;  
  45.     }  
  46.   
  47.     private static byte[] decrypt(byte[] raw, byte[] encrypted)  
  48.             throws Exception {  
  49.         SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");  
  50.         Cipher cipher = Cipher.getInstance("AES");  
  51.         cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(  
  52.                 new byte[cipher.getBlockSize()]));  
  53.         byte[] decrypted = cipher.doFinal(encrypted);  
  54.         return decrypted;  
  55.     }  
  56.   
  57.     private static String toHex(String txt) {  
  58.         return toHex(txt.getBytes());  
  59.     }  
  60.   
  61.     private static String fromHex(String hex) {  
  62.         return new String(toByte(hex));  
  63.     }  
  64.   
  65.     private static byte[] toByte(String hexString) {  
  66.         int len = hexString.length() / 2;  
  67.         byte[] result = new byte[len];  
  68.         for (int i = 0; i < len; i++)  
  69.             result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2),  
  70.                     16).byteValue();  
  71.         return result;  
  72.     }  
  73.   
  74.     private static String toHex(byte[] buf) {  
  75.         if (buf == null)  
  76.             return "";  
  77.         StringBuffer result = new StringBuffer(2 * buf.length);  
  78.         for (int i = 0; i < buf.length; i++) {  
  79.             appendHex(result, buf[i]);  
  80.         }  
  81.         return result.toString();  
  82.     }  
  83.   
  84.     private final static String HEX = "0123456789ABCDEF";  
  85.   
  86.     private static void appendHex(StringBuffer sb, byte b) {  
  87.         sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));  
  88.     }  
  89. }  


4、LoginActivity.Java

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.example.logindemo;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. import android.app.Activity;  
  6. import android.app.Dialog;  
  7. import android.graphics.drawable.ColorDrawable;  
  8. import android.os.Bundle;  
  9. import android.text.Editable;  
  10. import android.text.TextWatcher;  
  11. import android.util.DisplayMetrics;  
  12. import android.util.Log;  
  13. import android.view.View;  
  14. import android.view.ViewGroup;  
  15. import android.view.Window;  
  16. import android.view.WindowManager;  
  17. import android.view.View.OnClickListener;  
  18. import android.view.ViewGroup.LayoutParams;  
  19. import android.view.animation.Animation;  
  20. import android.view.animation.AnimationUtils;  
  21. import android.widget.AdapterView;  
  22. import android.widget.AdapterView.OnItemClickListener;  
  23. import android.widget.ArrayAdapter;  
  24. import android.widget.Button;  
  25. import android.widget.EditText;  
  26. import android.widget.ImageView;  
  27. import android.widget.LinearLayout;  
  28. import android.widget.ListView;  
  29. import android.widget.PopupWindow;  
  30. import android.widget.PopupWindow.OnDismissListener;  
  31. import android.widget.TextView;  
  32. import android.widget.Toast;  
  33.   
  34. public class LoginActivity extends Activity implements OnClickListener,  
  35.         OnItemClickListener, OnDismissListener {  
  36.     protected static final String TAG = "LoginActivity";  
  37.     private LinearLayout mLoginLinearLayout; // 登录内容的容器  
  38.     private LinearLayout mUserIdLinearLayout; // 将下拉弹出窗口在此容器下方显示  
  39.     private Animation mTranslate; // 位移动画  
  40.     private Dialog mLoginingDlg; // 显示正在登录的Dialog  
  41.     private EditText mIdEditText; // 登录ID编辑框  
  42.     private EditText mPwdEditText; // 登录密码编辑框  
  43.     private ImageView mMoreUser; // 下拉图标  
  44.     private Button mLoginButton; // 登录按钮  
  45.     private ImageView mLoginMoreUserView; // 弹出下拉弹出窗的按钮  
  46.     private String mIdString;  
  47.     private String mPwdString;  
  48.     private ArrayList<User> mUsers; // 用户列表  
  49.     private ListView mUserIdListView; // 下拉弹出窗显示的ListView对象  
  50.     private MyAapter mAdapter; // ListView的监听器  
  51.     private PopupWindow mPop; // 下拉弹出窗  
  52.   
  53.     @Override  
  54.     public void onCreate(Bundle savedInstanceState) {  
  55.         super.onCreate(savedInstanceState);  
  56.         setContentView(R.layout.activity_login);  
  57.         initView();  
  58.         setListener();  
  59.         mLoginLinearLayout.startAnimation(mTranslate); // Y轴水平移动  
  60.   
  61.         /* 获取已经保存好的用户密码 */  
  62.         mUsers = Utils.getUserList(LoginActivity.this);  
  63.   
  64.         if (mUsers.size() > 0) {  
  65.             /* 将列表中的第一个user显示在编辑框 */  
  66.             mIdEditText.setText(mUsers.get(0).getId());  
  67.             mPwdEditText.setText(mUsers.get(0).getPwd());  
  68.         }  
  69.   
  70.         LinearLayout parent = (LinearLayout) getLayoutInflater().inflate(  
  71.                 R.layout.userifo_listview, null);  
  72.         mUserIdListView = (ListView) parent.findViewById(android.R.id.list);  
  73.         parent.removeView(mUserIdListView); // 必须脱离父子关系,不然会报错  
  74.         mUserIdListView.setOnItemClickListener(this); // 设置点击事  
  75.         mAdapter = new MyAapter(mUsers);  
  76.         mUserIdListView.setAdapter(mAdapter);  
  77.   
  78.     }  
  79.   
  80.     /* ListView的适配器 */  
  81.     class MyAapter extends ArrayAdapter<User> {  
  82.   
  83.         public MyAapter(ArrayList<User> users) {  
  84.             super(LoginActivity.this0, users);  
  85.         }  
  86.   
  87.         public View getView(final int position, View convertView,  
  88.                 ViewGroup parent) {  
  89.             if (convertView == null) {  
  90.                 convertView = getLayoutInflater().inflate(  
  91.                         R.layout.listview_item, null);  
  92.             }  
  93.   
  94.             TextView userIdText = (TextView) convertView  
  95.                     .findViewById(R.id.listview_userid);  
  96.             userIdText.setText(getItem(position).getId());  
  97.   
  98.             ImageView deleteUser = (ImageView) convertView  
  99.                     .findViewById(R.id.login_delete_user);  
  100.             deleteUser.setOnClickListener(new OnClickListener() {  
  101.                 // 点击删除deleteUser时,在mUsers中删除选中的元素  
  102.                 @Override  
  103.                 public void onClick(View v) {  
  104.   
  105.                     if (getItem(position).getId().equals(mIdString)) {  
  106.                         // 如果要删除的用户Id和Id编辑框当前值相等,则清空  
  107.                         mIdString = "";  
  108.                         mPwdString = "";  
  109.                         mIdEditText.setText(mIdString);  
  110.                         mPwdEditText.setText(mPwdString);  
  111.                     }  
  112.                     mUsers.remove(getItem(position));  
  113.                     mAdapter.notifyDataSetChanged(); // 更新ListView  
  114.                 }  
  115.             });  
  116.             return convertView;  
  117.         }  
  118.   
  119.     }  
  120.   
  121.     private void setListener() {  
  122.         mIdEditText.addTextChangedListener(new TextWatcher() {  
  123.   
  124.             public void onTextChanged(CharSequence s, int start, int before,  
  125.                     int count) {  
  126.                 mIdString = s.toString();  
  127.             }  
  128.   
  129.             public void beforeTextChanged(CharSequence s, int start, int count,  
  130.                     int after) {  
  131.             }  
  132.   
  133.             public void afterTextChanged(Editable s) {  
  134.             }  
  135.         });  
  136.         mPwdEditText.addTextChangedListener(new TextWatcher() {  
  137.   
  138.             public void onTextChanged(CharSequence s, int start, int before,  
  139.                     int count) {  
  140.                 mPwdString = s.toString();  
  141.             }  
  142.   
  143.             public void beforeTextChanged(CharSequence s, int start, int count,  
  144.                     int after) {  
  145.             }  
  146.   
  147.             public void afterTextChanged(Editable s) {  
  148.             }  
  149.         });  
  150.         mLoginButton.setOnClickListener(this);  
  151.         mLoginMoreUserView.setOnClickListener(this);  
  152.     }  
  153.   
  154.     private void initView() {  
  155.         mIdEditText = (EditText) findViewById(R.id.login_edtId);  
  156.         mPwdEditText = (EditText) findViewById(R.id.login_edtPwd);  
  157.         mMoreUser = (ImageView) findViewById(R.id.login_more_user);  
  158.         mLoginButton = (Button) findViewById(R.id.login_btnLogin);  
  159.         mLoginMoreUserView = (ImageView) findViewById(R.id.login_more_user);  
  160.         mLoginLinearLayout = (LinearLayout) findViewById(R.id.login_linearLayout);  
  161.         mUserIdLinearLayout = (LinearLayout) findViewById(R.id.userId_LinearLayout);  
  162.         mTranslate = AnimationUtils.loadAnimation(this, R.anim.my_translate); // 初始化动画对象  
  163.         initLoginingDlg();  
  164.     }  
  165.   
  166.     public void initPop() {  
  167.         int width = mUserIdLinearLayout.getWidth() - 4;  
  168.         int height = LayoutParams.WRAP_CONTENT;  
  169.         mPop = new PopupWindow(mUserIdListView, width, height, true);  
  170.         mPop.setOnDismissListener(this);// 设置弹出窗口消失时监听器  
  171.   
  172.         // 注意要加这句代码,点击弹出窗口其它区域才会让窗口消失  
  173.         mPop.setBackgroundDrawable(new ColorDrawable(0xffffffff));  
  174.   
  175.     }  
  176.   
  177.     /* 初始化正在登录对话框 */  
  178.     private void initLoginingDlg() {  
  179.   
  180.         mLoginingDlg = new Dialog(this, R.style.loginingDlg);  
  181.         mLoginingDlg.setContentView(R.layout.logining_dlg);  
  182.   
  183.         Window window = mLoginingDlg.getWindow();  
  184.         WindowManager.LayoutParams params = window.getAttributes();  
  185.         // 获取和mLoginingDlg关联的当前窗口的属性,从而设置它在屏幕中显示的位置  
  186.   
  187.         // 获取屏幕的高宽  
  188.         DisplayMetrics dm = new DisplayMetrics();  
  189.         getWindowManager().getDefaultDisplay().getMetrics(dm);  
  190.         int cxScreen = dm.widthPixels;  
  191.         int cyScreen = dm.heightPixels;  
  192.   
  193.         int height = (int) getResources().getDimension(  
  194.                 R.dimen.loginingdlg_height);// 高42dp  
  195.         int lrMargin = (int) getResources().getDimension(  
  196.                 R.dimen.loginingdlg_lr_margin); // 左右边沿10dp  
  197.         int topMargin = (int) getResources().getDimension(  
  198.                 R.dimen.loginingdlg_top_margin); // 上沿20dp  
  199.   
  200.         params.y = (-(cyScreen - height) / 2) + topMargin; // -199  
  201.         /* 对话框默认位置在屏幕中心,所以x,y表示此控件到"屏幕中心"的偏移量 */  
  202.   
  203.         params.width = cxScreen;  
  204.         params.height = height;  
  205.         // width,height表示mLoginingDlg的实际大小  
  206.   
  207.         mLoginingDlg.setCanceledOnTouchOutside(true); // 设置点击Dialog外部任意区域关闭Dialog  
  208.     }  
  209.   
  210.     /* 显示正在登录对话框 */  
  211.     private void showLoginingDlg() {  
  212.         if (mLoginingDlg != null)  
  213.             mLoginingDlg.show();  
  214.     }  
  215.   
  216.     /* 关闭正在登录对话框 */  
  217.     private void closeLoginingDlg() {  
  218.         if (mLoginingDlg != null && mLoginingDlg.isShowing())  
  219.             mLoginingDlg.dismiss();  
  220.     }  
  221.   
  222.     @Override  
  223.     public void onClick(View v) {  
  224.         switch (v.getId()) {  
  225.         case R.id.login_btnLogin:  
  226.             // 启动登录  
  227.             showLoginingDlg(); // 显示"正在登录"对话框,因为此Demo没有登录到web服务器,所以效果可能看不出.可以结合情况使用  
  228.             Log.i(TAG, mIdString + "  " + mPwdString);  
  229.             if (mIdString == null || mIdString.equals("")) { // 账号为空时  
  230.                 Toast.makeText(LoginActivity.this"请输入账号", Toast.LENGTH_SHORT)  
  231.                         .show();  
  232.             } else if (mPwdString == null || mPwdString.equals("")) {// 密码为空时  
  233.                 Toast.makeText(LoginActivity.this"请输入密码", Toast.LENGTH_SHORT)  
  234.                         .show();  
  235.             } else {// 账号和密码都不为空时  
  236.                 boolean mIsSave = true;  
  237.                 try {  
  238.                     Log.i(TAG, "保存用户列表");  
  239.                     for (User user : mUsers) { // 判断本地文档是否有此ID用户  
  240.                         if (user.getId().equals(mIdString)) {  
  241.                             mIsSave = false;  
  242.                             break;  
  243.                         }  
  244.                     }  
  245.                     if (mIsSave) { // 将新用户加入users  
  246.                         User user = new User(mIdString, mPwdString);  
  247.                         mUsers.add(user);  
  248.                     }  
  249.   
  250.                 } catch (Exception e) {  
  251.                     e.printStackTrace();  
  252.                 }  
  253.                 closeLoginingDlg();// 关闭对话框  
  254.                 Toast.makeText(this"登录成功", Toast.LENGTH_SHORT).show();  
  255.                 finish();  
  256.             }  
  257.             break;  
  258.         case R.id.login_more_user: // 当点击下拉栏  
  259.             if (mPop == null) {  
  260.                 initPop();  
  261.             }  
  262.             if (!mPop.isShowing() && mUsers.size() > 0) {  
  263.                 // Log.i(TAG, "切换为角向上图标");  
  264.                 mMoreUser.setImageResource(R.drawable.login_more_down); // 切换图标  
  265.                 mPop.showAsDropDown(mUserIdLinearLayout, 21); // 显示弹出窗口  
  266.             }  
  267.             break;  
  268.         default:  
  269.             break;  
  270.         }  
  271.   
  272.     }  
  273.   
  274.     @Override  
  275.     public void onItemClick(AdapterView<?> parent, View view, int position,  
  276.             long id) {  
  277.         mIdEditText.setText(mUsers.get(position).getId());  
  278.         mPwdEditText.setText(mUsers.get(position).getPwd());  
  279.         mPop.dismiss();  
  280.     }  
  281.   
  282.     /* PopupWindow对象dismiss时的事件 */  
  283.     @Override  
  284.     public void onDismiss() {  
  285.         // Log.i(TAG, "切换为角向下图标");  
  286.         mMoreUser.setImageResource(R.drawable.login_more_up);  
  287.     }  
  288.   
  289.     /* 退出此Activity时保存users */  
  290.     @Override  
  291.     public void onPause() {  
  292.         super.onPause();  
  293.         try {  
  294.             Utils.saveUserList(LoginActivity.this, mUsers);  
  295.         } catch (Exception e) {  
  296.             e.printStackTrace();  
  297.         }  
  298.     }  
  299.   
  300. }  


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

0 0
原创粉丝点击