Android 實現登入介面和功能執行個體,android登入介面
最近一個android小程式需要登入功能,我簡單實現了一下。現在記錄下來也當做個筆記,同時也希望可以相互學習。所以,如果My Code有問題,還各位請提出來。多謝了!
下面,就簡述一下此執行個體的主要內容:
輸入使用者名稱和密碼 ,從本地檔案userinfo.json中讀取users。判斷此使用者名稱是否在users中,如果不在則加入users,每次退出Activity都使用AES演算法加密users,然後儲存到userinfo.json中。使用者名稱下拉式功能表是由PopupWindow + ListView 實現。
運行:
主要的代碼:
1、使用者類User
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<User> 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<User> getUserList(Context context) {/* 載入 */FileInputStream in = null;ArrayList<User> users = new ArrayList<User>();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; // 顯示正在登入的Dialogprivate EditText mIdEditText; // 登入ID編輯框private EditText mPwdEditText; // 登入密碼編輯框private ImageView mMoreUser; // 下拉表徵圖private Button mLoginButton; // 登入按鈕private ImageView mLoginMoreUserView; // 彈出下拉彈出窗的按鈕private String mIdString;private String mPwdString;private ArrayList<User> mUsers; // 使用者列表private ListView mUserIdListView; // 下拉彈出窗顯示的ListView對象private MyAapter mAdapter; // ListView的監聽器private PopupWindow mPop; // 下拉彈出窗@Overridepublic 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<User> {public MyAapter(ArrayList<User> 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中刪除選中的元素@Overridepublic 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);// 高42dpint lrMargin = (int) getResources().getDimension(R.dimen.loginingdlg_lr_margin); // 左右邊沿10dpint topMargin = (int) getResources().getDimension(R.dimen.loginingdlg_top_margin); // 上沿20dpparams.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();}@Overridepublic 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) { // 將新使用者加入usersUser 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;}}@Overridepublic 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時的事件 */@Overridepublic void onDismiss() {// Log.i(TAG, "切換為角向標");mMoreUser.setImageResource(R.drawable.login_more_up);}/* 退出此Activity時儲存users */@Overridepublic void onPause() {super.onPause();try {Utils.saveUserList(LoginActivity.this, mUsers);} catch (Exception e) {e.printStackTrace();}}}
其他一些布局和資源配置我就不詳細列出了,想看的可以下載 源碼
android 編程中,我想實現 第一次開始安裝時出來功可以簡介,第二次進入就不在出來功可以簡介,直接登陸介面,
安裝的時候是沒有功能簡介的,安裝的過程是android系統控制的,只會讀取你程式中聲明的許可權..
你說的是安裝按成第一次運行吧?
如果這樣的話就存個sharePreference吧.
每次啟動的時候讀取下,第一次肯定讀不到就顯示簡介介面,然後儲存sharePreference,
以後就不會顯示了..這個很簡單吧
Android上怎實現自動登陸功可以?
可以用SharedPreferences存貯你的賬戶資訊,也可以用資料庫,這裡你隨便。思路可以是這樣:寫一個Welcome介面,在onCreate方法中判斷,根據條件來跳轉到對應的活動。比如沒有設定checked,則啟動登入介面LoadActivity;設定了的話,讀取配置資訊或是資料庫中存有的使用者名稱和密碼來自動登入,驗證成功後跳轉到應用功能介面。