您的位置:首页 > 移动开发 > Android开发

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

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

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

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

运行效果图:







主要的代码:

1、用户类User

viewsourceprint?

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列表

viewsourceprint?

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加密/解密

viewsourceprint?

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

viewsourceprint?

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.
}


其他一些布局和资源配置我就不详细列出了,想看的可以下载http://www.it165.net/uploadfile/files/2014/1031/LoginDemo.zip
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: