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

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

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

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

运行效果图:

\\\

主要的代码:

1、用户类User

 

01. package com.example.logindemo;
02.   
03. import org.json.JSONException;
04. import org.json.JSONObject;
05. import android.util.Log;
06.   
07. public class User {
08.     private String mId;
09.     private String mPwd;
10.     private static finalString masterPass<A class=keylink href="http://www.it165.net/edu/ebg/"target=_blank>word</A> = "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(masterPass<A class=keylink href="http://www.it165.net/edu/ebg/"target=_blank>word</A>, 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列表

 

01. package com.example.logindemo;
02.   
03. import java.io.BufferedReader;
04. import java.io.FileInputStream;
05. import java.io.FileNotFoundException;
06. import java.io.IOException;
07. import java.io.InputStreamReader;
08. import java.io.OutputStream;
09. 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加密/解密

 

01. package com.example.logindemo;
02.   
03.   
04. import java.security.SecureRandom;
05.   
06. import javax.crypto.Cipher;
07. import javax.crypto.KeyGenerator;
08. import javax.crypto.SecretKey;
09. 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) throwsException {
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

 

001. package com.example.logindemo;
002.   
003. import java.util.ArrayList;
004.   
005. import android.app.Activity;
006. import android.app.Dialog;
007. import android.graphics.drawable.ColorDrawable;
008. import android.os.Bundle;
009. import android.text.Editable;
010. import android.text.TextWatcher;
011. import android.util.DisplayMetrics;
012. import android.util.Log;
013. import android.view.View;
014. import android.view.ViewGroup;
015. import android.view.Window;
016. import android.view.WindowManager;
017. import android.view.View.OnClickListener;
018. import android.view.ViewGroup.LayoutParams;
019. import android.view.animation.Animation;
020. import android.view.animation.AnimationUtils;
021. import android.widget.AdapterView;
022. import android.widget.AdapterView.OnItemClickListener;
023. import android.widget.ArrayAdapter;
024. import android.widget.Button;
025. import android.widget.EditText;
026. import android.widget.ImageView;
027. import android.widget.LinearLayout;
028. import android.widget.ListView;
029. import android.widget.PopupWindow;
030. import android.widget.PopupWindow.OnDismissListener;
031. import android.widget.TextView;
032. import android.widget.Toast;
033.   
034. public class LoginActivity extends Activity implements OnClickListener,
035.         OnItemClickListener, OnDismissListener {
036.     protected static final String TAG = "LoginActivity";
037.     private LinearLayout mLoginLinearLayout; // 登录内容的容器
038.     private LinearLayout mUserIdLinearLayout; // 将下拉弹出窗口在此容器下方显示
039.     private Animation mTranslate; // 位移动画
040.     private Dialog mLoginingDlg; // 显示正在登录的Dialog
041.     private EditText mIdEditText; // 登录ID编辑框
042.     private EditText mPwdEditText; // 登录密码编辑框
043.     private ImageView mMoreUser; // 下拉图标
044.     private Button mLoginButton; // 登录按钮
045.     private ImageView mLoginMoreUserView; // 弹出下拉弹出窗的按钮
046.     private String mIdString;
047.     private String mPwdString;
048.     private ArrayList<User> mUsers; // 用户列表
049.     private ListView mUserIdListView; // 下拉弹出窗显示的ListView对象
050.     private MyAapter mAdapter; // ListView的监听器
051.     private PopupWindow mPop; // 下拉弹出窗
052.   
053.     @Override
054.     public void onCreate(Bundle savedInstanceState) {
055.         super.onCreate(savedInstanceState);
056.         setContentView(R.layout.activity_login);
057.         initView();
058.         setListener();
059.         mLoginLinearLayout.startAnimation(mTranslate); // Y轴水平移动
060.   
061.         /* 获取已经保存好的用户密码 */
062.         mUsers = Utils.getUserList(LoginActivity.this);
063.   
064.         if (mUsers.size() > 0) {
065.             /* 将列表中的第一个user显示在编辑框 */
066.             mIdEditText.setText(mUsers.get(0).getId());
067.             mPwdEditText.setText(mUsers.get(0).getPwd());
068.         }
069.   
070.         LinearLayout parent = (LinearLayout) getLayoutInflater().inflate(
071.                 R.layout.userifo_listview, null);
072.         mUserIdListView = (ListView) parent.findViewById(android.R.id.list);
073.         parent.removeView(mUserIdListView); // 必须脱离父子关系,不然会报错
074.         mUserIdListView.setOnItemClickListener(this); // 设置点击事
075.         mAdapter = new MyAapter(mUsers);
076.         mUserIdListView.setAdapter(mAdapter);
077.   
078.     }
079.   
080.     /* ListView的适配器 */
081.     class MyAapter extends ArrayAdapter<User> {
082.   
083.         public MyAapter(ArrayList<User> users) {
084.             super(LoginActivity.this0, users);
085.         }
086.   
087.         public View getView(final int position, View convertView,
088.                 ViewGroup parent) {
089.             if (convertView == null) {
090.                 convertView = getLayoutInflater().inflate(
091.                         R.layout.listview_item, null);
092.             }
093.   
094.             TextView userIdText = (TextView) convertView
095.                     .findViewById(R.id.listview_userid);
096.             userIdText.setText(getItem(position).getId());
097.   
098.             ImageView deleteUser = (ImageView) convertView
099.                     .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, intbefore,
125.                     int count) {
126.                 mIdString = s.toString();
127.             }
128.   
129.             public void beforeTextChanged(CharSequence s, intstart, 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, intbefore,
139.                     int count) {
140.                 mPwdString = s.toString();
141.             }
142.   
143.             public void beforeTextChanged(CharSequence s, intstart, 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 = newUser(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. }

 

其他一些布局和资源配置我就不详细列出了,想看的可以下载 http://www.it165.net/uploadfile/files/2014/1031/LoginDemo.zip

猜你喜欢

转载自blog.csdn.net/scdnzhoulu/article/details/78812874