正式版1.0版

新增icon
新增指纹/PIN码验证启动
This commit is contained in:
Yutousama 2021-02-22 23:05:34 +08:00
parent 9057f8b765
commit e12cd888b5
26 changed files with 130 additions and 96 deletions

View File

@ -43,5 +43,6 @@ dependencies {
implementation "androidx.room:room-runtime:$room_version" implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version" annotationProcessor "androidx.room:room-compiler:$room_version"
implementation "androidx.biometric:biometric:1.1.0"
} }

View File

@ -4,7 +4,7 @@
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<application <application
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/app_icon"
android:label="@string/app_name" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@ -73,7 +73,7 @@ public class PassWordListAdapter extends RecyclerView.Adapter<PassWordListAdapte
holder.item_layout.setOnClickListener(new View.OnClickListener() { holder.item_layout.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
showDialog(data); showDialog(data, position);
} }
}); });
@ -81,7 +81,7 @@ public class PassWordListAdapter extends RecyclerView.Adapter<PassWordListAdapte
AlertDialog removeDialog = null; AlertDialog removeDialog = null;
private void showDialog(ToolsPassword data) { private void showDialog(ToolsPassword data, int position) {
View view = LayoutInflater.from(context.getApplicationContext()).inflate(R.layout.dialog_add_passworld, null); View view = LayoutInflater.from(context.getApplicationContext()).inflate(R.layout.dialog_add_passworld, null);
Button delete = view.findViewById(R.id.delete); Button delete = view.findViewById(R.id.delete);
EditText title, account, password; EditText title, account, password;
@ -117,15 +117,21 @@ public class PassWordListAdapter extends RecyclerView.Adapter<PassWordListAdapte
void remove(boolean isError) { void remove(boolean isError) {
new Thread(() -> { new Thread(() -> {
if (isError) { if (isError) {
if (data.isUpload()) {
data.setRemove(true); data.setRemove(true);
dao.update(data); dao.update(data);
} else { } else {
dao.delete(data); dao.delete(data);
} }
} else {
dao.delete(data);
}
Handler handler = new Handler(Looper.getMainLooper()); Handler handler = new Handler(Looper.getMainLooper());
handler.post(() -> { handler.post(() -> {
dialog.dismiss(); dialog.dismiss();
removeDialog.dismiss();
Toast.makeText(context, "删除成功", Toast.LENGTH_LONG).show(); Toast.makeText(context, "删除成功", Toast.LENGTH_LONG).show();
list.remove(position);
notifyDataSetChanged(); notifyDataSetChanged();
}); });
}).start(); }).start();

View File

@ -1,49 +0,0 @@
package com.yutou.passmanage.Datas;
public class PassWordData {
private String icon;
private String packageName;
private String name;
private String user;
private String password;
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public String getPackageName() {
return packageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}

View File

@ -11,6 +11,8 @@ import java.util.List;
@Dao @Dao
public interface ToolsPasswordDao { public interface ToolsPasswordDao {
@Query("select * from ToolsPassword") @Query("select * from ToolsPassword")
List<ToolsPassword> getAllAndRemove();
@Query("select * from ToolsPassword where remove=0")
List<ToolsPassword> getAll(); List<ToolsPassword> getAll();
@Query("select * from ToolsPassword where title=:title and account=:account and password=:password") @Query("select * from ToolsPassword where title=:title and account=:account and password=:password")
ToolsPassword isExist(String title,String account,String password); ToolsPassword isExist(String title,String account,String password);
@ -24,4 +26,6 @@ public interface ToolsPasswordDao {
void delete(ToolsPassword password); void delete(ToolsPassword password);
@Update @Update
void update(ToolsPassword password); void update(ToolsPassword password);
@Query("DELETE FROM ToolsPassword")
void clear();
} }

View File

@ -1,28 +1,15 @@
package com.yutou.passmanage; package com.yutou.passmanage;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.content.DialogInterface;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.AdapterView; import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.MultiAutoCompleteTextView;
import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
@ -40,6 +27,17 @@ import com.yutou.passmanage.Tools.Tools;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.biometric.BiometricManager;
import androidx.biometric.BiometricPrompt;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import static androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_WEAK;
import static androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL;
import static com.yutou.passmanage.Tools.RoomDatabaseManager.addPassword; import static com.yutou.passmanage.Tools.RoomDatabaseManager.addPassword;
public class MainActivity extends AppCompatActivity { public class MainActivity extends AppCompatActivity {
@ -52,12 +50,67 @@ public class MainActivity extends AppCompatActivity {
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); setContentView(R.layout.activity_main);
auth();
}
BiometricPrompt prompt;
void auth() {
BiometricManager manager = BiometricManager.from(this);
if (manager.canAuthenticate(BIOMETRIC_WEAK | DEVICE_CREDENTIAL) == BiometricManager.BIOMETRIC_SUCCESS) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
/* Intent enrollIntent = new Intent(Settings.ACTION_BIOMETRIC_ENROLL);
enrollIntent.putExtra(Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED,
BIOMETRIC_STRONG | DEVICE_CREDENTIAL);
startActivityForResult(enrollIntent, 233);*/
}
prompt=new BiometricPrompt(this, ContextCompat.getMainExecutor(this), new BiometricPrompt.AuthenticationCallback() {
@Override
public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
Toast.makeText(MainActivity.this, "验证成功", Toast.LENGTH_LONG).show();
initView(); initView();
init(); init();
} }
@Override
public void onAuthenticationFailed() {
super.onAuthenticationFailed();
Toast.makeText(MainActivity.this, "验证失败,已退出", Toast.LENGTH_LONG).show();
exit();
}
@Override
public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
super.onAuthenticationError(errorCode, errString);
System.out.println("errorCode = " + errorCode + ", errString = " + errString);
if(errorCode==10){
auth();
}else if(errorCode==13){
}
}
});
BiometricPrompt.PromptInfo promptInfo = new BiometricPrompt.PromptInfo.Builder()
.setTitle("验证指纹")
.setSubtitle("使用指纹来解锁应用")
.setAllowedAuthenticators(BIOMETRIC_WEAK | DEVICE_CREDENTIAL)
.build();
prompt.authenticate(promptInfo);
System.out.println("调用指纹");
} else {
Toast.makeText(this, "必须在支持指纹的设备上使用", Toast.LENGTH_LONG).show();
}
}
void exit(){
MainActivity.this.finish();
System.exit(0);
}
void initView() { void initView() {
dao = RoomDatabaseManager.build(this).passwordDao(); dao = RoomDatabaseManager.build(this).passwordDao();
adapter = new PassWordListAdapter(this, new ArrayList<>()); adapter = new PassWordListAdapter(this, new ArrayList<>());
@ -72,6 +125,7 @@ public class MainActivity extends AppCompatActivity {
search.setText(""); search.setText("");
new Thread(this::showData).start(); new Thread(this::showData).start();
}); });
search.addTextChangedListener(new TextWatcher() { search.addTextChangedListener(new TextWatcher() {
@Override @Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { public void beforeTextChanged(CharSequence s, int start, int count, int after) {
@ -150,13 +204,13 @@ public class MainActivity extends AppCompatActivity {
void init() { void init() {
AppData.key = Tools.getConfig("key", this); AppData.key = Tools.getConfig("key", this);
AppData.key = "6B059119-C8F6-4E19-A8F0-71801D776A1F";
if (Tools.isEmpty(AppData.key)) { if (Tools.isEmpty(AppData.key)) {
EditText key = new EditText(this); EditText key = new EditText(this);
key.setHint("激活码"); key.setHint("激活码");
AlertDialog dialog = new AlertDialog.Builder(this) AlertDialog dialog = new AlertDialog.Builder(this)
.setTitle("输入激活码") .setTitle("输入激活码")
.setView(key) .setView(key)
.setCancelable(false)
.setPositiveButton("确定", (dialog1, which) -> { .setPositiveButton("确定", (dialog1, which) -> {
String k = key.getText().toString().trim(); String k = key.getText().toString().trim();
if (Tools.isEmpty(k)) { if (Tools.isEmpty(k)) {
@ -178,10 +232,10 @@ public class MainActivity extends AppCompatActivity {
void initData() { void initData() {
new Thread(() -> { new Thread(() -> {
List<ToolsPassword> list = dao.getAll(); List<ToolsPassword> list = dao.getAllAndRemove();
for (ToolsPassword password : list) { for (ToolsPassword password : list) {
System.out.println(JSONObject.toJSONString(password)); System.out.println(JSONObject.toJSONString(password));
if (!password.isUpload()&&!password.isRemove()) { if (!password.isUpload() && !password.isRemove()) {
addPassword(password.getTitle(), password.getAccount(), password.getPassword(), -1, true, new NetworkInterface() { addPassword(password.getTitle(), password.getAccount(), password.getPassword(), -1, true, new NetworkInterface() {
@Override @Override
public void httpGetData(Object data, int state) { public void httpGetData(Object data, int state) {
@ -197,7 +251,7 @@ public class MainActivity extends AppCompatActivity {
} }
}); });
}else if(password.isRemove()){ } else if (password.isRemove()) {
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();
json.put("id", password.getId()); json.put("id", password.getId());
NetworkTool.httpPost(NetworkTool.NetworkAPI.PASSWORD_REMOVE, json, new NetworkInterface() { NetworkTool.httpPost(NetworkTool.NetworkAPI.PASSWORD_REMOVE, json, new NetworkInterface() {
@ -216,11 +270,16 @@ public class MainActivity extends AppCompatActivity {
@Override @Override
public void run() { public void run() {
if (isError) { if (isError) {
if (password.isUpload()) {
password.setRemove(true); password.setRemove(true);
dao.update(password); dao.update(password);
} else { } else {
dao.delete(password); dao.delete(password);
} }
} else {
dao.delete(password);
}
showData();
} }
}).start(); }).start();
@ -236,13 +295,26 @@ public class MainActivity extends AppCompatActivity {
if (json.getInteger("code") == 0) { if (json.getInteger("code") == 0) {
List<ToolsPassword> list = JSONArray.parseArray(json.getJSONArray("data").toJSONString(), ToolsPassword.class); List<ToolsPassword> list = JSONArray.parseArray(json.getJSONArray("data").toJSONString(), ToolsPassword.class);
new Thread(() -> { new Thread(() -> {
try {
for (ToolsPassword password : list) { for (ToolsPassword password : list) {
if (dao.isExist(password.getTitle(), password.getAccount(), password.getPassword()) == null) { if (dao.isExist(password.getTitle(), password.getAccount(), password.getPassword()) == null) {
password.setUpload(true); password.setUpload(true);
dao.insert(password); dao.insert(password);
} }
} }
} catch (Exception e) {
e.printStackTrace();
dao.clear();
for (ToolsPassword password : list) {
if (dao.isExist(password.getTitle(), password.getAccount(), password.getPassword()) == null) {
password.setUpload(true);
dao.insert(password);
}
}
} finally {
showData(); showData();
}
}).start(); }).start();
} }
} }

View File

@ -9,22 +9,13 @@ import com.yutou.passmanage.Datas.AppData;
import com.yutou.passmanage.Interfaces.NetworkInterface; import com.yutou.passmanage.Interfaces.NetworkInterface;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.ConnectException;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL; import java.net.URL;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
@ -33,7 +24,7 @@ public class NetworkTool {
private final static String TAG = NetworkTool.class.getSimpleName(); private final static String TAG = NetworkTool.class.getSimpleName();
public static class NetworkAPI { public static class NetworkAPI {
public static String HOME = "http://192.168.137.1/tools/password/"; public static String HOME = "http://tools.yutou233.cn/tools/password/";
public static String PASSWORD_ALL = HOME + "get/all.do"; public static String PASSWORD_ALL = HOME + "get/all.do";
public static String PASSWORD_ADD = HOME + "set/add.do"; public static String PASSWORD_ADD = HOME + "set/add.do";
public static String PASSWORD_UPDATE = HOME + "set/update.do"; public static String PASSWORD_UPDATE = HOME + "set/update.do";
@ -45,11 +36,6 @@ public class NetworkTool {
} }
private NetworkTool() {
//HOME = "http://192.168.31.92:8000/nas";
}
public static void httpGet(String url, JSONObject body, NetworkInterface networkInterface) { public static void httpGet(String url, JSONObject body, NetworkInterface networkInterface) {
new Thread(new Runnable() { new Thread(new Runnable() {
@Override @Override

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/app_icon_background"/>
<foreground android:drawable="@mipmap/app_icon_foreground"/>
</adaptive-icon>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/app_icon_background"/>
<foreground android:drawable="@mipmap/app_icon_foreground"/>
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 973 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="app_icon_background">#639BFF</color>
</resources>