Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 實現登錄界面和功能實例

Android 實現登錄界面和功能實例

編輯:關於Android編程

最近一個android小程序需要登錄功能,我簡單實現了一下。現在記錄下來也當做個筆記,同時也希望可以相互學習。所以,如果我的代碼有問題,還各位請提出來。多謝了!


下面,就簡述一下此實例的主要內容:

輸入用戶名和密碼 ,從本地文件userinfo.json中讀取users。判斷此用戶名是否在users中,如果不在則加入users,每次退出Activity都使用AES算法加密users,然後保存到userinfo.json中。用戶名下拉菜單是由PopupWindow + ListView 實現。


運行效果圖:

\\\


主要的代碼:

1、用戶類User

<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHByZSBjbGFzcz0="brush:java;">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 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 getUserList(Context context) {
		/* 加載 */
		FileInputStream in = null;
		ArrayList users = new ArrayList();
		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; // 登錄密碼編輯框
	private ImageView mMoreUser; // 下拉圖標
	private Button mLoginButton; // 登錄按鈕
	private ImageView mLoginMoreUserView; // 彈出下拉彈出窗的按鈕
	private String mIdString;
	private String mPwdString;
	private ArrayList 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軸水平移動

		/* 獲取已經保存好的用戶密碼 */
		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 {

		public MyAapter(ArrayList 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沒有登錄到web服務器,所以效果可能看不出.可以結合情況使用
			Log.i(TAG, mIdString + "  " + mPwdString);
			if (mIdString == null || mIdString.equals("")) { // 賬號為空時
				Toast.makeText(LoginActivity.this, "請輸入賬號", Toast.LENGTH_SHORT)
						.show();
			} else if (mPwdString == null || mPwdString.equals("")) {// 密碼為空時
				Toast.makeText(LoginActivity.this, "請輸入密碼", Toast.LENGTH_SHORT)
						.show();
			} else {// 賬號和密碼都不為空時
				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();
		}
	}

}


其他一些布局和資源配置我就不詳細列出了,想看的可以下載 源碼


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved