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 {
尾声
最后,我再重复一次,如果你想成为一个优秀的 Android 开发人员,请集中精力,对基础和重要的事情做深度研究。
对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。 整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。
这里,笔者分享一份从架构哲学的层面来剖析的视频及资料分享给大家梳理了多年的架构经验,筹备近6个月最新录制的,相信这份视频能给你带来不一样的启发、收获。
Android进阶学习资料库
一共十个专题,包括了Android进阶所有学习资料,Android进阶视频,Flutter,java基础,kotlin,NDK模块,计算机网络,数据结构与算法,微信小程序,面试题解析,framework源码!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!
读者们能谨记这一点。
这里,笔者分享一份从架构哲学的层面来剖析的视频及资料分享给大家梳理了多年的架构经验,筹备近6个月最新录制的,相信这份视频能给你带来不一样的启发、收获。
[外链图片转存中…(img-iFS2GveD-1714884029275)]
Android进阶学习资料库
一共十个专题,包括了Android进阶所有学习资料,Android进阶视频,Flutter,java基础,kotlin,NDK模块,计算机网络,数据结构与算法,微信小程序,面试题解析,framework源码!
[外链图片转存中…(img-cgShwnkD-1714884029280)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!