正式版1.0版
新增icon 新增指纹/PIN码验证启动
@ -43,5 +43,6 @@ dependencies {
|
||||
|
||||
implementation "androidx.room:room-runtime:$room_version"
|
||||
annotationProcessor "androidx.room:room-compiler:$room_version"
|
||||
implementation "androidx.biometric:biometric:1.1.0"
|
||||
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:icon="@mipmap/app_icon"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
|
BIN
app/src/main/app_icon-playstore.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
@ -73,7 +73,7 @@ public class PassWordListAdapter extends RecyclerView.Adapter<PassWordListAdapte
|
||||
holder.item_layout.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
showDialog(data);
|
||||
showDialog(data, position);
|
||||
}
|
||||
});
|
||||
|
||||
@ -81,7 +81,7 @@ public class PassWordListAdapter extends RecyclerView.Adapter<PassWordListAdapte
|
||||
|
||||
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);
|
||||
Button delete = view.findViewById(R.id.delete);
|
||||
EditText title, account, password;
|
||||
@ -117,15 +117,21 @@ public class PassWordListAdapter extends RecyclerView.Adapter<PassWordListAdapte
|
||||
void remove(boolean isError) {
|
||||
new Thread(() -> {
|
||||
if (isError) {
|
||||
if (data.isUpload()) {
|
||||
data.setRemove(true);
|
||||
dao.update(data);
|
||||
} else {
|
||||
dao.delete(data);
|
||||
}
|
||||
} else {
|
||||
dao.delete(data);
|
||||
}
|
||||
Handler handler = new Handler(Looper.getMainLooper());
|
||||
handler.post(() -> {
|
||||
dialog.dismiss();
|
||||
removeDialog.dismiss();
|
||||
Toast.makeText(context, "删除成功", Toast.LENGTH_LONG).show();
|
||||
list.remove(position);
|
||||
notifyDataSetChanged();
|
||||
});
|
||||
}).start();
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -11,6 +11,8 @@ import java.util.List;
|
||||
@Dao
|
||||
public interface ToolsPasswordDao {
|
||||
@Query("select * from ToolsPassword")
|
||||
List<ToolsPassword> getAllAndRemove();
|
||||
@Query("select * from ToolsPassword where remove=0")
|
||||
List<ToolsPassword> getAll();
|
||||
@Query("select * from ToolsPassword where title=:title and account=:account and password=:password")
|
||||
ToolsPassword isExist(String title,String account,String password);
|
||||
@ -24,4 +26,6 @@ public interface ToolsPasswordDao {
|
||||
void delete(ToolsPassword password);
|
||||
@Update
|
||||
void update(ToolsPassword password);
|
||||
@Query("DELETE FROM ToolsPassword")
|
||||
void clear();
|
||||
}
|
||||
|
@ -1,28 +1,15 @@
|
||||
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.Handler;
|
||||
import android.os.Looper;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.AutoCompleteTextView;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.MultiAutoCompleteTextView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
@ -40,6 +27,17 @@ import com.yutou.passmanage.Tools.Tools;
|
||||
import java.util.ArrayList;
|
||||
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;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
@ -52,12 +50,67 @@ public class MainActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
|
||||
super.onCreate(savedInstanceState);
|
||||
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();
|
||||
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() {
|
||||
dao = RoomDatabaseManager.build(this).passwordDao();
|
||||
adapter = new PassWordListAdapter(this, new ArrayList<>());
|
||||
@ -72,6 +125,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
search.setText("");
|
||||
new Thread(this::showData).start();
|
||||
});
|
||||
|
||||
search.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
@ -150,13 +204,13 @@ public class MainActivity extends AppCompatActivity {
|
||||
|
||||
void init() {
|
||||
AppData.key = Tools.getConfig("key", this);
|
||||
AppData.key = "6B059119-C8F6-4E19-A8F0-71801D776A1F";
|
||||
if (Tools.isEmpty(AppData.key)) {
|
||||
EditText key = new EditText(this);
|
||||
key.setHint("激活码");
|
||||
AlertDialog dialog = new AlertDialog.Builder(this)
|
||||
.setTitle("输入激活码")
|
||||
.setView(key)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton("确定", (dialog1, which) -> {
|
||||
String k = key.getText().toString().trim();
|
||||
if (Tools.isEmpty(k)) {
|
||||
@ -178,10 +232,10 @@ public class MainActivity extends AppCompatActivity {
|
||||
|
||||
void initData() {
|
||||
new Thread(() -> {
|
||||
List<ToolsPassword> list = dao.getAll();
|
||||
List<ToolsPassword> list = dao.getAllAndRemove();
|
||||
for (ToolsPassword password : list) {
|
||||
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() {
|
||||
@Override
|
||||
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();
|
||||
json.put("id", password.getId());
|
||||
NetworkTool.httpPost(NetworkTool.NetworkAPI.PASSWORD_REMOVE, json, new NetworkInterface() {
|
||||
@ -216,11 +270,16 @@ public class MainActivity extends AppCompatActivity {
|
||||
@Override
|
||||
public void run() {
|
||||
if (isError) {
|
||||
if (password.isUpload()) {
|
||||
password.setRemove(true);
|
||||
dao.update(password);
|
||||
} else {
|
||||
dao.delete(password);
|
||||
}
|
||||
} else {
|
||||
dao.delete(password);
|
||||
}
|
||||
showData();
|
||||
}
|
||||
}).start();
|
||||
|
||||
@ -236,13 +295,26 @@ public class MainActivity extends AppCompatActivity {
|
||||
if (json.getInteger("code") == 0) {
|
||||
List<ToolsPassword> list = JSONArray.parseArray(json.getJSONArray("data").toJSONString(), ToolsPassword.class);
|
||||
new Thread(() -> {
|
||||
try {
|
||||
for (ToolsPassword password : list) {
|
||||
if (dao.isExist(password.getTitle(), password.getAccount(), password.getPassword()) == null) {
|
||||
password.setUpload(true);
|
||||
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();
|
||||
}
|
||||
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
@ -9,22 +9,13 @@ import com.yutou.passmanage.Datas.AppData;
|
||||
import com.yutou.passmanage.Interfaces.NetworkInterface;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.ConnectException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.URL;
|
||||
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;
|
||||
|
||||
|
||||
@ -33,7 +24,7 @@ public class NetworkTool {
|
||||
private final static String TAG = NetworkTool.class.getSimpleName();
|
||||
|
||||
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_ADD = HOME + "set/add.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) {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
|
5
app/src/main/res/mipmap-anydpi-v26/app_icon.xml
Normal 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>
|
5
app/src/main/res/mipmap-anydpi-v26/app_icon_round.xml
Normal 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>
|
BIN
app/src/main/res/mipmap-hdpi/app_icon.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
app/src/main/res/mipmap-hdpi/app_icon_foreground.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/mipmap-hdpi/app_icon_round.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
app/src/main/res/mipmap-mdpi/app_icon.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/mipmap-mdpi/app_icon_foreground.png
Normal file
After Width: | Height: | Size: 973 B |
BIN
app/src/main/res/mipmap-mdpi/app_icon_round.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
app/src/main/res/mipmap-xhdpi/app_icon.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
app/src/main/res/mipmap-xhdpi/app_icon_foreground.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
app/src/main/res/mipmap-xhdpi/app_icon_round.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/app_icon.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/app_icon_foreground.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/app_icon_round.png
Normal file
After Width: | Height: | Size: 6.9 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/app_icon.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/app_icon_foreground.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/app_icon_round.png
Normal file
After Width: | Height: | Size: 9.8 KiB |
4
app/src/main/res/values/app_icon_background.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="app_icon_background">#639BFF</color>
|
||||
</resources>
|