Android实现登录界面和功能实例
2015-04-01 09:46
801 查看
最近一个android小程序需要登录功能,我简单实现了一下。现在记录下来也当做个笔记,同时也希望可以相互学习。所以,如果我的代码有问题,还各位请提出来。多谢了!
下面,就简述一下此实例的主要内容:
输入用户名和密码,从本地文件userinfo.json中读取users。判断此用户名是否在users中,如果不在则加入users,每次退出Activity都使用AES算法加密users,然后保存到userinfo.json中。用户名下拉菜单是由PopupWindow+ListView实现。
运行效果图:
主要的代码:
1、用户类User
viewsourceprint?
2、保存和加载本地User列表
viewsourceprint?
3、AES加密/解密
viewsourceprint?
4、LoginActivity.java
viewsourceprint?
其他一些布局和资源配置我就不详细列出了,想看的可以下载http://www.it165.net/uploadfile/files/2014/1031/LoginDemo.zip
下面,就简述一下此实例的主要内容:
输入用户名和密码,从本地文件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
StringmId;
09.
private
StringmPwd;
10.
private
static
final
StringmasterPass<A
class
=keylinkhref=
"http://www.it165.net/edu/ebg/"
target=_blank>word</A>=
"FORYOU"
;//AES加密算法的种子
11.
private
static
final
StringJSON_ID=
"user_id"
;
12.
private
static
final
StringJSON_PWD=
"user_pwd"
;
13.
private
static
final
StringTAG=
"User"
;
14.
15.
public
User(Stringid,Stringpwd){
16.
this
.mId=id;
17.
this
.mPwd=pwd;
18.
}
19.
20.
public
User(JSONObjectjson)
throws
Exception{
21.
if
(json.has(JSON_ID)){
22.
Stringid=json.getString(JSON_ID);
23.
Stringpwd=json.getString(JSON_PWD);
24.
//解密后存放
25.
mId=AESUtils.decrypt(masterPass<A
class
=keylinkhref=
"http://www.it165.net/edu/ebg/"
target=_blank>word</A>,id);
26.
mPwd=AESUtils.decrypt(masterPassword,pwd);
27.
}
28.
}
29.
30.
public
JSONObjecttoJSON()
throws
Exception{
31.
//使用AES加密算法加密后保存
32.
Stringid=AESUtils.encrypt(masterPassword,mId);
33.
Stringpwd=AESUtils.encrypt(masterPassword,mPwd);
34.
Log.i(TAG,
"加密后:"
+id+
""
+pwd);
35.
JSONObjectjson=
new
JSONObject();
36.
try
{
37.
json.put(JSON_ID,id);
38.
json.put(JSON_PWD,pwd);
39.
}
catch
(JSONExceptione){
40.
e.printStackTrace();
41.
}
42.
return
json;
43.
}
44.
45.
public
StringgetId(){
46.
return
mId;
47.
}
48.
49.
public
StringgetPwd(){
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
StringFILENAME=
"userinfo.json"
;
//用户保存文件名
22.
private
static
final
StringTAG=
"Utils"
;
23.
24.
/*保存用户登录信息列表*/
25.
public
static
void
saveUserList(Contextcontext,ArrayList<User>users)
26.
throws
Exception{
27.
/*保存*/
28.
Log.i(TAG,
"正在保存"
);
29.
Writerwriter=
null
;
30.
OutputStreamout=
null
;
31.
JSONArrayarray=
new
JSONArray();
32.
for
(Useruser: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(Contextcontext){
49.
/*加载*/
50.
FileInputStreamin=
null
;
51.
ArrayList<User>users=
new
ArrayList<User>();
52.
try
{
53.
54.
in=context.openFileInput(FILENAME);
55.
BufferedReaderreader=
new
BufferedReader(
56.
new
InputStreamReader(in));
57.
StringBuilderjsonString=
new
StringBuilder();
58.
JSONArrayjsonArray=
new
JSONArray();
59.
Stringline;
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.
Useruser=
new
User(jsonArray.getJSONObject(i));
68.
users.add(user);
69.
}
70.
71.
}
catch
(FileNotFoundExceptione){
72.
e.printStackTrace();
73.
}
catch
(IOExceptione){
74.
e.printStackTrace();
75.
}
catch
(JSONExceptione){
76.
e.printStackTrace();
77.
}
catch
(Exceptione){
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
Stringencrypt(Stringseed,Stringcleartext)
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
Stringdecrypt(Stringseed,Stringencrypted)
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.
KeyGeneratorkgen=KeyGenerator.getInstance(
"AES"
);
30.
SecureRandomsr=SecureRandom.getInstance(
"SHA1PRNG"
,
"Crypto"
);
31.
sr.setSeed(seed);
32.
kgen.init(
128
,sr);
33.
SecretKeyskey=kgen.generateKey();
34.
byte
[]raw=skey.getEncoded();
35.
return
raw;
36.
}
37.
38.
private
static
byte
[]encrypt(
byte
[]raw,
byte
[]clear)
throws
Exception{
39.
SecretKeySpecskeySpec=
new
SecretKeySpec(raw,
"AES"
);
40.
Ciphercipher=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.
SecretKeySpecskeySpec=
new
SecretKeySpec(raw,
"AES"
);
50.
Ciphercipher=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
StringtoHex(Stringtxt){
58.
return
toHex(txt.getBytes());
59.
}
60.
61.
private
static
StringfromHex(Stringhex){
62.
return
new
String(toByte(hex));
63.
}
64.
65.
private
static
byte
[]toByte(StringhexString){
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
StringtoHex(
byte
[]buf){
75.
if
(buf==
null
)
76.
return
""
;
77.
StringBufferresult=
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
StringHEX=
"0123456789ABCDEF"
;
85.
86.
private
static
void
appendHex(StringBuffersb,
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
StringTAG=
"LoginActivity"
;
037.
private
LinearLayoutmLoginLinearLayout;
//登录内容的容器
038.
private
LinearLayoutmUserIdLinearLayout;
//将下拉弹出窗口在此容器下方显示
039.
private
AnimationmTranslate;
//位移动画
040.
private
DialogmLoginingDlg;
//显示正在登录的Dialog
041.
private
EditTextmIdEditText;
//登录ID编辑框
042.
private
EditTextmPwdEditText;
//登录密码编辑框
043.
private
ImageViewmMoreUser;
//下拉图标
044.
private
ButtonmLoginButton;
//登录按钮
045.
private
ImageViewmLoginMoreUserView;
//弹出下拉弹出窗的按钮
046.
private
StringmIdString;
047.
private
StringmPwdString;
048.
private
ArrayList<User>mUsers;
//用户列表
049.
private
ListViewmUserIdListView;
//下拉弹出窗显示的ListView对象
050.
private
MyAaptermAdapter;
//ListView的监听器
051.
private
PopupWindowmPop;
//下拉弹出窗
052.
053.
@Override
054.
public
void
onCreate(BundlesavedInstanceState){
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.
LinearLayoutparent=(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.
this
,
0
,users);
085.
}
086.
087.
public
ViewgetView(
final
int
position,ViewconvertView,
088.
ViewGroupparent){
089.
if
(convertView==
null
){
090.
convertView=getLayoutInflater().inflate(
091.
R.layout.listview_item,
null
);
092.
}
093.
094.
TextViewuserIdText=(TextView)convertView
095.
.findViewById(R.id.listview_userid);
096.
userIdText.setText(getItem(position).getId());
097.
098.
ImageViewdeleteUser=(ImageView)convertView
099.
.findViewById(R.id.login_delete_user);
100.
deleteUser.setOnClickListener(
new
OnClickListener(){
101.
//点击删除deleteUser时,在mUsers中删除选中的元素
102.
@Override
103.
public
void
onClick(Viewv){
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(CharSequences,
int
start,
int
before,
125.
int
count){
126.
mIdString=s.toString();
127.
}
128.
129.
public
void
beforeTextChanged(CharSequences,
int
start,
int
count,
130.
int
after){
131.
}
132.
133.
public
void
afterTextChanged(Editables){
134.
}
135.
});
136.
mPwdEditText.addTextChangedListener(
new
TextWatcher(){
137.
138.
public
void
onTextChanged(CharSequences,
int
start,
int
before,
139.
int
count){
140.
mPwdString=s.toString();
141.
}
142.
143.
public
void
beforeTextChanged(CharSequences,
int
start,
int
count,
144.
int
after){
145.
}
146.
147.
public
void
afterTextChanged(Editables){
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.
Windowwindow=mLoginingDlg.getWindow();
184.
WindowManager.LayoutParamsparams=window.getAttributes();
185.
//获取和mLoginingDlg关联的当前窗口的属性,从而设置它在屏幕中显示的位置
186.
187.
//获取屏幕的高宽
188.
DisplayMetricsdm=
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(Viewv){
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
(Useruser:mUsers){
//判断本地文档是否有此ID用户
240.
if
(user.getId().equals(mIdString)){
241.
mIsSave=
false
;
242.
break
;
243.
}
244.
}
245.
if
(mIsSave){
//将新用户加入users
246.
Useruser=
new
User(mIdString,mPwdString);
247.
mUsers.add(user);
248.
}
249.
250.
}
catch
(Exceptione){
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,
2
,
1
);
//显示弹出窗口
266.
}
267.
break
;
268.
default
:
269.
break
;
270.
}
271.
272.
}
273.
274.
@Override
275.
public
void
onItemClick(AdapterView<?>parent,Viewview,
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
(Exceptione){
296.
e.printStackTrace();
297.
}
298.
}
299.
300.
}
其他一些布局和资源配置我就不详细列出了,想看的可以下载
相关文章推荐
- Android 实现登录界面和功能实例
- Android实现登录界面和功能实例
- Android 实现登录界面和功能实例
- Android 实现登录界面和功能实例
- Android实现登录界面和功能实例
- Android开发实例之miniTwitter登录界面的实现
- Android开发实例之登录界面的实现
- Android实现登录界面功能和实现详解
- Android开发实例之登录界面的实现
- Android登录界面用SharedPreferences实现记住密码功能
- Android探索之路:实现登录界面的记住密码功能
- Android开发实例之miniTwitter登录界面的实现
- 功能强大的登录界面Android实现代码
- Android开发实例之登录界面的实现
- Android开发实例之miniTwitter登录界面的实现
- Android开发实例之miniTwitter登录界面的实现
- Android登录界面用SharedPreferences实现记住密码功能
- Android_登录界面功能和实现详解
- Android实现注册登录界面的实例代码
- Android实现注册登录头像上传等功能常规开发(Android端,服务器端开发实例)