diff --git a/app/build.gradle b/app/build.gradle index 5e6f9b3..5a72c0f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -36,4 +36,6 @@ dependencies { testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' + + implementation 'com.alibaba:fastjson:1.2.68' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1f98c1d..c559a6c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,13 +1,14 @@ - + diff --git a/app/src/main/java/com/yutou/passmanage/Adapters/PassWordListAdapter.java b/app/src/main/java/com/yutou/passmanage/Adapters/PassWordListAdapter.java new file mode 100644 index 0000000..d0a2241 --- /dev/null +++ b/app/src/main/java/com/yutou/passmanage/Adapters/PassWordListAdapter.java @@ -0,0 +1,71 @@ +package com.yutou.passmanage.Adapters; + +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ImageButton; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.yutou.passmanage.Datas.PassWordData; +import com.yutou.passmanage.R; + +import java.util.List; + +public class PassWordListAdapter extends RecyclerView.Adapter { + private Context context; + private List list; + + public PassWordListAdapter(Context context, List list) { + this.context = context; + this.list = list; + } + + @NonNull + @Override + public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + return new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.recycler_list,parent,false)); + } + + @Override + public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { + PassWordData data=list.get(position); + holder.name.setText(data.getName()); + holder.user.setText(data.getUser()); + holder.password.setText(data.getPassword()); + holder.copy.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ClipboardManager clipboard = (ClipboardManager)context.getSystemService(Context.CLIPBOARD_SERVICE); + ClipData clip = ClipData.newPlainText("simple text", data.getPassword()); + clipboard.setPrimaryClip(clip); + } + }); + + } + + @Override + public int getItemCount() { + return list.size(); + } + public static class MyViewHolder extends RecyclerView.ViewHolder{ + ImageButton icon; + TextView name,user,password; + Button copy; + + public MyViewHolder(@NonNull View itemView) { + super(itemView); + icon=itemView.findViewById(R.id.icon); + name=itemView.findViewById(R.id.name); + user=itemView.findViewById(R.id.user); + password=itemView.findViewById(R.id.password); + copy=itemView.findViewById(R.id.copy); + } + } +} diff --git a/app/src/main/java/com/yutou/passmanage/Datas/AppData.java b/app/src/main/java/com/yutou/passmanage/Datas/AppData.java new file mode 100644 index 0000000..1afb5f9 --- /dev/null +++ b/app/src/main/java/com/yutou/passmanage/Datas/AppData.java @@ -0,0 +1,9 @@ +package com.yutou.passmanage.Datas; + +import android.os.Handler; +import android.os.Looper; + +public class AppData { + public static Handler handler=new Handler(Looper.getMainLooper()); + public static String key; +} diff --git a/app/src/main/java/com/yutou/passmanage/Datas/PassWordData.java b/app/src/main/java/com/yutou/passmanage/Datas/PassWordData.java new file mode 100644 index 0000000..a744a9f --- /dev/null +++ b/app/src/main/java/com/yutou/passmanage/Datas/PassWordData.java @@ -0,0 +1,49 @@ +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; + } +} diff --git a/app/src/main/java/com/yutou/passmanage/Datas/ToolsPassword.java b/app/src/main/java/com/yutou/passmanage/Datas/ToolsPassword.java new file mode 100644 index 0000000..46f8724 --- /dev/null +++ b/app/src/main/java/com/yutou/passmanage/Datas/ToolsPassword.java @@ -0,0 +1,88 @@ +package com.yutou.passmanage.Datas; + + +/** + * tools_password + * @author + */ +public class ToolsPassword{ + private Integer id; + + private String title; + + private String username; + + private String password; + + private String url; + + private String info; + + private Integer type; + + private Integer uid; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getInfo() { + return info; + } + + public void setInfo(String info) { + this.info = info; + } + + public Integer getType() { + return type; + } + + public void setType(Integer type) { + this.type = type; + } + + public Integer getUid() { + return uid; + } + + public void setUid(Integer uid) { + this.uid = uid; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yutou/passmanage/Datas/ToolsPasswordType.java b/app/src/main/java/com/yutou/passmanage/Datas/ToolsPasswordType.java new file mode 100644 index 0000000..692dc8f --- /dev/null +++ b/app/src/main/java/com/yutou/passmanage/Datas/ToolsPasswordType.java @@ -0,0 +1,38 @@ +package com.yutou.passmanage.Datas; + + +/** + * tools_password_type + * @author + */ +public class ToolsPasswordType { + private Integer id; + + private Integer uid; + + private String title; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public Integer getUid() { + return uid; + } + + public void setUid(Integer uid) { + this.uid = uid; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yutou/passmanage/Interfaces/DownloadInterface.java b/app/src/main/java/com/yutou/passmanage/Interfaces/DownloadInterface.java new file mode 100644 index 0000000..d2e3fe6 --- /dev/null +++ b/app/src/main/java/com/yutou/passmanage/Interfaces/DownloadInterface.java @@ -0,0 +1,15 @@ +package com.yutou.passmanage.Interfaces; + +import java.io.File; + +/** + * 下载接口 + */ +public abstract class DownloadInterface { + /** + * 下载完成 + * @param oldJar + */ + public abstract void onDownloadOver(File oldJar); + public void onError(Exception e){}; +} diff --git a/app/src/main/java/com/yutou/passmanage/Interfaces/NetworkInterface.java b/app/src/main/java/com/yutou/passmanage/Interfaces/NetworkInterface.java new file mode 100644 index 0000000..3db76ae --- /dev/null +++ b/app/src/main/java/com/yutou/passmanage/Interfaces/NetworkInterface.java @@ -0,0 +1,16 @@ +package com.yutou.passmanage.Interfaces; + +public interface NetworkInterface { + /** + * 请求成功 + * @param data 请求参数 + * @param state http状态 + */ + void httpGetData(Object data, int state); + + /** + * 请求异常 + * @param e 异常 + */ + void httpError(Exception e); +} diff --git a/app/src/main/java/com/yutou/passmanage/MainActivity.java b/app/src/main/java/com/yutou/passmanage/MainActivity.java index c66445b..7560c06 100644 --- a/app/src/main/java/com/yutou/passmanage/MainActivity.java +++ b/app/src/main/java/com/yutou/passmanage/MainActivity.java @@ -1,14 +1,119 @@ package com.yutou.passmanage; +import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; +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.view.LayoutInflater; +import android.view.View; +import android.widget.EditText; +import android.widget.ImageButton; +import android.widget.Toast; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import com.yutou.passmanage.Datas.AppData; +import com.yutou.passmanage.Datas.ToolsPassword; +import com.yutou.passmanage.Interfaces.NetworkInterface; +import com.yutou.passmanage.Tools.NetworkTool; +import com.yutou.passmanage.Tools.Tools; + +import java.util.List; public class MainActivity extends AppCompatActivity { + EditText search; + ImageButton clearSearch; + RecyclerView passList; + FloatingActionButton floatButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); + initView(); + init(); + } + + void initView() { + search = findViewById(R.id.search); + clearSearch = findViewById(R.id.clearSearch); + passList = findViewById(R.id.passList); + floatButton = findViewById(R.id.floatButton); + floatButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.dialog_add_passworld, null); + AlertDialog dialog = new AlertDialog.Builder(MainActivity.this) + .setTitle("添加账号") + .setView(view) + .setPositiveButton("保存", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }) + .setNegativeButton("取消", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + + } + }).create(); + dialog.show(); + } + }); + } + + void init() { + AppData.key = Tools.getConfig("key", this); + if (Tools.isEmpty(AppData.key)) { + EditText key = new EditText(this); + key.setHint("激活码"); + AlertDialog dialog = new AlertDialog.Builder(this) + .setTitle("输入激活码") + .setView(key) + .setPositiveButton("确定", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + String k = key.getText().toString().trim(); + if (Tools.isEmpty(k)) { + Toast.makeText(MainActivity.this, "激活码不能为空", Toast.LENGTH_LONG).show(); + return; + } + Tools.setConfig("key", k, MainActivity.this); + AppData.key = k; + dialog.dismiss(); + initData(); + } + }).create(); + dialog.show(); + }else{ + initData(); + } + } + void initData(){ + NetworkTool.httpGet(NetworkTool.NetworkAPI.PASSWORD_ALL, new JSONObject(), new NetworkInterface() { + @Override + public void httpGetData(Object data, int state) { + JSONObject json=JSONObject.parseObject((String) data); + if(json.getInteger("code")==0){ + List list= JSONArray.parseArray(json.getJSONArray("data").toJSONString(),ToolsPassword.class); + showData(list); + } + } + + @Override + public void httpError(Exception e) { + + } + }); + } + void showData(List list){ + } } \ No newline at end of file diff --git a/app/src/main/java/com/yutou/passmanage/Tools/NetworkTool.java b/app/src/main/java/com/yutou/passmanage/Tools/NetworkTool.java new file mode 100644 index 0000000..f991bbd --- /dev/null +++ b/app/src/main/java/com/yutou/passmanage/Tools/NetworkTool.java @@ -0,0 +1,216 @@ +package com.yutou.passmanage.Tools; + + +import android.util.Log; + +import com.alibaba.fastjson.JSONException; +import com.alibaba.fastjson.JSONObject; +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; + + +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 PASSWORD_ALL = HOME + "get/all.do"; + public static String PASSWORD_ADD = HOME + "set/add.do"; + public static String PASSWORD_UPDATE = HOME + "set/update.do"; + public static String PASSWORD_TYPE_ALL = HOME + "type/get/list.do"; + public static String PASSWORD_TYPE_ADD = HOME + "type/set/add.do"; + + + } + + + 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 + public void run() { + try { + System.out.println(url + "?" + toGetSplice(body)); + HttpURLConnection connection = (HttpURLConnection) new URL(url + "?" + toGetSplice(body)).openConnection(); + BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + connection.connect(); + if (connection.getResponseCode() != 200) { + networkInterface.httpError(new RuntimeException("http code to :" + connection.getResponseCode())); + return; + } + String tmp; + StringBuilder str = new StringBuilder(); + while ((tmp = reader.readLine()) != null) { + str.append(tmp); + } + reader.close(); + AppData.handler.post(new Runnable() { + @Override + public void run() { + if (networkInterface != null) { + try { + networkInterface.httpGetData(str.toString(), connection.getResponseCode()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + } + }); + //Log.i(TAG + "[" + url + "]", "body:" + str + " (" + connection.getResponseCode() + ")"); + } catch (Exception e) { + e.printStackTrace(); + AppData.handler.post(new Runnable() { + @Override + public void run() { + if (networkInterface != null) + networkInterface.httpError(e); + } + }); + Log.e(TAG, url + " body =" + body.toJSONString()); + } + } + }).start(); + + } + + private void ping(String url, NetworkInterface networkInterface) { + new Thread(new Runnable() { + @Override + public void run() { + try { + HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); + connection.setConnectTimeout(50); + connection.setReadTimeout(50); + connection.connect(); + InputStream inputStream = connection.getErrorStream(); + System.out.println(inputStream.read()); + inputStream.close(); + System.out.println(connection.getResponseCode()); + networkInterface.httpGetData(null, 0); + connection.disconnect(); + } catch (Exception e) { + networkInterface.httpError(e); + } + } + }).start(); + } + + + public static void httpPost(final String url, final JSONObject body, final NetworkInterface networkInterface) { + if (!url.startsWith("http:") && !Tools.isEmpty(NetworkAPI.HOME)) { + httpPost(NetworkAPI.HOME + url, body, networkInterface); + return; + } + body.put("token", AppData.key); + new Thread(new Runnable() { + + @Override + public void run() { + String tmp; + StringBuilder str = new StringBuilder(); + try { + HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); + connection.setRequestMethod("POST"); + connection.setDoOutput(true); + connection.setDoInput(true); + connection.setConnectTimeout(5 * 1000); + connection.setReadTimeout(10 * 1000); + //connection.addRequestProperty("Connection", "keep-alive"); + //connection.addRequestProperty("User-Agent", getExtUa()); + connection.addRequestProperty("content-type", "application/json"); + connection.addRequestProperty("charset", "UTF-8"); + OutputStream outputStream = connection.getOutputStream(); + + outputStream.write(body.toJSONString().getBytes()); + outputStream.flush(); + outputStream.close(); + System.out.println(connection.getResponseCode()); + BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + while ((tmp = reader.readLine()) != null) { + str.append(tmp); + } + final String finalStr = str.toString(); + + // Log.i(TAG + "[" + url + "?" + toGetSplice(body) + "]", "body:" + str + " (" + connection.getResponseCode() + ")"); + AppData.handler.post(new Runnable() { + @Override + public void run() { + if (networkInterface != null) { + try { + networkInterface.httpGetData(str.toString(), connection.getResponseCode()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + } + }); + connection.disconnect(); + reader.close(); + } catch (Exception e) { + e.printStackTrace(); + if (networkInterface != null) + networkInterface.httpError(e); + } finally { + Log.e(TAG, url + "\n传参:" + body.toString() + "\n接收:" + str); + } + } + }).start(); + + } + + private String getExtUa() { + return "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36"; + } + + public static String toGetSplice(JSONObject json) { + try { + json.put("token", AppData.key); + } catch (JSONException e) { + e.printStackTrace(); + } + StringBuilder string = new StringBuilder(); + Set keys = json.keySet(); + for (String key : keys) { + try { + string.append("&").append(key).append("=").append(URLEncoder.encode(json.getString(key), "UTF-8")); + } catch (Exception e) { + e.printStackTrace(); + try { + string.append("&").append(URLEncoder.encode(key, "UTF-8")).append("="); + // string += "&" + key + "="; + } catch (Exception e1) { + string.append("&").append(key).append("="); + } + } + } + + string = new StringBuilder(string.substring(1, string.length()).replaceAll(" ", "")); + return string.toString(); + } +} diff --git a/app/src/main/java/com/yutou/passmanage/Tools/Tools.java b/app/src/main/java/com/yutou/passmanage/Tools/Tools.java new file mode 100644 index 0000000..5571a10 --- /dev/null +++ b/app/src/main/java/com/yutou/passmanage/Tools/Tools.java @@ -0,0 +1,38 @@ +package com.yutou.passmanage.Tools; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.pm.PackageInfo; + +import java.util.List; + +public class Tools { + public static boolean isEmpty(String str){ + if(str==null||str.trim().length()==0){ + return true; + } + return false; + } + public static PackageInfo getPackageInfo(String packageName, Context context){ + List list=context.getPackageManager().getInstalledPackages(0); + if(list!=null){ + for (PackageInfo packageInfo : list) { + if(packageInfo.packageName.equals(packageName)){ + return packageInfo; + } + } + } + return null; + } + public static List getAllPackageInfo(Context context){ + return context.getPackageManager().getInstalledPackages(0); + } + public static void setConfig(String key,String value,Context context){ + SharedPreferences preferences=context.getSharedPreferences("config.cfg",Context.MODE_PRIVATE); + preferences.edit().putString(key,value).apply(); + } + public static String getConfig(String key,Context context){ + SharedPreferences preferences=context.getSharedPreferences("config.cfg",Context.MODE_PRIVATE); + return preferences.getString(key,null); + } +} diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 4fc2444..683f279 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -6,13 +6,47 @@ android:layout_height="match_parent" tools:context=".MainActivity"> - + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_add_passworld.xml b/app/src/main/res/layout/dialog_add_passworld.xml new file mode 100644 index 0000000..f6128f4 --- /dev/null +++ b/app/src/main/res/layout/dialog_add_passworld.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/recycler_list.xml b/app/src/main/res/layout/recycler_list.xml new file mode 100644 index 0000000..f193d0f --- /dev/null +++ b/app/src/main/res/layout/recycler_list.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + +