diff --git a/TabLayout/build.gradle b/TabLayout/build.gradle index ef68234..9121810 100644 --- a/TabLayout/build.gradle +++ b/TabLayout/build.gradle @@ -3,13 +3,10 @@ apply plugin: 'kotlin-android' android { compileSdkVersion 33 - buildToolsVersion "30.0.2" defaultConfig { minSdkVersion 28 targetSdkVersion 33 - versionCode 1 - versionName "1.2" consumerProguardFiles 'consumer-rules.pro' } @@ -20,6 +17,7 @@ android { proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + namespace 'com.angcyo.tablayout' } dependencies { diff --git a/TabLayout/src/main/AndroidManifest.xml b/TabLayout/src/main/AndroidManifest.xml index e86e891..94cbbcf 100644 --- a/TabLayout/src/main/AndroidManifest.xml +++ b/TabLayout/src/main/AndroidManifest.xml @@ -1,2 +1 @@ - + diff --git a/ViewPager2Delegate/build.gradle b/ViewPager2Delegate/build.gradle index 7adf744..db5bfe3 100644 --- a/ViewPager2Delegate/build.gradle +++ b/ViewPager2Delegate/build.gradle @@ -3,13 +3,10 @@ apply plugin: 'kotlin-android' android { compileSdkVersion 33 - buildToolsVersion "30.0.2" defaultConfig { minSdkVersion 28 targetSdkVersion 33 - versionCode 1 - versionName "1.2" consumerProguardFiles 'consumer-rules.pro' } @@ -20,6 +17,7 @@ android { proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + namespace 'com.angcyo.tablayout.delegate2' } diff --git a/ViewPager2Delegate/src/main/AndroidManifest.xml b/ViewPager2Delegate/src/main/AndroidManifest.xml index f55a840..94cbbcf 100644 --- a/ViewPager2Delegate/src/main/AndroidManifest.xml +++ b/ViewPager2Delegate/src/main/AndroidManifest.xml @@ -1,2 +1 @@ - + diff --git a/app/build.gradle b/app/build.gradle index 4bee868..a812a3a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,15 +17,14 @@ android { keyPassword '34864394' } } - compileSdkVersion 33 - buildToolsVersion "30.0.2" + compileSdkVersion 34 defaultConfig { applicationId "com.yutou.passmanage" minSdkVersion 28 - targetSdkVersion 33 + targetSdkVersion 34 versionCode 1 - versionName "1.2" + versionName "1.3" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" signingConfig signingConfigs.yutou @@ -41,24 +40,35 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + namespace 'com.yutou.passmanage' + buildFeatures { + viewBinding true + } } dependencies { - implementation 'androidx.appcompat:appcompat:1.2.0' - implementation 'com.google.android.material:material:1.2.1' - implementation 'androidx.constraintlayout:constraintlayout:2.0.4' - testImplementation 'junit:junit:4.+' - androidTestImplementation 'androidx.test.ext:junit:1.1.2' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' + implementation 'androidx.appcompat:appcompat:1.7.0' + implementation 'com.google.android.material:material:1.12.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + implementation 'androidx.navigation:navigation-fragment:2.7.7' + implementation 'androidx.navigation:navigation-ui:2.7.7' + implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.8.4' + implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.4' + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.2.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1' - implementation 'com.alibaba:fastjson:1.2.68' + implementation 'com.alibaba.fastjson2:fastjson2:2.0.52' - def room_version = "2.2.6" - - implementation "androidx.room:room-runtime:$room_version" - annotationProcessor "androidx.room:room-compiler:$room_version" + implementation "androidx.room:room-runtime:2.6.1" + annotationProcessor "androidx.room:room-compiler:2.6.1" implementation "androidx.biometric:biometric:1.1.0" + implementation 'com.squareup.okhttp3:okhttp:3.14.9' + implementation 'com.squareup.retrofit2:retrofit:2.3.0' + api project(path:':TabLayout') api project(path:':ViewPager2Delegate') + api project(path:':netlibs') + } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0d3c28c..7562715 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,18 +1,19 @@ - - - + + + + - + android:theme="@style/Theme.MyPassworldManage" + android:usesCleartextTraffic="true" > + diff --git a/app/src/main/java/com/yutou/passmanage/Adapters/PassWordListAdapter.java b/app/src/main/java/com/yutou/passmanage/Adapters/PassWordListAdapter.java index c12ab0d..bc76a03 100644 --- a/app/src/main/java/com/yutou/passmanage/Adapters/PassWordListAdapter.java +++ b/app/src/main/java/com/yutou/passmanage/Adapters/PassWordListAdapter.java @@ -21,14 +21,17 @@ import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.recyclerview.widget.RecyclerView; -import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson2.JSONObject; +import com.yutou.netlibs.http.HttpCallback; import com.yutou.passmanage.Datas.ToolsPassword; import com.yutou.passmanage.Datas.ToolsPasswordDao; import com.yutou.passmanage.Interfaces.NetworkInterface; +import com.yutou.passmanage.NetUtils.NetTools; import com.yutou.passmanage.R; import com.yutou.passmanage.Tools.NetworkTool; import com.yutou.passmanage.Tools.ResTools; import com.yutou.passmanage.Tools.RoomDatabaseManager; +import com.yutou.passmanage.bean.BaseBean; import java.util.List; @@ -58,8 +61,8 @@ public class PassWordListAdapter extends RecyclerView.Adapter() { + @Override + public void onResponse(int code, String status, String response) { + data.setPassword(response); + showDialog(data, holder.getAdapterPosition()); + save(data); + } + + @Override + public void onFailure(Throwable throwable) { + new Thread(() -> { + ToolsPassword queried = dao.queryPassword(data.getId()); + if (queried != null) { + new Handler(Looper.getMainLooper()) + .post(() -> showDialog(data, holder.getAdapterPosition())); + } + }).start(); + } + + public void save(ToolsPassword pwd) { + new Thread(new Runnable() { + @Override + public void run() { + ToolsPassword queried = dao.queryPassword(pwd.getId()); + if (queried == null) { + dao.insert(pwd); + } else { + dao.update(pwd); + } + } + }).start(); + } + }); } }); @@ -86,11 +121,11 @@ public class PassWordListAdapter extends RecyclerView.Adapter() { @Override - public void httpGetData(Object data, int state) { + public void onResponse(int code, String status, BaseBean response) { remove(false); } @Override - public void httpError(Exception e) { + public void onFailure(Throwable throwable) { remove(true); } void remove(boolean isError) { - new Thread(() -> { - if (isError) { - if (data.isUpload()) { - data.setRemove(true); - dao.update(data); - } else { - dao.delete(data); - } + if (isError) { + if (data.isUpload()) { + data.setRemove(true); + dao.update(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(); + } 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(); + }); } }); @@ -153,12 +184,13 @@ public class PassWordListAdapter extends RecyclerView.Adapter { - addPassword(title.getText().toString(), account.getText().toString(), password.getText().toString(),info.getText().toString(), data.getId(), false, new NetworkInterface() { + addPassword(title.getText().toString(), account.getText().toString(), password.getText().toString(), info.getText().toString(), data.getId(), false, new NetworkInterface() { @Override public void httpGetData(Object data, int state) { addDatabase(title.getText().toString(), account.getText().toString(), password.getText().toString(), + info.getText().toString(), true); } @@ -167,20 +199,23 @@ public class PassWordListAdapter extends RecyclerView.Adapter { + data.setAccount(account1); data.setTitle(title1); data.setPassword(password1); + data.setInfo(info); data.setUpload(upload); dao.update(data); Handler handler = new Handler(Looper.getMainLooper()); handler.post(new Runnable() { @Override public void run() { - Toast.makeText(context, ResTools.getString(context,R.string.toast_update), Toast.LENGTH_LONG).show(); + Toast.makeText(context, ResTools.getString(context, R.string.toast_update), Toast.LENGTH_LONG).show(); notifyDataSetChanged(); } }); diff --git a/app/src/main/java/com/yutou/passmanage/Datas/ToolsPassword.java b/app/src/main/java/com/yutou/passmanage/Datas/ToolsPassword.java index a210ecf..ccc7f47 100644 --- a/app/src/main/java/com/yutou/passmanage/Datas/ToolsPassword.java +++ b/app/src/main/java/com/yutou/passmanage/Datas/ToolsPassword.java @@ -6,9 +6,11 @@ import androidx.room.Entity; import androidx.room.Ignore; import androidx.room.PrimaryKey; +import com.alibaba.fastjson2.annotation.JSONField; + /** * tools_password - * @author + * @author */ @Entity public class ToolsPassword{ @@ -17,6 +19,7 @@ public class ToolsPassword{ @ColumnInfo private String title; @ColumnInfo + @JSONField(name = "username") private String account; @ColumnInfo private String password; @@ -112,4 +115,20 @@ public class ToolsPassword{ public void setRemove(boolean remove) { this.remove = remove; } + + @Override + public String toString() { + return "ToolsPassword{" + + "id=" + id + + ", title='" + title + '\'' + + ", account='" + account + '\'' + + ", password='" + password + '\'' + + ", url='" + url + '\'' + + ", info='" + info + '\'' + + ", type=" + type + + ", uid=" + uid + + ", upload=" + upload + + ", remove=" + remove + + '}'; + } } \ No newline at end of file diff --git a/app/src/main/java/com/yutou/passmanage/Datas/ToolsPasswordDao.java b/app/src/main/java/com/yutou/passmanage/Datas/ToolsPasswordDao.java index 89ff266..78ba6be 100644 --- a/app/src/main/java/com/yutou/passmanage/Datas/ToolsPasswordDao.java +++ b/app/src/main/java/com/yutou/passmanage/Datas/ToolsPasswordDao.java @@ -16,6 +16,8 @@ public interface ToolsPasswordDao { List getAll(); @Query("select * from ToolsPassword where title=:title and account=:account and password=:password and info=:info") ToolsPassword isExist(String title,String account,String password,String info); + @Query("select * from ToolsPassword where id=:id") + ToolsPassword queryPassword(int id); @Query("select * from ToolsPassword where title like :title and remove=0") List queryPassword(String title); @Insert diff --git a/app/src/main/java/com/yutou/passmanage/MainActivity.java b/app/src/main/java/com/yutou/passmanage/MainActivity.java index 2eb99a3..2f49ece 100644 --- a/app/src/main/java/com/yutou/passmanage/MainActivity.java +++ b/app/src/main/java/com/yutou/passmanage/MainActivity.java @@ -16,18 +16,22 @@ import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; import com.angcyo.tablayout.DslTabLayout; +import com.angcyo.tablayout.DslTabLayoutConfig; import com.google.android.material.floatingactionbutton.FloatingActionButton; +import com.yutou.netlibs.http.HttpCallback; import com.yutou.passmanage.Adapters.PassWordListAdapter; import com.yutou.passmanage.Datas.AppData; import com.yutou.passmanage.Datas.ToolsPassword; import com.yutou.passmanage.Datas.ToolsPasswordDao; import com.yutou.passmanage.Interfaces.NetworkInterface; +import com.yutou.passmanage.NetUtils.NetTools; import com.yutou.passmanage.Tools.NetworkTool; import com.yutou.passmanage.Tools.RoomDatabaseManager; import com.yutou.passmanage.Tools.Tools; +import com.yutou.passmanage.bean.BaseBean; import com.yutou.passmanage.bean.PasswordBean; import com.yutou.passmanage.bean.PasswordTypeBean; @@ -47,6 +51,10 @@ 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 kotlin.Unit; +import kotlin.jvm.functions.Function1; +import kotlin.jvm.functions.Function4; + public class MainActivity extends AppCompatActivity { EditText search; ImageView clearSearch; @@ -69,7 +77,7 @@ public class MainActivity extends AppCompatActivity { BiometricPrompt prompt; void auth() { - if(true){ + if (BuildConfig.DEBUG) { init(); authError.setVisibility(View.GONE); passList.setVisibility(View.VISIBLE); @@ -175,6 +183,32 @@ public class MainActivity extends AppCompatActivity { } }); + tabLayout.configTabLayoutConfig(new Function1() { + @Override + public Unit invoke(DslTabLayoutConfig dslTabLayoutConfig) { + dslTabLayoutConfig.setOnSelectItemView(new Function4() { + @Override + public Boolean invoke(View view, Integer integer, Boolean aBoolean, Boolean aBoolean2) { + if (aBoolean) { + PasswordTypeBean typeBean = (PasswordTypeBean) view.getTag(); + NetTools.getApi().getTypePassword(typeBean.getId()).enqueue(new HttpCallback>() { + @Override + public void onResponse(int code, String status, List response) { + setShow(response); + } + + @Override + public void onFailure(Throwable throwable) { + throwable.printStackTrace(); + } + }); + } + return false; + } + }); + return null; + } + }); } void showAddPasswordDialog() { @@ -254,137 +288,52 @@ public class MainActivity extends AppCompatActivity { ToolsPasswordDao dao; void initData() { - - NetworkTool.httpGet(NetworkTool.NetworkAPI.PASSWORD_TYPE_ALL, new JSONObject(), new NetworkInterface() { + NetTools.getApi().getAllTypePassword().enqueue(new HttpCallback>() { @Override - public void httpGetData(JSONObject json, int state) { - List data = JSONArray.parseArray(json.getJSONArray("data").toJSONString(), PasswordTypeBean.class); - for (PasswordTypeBean bean : data) { + public void onResponse(int code, String status, List response) { + for (PasswordTypeBean bean : response) { Button tab = new Button(MainActivity.this); - tab.setOnClickListener(view -> { - - }); tab.setText(bean.getTitle()); tab.setTag(bean); tabLayout.addView(tab); } + showLocalData(); } @Override - public void httpError(Exception e) { - e.printStackTrace(); + public void onFailure(Throwable throwable) { + showLocalData(); } }); - new Thread(() -> { - List list = dao.getAllAndRemove(); - if (list.size() == 0) { + new Thread(() -> { + if (dao.getAll().isEmpty()) { authError.setText("列表为空,点击右下角+新增配置"); authError.setVisibility(View.VISIBLE); passList.setVisibility(View.GONE); - } else { - for (ToolsPassword password : list) { - if (!password.isUpload() && !password.isRemove()) { - addPassword(password.getTitle(), password.getAccount(), password.getPassword(), password.getInfo(), -1, true, new NetworkInterface() { - @Override - public void httpGetData(Object data, int state) { - new Thread(() -> { - password.setUpload(true); - dao.update(password); - }).start(); - - } - - @Override - public void httpError(Exception e) { - - } - }); - } else if (password.isRemove()) { - JSONObject json = new JSONObject(); - json.put("id", password.getId()); - NetworkTool.httpPost(NetworkTool.NetworkAPI.PASSWORD_REMOVE, json, new NetworkInterface() { - @Override - public void httpGetData(Object data, int state) { - remove(false); - } - - @Override - public void httpError(Exception e) { - remove(true); - } - - void remove(boolean isError) { - new Thread(new Runnable() { - @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(); - - } - }); - } - } } + }).start(); + } - NetworkTool.httpGet(NetworkTool.NetworkAPI.PASSWORD_ALL, new JSONObject(), new NetworkInterface() { - @Override - public void httpGetData(JSONObject json, int state) { -// data = ((String) data).replace("desc", "info"); -// JSONObject json = JSONObject.parseObject((String) data); - if (json.getInteger("code") == 0) { - List 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(), password.getInfo()) == 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(), password.getInfo()) == null) { - password.setUpload(true); - dao.insert(password); - } - } - } finally { - showData(); - } - - }).start(); - } - } - - @Override - public void httpError(Exception e) { - new Thread(() -> showData()).start(); - } - }); + private void showLocalData() { + showData(); + } + private void setShow(List data) { + adapter.setList(data); + adapter.notifyDataSetChanged(); + } + void showData() { + new Thread(new Runnable() { + @Override + public void run() { + List list = dao.getAll(); + handler.post(() -> { + adapter.setList(list); + adapter.notifyDataSetChanged(); + }); + } }).start(); } - - void showData() { - List list = dao.getAll(); - handler.post(() -> { - adapter.setList(list); - adapter.notifyDataSetChanged(); - }); - } } \ No newline at end of file diff --git a/app/src/main/java/com/yutou/passmanage/NetUtils/NetApi.java b/app/src/main/java/com/yutou/passmanage/NetUtils/NetApi.java new file mode 100644 index 0000000..a8fa414 --- /dev/null +++ b/app/src/main/java/com/yutou/passmanage/NetUtils/NetApi.java @@ -0,0 +1,48 @@ +package com.yutou.passmanage.NetUtils; + +import com.yutou.netlibs.http.HttpBody; +import com.yutou.passmanage.Datas.ToolsPassword; +import com.yutou.passmanage.bean.BaseBean; +import com.yutou.passmanage.bean.PasswordTypeBean; + +import java.util.List; + +import okhttp3.FormBody; +import retrofit2.Call; +import retrofit2.http.Field; +import retrofit2.http.FormUrlEncoded; +import retrofit2.http.GET; +import retrofit2.http.POST; +import retrofit2.http.Query; + +public interface NetApi { + @GET("/tools/password/type/get/list.do") + Call>> getAllTypePassword(); + @GET("/tools/password/get/list.do") + Call>> getTypePassword( + @Query("type") int type + ); + + @GET("/tools/password/get/password.do") + Call> getPassword( + @Query("id") int id + ); + + @FormUrlEncoded + @POST("/tools/password/set/add.do") + Call> addPassword(@Field("title") String title, + @Field("account") String account, + @Field("password") String password, + @Field("info") String info); + + @FormUrlEncoded + @POST("/tools/password/set/update.do") + Call> updatePassword(@Field("id") int id, + @Field("title") String title, + @Field("account") String account, + @Field("password") String password, + @Field("info") String info); + @FormUrlEncoded + @POST("/tools/password/set/remove.do") + Call> removePassword(@Field("id") int id); +} diff --git a/app/src/main/java/com/yutou/passmanage/NetUtils/NetTools.java b/app/src/main/java/com/yutou/passmanage/NetUtils/NetTools.java new file mode 100644 index 0000000..9ce9d80 --- /dev/null +++ b/app/src/main/java/com/yutou/passmanage/NetUtils/NetTools.java @@ -0,0 +1,19 @@ +package com.yutou.passmanage.NetUtils; + +import com.yutou.netlibs.http.API; +import com.yutou.netlibs.http.BaseAPI; +import com.yutou.passmanage.Datas.AppData; + +import java.util.HashMap; + +public class NetTools extends API { + private NetTools(String url,HashMap map) { + super(url,map); + } + + public static NetApi getApi(){ + HashMap map=new HashMap<>(); + map.put("token", AppData.key); + return new NetTools("https://tools.yutou233.cn",map).createAPI(NetApi.class); + } +} diff --git a/app/src/main/java/com/yutou/passmanage/Tools/NetworkTool.java b/app/src/main/java/com/yutou/passmanage/Tools/NetworkTool.java index accb07e..28795cd 100644 --- a/app/src/main/java/com/yutou/passmanage/Tools/NetworkTool.java +++ b/app/src/main/java/com/yutou/passmanage/Tools/NetworkTool.java @@ -3,10 +3,8 @@ package com.yutou.passmanage.Tools; import android.util.Log; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONException; -import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson2.JSONException; +import com.alibaba.fastjson2.JSONObject; import com.yutou.passmanage.Datas.AppData; import com.yutou.passmanage.Interfaces.NetworkInterface; @@ -29,162 +27,11 @@ public class NetworkTool { private final static String TAG = NetworkTool.class.getSimpleName(); public static class NetworkAPI { - 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"; - public static String PASSWORD_REMOVE = HOME + "set/remove.do"; - public static String PASSWORD_TYPE_ALL = HOME + "type/get/list.do"; - public static String PASSWORD_TYPE_ADD = HOME + "type/set/add.do"; } - 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 { - JSONObject json=JSONObject.parseObject(str.toString()); - Type[] types = ((ParameterizedType) networkInterface.getClass().getGenericSuperclass()).getActualTypeArguments(); - if(types.length==0){ - networkInterface.httpGetData((T) JSONObject.parseObject(str.toString()),connection.getResponseCode()); - }else { - Type type=types[0]; - if (type.getTypeName().contains("JSON")) { - networkInterface.httpGetData((T) JSONObject.parseObject(str.toString()), connection.getResponseCode()); - }else { - networkInterface.httpGetData(JSONObject.parseObject(json.getJSONObject("data").toJSONString(), type), connection.getResponseCode()); - } - } - } catch (Exception 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(toGetSplice(body).getBytes()); - outputStream.flush(); - outputStream.close(); - 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"; diff --git a/app/src/main/java/com/yutou/passmanage/Tools/RoomDatabaseManager.java b/app/src/main/java/com/yutou/passmanage/Tools/RoomDatabaseManager.java index 798a1a0..2b61ae9 100644 --- a/app/src/main/java/com/yutou/passmanage/Tools/RoomDatabaseManager.java +++ b/app/src/main/java/com/yutou/passmanage/Tools/RoomDatabaseManager.java @@ -1,6 +1,7 @@ package com.yutou.passmanage.Tools; import android.content.Context; +import android.widget.Toast; import androidx.annotation.NonNull; import androidx.room.Database; @@ -12,10 +13,17 @@ import androidx.room.migration.Migration; import androidx.sqlite.db.SupportSQLiteDatabase; import androidx.sqlite.db.SupportSQLiteOpenHelper; -import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson2.JSONObject; +import com.yutou.netlibs.http.HttpBody; import com.yutou.passmanage.Datas.ToolsPassword; import com.yutou.passmanage.Datas.ToolsPasswordDao; import com.yutou.passmanage.Interfaces.NetworkInterface; +import com.yutou.passmanage.NetUtils.NetTools; +import com.yutou.passmanage.bean.BaseBean; + +import retrofit2.Call; +import retrofit2.HttpException; +import retrofit2.Response; @Database(entities = {ToolsPassword.class}, version = 2,exportSchema = false) public abstract class RoomDatabaseManager extends RoomDatabase { @@ -62,9 +70,29 @@ public abstract class RoomDatabaseManager extends RoomDatabase { json.put("id",id); } if(isAdd) { - NetworkTool.httpPost(NetworkTool.NetworkAPI.PASSWORD_ADD, json, networkInterface); + NetTools.getApi().addPassword(title,account,password,info).enqueue(new retrofit2.Callback>() { + @Override + public void onResponse(Call> call, Response> response) { + networkInterface.httpGetData(response.body().getData(), response.body().getCode()); + } + + @Override + public void onFailure(Call> call, Throwable t) { + networkInterface.httpError(new RuntimeException(t.getMessage())); + } + }); }else{ - NetworkTool.httpPost(NetworkTool.NetworkAPI.PASSWORD_UPDATE, json, networkInterface); + NetTools.getApi().updatePassword(id,title,account,password,info).enqueue(new retrofit2.Callback>() { + @Override + public void onResponse(Call> call, Response> response) { + networkInterface.httpGetData(response.body().getData(), response.body().getCode()); + } + + @Override + public void onFailure(Call> call, Throwable t) { + networkInterface.httpError(new RuntimeException(t.getMessage())); + } + }); } } } diff --git a/app/src/main/java/com/yutou/passmanage/Tools/Tools.java b/app/src/main/java/com/yutou/passmanage/Tools/Tools.java index 5571a10..457c604 100644 --- a/app/src/main/java/com/yutou/passmanage/Tools/Tools.java +++ b/app/src/main/java/com/yutou/passmanage/Tools/Tools.java @@ -8,7 +8,7 @@ import java.util.List; public class Tools { public static boolean isEmpty(String str){ - if(str==null||str.trim().length()==0){ + if(str==null|| str.trim().isEmpty()){ return true; } return false; diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 14d6a1c..fb46e1a 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -71,4 +71,6 @@ app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:srcCompat="@android:drawable/ic_input_add" /> + + \ No newline at end of file diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml index 53c6945..774ca1f 100644 --- a/app/src/main/res/values-night/themes.xml +++ b/app/src/main/res/values-night/themes.xml @@ -13,4 +13,9 @@ ?attr/colorPrimaryVariant + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2d7e148..4b83cf6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -7,4 +7,50 @@ 名字 已复制密码 更新成功 + + First Fragment + Second Fragment + Next + Previous + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam in scelerisque sem. Mauris + volutpat, dolor id interdum ullamcorper, risus dolor egestas lectus, sit amet mattis purus + dui nec risus. Maecenas non sodales nisi, vel dictum dolor. Class aptent taciti sociosqu ad + litora torquent per conubia nostra, per inceptos himenaeos. Suspendisse blandit eleifend + diam, vel rutrum tellus vulputate quis. Aliquam eget libero aliquet, imperdiet nisl a, + ornare ex. Sed rhoncus est ut libero porta lobortis. Fusce in dictum tellus.\n\n + Suspendisse interdum ornare ante. Aliquam nec cursus lorem. Morbi id magna felis. Vivamus + egestas, est a condimentum egestas, turpis nisl iaculis ipsum, in dictum tellus dolor sed + neque. Morbi tellus erat, dapibus ut sem a, iaculis tincidunt dui. Interdum et malesuada + fames ac ante ipsum primis in faucibus. Curabitur et eros porttitor, ultricies urna vitae, + molestie nibh. Phasellus at commodo eros, non aliquet metus. Sed maximus nisl nec dolor + bibendum, vel congue leo egestas.\n\n + Sed interdum tortor nibh, in sagittis risus mollis quis. Curabitur mi odio, condimentum sit + amet auctor at, mollis non turpis. Nullam pretium libero vestibulum, finibus orci vel, + molestie quam. Fusce blandit tincidunt nulla, quis sollicitudin libero facilisis et. Integer + interdum nunc ligula, et fermentum metus hendrerit id. Vestibulum lectus felis, dictum at + lacinia sit amet, tristique id quam. Cras eu consequat dui. Suspendisse sodales nunc ligula, + in lobortis sem porta sed. Integer id ultrices magna, in luctus elit. Sed a pellentesque + est.\n\n + Aenean nunc velit, lacinia sed dolor sed, ultrices viverra nulla. Etiam a venenatis nibh. + Morbi laoreet, tortor sed facilisis varius, nibh orci rhoncus nulla, id elementum leo dui + non lorem. Nam mollis ipsum quis auctor varius. Quisque elementum eu libero sed commodo. In + eros nisl, imperdiet vel imperdiet et, scelerisque a mauris. Pellentesque varius ex nunc, + quis imperdiet eros placerat ac. Duis finibus orci et est auctor tincidunt. Sed non viverra + ipsum. Nunc quis augue egestas, cursus lorem at, molestie sem. Morbi a consectetur ipsum, a + placerat diam. Etiam vulputate dignissim convallis. Integer faucibus mauris sit amet finibus + convallis.\n\n + Phasellus in aliquet mi. Pellentesque habitant morbi tristique senectus et netus et + malesuada fames ac turpis egestas. In volutpat arcu ut felis sagittis, in finibus massa + gravida. Pellentesque id tellus orci. Integer dictum, lorem sed efficitur ullamcorper, + libero justo consectetur ipsum, in mollis nisl ex sed nisl. Donec maximus ullamcorper + sodales. Praesent bibendum rhoncus tellus nec feugiat. In a ornare nulla. Donec rhoncus + libero vel nunc consequat, quis tincidunt nisl eleifend. Cras bibendum enim a justo luctus + vestibulum. Fusce dictum libero quis erat maximus, vitae volutpat diam dignissim. + + MainActivity2 + Home + Dashboard + Notifications \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index a2abcc3..ad1fbe7 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -13,4 +13,9 @@ ?attr/colorPrimaryVariant + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index cc687cd..4f37b90 100644 --- a/build.gradle +++ b/build.gradle @@ -5,8 +5,8 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:7.0.0' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.20" + classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } diff --git a/gradle.properties b/gradle.properties index e7b029c..81ab4cd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -22,3 +22,6 @@ systemProp.http.proxyHost=127.0.0.1 systemProp.https.proxyHost=127.0.0.1 systemProp.https.proxyPort=7980 systemProp.http.proxyPort=7890 +android.defaults.buildfeatures.buildconfig=true +android.nonTransitiveRClass=false +android.nonFinalResIds=false diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 75668a3..20db9ad 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..79a61d4 --- /dev/null +++ b/gradlew @@ -0,0 +1,244 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..93e3f59 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/netlibs/.gitignore b/netlibs/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/netlibs/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/netlibs/build.gradle b/netlibs/build.gradle new file mode 100644 index 0000000..d7cd84c --- /dev/null +++ b/netlibs/build.gradle @@ -0,0 +1,34 @@ +plugins { + id 'com.android.library' +} + +android { + namespace 'com.yutou.netlibs' + compileSdk 34 + + defaultConfig { + minSdk 28 + targetSdk 34 + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + + api 'com.squareup.okhttp3:okhttp:3.14.9' + api 'com.squareup.retrofit2:retrofit:2.3.0' + api 'com.alibaba.fastjson2:fastjson2:2.0.52' + +} \ No newline at end of file diff --git a/netlibs/proguard-rules.pro b/netlibs/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/netlibs/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/netlibs/src/main/AndroidManifest.xml b/netlibs/src/main/AndroidManifest.xml new file mode 100644 index 0000000..0443622 --- /dev/null +++ b/netlibs/src/main/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/netlibs/src/main/java/com/yutou/netlibs/converter/JsonCallAdapter.java b/netlibs/src/main/java/com/yutou/netlibs/converter/JsonCallAdapter.java new file mode 100644 index 0000000..b466b72 --- /dev/null +++ b/netlibs/src/main/java/com/yutou/netlibs/converter/JsonCallAdapter.java @@ -0,0 +1,17 @@ +package com.yutou.netlibs.converter; + +import retrofit2.CallAdapter; +import retrofit2.Retrofit; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; + +public class JsonCallAdapter extends CallAdapter.Factory{ + public static JsonCallAdapter create(){ + return new JsonCallAdapter(); + } + @Override + public CallAdapter get(Type type, Annotation[] annotations, Retrofit retrofit) { + return null; + } +} diff --git a/netlibs/src/main/java/com/yutou/netlibs/converter/JsonConverterFactory.java b/netlibs/src/main/java/com/yutou/netlibs/converter/JsonConverterFactory.java new file mode 100644 index 0000000..48f417c --- /dev/null +++ b/netlibs/src/main/java/com/yutou/netlibs/converter/JsonConverterFactory.java @@ -0,0 +1,27 @@ +package com.yutou.netlibs.converter; + +import okhttp3.RequestBody; +import okhttp3.ResponseBody; +import retrofit2.Converter; +import retrofit2.Retrofit; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; + +public class JsonConverterFactory extends Converter.Factory { + public static JsonConverterFactory create() { + return new JsonConverterFactory(); + } + + @Override + public Converter requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { + // return super.requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit); + return new JsonRequestBodyConverter<>(); + } + + @Override + public Converter responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { + // return super.responseBodyConverter(type, annotations, retrofit); + return new JsonResponseBodyConverter<>(type); + } +} diff --git a/netlibs/src/main/java/com/yutou/netlibs/converter/JsonRequestBodyConverter.java b/netlibs/src/main/java/com/yutou/netlibs/converter/JsonRequestBodyConverter.java new file mode 100644 index 0000000..3bccb1c --- /dev/null +++ b/netlibs/src/main/java/com/yutou/netlibs/converter/JsonRequestBodyConverter.java @@ -0,0 +1,14 @@ +package com.yutou.netlibs.converter; + +import okhttp3.MediaType; +import okhttp3.RequestBody; +import retrofit2.Converter; + +import java.io.IOException; + +public class JsonRequestBodyConverter implements Converter { + @Override + public RequestBody convert(T t) throws IOException { + return RequestBody.create(MediaType.parse("application/json);charset=UTF-8"), t.toString()); + } +} diff --git a/netlibs/src/main/java/com/yutou/netlibs/converter/JsonResponseBodyConverter.java b/netlibs/src/main/java/com/yutou/netlibs/converter/JsonResponseBodyConverter.java new file mode 100644 index 0000000..4e80f6b --- /dev/null +++ b/netlibs/src/main/java/com/yutou/netlibs/converter/JsonResponseBodyConverter.java @@ -0,0 +1,34 @@ +package com.yutou.netlibs.converter; + +import com.alibaba.fastjson2.JSONObject; +import com.yutou.netlibs.http.HttpBody; + +import okhttp3.ResponseBody; +import retrofit2.Converter; + +import java.io.IOException; +import java.lang.reflect.Type; + +public class JsonResponseBodyConverter implements Converter { + Type type; + public JsonResponseBodyConverter(Type type) { + this.type=type; + } + + @Override + public T convert(ResponseBody responseBody) throws IOException { + String string = new String(responseBody.bytes()); + responseBody.close(); + HttpBody body ; + try { + body = JSONObject.parseObject(string, type); + return (T) body; + } catch (Exception e) { + e.printStackTrace(); + body = new HttpBody(); + body.setSrc(string); + } + return (T) body; + + } +} diff --git a/netlibs/src/main/java/com/yutou/netlibs/http/API.java b/netlibs/src/main/java/com/yutou/netlibs/http/API.java new file mode 100644 index 0000000..a0ffbd0 --- /dev/null +++ b/netlibs/src/main/java/com/yutou/netlibs/http/API.java @@ -0,0 +1,57 @@ +package com.yutou.netlibs.http; + +import com.yutou.netlibs.converter.JsonCallAdapter; +import com.yutou.netlibs.converter.JsonConverterFactory; +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; + +import java.io.IOException; +import java.util.HashMap; + +public class API extends BaseAPI { + private String URL; + private HashMap params; + + public API(String url, HashMap params) { + this.URL = url; + this.params = params; + } + + public API(String url) { + this.URL = url; + this.params = new HashMap<>(); + } + + + @Override + public T createAPI(Class t) { + HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor("http"); + loggingInterceptor.setPrintLevel(HttpLoggingInterceptor.Level.BODY); + OkHttpClient.Builder builder = new OkHttpClient() + .newBuilder() + + .addInterceptor(initQuery()) + .addInterceptor(loggingInterceptor); + return create(builder.build(), + JsonConverterFactory.create(), + JsonCallAdapter.create(), + URL, + t); + } + + public Interceptor initQuery() { + Interceptor addQueryParameterInterceptor = new Interceptor() { + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + //配置公共参数 + request = new ParamsContext(params,request).getInRequest(); + return chain.proceed(request); + } + }; + return addQueryParameterInterceptor; + } + +} diff --git a/netlibs/src/main/java/com/yutou/netlibs/http/BaseAPI.java b/netlibs/src/main/java/com/yutou/netlibs/http/BaseAPI.java new file mode 100644 index 0000000..ac2fdec --- /dev/null +++ b/netlibs/src/main/java/com/yutou/netlibs/http/BaseAPI.java @@ -0,0 +1,44 @@ +package com.yutou.netlibs.http; + +import okhttp3.OkHttpClient; +import retrofit2.CallAdapter; +import retrofit2.Converter; +import retrofit2.Retrofit; + +public abstract class BaseAPI { + public abstract T createAPI(Class t); + /** + * 创建一个接口方法 + * + * @param okHttpClient okhttp客户端 + * @param converterFactory 处理工厂类 + * @param callAdapterFactory 请求适配器工厂 + * @param baseUrl 基础地质 + * @param service 接口 + * @return 接口 + */ + public T create(OkHttpClient okHttpClient, + Converter.Factory converterFactory, + CallAdapter.Factory callAdapterFactory, + String baseUrl, + Class service) { + Retrofit.Builder builder = new Retrofit.Builder() + //基础url + .baseUrl(baseUrl) + //客户端OKHttp + .client(okHttpClient); + //添加转换工厂 + if (null != converterFactory) { + builder.addConverterFactory(converterFactory); + } + //添加请求工厂 + if (null != callAdapterFactory) { + builder.addCallAdapterFactory(callAdapterFactory); + } + //创建retrofit对象 + Retrofit retrofit = builder.build(); + + //返回创建的api + return retrofit.create(service); + } +} diff --git a/netlibs/src/main/java/com/yutou/netlibs/http/GetRequestParams.java b/netlibs/src/main/java/com/yutou/netlibs/http/GetRequestParams.java new file mode 100644 index 0000000..d996524 --- /dev/null +++ b/netlibs/src/main/java/com/yutou/netlibs/http/GetRequestParams.java @@ -0,0 +1,25 @@ +package com.yutou.netlibs.http; + + +import okhttp3.HttpUrl; +import okhttp3.Request; + +import java.util.HashMap; + +public class GetRequestParams implements IRequestParam { + /** + * 构建Request + * + * @param request + * @return + */ + @Override + public Request getRequest(HashMap map, Request request) { + //添加公共参数 + HttpUrl.Builder builder = request.url().newBuilder(); + for (String key : map.keySet()) { + builder.addQueryParameter(key, String.valueOf(map.get(key))); + } + return request.newBuilder().url(builder.build()).build(); + } +} diff --git a/netlibs/src/main/java/com/yutou/netlibs/http/HttpBody.java b/netlibs/src/main/java/com/yutou/netlibs/http/HttpBody.java new file mode 100644 index 0000000..85da1dd --- /dev/null +++ b/netlibs/src/main/java/com/yutou/netlibs/http/HttpBody.java @@ -0,0 +1,40 @@ +package com.yutou.netlibs.http; + +public class HttpBody { + private String msg; + private int code; + private T data; + private String src; + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } + + public String getSrc() { + return src; + } + + public void setSrc(String src) { + this.src = src; + } +} diff --git a/netlibs/src/main/java/com/yutou/netlibs/http/HttpCallback.java b/netlibs/src/main/java/com/yutou/netlibs/http/HttpCallback.java new file mode 100644 index 0000000..93b97a3 --- /dev/null +++ b/netlibs/src/main/java/com/yutou/netlibs/http/HttpCallback.java @@ -0,0 +1,27 @@ +package com.yutou.netlibs.http; + +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; + +public abstract class HttpCallback implements Callback> { + + public abstract void onResponse(int code,String status,T response); + public abstract void onFailure(Throwable throwable); + + @Override + public void onResponse(Call> call, Response> response) { + if (response.body() != null) { + System.out.println("response = " + response.body()); + System.out.println("response.data = " + response.body().getData()); + onResponse(response.body().getCode(),response.body().getMsg(),response.body().getData()); + }else{ + onFailure(new NullPointerException("response body is null")); + } + } + + @Override + public void onFailure(Call> call, Throwable throwable) { + onFailure(throwable); + } +} diff --git a/netlibs/src/main/java/com/yutou/netlibs/http/HttpLoggingInterceptor.java b/netlibs/src/main/java/com/yutou/netlibs/http/HttpLoggingInterceptor.java new file mode 100644 index 0000000..45bb196 --- /dev/null +++ b/netlibs/src/main/java/com/yutou/netlibs/http/HttpLoggingInterceptor.java @@ -0,0 +1,213 @@ +package com.yutou.netlibs.http; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; + +import okhttp3.Connection; +import okhttp3.Headers; +import okhttp3.Interceptor; +import okhttp3.MediaType; +import okhttp3.Protocol; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import okhttp3.ResponseBody; +import okhttp3.internal.http.HttpHeaders; +import okio.Buffer; + +public class HttpLoggingInterceptor implements Interceptor { + + private static final String TAG = "HttpLog"; + private static final Charset UTF8 = StandardCharsets.UTF_8; + + private volatile Level printLevel = Level.NONE; + private java.util.logging.Level colorLevel; + private Logger logger; + + public enum Level { + NONE, //不打印log + BASIC, //只打印 请求首行 和 响应首行 + HEADERS, //打印请求和响应的所有 Header + BODY //所有数据全部打印 + } + + public HttpLoggingInterceptor(String tag) { + logger = Logger.getLogger(tag); + colorLevel = java.util.logging.Level.ALL; + } + + public void setPrintLevel(Level level) { + if (printLevel == null) + throw new NullPointerException("printLevel == null. Use Level.NONE instead."); + printLevel = level; + } + + public void setColorLevel(java.util.logging.Level level) { + colorLevel = level; + } + + private void log(String message) { + logger.log(colorLevel, message); + System.err.println(message); + } + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + if (printLevel == Level.NONE) { + return chain.proceed(request); + } + + //请求日志拦截 + // logForRequest(request, chain.connection()); + + //执行请求,计算请求时间 + long startNs = System.nanoTime(); + Response response; + try { + response = chain.proceed(request); + } catch (Exception e) { + log("<-- HTTP FAILED: " + e); + throw e; + } + long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs); + + //响应日志拦截 + return logForResponse(request, response, tookMs); + } + + private void logForRequest(Request request, Connection connection) throws IOException { + boolean logBody = (printLevel == Level.BODY); + boolean logHeaders = (printLevel == Level.BODY || printLevel == Level.HEADERS); + RequestBody requestBody = request.body(); + boolean hasRequestBody = requestBody != null; + Protocol protocol = connection != null ? connection.protocol() : Protocol.HTTP_1_1; + try { + String requestStartMessage = "--> " + request.method() + ' ' + request.url() + ' ' + protocol; + log(requestStartMessage); + + if (logHeaders) { + if (hasRequestBody) { + // Request body headers are only present when installed as a network interceptor. Force + // them to be included (when available) so there values are known. + if (requestBody.contentType() != null) { + log("\tContent-Type: " + requestBody.contentType()); + } + if (requestBody.contentLength() != -1) { + log("\tContent-Length: " + requestBody.contentLength()); + } + } + Headers headers = request.headers(); + for (int i = 0, count = headers.size(); i < count; i++) { + String name = headers.name(i); + // Skip headers from the request body as they are explicitly logged above. + if (!"Content-Type".equalsIgnoreCase(name) && !"Content-Length".equalsIgnoreCase(name)) { + log("\t" + name + ": " + headers.value(i)); + } + } + + log(" "); + if (logBody && hasRequestBody) { + if (isPlaintext(requestBody.contentType())) { + bodyToString(request); + } else { + log("\tbody: maybe [binary body], omitted!"); + } + } + } + } catch (Exception e) { + logger.log(colorLevel, "error", e); + } finally { + log("--> END " + request.method()); + } + } + + private Response logForResponse(Request request, Response response, long tookMs) { + Response.Builder builder = response.newBuilder(); + Response clone = builder.build(); + ResponseBody responseBody = clone.body(); + RequestBody requestBody = request.body(); + boolean hasRequestBody = requestBody != null; + boolean logBody = (printLevel == Level.BODY); + boolean logHeaders = (printLevel == Level.BODY || printLevel == Level.HEADERS); + + try { + log("<-- " + clone.code() + ' ' + clone.message() + ' ' + clone.request().url() + " (" + tookMs + "ms)"); + if (logHeaders) { + Headers headers = clone.headers(); + for (int i = 0, count = headers.size(); i < count; i++) { + log("\t" + headers.name(i) + ": " + headers.value(i)); + } + log(" "); + if (logBody && hasRequestBody) { + if (isPlaintext(requestBody.contentType())) { + bodyToString(request); + } else { + log("\trequest: maybe [binary body], omitted!"); + } + } + if (logBody && HttpHeaders.hasBody(clone)) { + if (responseBody == null) return response; + + if (isPlaintext(responseBody.contentType())) { + byte[] bytes = responseBody.bytes();// IOUtils.toByteArray(responseBody.byteStream()); + MediaType contentType = responseBody.contentType(); + String body = new String(bytes, getCharset(contentType)); + log("\tbody:" + body); + responseBody = ResponseBody.create(responseBody.contentType(), bytes); + return response.newBuilder().body(responseBody).build(); + } else { + log("\tbody: maybe [binary body], omitted!"); + } + } + } + } catch (Exception e) { + logger.log(colorLevel, "error", e); + } finally { + log("<-- END HTTP"); + } + return response; + } + + private static Charset getCharset(MediaType contentType) { + Charset charset = contentType != null ? contentType.charset(UTF8) : UTF8; + if (charset == null) charset = UTF8; + return charset; + } + + /** + * Returns true if the body in question probably contains human readable text. Uses a small sample + * of code points to detect unicode control characters commonly used in binary file signatures. + */ + private static boolean isPlaintext(MediaType mediaType) { + if (mediaType == null) return false; + if (mediaType.type() != null && mediaType.type().equals("text")) { + return true; + } + String subtype = mediaType.subtype(); + if (subtype != null) { + subtype = subtype.toLowerCase(); + if (subtype.contains("x-www-form-urlencoded") || subtype.contains("json") || subtype.contains("xml") || subtype.contains("html")) // + return true; + } + return false; + } + + private void bodyToString(Request request) { + try { + Request copy = request.newBuilder().build(); + RequestBody body = copy.body(); + if (body == null) return; + Buffer buffer = new Buffer(); + body.writeTo(buffer); + Charset charset = getCharset(body.contentType()); + log("\tbody:" + buffer.readString(charset)); + } catch (Exception e) { + logger.log(colorLevel, "error", e); + } + } +} diff --git a/netlibs/src/main/java/com/yutou/netlibs/http/IRequestParam.java b/netlibs/src/main/java/com/yutou/netlibs/http/IRequestParam.java new file mode 100644 index 0000000..aa6074e --- /dev/null +++ b/netlibs/src/main/java/com/yutou/netlibs/http/IRequestParam.java @@ -0,0 +1,9 @@ +package com.yutou.netlibs.http; + +import okhttp3.Request; + +import java.util.HashMap; + +public interface IRequestParam { + Request getRequest(HashMap map, Request request); +} diff --git a/netlibs/src/main/java/com/yutou/netlibs/http/ParamsContext.java b/netlibs/src/main/java/com/yutou/netlibs/http/ParamsContext.java new file mode 100644 index 0000000..9944e40 --- /dev/null +++ b/netlibs/src/main/java/com/yutou/netlibs/http/ParamsContext.java @@ -0,0 +1,29 @@ +package com.yutou.netlibs.http; + + +import okhttp3.Request; + +import java.util.HashMap; + +public class ParamsContext { + private IRequestParam iRequestParam; + private Request request; + private HashMap map; + + public ParamsContext(HashMap map,Request request) { + this.map=map; + this.request = request; + } + + public Request getInRequest() { + switch (request.method()) { + case "GET": + iRequestParam = new GetRequestParams(); + break; + case "POST": + iRequestParam = new PostRequestParams(); + break; + } + return iRequestParam.getRequest(map,request); + } +} diff --git a/netlibs/src/main/java/com/yutou/netlibs/http/PostRequestParams.java b/netlibs/src/main/java/com/yutou/netlibs/http/PostRequestParams.java new file mode 100644 index 0000000..07588a8 --- /dev/null +++ b/netlibs/src/main/java/com/yutou/netlibs/http/PostRequestParams.java @@ -0,0 +1,65 @@ +package com.yutou.netlibs.http; + + +import com.alibaba.fastjson2.JSONObject; + +import okhttp3.*; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class PostRequestParams implements IRequestParam { + @Override + public Request getRequest(HashMap map, Request request) { + if (request.body() instanceof FormBody) { + FormBody.Builder bodyBuilder = new FormBody.Builder(); + FormBody formBody = (FormBody) request.body(); + + for (int i = 0; i < formBody.size(); i++) { + bodyBuilder.addEncoded(formBody.encodedName(i), formBody.encodedValue(i)); + } + for (String key : map.keySet()) { + bodyBuilder.addEncoded(key, String.valueOf(map.get(key))); + } + formBody = bodyBuilder.build(); + request = request.newBuilder().post(formBody).build(); + } else if (request.body() != null) { + RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),toUrlParams(map)); + request = request.newBuilder().post(request.body()) + .post(requestBody).build(); + } + return request; + } + + public static String toUrlParams(JSONObject json) { + 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(); + } + + public static String toUrlParams(Map map) { + StringBuilder builder = new StringBuilder(); + for (String key : map.keySet()) { + builder.append(key).append("=").append(map.get(key)).append("&"); + } + return builder.substring(0, builder.length() - 1); + } +} diff --git a/settings.gradle b/settings.gradle index 9d70ee3..114af78 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1,5 @@ include ':app' include ':ViewPager2Delegate' include ':TabLayout' +include ':netlibs' rootProject.name = "MyPassworldManage" \ No newline at end of file