Bläddra i källkod

refactor(更新)
- 基础代码添加

周文健 5 månader sedan
förälder
incheckning
2f0c15eaef
33 ändrade filer med 589 tillägg och 7 borttagningar
  1. 6 1
      app/build.gradle.kts
  2. BIN
      app/libs/adh_series_sdk.jar
  3. BIN
      app/libs/arcsoft_face.jar
  4. BIN
      app/libs/arcsoft_image_util.jar
  5. BIN
      app/libs/zkandroidcore.jar
  6. BIN
      app/libs/zkandroidfingerservice.jar
  7. BIN
      app/libs/zkandroidfpreader.jar
  8. 11 1
      app/proguard-rules.pro
  9. 1 0
      app/src/main/AndroidManifest.xml
  10. 19 0
      app/src/main/java/com/grkj/iscs/ISCSApplication.kt
  11. 325 0
      app/src/main/java/com/grkj/iscs/utils/fingerprint/FingerprintUtil.kt
  12. 162 0
      app/src/main/java/com/grkj/iscs/utils/fingerprint/ZKUSBManager.java
  13. 15 0
      app/src/main/java/com/grkj/iscs/utils/fingerprint/ZKUSBManagerListener.java
  14. BIN
      app/src/main/jniLibs/arm64-v8a/libarcsoft_face.so
  15. BIN
      app/src/main/jniLibs/arm64-v8a/libarcsoft_face_engine.so
  16. BIN
      app/src/main/jniLibs/arm64-v8a/libarcsoft_image_util.so
  17. BIN
      app/src/main/jniLibs/arm64-v8a/libslkidcap.so
  18. BIN
      app/src/main/jniLibs/arm64-v8a/libzkalg12.so
  19. BIN
      app/src/main/jniLibs/arm64-v8a/libzkfinger10.so
  20. BIN
      app/src/main/jniLibs/arm64-v8a/libzksensorcore.so
  21. BIN
      app/src/main/jniLibs/armeabi-v7a/libarcsoft_face.so
  22. BIN
      app/src/main/jniLibs/armeabi-v7a/libarcsoft_face_engine.so
  23. BIN
      app/src/main/jniLibs/armeabi-v7a/libarcsoft_image_util.so
  24. BIN
      app/src/main/jniLibs/armeabi-v7a/libserial_port.so
  25. BIN
      app/src/main/jniLibs/armeabi-v7a/libslkidcap.so
  26. BIN
      app/src/main/jniLibs/armeabi-v7a/libzkalg12.so
  27. BIN
      app/src/main/jniLibs/armeabi-v7a/libzkfinger10.so
  28. BIN
      app/src/main/jniLibs/armeabi-v7a/libzksensorcore.so
  29. 43 0
      app/src/main/res/values/logback.xml
  30. 2 0
      gradle/libs.versions.toml
  31. 3 3
      shared/build.gradle.kts
  32. 1 1
      sync/build.gradle.kts
  33. 1 1
      ui-base/build.gradle.kts

+ 6 - 1
app/build.gradle.kts

@@ -4,7 +4,7 @@ plugins {
 }
 
 android {
-    namespace = "com.grkj.ui_base"
+    namespace = "com.grkj.iscs"
     compileSdk = 35
 
     defaultConfig {
@@ -44,11 +44,16 @@ dependencies {
     implementation(libs.androidx.constraintlayout)
     implementation(libs.brv)
     implementation(libs.android.autosize)
+    implementation(libs.dialogx)
     implementation(project(":sync"))
     implementation(project(":ui-base"))
     implementation(project(":data"))
     implementation(project(":shared"))
     implementation(project(":domain"))
+    implementation(fileTree(mapOf(
+        "dir" to "libs",
+        "include" to listOf("*.jar", "*.aar")
+    )))
     testImplementation(libs.junit)
     androidTestImplementation(libs.androidx.junit)
     androidTestImplementation(libs.androidx.espresso.core)

BIN
app/libs/adh_series_sdk.jar


BIN
app/libs/arcsoft_face.jar


BIN
app/libs/arcsoft_image_util.jar


BIN
app/libs/zkandroidcore.jar


BIN
app/libs/zkandroidfingerservice.jar


BIN
app/libs/zkandroidfpreader.jar


+ 11 - 1
app/proguard-rules.pro

@@ -18,4 +18,14 @@
 
 # If you keep the line number information, uncomment this to
 # hide the original source file name.
-#-renamesourcefileattribute SourceFile
+#-renamesourcefileattribute SourceFile
+
+-keep class com.kongzue.dialogx.** { *; }
+-dontwarn com.kongzue.dialogx.**
+
+# 额外的,建议将 android.view 也列入 keep 范围:
+-keep class android.view.** { *; }
+
+# 若启用模糊效果,请增加如下配置:
+-dontwarn androidx.renderscript.**
+-keep public class androidx.renderscript.** { *; }

+ 1 - 0
app/src/main/AndroidManifest.xml

@@ -5,6 +5,7 @@
     <uses-permission android:name="android.permission.INTERNET" />
 
     <application
+        android:name=".ISCSApplication"
         android:allowBackup="true"
         android:dataExtractionRules="@xml/data_extraction_rules"
         android:fullBackupContent="@xml/backup_rules"

+ 19 - 0
app/src/main/java/com/grkj/iscs/ISCSApplication.kt

@@ -0,0 +1,19 @@
+package com.grkj.iscs
+
+import android.app.Application
+import com.kongzue.dialogx.DialogX
+import com.sik.sikcore.SIKCore
+
+/**
+ * 启动入口
+ */
+class ISCSApplication : Application() {
+    /**
+     * 程序创建
+     */
+    override fun onCreate() {
+        super.onCreate()
+        DialogX.init(this)
+        SIKCore.init(this)
+    }
+}

+ 325 - 0
app/src/main/java/com/grkj/iscs/utils/fingerprint/FingerprintUtil.kt

@@ -0,0 +1,325 @@
+package com.grkj.iscs.utils.fingerprint
+
+import android.Manifest
+import android.content.Context
+import android.graphics.Bitmap
+import android.hardware.usb.UsbDevice
+import android.hardware.usb.UsbManager
+import android.util.Base64
+import android.util.Log
+import androidx.appcompat.app.AppCompatActivity.USB_SERVICE
+import com.sik.sikandroid.permission.PermissionUtils
+import com.sik.sikcore.SIKCore
+import com.sik.sikcore.activity.ActivityTracker
+import com.sik.sikcore.thread.ThreadUtils
+import com.zkteco.android.biometric.FingerprintExceptionListener
+import com.zkteco.android.biometric.core.device.ParameterHelper
+import com.zkteco.android.biometric.core.device.TransportType
+import com.zkteco.android.biometric.core.utils.LogHelper
+import com.zkteco.android.biometric.core.utils.ToolUtils
+import com.zkteco.android.biometric.module.fingerprintreader.FingerprintCaptureListener
+import com.zkteco.android.biometric.module.fingerprintreader.FingerprintSensor
+import com.zkteco.android.biometric.module.fingerprintreader.FingprintFactory
+import com.zkteco.android.biometric.module.fingerprintreader.ZKFingerService
+import com.zkteco.android.biometric.module.fingerprintreader.exception.FingerprintException
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+
+/**
+ * 指纹工具
+ */
+object FingerprintUtil {
+    private val logger: Logger = LoggerFactory.getLogger(FingerprintUtil::class.java)
+    private const val REQUEST_PERMISSION_CODE = 9
+    private const val ZKTECO_VID: Int = 0x1b55
+    private const val LIVE20R_PID: Int = 0x0120
+    private const val LIVE10R_PID: Int = 0x0124
+    private const val ENROLL_COUNT: Int = 3
+
+    private var bStarted = false
+    private var usb_pid = 0
+    private var zkusbManager: ZKUSBManager? = null
+    private val usb_vid: Int = ZKTECO_VID
+    private var fingerprintSensor: FingerprintSensor? = null
+    private var bRegister = false
+    private var enroll_index = 0
+    private var isReseted = false
+    private val deviceIndex = 0
+    private val regtemparray = Array(3) {
+        ByteArray(
+            2048
+        )
+    }
+
+    private var strUid: String? = null
+
+    private var onScanListener: OnScanListener? = null
+
+    fun setScanListener(listener: OnScanListener) {
+        onScanListener = listener
+    }
+
+    fun init(ctx: Context) {
+        zkusbManager ?: let {
+            zkusbManager = ZKUSBManager(ctx, zkusbManagerListener)
+        }
+        zkusbManager?.registerUSBPermissionReceiver()
+    }
+
+    fun unInit() {
+        if (bStarted) {
+            closeDevice()
+        }
+        zkusbManager?.unRegisterUSBPermissionReceiver()
+    }
+
+    fun start() {
+        if (bStarted) {
+            logger.info("Device already connected!")
+            return
+        }
+        if (!enumSensor()) {
+            logger.info("Device not found!")
+            return
+        }
+        tryGetUSBPermission()
+    }
+
+    fun stop() {
+        if (!bStarted) {
+            logger.info("Device not connected!")
+            return
+        }
+        closeDevice()
+        logger.info("Device closed!")
+    }
+
+    private fun afterGetUsbPermission() {
+        openDevice()
+    }
+
+    private fun tryGetUSBPermission() {
+        zkusbManager?.initUSBPermission(usb_vid, usb_pid)
+    }
+
+
+    private val fingerprintCaptureListener: FingerprintCaptureListener =
+        object : FingerprintCaptureListener {
+            override fun captureOK(fpImage: ByteArray?) {
+                val bitmap: Bitmap = ToolUtils.renderCroppedGreyScaleBitmap(
+                    fpImage,
+                    fingerprintSensor?.getImageWidth()!!,
+                    fingerprintSensor?.getImageHeight()!!
+                )
+                ThreadUtils.runOnMain {
+                    onScanListener?.onScan(bitmap)
+                }
+            }
+
+            override fun captureError(e: FingerprintException?) {
+                // nothing to do
+            }
+
+            override fun extractOK(fpTemplate: ByteArray?) {
+                if (bRegister) {
+                    doRegister(fpTemplate)
+                } else {
+                    doIdentify(fpTemplate)
+                }
+            }
+
+            override fun extractError(i: Int) {
+                // nothing to do
+            }
+        }
+
+    private val fingerprintExceptionListener: FingerprintExceptionListener =
+        object : FingerprintExceptionListener {
+            override fun onDeviceException() {
+                logger.error("usb exception!!!")
+                if (!isReseted) {
+                    try {
+                        fingerprintSensor?.openAndReboot(deviceIndex)
+                    } catch (e: FingerprintException) {
+                        e.printStackTrace()
+                    }
+                    isReseted = true
+                }
+            }
+        }
+
+    private val zkusbManagerListener: ZKUSBManagerListener = object : ZKUSBManagerListener {
+        override fun onCheckPermission(result: Int) {
+            afterGetUsbPermission()
+        }
+
+        override fun onUSBArrived(device: UsbDevice?) {
+            if (bStarted) {
+                closeDevice()
+                tryGetUSBPermission()
+            }
+        }
+
+        override fun onUSBRemoved(device: UsbDevice?) {
+            logger.debug("usb removed!")
+        }
+    }
+
+    private fun openDevice() {
+        createFingerprintSensor()
+        bRegister = false
+        enroll_index = 0
+        isReseted = false
+        try {
+            fingerprintSensor?.open(deviceIndex)
+            run {
+                // device parameter
+                logger.debug("sdk version" + fingerprintSensor?.getSDK_Version())
+                logger.debug("firmware version" + fingerprintSensor?.getFirmwareVersion())
+                logger.debug("serial:" + fingerprintSensor?.getStrSerialNumber())
+                logger.debug("width=" + fingerprintSensor?.getImageWidth() + ", height=" + fingerprintSensor?.getImageHeight())
+            }
+            fingerprintSensor?.setFingerprintCaptureListener(
+                deviceIndex,
+                fingerprintCaptureListener
+            )
+            fingerprintSensor?.SetFingerprintExceptionListener(fingerprintExceptionListener)
+            fingerprintSensor?.startCapture(deviceIndex)
+            bStarted = true
+            logger.info("connect success!")
+        } catch (e: FingerprintException) {
+            e.printStackTrace()
+            // try to  reboot the sensor
+            try {
+                fingerprintSensor?.openAndReboot(deviceIndex)
+            } catch (ex: FingerprintException) {
+                ex.printStackTrace()
+            }
+            logger.info("connect failed!")
+        }
+    }
+
+    private fun closeDevice() {
+        if (bStarted) {
+            try {
+                fingerprintSensor?.stopCapture(deviceIndex)
+                fingerprintSensor?.close(deviceIndex)
+            } catch (e: FingerprintException) {
+                e.printStackTrace()
+            }
+            bStarted = false
+        }
+    }
+
+    private fun enumSensor(): Boolean {
+        val usbManager = SIKCore.getApplication().getSystemService(USB_SERVICE) as UsbManager
+        for (device in usbManager.deviceList.values) {
+            val device_vid = device.vendorId
+            val device_pid = device.productId
+            if (device_vid == ZKTECO_VID && (device_pid == LIVE20R_PID || device_pid == LIVE10R_PID)) {
+                usb_pid = device_pid
+                return true
+            }
+        }
+        return false
+    }
+
+    private fun createFingerprintSensor() {
+        if (null != fingerprintSensor) {
+            FingprintFactory.destroy(fingerprintSensor)
+            fingerprintSensor = null
+        }
+        // Define output log level
+        LogHelper.setLevel(Log.VERBOSE)
+        LogHelper.setNDKLogLevel(Log.ASSERT)
+        // Start fingerprint sensor
+        val deviceParams = HashMap<String?, Any?>()
+        //set vid
+        deviceParams[ParameterHelper.PARAM_KEY_VID] = usb_vid
+        //set pid
+        deviceParams[ParameterHelper.PARAM_KEY_PID] = usb_pid
+        fingerprintSensor = FingprintFactory.createFingerprintSensor(
+            SIKCore.getApplication(),
+            TransportType.USB,
+            deviceParams
+        )
+    }
+
+    fun doRegister(template: ByteArray?) {
+        val bufids = ByteArray(256)
+        var ret = ZKFingerService.identify(template, bufids, 70, 1)
+        if (ret > 0) {
+            val strRes = String(bufids).split("\t".toRegex()).dropLastWhile { it.isEmpty() }
+                .toTypedArray()
+            setResult("the finger already enroll by " + strRes[0] + ",cancel enroll")
+            bRegister = false
+            enroll_index = 0
+            return
+        }
+        if (enroll_index > 0 && (ZKFingerService.verify(
+                regtemparray.get(enroll_index - 1),
+                template
+            ).also {
+                ret = it
+            }) <= 0
+        ) {
+            setResult("please press the same finger 3 times for the enrollment, cancel enroll, socre=$ret")
+            bRegister = false
+            enroll_index = 0
+            return
+        }
+        System.arraycopy(template, 0, regtemparray.get(enroll_index), 0, 2048)
+        enroll_index++
+        if (enroll_index == ENROLL_COUNT) {
+            bRegister = false
+            enroll_index = 0
+            val regTemp = ByteArray(2048)
+            if (0 < (ZKFingerService.merge(
+                    regtemparray.get(0),
+                    regtemparray.get(1),
+                    regtemparray.get(2),
+                    regTemp
+                ).also {
+                    ret = it
+                })
+            ) {
+                var retVal = 0
+                retVal = ZKFingerService.save(regTemp, strUid)
+                if (0 == retVal) {
+                    val strFeature = Base64.encodeToString(regTemp, 0, ret, Base64.NO_WRAP)
+//                    dbManager.insertUser(strUid, strFeature)
+                    setResult("enroll succ")
+                } else {
+                    setResult("enroll fail, add template fail, ret=$retVal")
+                }
+            } else {
+                setResult("enroll fail")
+            }
+            bRegister = false
+        } else {
+            setResult("You need to press the " + (3 - enroll_index) + " times fingerprint")
+        }
+    }
+
+    private fun setResult(result: String) {
+        logger.info(result)
+//        val mStrText = result
+//        runOnUiThread { mBinding?.txtResult?.setText(mStrText) }
+    }
+
+    fun doIdentify(template: ByteArray?) {
+        val bufids = ByteArray(256)
+        val ret = ZKFingerService.identify(template, bufids, 70, 1)
+        if (ret > 0) {
+            val strRes = String(bufids).split("\t".toRegex()).dropLastWhile { it.isEmpty() }
+                .toTypedArray()
+            setResult("identify succ, userid:" + strRes[0].trim { it <= ' ' } + ", score:" + strRes[1].trim { it <= ' ' })
+        } else {
+            setResult("identify fail, ret=$ret")
+        }
+    }
+
+    interface OnScanListener {
+        fun onScan(bitmap: Bitmap)
+    }
+}

+ 162 - 0
app/src/main/java/com/grkj/iscs/utils/fingerprint/ZKUSBManager.java

@@ -0,0 +1,162 @@
+package com.grkj.iscs.utils.fingerprint;
+
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.usb.UsbDevice;
+import android.hardware.usb.UsbManager;
+
+import androidx.annotation.NonNull;
+
+import java.util.Random;
+
+/**
+ * usb permission and hotplug
+ */
+public class ZKUSBManager {
+    //usb's vendor id for zkteco
+    private int vid = 0x1b55;
+    //usb's product id
+    private int pid = 0;
+    //application context
+    private Context mContext = null;
+
+    /////////////////////////////////////////////
+    //for usb permission
+    private static final String SOURCE_STRING = "0123456789-_abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ";
+    private static final int DEFAULT_LENGTH = 16;
+    private String ACTION_USB_PERMISSION;
+    private boolean mbRegisterFilter = false;
+    private ZKUSBManagerListener zknirusbManagerListener = null;
+
+    private BroadcastReceiver usbMgrReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (ACTION_USB_PERMISSION.equals(action))
+            {
+                UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
+                if (device.getVendorId() == vid && device.getProductId() == pid) {
+                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
+                        zknirusbManagerListener.onCheckPermission(0);
+                    } else {
+                        zknirusbManagerListener.onCheckPermission(-2);
+                    }
+                }
+            }
+            else if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action))
+            {
+                UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
+                if (device.getVendorId() == vid && device.getProductId() == pid) {
+                    zknirusbManagerListener.onUSBArrived(device);
+                }
+            }
+            else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action))
+            {
+                UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
+                if (device.getVendorId() == vid && device.getProductId() == pid) {
+                    zknirusbManagerListener.onUSBRemoved(device);
+                }
+            }
+        }
+    };
+
+
+    private boolean isNullOrEmpty(String target) {
+        if (null == target || "".equals(target) || target.isEmpty()) {
+            return true;
+        }
+        return false;
+    }
+
+    private String createRandomString(String source, int length) {
+        if (this.isNullOrEmpty(source)) {
+            return "";
+        }
+
+        StringBuffer result = new StringBuffer();
+        Random random = new Random();
+
+        for(int index = 0; index < length; index++) {
+            result.append(source.charAt(random.nextInt(source.length())));
+        }
+        return result.toString();
+    }
+
+    public boolean registerUSBPermissionReceiver()
+    {
+        if (null == mContext || mbRegisterFilter)
+        {
+            return false;
+        }
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(ACTION_USB_PERMISSION);
+        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
+        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
+        mContext.registerReceiver(usbMgrReceiver, filter);
+        mbRegisterFilter = true;
+        return true;
+    }
+
+    public void unRegisterUSBPermissionReceiver()
+    {
+        if (null == mContext || !mbRegisterFilter)
+        {
+            return;
+        }
+        mContext.unregisterReceiver(usbMgrReceiver);
+        mbRegisterFilter = false;
+    }
+
+
+    //End USB Permission
+    /////////////////////////////////////////////
+
+    public ZKUSBManager(@NonNull Context context, @NonNull ZKUSBManagerListener listener)
+    {
+        super();
+        if (null == context || null == listener)
+        {
+            throw new NullPointerException("context or listener is null");
+        }
+        zknirusbManagerListener = listener;
+        ACTION_USB_PERMISSION = createRandomString(SOURCE_STRING, DEFAULT_LENGTH);
+        mContext = context;
+    }
+
+    //0 means success
+    //-1 means device no found
+    //-2 means device no permission
+    public void initUSBPermission(int vid, int pid){
+        UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);
+        UsbDevice usbDevice = null;
+        for (UsbDevice device : usbManager.getDeviceList().values()) {
+            int device_vid = device.getVendorId();
+            int device_pid = device.getProductId();
+            if (device_vid == vid && device_pid == pid)
+            {
+                usbDevice = device;
+                break;
+            }
+        }
+        if (null == usbDevice)
+        {
+            zknirusbManagerListener.onCheckPermission(-1);
+            return;
+        }
+        this.vid = vid;
+        this.pid = pid;
+        if (!usbManager.hasPermission(usbDevice))
+        {
+            Intent intent = new Intent(this.ACTION_USB_PERMISSION);
+            PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_IMMUTABLE);
+            usbManager.requestPermission(usbDevice, pendingIntent);
+        }
+        else {
+            zknirusbManagerListener.onCheckPermission(0);
+        }
+    }
+
+}

+ 15 - 0
app/src/main/java/com/grkj/iscs/utils/fingerprint/ZKUSBManagerListener.java

@@ -0,0 +1,15 @@
+package com.grkj.iscs.utils.fingerprint;
+
+import android.hardware.usb.UsbDevice;
+
+public interface ZKUSBManagerListener
+{
+    //0 means success
+    //-1 means device no found
+    //-2 means device no permission
+    void onCheckPermission(int result);
+
+    void onUSBArrived(UsbDevice device);
+
+    void onUSBRemoved(UsbDevice device);
+}

BIN
app/src/main/jniLibs/arm64-v8a/libarcsoft_face.so


BIN
app/src/main/jniLibs/arm64-v8a/libarcsoft_face_engine.so


BIN
app/src/main/jniLibs/arm64-v8a/libarcsoft_image_util.so


BIN
app/src/main/jniLibs/arm64-v8a/libslkidcap.so


BIN
app/src/main/jniLibs/arm64-v8a/libzkalg12.so


BIN
app/src/main/jniLibs/arm64-v8a/libzkfinger10.so


BIN
app/src/main/jniLibs/arm64-v8a/libzksensorcore.so


BIN
app/src/main/jniLibs/armeabi-v7a/libarcsoft_face.so


BIN
app/src/main/jniLibs/armeabi-v7a/libarcsoft_face_engine.so


BIN
app/src/main/jniLibs/armeabi-v7a/libarcsoft_image_util.so


BIN
app/src/main/jniLibs/armeabi-v7a/libserial_port.so


BIN
app/src/main/jniLibs/armeabi-v7a/libslkidcap.so


BIN
app/src/main/jniLibs/armeabi-v7a/libzkalg12.so


BIN
app/src/main/jniLibs/armeabi-v7a/libzkfinger10.so


BIN
app/src/main/jniLibs/armeabi-v7a/libzksensorcore.so


+ 43 - 0
app/src/main/res/values/logback.xml

@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration
+    xmlns="https://tony19.github.io/logback-android/xml"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="https://tony19.github.io/logback-android/xml https://cdn.jsdelivr.net/gh/tony19/logback-android/logback.xsd">
+
+    <!-- 文件日志输出,生成每日滚动日志 -->
+    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 日志文件路径,在 Android 中存储在应用的 filesDir/logs 目录 -->
+        <file>${DATA_DIR}/logs/app.log</file>
+
+        <!-- 每日滚动日志策略 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>${DATA_DIR}/logs/app.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <maxHistory>7</maxHistory>  <!-- 最大保留 7 天日志 -->
+            <totalSizeCap>100MB</totalSizeCap>  <!-- 总日志大小限制 -->
+        </rollingPolicy>
+
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{~36} - %msg%n</pattern>
+        </encoder>
+    </appender>
+
+    <!-- Logcat 输出,适用于 Android Studio 的调试 -->
+    <appender name="LOGCAT" class="ch.qos.logback.classic.android.LogcatAppender">
+        <encoder>
+            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{~36}.%M:%line - %msg%n</pattern>
+        </encoder>
+    </appender>
+
+    <!-- 日志级别配置 -->
+    <logger name="${PACKAGE_NAME}" level="DEBUG" additivity="false">
+        <appender-ref ref="FILE" />
+        <appender-ref ref="LOGCAT" />
+    </logger>
+
+    <!-- 根日志器,默认级别为 INFO -->
+    <root level="INFO">
+        <appender-ref ref="FILE" />
+        <appender-ref ref="LOGCAT" />
+    </root>
+
+</configuration>

+ 2 - 0
gradle/libs.versions.toml

@@ -16,6 +16,7 @@ sikcronjob = "1.0.3"
 sikfontmanager = "1.0.2"
 brv = "1.6.1"
 androidautosize = "v1.2.1"
+dialogx = "0.0.49"
 
 [libraries]
 androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
@@ -40,6 +41,7 @@ sik-cronjob = { group = "com.github.SilverIceKey", name = "SIKCronJob", version.
 sik-fontmanager = { group = "com.github.SilverIceKey", name = "SIKFontManager", version.ref = "sikfontmanager" }
 
 brv = { group = "com.github.liangjingkanji", name = "brv", version.ref = "brv" }
+dialogx = { group = "com.github.kongzue.DialogX", name = "DialogX", version.ref = "dialogx" }
 android-autosize = { group = "com.github.JessYanCoding", name = "AndroidAutoSize", version.ref = "androidautosize" }
 
 [plugins]

+ 3 - 3
shared/build.gradle.kts

@@ -4,7 +4,7 @@ plugins {
 }
 
 android {
-    namespace = "com.grkj.core"
+    namespace = "com.grkj.shared"
     compileSdk = 35
 
     defaultConfig {
@@ -35,7 +35,7 @@ android {
 dependencies {
 
     implementation(libs.androidx.core.ktx)
-    implementation(libs.sik.extension.core)
-    implementation(libs.sik.extension.encrypt)
+    api(libs.sik.extension.core)
+    api(libs.sik.extension.encrypt)
     testImplementation(libs.junit)
 }

+ 1 - 1
sync/build.gradle.kts

@@ -4,7 +4,7 @@ plugins {
 }
 
 android {
-    namespace = "com.grkj.data"
+    namespace = "com.grkj.sync"
     compileSdk = 35
 
     defaultConfig {

+ 1 - 1
ui-base/build.gradle.kts

@@ -39,7 +39,7 @@ dependencies {
     implementation(libs.material)
     implementation(libs.androidx.activity)
     implementation(libs.androidx.constraintlayout)
-    implementation(libs.sik.extension.android)
+    api(libs.sik.extension.android)
     implementation(project(":shared"))
     testImplementation(libs.junit)
 }