diff --git a/.idea/misc.xml b/.idea/misc.xml
index 74dd639..9cafd9a 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -7,4 +7,11 @@
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 8bd5963..e77a224 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,5 +1,3 @@
-import org.gradle.kotlin.dsl.implementation
-
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
@@ -41,6 +39,9 @@ android {
kotlinOptions {
jvmTarget = "11"
}
+ viewBinding {
+ enable = true
+ }
}
dependencies {
@@ -53,4 +54,28 @@ dependencies {
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
+
+ // camerax
+ implementation(libs.androidx.camera.core)
+ implementation(libs.androidx.camera.camera2)
+ implementation(libs.androidx.camera.lifecycle)
+ implementation(libs.androidx.camera.view)
+ implementation(libs.androidx.camera.extensions)
+
+ // 权限申请
+ implementation(libs.accompanist.permissions)
+ // hilt注入
+ implementation(libs.hilt.android)
+ ksp(libs.hilt.android.compiler)
+
+ // retrofit网络请求
+ implementation(libs.retrofit)
+ implementation(libs.converter.gson)
+ // okhttp
+ implementation(libs.okhttp)
+ implementation(libs.logging.interceptor)
+ // gson
+ implementation(libs.gson)
+ // 日志打印
+ implementation(libs.timber)
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 86bf6e0..6e88fdb 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,6 +2,13 @@
+
+
+
+
+
+ android:name=".activity.LoginByPwdActivity"
+ android:exported="false"
+ android:launchMode="singleTask" />
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/sw/platecabinet/MainActivity.kt b/app/src/main/java/com/sw/platecabinet/MainActivity.kt
deleted file mode 100644
index 1f03a26..0000000
--- a/app/src/main/java/com/sw/platecabinet/MainActivity.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.sw.platecabinet
-
-import android.os.Bundle
-import androidx.activity.enableEdgeToEdge
-import androidx.appcompat.app.AppCompatActivity
-import androidx.core.view.ViewCompat
-import androidx.core.view.WindowInsetsCompat
-
-class MainActivity : AppCompatActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- enableEdgeToEdge()
- setContentView(R.layout.activity_main)
- ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
- val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
- v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
- insets
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/sw/platecabinet/activity/BaseActivity.kt b/app/src/main/java/com/sw/platecabinet/activity/BaseActivity.kt
new file mode 100644
index 0000000..6d54a83
--- /dev/null
+++ b/app/src/main/java/com/sw/platecabinet/activity/BaseActivity.kt
@@ -0,0 +1,40 @@
+package com.sw.platecabinet.activity
+
+import android.content.Context
+import android.os.Bundle
+import android.view.WindowManager
+import androidx.activity.enableEdgeToEdge
+import androidx.appcompat.app.AppCompatActivity
+import androidx.viewbinding.ViewBinding
+
+/**
+ * activity 基类
+ */
+abstract class BaseActivity : AppCompatActivity() {
+
+ protected lateinit var binding: VB
+ private set
+ protected lateinit var context: Context
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ enableEdgeToEdge()
+ window.setFlags(
+ WindowManager.LayoutParams.FLAG_FULLSCREEN,
+ WindowManager.LayoutParams.FLAG_FULLSCREEN
+ )
+ context = this
+ binding = inflateViewBinding()
+ setContentView(binding.root)
+ initialize()
+ }
+
+ protected abstract fun inflateViewBinding(): VB
+
+ protected abstract fun initialize()
+
+
+ override fun onDestroy() {
+ super.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/sw/platecabinet/activity/LoginByFaceActivity.kt b/app/src/main/java/com/sw/platecabinet/activity/LoginByFaceActivity.kt
new file mode 100644
index 0000000..1467240
--- /dev/null
+++ b/app/src/main/java/com/sw/platecabinet/activity/LoginByFaceActivity.kt
@@ -0,0 +1,73 @@
+package com.sw.platecabinet.activity
+
+import android.content.Intent
+import android.graphics.Outline
+import android.view.View
+import android.view.ViewOutlineProvider
+import androidx.camera.core.CameraSelector
+import androidx.camera.core.Preview
+import androidx.camera.lifecycle.ProcessCameraProvider
+import androidx.core.content.ContextCompat
+import com.google.common.util.concurrent.ListenableFuture
+import com.sw.platecabinet.databinding.ActivityLoginFaceBinding
+import timber.log.Timber
+
+/**
+ * 人脸识别
+ */
+class LoginByFaceActivity : BaseActivity() {
+ private lateinit var cameraProviderFuture: ListenableFuture
+
+ override fun inflateViewBinding(): ActivityLoginFaceBinding {
+ return ActivityLoginFaceBinding.inflate(layoutInflater)
+ }
+
+ override fun initialize() {
+ initView()
+ startCamera()
+ binding.llToPwd.setOnClickListener {
+ val intent = Intent(this, LoginByPwdActivity::class.java)
+ startActivity(intent)
+ }
+ }
+
+ private fun initView() {
+ binding.previewView.outlineProvider = object : ViewOutlineProvider() {
+ override fun getOutline(view: View, outline: Outline) {
+// outline.setRoundRect(0, 0, view.width, view.height, 12f.dp)
+ outline.setOval(0, 0, view.width, view.height)
+ }
+ }
+ binding.previewView.clipToOutline = true
+ }
+
+ private fun startCamera() {
+ cameraProviderFuture = ProcessCameraProvider.getInstance(this)
+ cameraProviderFuture.addListener({
+ val cameraProvider = cameraProviderFuture.get()
+
+ // 创建预览用例
+ val preview = Preview.Builder()
+ .build()
+ .also {
+ it.setSurfaceProvider(binding.previewView.surfaceProvider)
+ }
+
+ // 选择后置摄像头
+ val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
+
+ try {
+ // 解绑所有用例
+ cameraProvider.unbindAll()
+
+ // 绑定到生命周期
+ cameraProvider.bindToLifecycle(
+ this, cameraSelector, preview
+ )
+ } catch (exc: Exception) {
+ Timber.e(exc, "Use case binding failed")
+ }
+ }, ContextCompat.getMainExecutor(this))
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/sw/platecabinet/activity/LoginByPwdActivity.kt b/app/src/main/java/com/sw/platecabinet/activity/LoginByPwdActivity.kt
new file mode 100644
index 0000000..011ef3b
--- /dev/null
+++ b/app/src/main/java/com/sw/platecabinet/activity/LoginByPwdActivity.kt
@@ -0,0 +1,18 @@
+package com.sw.platecabinet.activity
+
+import android.content.Intent
+import com.sw.platecabinet.databinding.ActivityLoginByPwdBinding
+
+class LoginByPwdActivity : BaseActivity() {
+ override fun inflateViewBinding(): ActivityLoginByPwdBinding {
+ return ActivityLoginByPwdBinding.inflate(layoutInflater)
+ }
+
+ override fun initialize() {
+ binding.tvFaceRec.setOnClickListener {
+ val intent = Intent(this, LoginByFaceActivity::class.java)
+ startActivity(intent)
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/sw/platecabinet/activity/MainActivity.kt b/app/src/main/java/com/sw/platecabinet/activity/MainActivity.kt
new file mode 100644
index 0000000..794c2eb
--- /dev/null
+++ b/app/src/main/java/com/sw/platecabinet/activity/MainActivity.kt
@@ -0,0 +1,14 @@
+package com.sw.platecabinet.activity
+
+import com.sw.platecabinet.databinding.ActivityMainBinding
+
+class MainActivity : BaseActivity() {
+
+ override fun inflateViewBinding(): ActivityMainBinding {
+ return ActivityMainBinding.inflate(layoutInflater)
+ }
+
+ override fun initialize() {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/sw/platecabinet/ext/CommonExt.kt b/app/src/main/java/com/sw/platecabinet/ext/CommonExt.kt
new file mode 100644
index 0000000..ef20401
--- /dev/null
+++ b/app/src/main/java/com/sw/platecabinet/ext/CommonExt.kt
@@ -0,0 +1,49 @@
+package com.sw.platecabinet.ext
+
+import android.content.res.Resources
+import android.util.TypedValue
+import androidx.annotation.Dimension
+
+/**
+ * 将 Int 值转换为 dp 值
+ */
+val Int.dp: Int
+ @Dimension(unit = Dimension.DP)
+ get() = TypedValue.applyDimension(
+ TypedValue.COMPLEX_UNIT_DIP,
+ this.toFloat(),
+ Resources.getSystem().displayMetrics
+ ).toInt()
+
+/**
+ * 将 Float 值转换为 dp 值
+ */
+val Float.dp: Float
+ @Dimension(unit = Dimension.DP)
+ get() = TypedValue.applyDimension(
+ TypedValue.COMPLEX_UNIT_DIP,
+ this,
+ Resources.getSystem().displayMetrics
+ )
+
+/**
+ * 将 Int 值转换为 sp 值
+ */
+val Int.sp: Float
+ @Dimension(unit = Dimension.SP)
+ get() = TypedValue.applyDimension(
+ TypedValue.COMPLEX_UNIT_SP,
+ this.toFloat(),
+ Resources.getSystem().displayMetrics
+ )
+
+/**
+ * 将 Float 值转换为 sp 值
+ */
+val Float.sp: Float
+ @Dimension(unit = Dimension.SP)
+ get() = TypedValue.applyDimension(
+ TypedValue.COMPLEX_UNIT_SP,
+ this,
+ Resources.getSystem().displayMetrics
+ )
\ No newline at end of file
diff --git a/app/src/main/res/drawable/btn_outline_887872.xml b/app/src/main/res/drawable/btn_outline_887872.xml
new file mode 100644
index 0000000..c3590b6
--- /dev/null
+++ b/app/src/main/res/drawable/btn_outline_887872.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/circle_dashed_border.xml b/app/src/main/res/drawable/circle_dashed_border.xml
new file mode 100644
index 0000000..4136a47
--- /dev/null
+++ b/app/src/main/res/drawable/circle_dashed_border.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/rounded_border_transparent.xml b/app/src/main/res/drawable/rounded_border_transparent.xml
new file mode 100644
index 0000000..2fb80c3
--- /dev/null
+++ b/app/src/main/res/drawable/rounded_border_transparent.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/shape_btn_bg.xml b/app/src/main/res/drawable/shape_btn_bg.xml
new file mode 100644
index 0000000..191bd6f
--- /dev/null
+++ b/app/src/main/res/drawable/shape_btn_bg.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/shape_pwd_bg.xml b/app/src/main/res/drawable/shape_pwd_bg.xml
new file mode 100644
index 0000000..c8301e0
--- /dev/null
+++ b/app/src/main/res/drawable/shape_pwd_bg.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_login_by_pwd.xml b/app/src/main/res/layout/activity_login_by_pwd.xml
new file mode 100644
index 0000000..0b2b90e
--- /dev/null
+++ b/app/src/main/res/layout/activity_login_by_pwd.xml
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_login_face.xml b/app/src/main/res/layout/activity_login_face.xml
new file mode 100644
index 0000000..f4a12dc
--- /dev/null
+++ b/app/src/main/res/layout/activity_login_face.xml
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 86a5d97..958f021 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,19 +1,10 @@
+ tools:context=".activity.MainActivity">
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_title_time.xml b/app/src/main/res/layout/item_title_time.xml
new file mode 100644
index 0000000..caea9e9
--- /dev/null
+++ b/app/src/main/res/layout/item_title_time.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-xxhdpi/bg.png b/app/src/main/res/mipmap-xxhdpi/bg.png
new file mode 100644
index 0000000..5979fa6
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/bg.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/bg_face.png b/app/src/main/res/mipmap-xxhdpi/bg_face.png
new file mode 100644
index 0000000..64c96b9
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/bg_face.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_password.png b/app/src/main/res/mipmap-xxhdpi/ic_password.png
new file mode 100644
index 0000000..ca70159
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_password.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_phone.png b/app/src/main/res/mipmap-xxhdpi/ic_phone.png
new file mode 100644
index 0000000..9cc79e7
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_phone.png differ
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 2a98c16..d4108e0 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -2,6 +2,5 @@
#FF000000
#FFFFFFFF
-
- #80000000
+ #00000000
\ No newline at end of file
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 86f0dec..1fee65b 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -10,6 +10,14 @@ material = "1.10.0"
activity = "1.8.0"
constraintlayout = "2.1.4"
+accompanistPermissions = "0.37.3"
+cameraCore = "1.3.0"
+retrofit = "3.0.0"
+okhttp = "4.12.0"
+timber = "5.0.1"
+gson = "2.13.1"
+hiltAndroid = "2.56.2"
+
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
@@ -20,6 +28,23 @@ material = { group = "com.google.android.material", name = "material", version.r
androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
+accompanist-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanistPermissions" }
+androidx-camera-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "cameraCore" }
+androidx-camera-core = { module = "androidx.camera:camera-core", version.ref = "cameraCore" }
+androidx-camera-extensions = { module = "androidx.camera:camera-extensions", version.ref = "cameraCore" }
+androidx-camera-view = { module = "androidx.camera:camera-view", version.ref = "cameraCore" }
+androidx-camera-lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref = "cameraCore" }
+
+gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
+hilt-android-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hiltAndroid" }
+hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hiltAndroid" }
+
+logging-interceptor = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "okhttp" }
+okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
+retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
+converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofit" }
+timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" }
+
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }