Sfoglia il codice sorgente

1.添加全局异常捕获
2.新增权限申请
3.新增log记录
4.新增crash记录

JaycePC 11 mesi fa
parent
commit
28ae60b4c7

+ 2 - 6
.gitignore

@@ -2,12 +2,8 @@
 .gradle
 .idea
 /local.properties
-/.idea/caches
-/.idea/libraries
-/.idea/modules.xml
-/.idea/workspace.xml
-/.idea/navEditor.xml
-/.idea/assetWizardSettings.xml
+/.idea
+/gradle-build
 .DS_Store
 /build
 /captures

+ 1 - 0
HttpCoreLibrary/build.gradle

@@ -38,6 +38,7 @@ dependencies {
     implementation dep.androidxCoreKtx
     implementation dep.androidxLocalbroadcastmanager
 
+    implementation 'com.blankj:utilcodex:1.31.1'
     api dep.retrofit
     implementation dep.converterGson
     implementation dep.converterScalars

+ 56 - 52
HttpCoreLibrary/src/main/java/com/rc/httpcore/interceptor/ParameterValidationInterceptor.kt

@@ -2,6 +2,7 @@ package com.rc.httpcore.interceptor
 
 import android.annotation.SuppressLint
 import android.util.Log
+import com.blankj.utilcode.util.LogUtils
 import okhttp3.Interceptor
 import okhttp3.Response
 import okhttp3.ResponseBody
@@ -13,62 +14,65 @@ class ParameterValidationInterceptor : Interceptor {
     companion object {
         private const val TAG = "ParameterValidationInterceptor"
     }
+
     @SuppressLint("LongLogTag")
     override fun intercept(chain: Interceptor.Chain): Response {
         val request = chain.request()
-
-        // 检查查询参数
-        val originalUrl = request.url()
-        Log.d(TAG, "Request parameters: $originalUrl")
-        // 创建一个新的请求体,便于后续使用
-        val requestBody = request.body()
-        val buffer = Buffer()
-        requestBody?.writeTo(buffer)
-
-        // 获取请求体的字符串形式(假设为 JSON)
-        val requestBodyString = buffer.readUtf8()
-
-        // 建立一个标志来跟踪是否有空参数
-        val hasEmptyParameter = StringBuilder()
-        val queryParametersLog = StringBuilder()
-        val bodyParametersLog = StringBuilder()
-
-        // 检查请求体(例如,POST 请求)
-        if (request.method() == "POST" && requestBody != null) {
-            try {
-                val jsonParams = JSONObject(requestBodyString)
-                jsonParams.keys().forEach { key ->
-                    val value = jsonParams.optString(key)
-                    if (value.isEmpty()) {
-                        hasEmptyParameter.append("Body parameter '$key' is empty; ")
-                    } else {
-                        bodyParametersLog.append("Body parameter '$key': $value; ")
-                    }
-                }
-            } catch (e: Exception) {
-                Log.e(TAG, "Failed to parse request body as JSON: ${e.message}")
-            }
-        }
-
-        if (originalUrl.queryParameterNames().isNotEmpty()) {
-            for (name in originalUrl.queryParameterNames()) {
-                val value = originalUrl.queryParameter(name)
-                if (value.isNullOrEmpty()) {
-                    hasEmptyParameter.append("Query parameter '$name' is empty; ")
-                } else {
-                    queryParametersLog.append("Query parameter '$name': $value; ")
-                }
-            }
-        }
-
+//
+//        // 检查查询参数
+//        val originalUrl = request.url()
+//        Log.d(TAG, "Request parameters: $originalUrl")
+//        // 创建一个新的请求体,便于后续使用
+//        val requestBody = request.body()
+//        val buffer = Buffer()
+//        requestBody?.writeTo(buffer)
+//
+//        // 获取请求体的字符串形式(假设为 JSON)
+//        val requestBodyString = buffer.readUtf8()
+//
+//        // 建立一个标志来跟踪是否有空参数
+//        val hasEmptyParameter = StringBuilder()
+//        val queryParametersLog = StringBuilder()
+//        val bodyParametersLog = StringBuilder()
+//
+//        // 检查请求体(例如,POST 请求)
+//        if (request.method() == "POST" && requestBody != null) {
+//            try {
+//                val jsonParams = JSONObject(requestBodyString)
+//                jsonParams.keys().forEach { key ->
+//                    val value = jsonParams.optString(key)
+//                    if (value.isEmpty()) {
+//                        hasEmptyParameter.append("Body parameter '$key' is empty; ")
+//                    } else {
+//                        bodyParametersLog.append("Body parameter '$key': $value; ")
+//                    }
+//                }
+//            } catch (e: Exception) {
+//                Log.e(TAG, "Failed to parse request body as JSON: ${e.message}")
+//            }
+//        }
+//
+//        if (originalUrl.queryParameterNames().isNotEmpty()) {
+//            for (name in originalUrl.queryParameterNames()) {
+//                val value = originalUrl.queryParameter(name)
+//                if (value.isNullOrEmpty()) {
+//                    hasEmptyParameter.append("Query parameter '$name' is empty; ")
+//                } else {
+//                    queryParametersLog.append("Query parameter '$name': $value; ")
+//                }
+//            }
+//        }
+
+        LogUtils.d(request.toString())
         // 打印所有请求参数(合并为一行)
-        Log.d(TAG, "Request parameters: ${queryParametersLog.toString()}${bodyParametersLog.toString()}")
+//        Log.d(TAG, "Request body: $bodyParametersLog")
+//        Log.d(TAG, "Request query: $queryParametersLog")
 
 
-        // 打印空参数信息
-        if (hasEmptyParameter.isNotEmpty()) {
-            Log.e(TAG, "Request contains empty parameters: $hasEmptyParameter")
-        }
+//        // 打印空参数信息
+//        if (hasEmptyParameter.isNotEmpty()) {
+//            Log.e(TAG, "Request contains empty parameters: $hasEmptyParameter")
+//        }
 
         // 继续处理请求
         val response = chain.proceed(request)
@@ -78,8 +82,8 @@ class ParameterValidationInterceptor : Interceptor {
         val responseBodyString = responseBody?.string() ?: ""
 
         // 打印返回值日志
-        Log.d(TAG, "Response: $responseBodyString")
-
+//        Log.d(TAG, "Response: $responseBodyString")
+        LogUtils.d(response.toString(),responseBodyString)
         // 创建一个新的响应体,以便返回
         return response.newBuilder()
             .body(ResponseBody.create(responseBody?.contentType(), responseBodyString))

+ 20 - 15
app/build.gradle

@@ -34,20 +34,20 @@ android {
         }
     }
 
-    buildTypes {
-        debug {
-            minifyEnabled false
-            multiDexEnabled true
-            signingConfig signingConfigs.signing
-            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
-        }
-        release {
-            minifyEnabled false
-            multiDexEnabled true
-            signingConfig signingConfigs.signing
-            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
-        }
-    }
+//    buildTypes {
+//        debug {
+//            minifyEnabled false
+//            multiDexEnabled true
+//            signingConfig signingConfigs.signing
+//            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+//        }
+//        release {
+//            minifyEnabled false
+//            multiDexEnabled true
+//            signingConfig signingConfigs.signing
+//            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+//        }
+//    }
     compileOptions {
         sourceCompatibility env.jdk_version
         targetCompatibility env.jdk_version
@@ -73,7 +73,7 @@ android {
         variant.outputs.all {
             def buildType = variant.buildType.name
 //            def buildTime = new Date().format("yyyyMMddHHmm", TimeZone.getDefault())
-            outputFileName = "Chemical_Xibei.apk"
+            outputFileName = "Chemical_Xibei_" + android.defaultConfig.versionName + ".apk"
         }
     }
 }
@@ -133,5 +133,10 @@ dependencies {
 
     implementation 'com.github.codbking:PickTime:v1.0.1'
 
+    implementation 'com.github.getActivity:XXPermissions:20.0'
+    implementation "com.kongzue.dialogx:DialogX:0.0.49"
+    implementation 'com.blankj:utilcodex:1.31.1'
+
+
 
 }

BIN
app/release/Chemical_Xibei.apk


+ 0 - 18
app/release/output-metadata.json

@@ -1,18 +0,0 @@
-{
-  "version": 2,
-  "artifactType": {
-    "type": "APK",
-    "kind": "Directory"
-  },
-  "applicationId": "com.zhong.che",
-  "variantName": "processReleaseResources",
-  "elements": [
-    {
-      "type": "SINGLE",
-      "filters": [],
-      "versionCode": 13,
-      "versionName": "1.13",
-      "outputFile": "Chemical_Xibei.apk"
-    }
-  ]
-}

+ 8 - 3
app/src/main/AndroidManifest.xml

@@ -73,12 +73,17 @@
         android:theme="@style/Theme.AppFullTheme"
         android:usesCleartextTraffic="true"
         tools:targetApi="m">
-        <activity android:name=".ui.verify.TwoVerificationActivity"
+
+        <meta-data
+            android:name="ScopedStorage"
+            android:value="true" />
+
+        <activity
+            android:name=".ui.verify.TwoVerificationActivity"
             android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|fontScale"
             android:launchMode="singleTask"
             android:screenOrientation="landscape"
-            android:windowSoftInputMode="adjustPan"
-            />
+            android:windowSoftInputMode="adjustPan" />
         <activity
             android:name=".ui.SettingActivity"
             android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|fontScale"

+ 36 - 2
app/src/main/java/com/example/chemical/ChemicalApp.kt

@@ -5,6 +5,10 @@ import android.content.Context
 
 import android.util.Log
 import androidx.multidex.MultiDex
+import com.blankj.utilcode.util.AppUtils
+import com.blankj.utilcode.util.CrashUtils
+import com.blankj.utilcode.util.FileUtils
+import com.blankj.utilcode.util.LogUtils
 import com.example.chemical.comm.Constants
 import com.rc.core.log.RcLog
 import com.rc.core.util.CrashHandler.initCrash
@@ -36,10 +40,40 @@ class ChemicalApp : Application() {
     override fun onCreate() {
         super.onCreate()
         ScreenAdapter.initAppDensity(this)
-        initCrash(this)
-        initBugly()
+//        initCrash(this)
+//        initBugly()
         initX5()
         appContext = applicationContext
+        initLog()
+    }
+
+    private fun initLog() {
+        val logPath = "/sdcard/logs/"
+        val crashPath = "/sdcard/logs/crash/"
+        // log文件存储地址
+        FileUtils.createOrExistsDir(logPath)
+        FileUtils.createOrExistsDir(crashPath)
+        CrashUtils.init(crashPath) { crashInfo ->
+            LogUtils.e(crashInfo)
+        }
+        val config = LogUtils.getConfig()
+        // log开关控制
+        config.setLogSwitch(true)
+        // log控制台开关
+        config.setConsoleSwitch(true)
+        // logTag
+        config.setGlobalTag("Jayce")
+        // log头部信息开关
+        config.setLogHeadSwitch(true)
+        // log文件开关
+        config.setLog2FileSwitch(true)
+        config.setDir(logPath)
+        // log文件前缀
+        config.setFilePrefix(AppUtils.getAppName())
+        // log边框开关
+        config.setBorderSwitch(true)
+        // log文件保存天数
+        config.setSaveDays(30)
     }
 
     private fun initBugly() {

+ 108 - 78
app/src/main/java/com/example/chemical/ui/SplashActivity.kt

@@ -7,9 +7,9 @@ import android.net.Uri
 import android.os.Build
 import android.os.Bundle
 import android.os.Handler
-import android.util.Log
 import android.view.LayoutInflater
 import androidx.core.content.FileProvider
+import com.blankj.utilcode.util.LogUtils
 import com.example.chemical.BuildConfig
 import com.example.chemical.ChemicalApp
 import com.example.chemical.comm.Constants
@@ -17,7 +17,10 @@ import com.example.chemical.databinding.ActivitySplashBinding
 import com.example.chemical.utils.NetworkUtils
 import com.example.chemical.utils.SharedPreferencesHelper
 import com.example.chemical.utils.UiManager
-import com.google.gson.Gson
+import com.hjq.permissions.OnPermissionCallback
+import com.hjq.permissions.Permission
+import com.hjq.permissions.XXPermissions
+import com.kongzue.dialogx.dialogs.MessageDialog
 import com.lztek.toolkit.Lztek
 import com.rc.core.log.RcLog
 import com.rc.core.ui.activity.RcBaseActivity
@@ -33,10 +36,15 @@ class SplashActivity : RcBaseActivity<ActivitySplashBinding>() {
     private var mLztek: Lztek? = null
     private var mDeviceNum: String? = null  //设备唯一标识
     private var isOk = false
+    private var test: String = ""
     override fun createViewBinding() = ActivitySplashBinding.inflate(LayoutInflater.from(this))
 
     override fun initViews(savedInstanceState: Bundle?) {
         super.initViews(savedInstanceState)
+        requestPermission()
+    }
+
+    private fun initView() {
         viewBinding.versionName.text = "版本号:${DeviceUtils.getVersionName(this)}"
         mLztek = Lztek.create(this)
         val toUpperCase = mLztek!!.ethMac.toUpperCase()
@@ -55,43 +63,65 @@ class SplashActivity : RcBaseActivity<ActivitySplashBinding>() {
                 Constants.FACE_TAG = urlBase.d.toInt()
             }
         }
-        requestPermission()
+
+        val isNetworkAvailable = NetworkUtils.isNetworkAvailable(this)
+        if (isNetworkAvailable) {
+            // 当前网络可用
+            queryAppVersion()
+        } else {
+            if (!isOk) {
+                // 启动定时任务
+                myHandler.start()
+                isOk = true
+            }
+
+        }
     }
 
 
     private fun requestPermission() {
-        val disposable = RxPermissions(this)
-                .request(
-                        Manifest.permission.WRITE_EXTERNAL_STORAGE,
-                        Manifest.permission.READ_EXTERNAL_STORAGE,
-                        Manifest.permission.CAMERA,
-                        Manifest.permission.READ_PHONE_STATE,
-                        Manifest.permission.RECORD_AUDIO,
-                )
-                .subscribe { granted ->
-                    if (granted) {
-                        val isNetworkAvailable = NetworkUtils.isNetworkAvailable(this)
-                        if (isNetworkAvailable) {
-                            // 当前网络可用
-                            queryAppVersion()
-                        } else {
-                            if (!isOk) {
-                                // 启动定时任务
-                                myHandler.start()
-                                isOk = true
+
+        XXPermissions.with(this)
+            .permission(
+                Permission.CAMERA,
+                Permission.READ_EXTERNAL_STORAGE,
+                Permission.WRITE_EXTERNAL_STORAGE,
+                Permission.READ_PHONE_STATE,
+                Permission.RECORD_AUDIO
+            )
+            .request(object : OnPermissionCallback {
+                override fun onGranted(permissions: MutableList<String>, allGranted: Boolean) {
+                    if (allGranted) {
+                        initView()
+                    } else {
+                        MessageDialog.show("提示", "您必须同意所有权限才可以继续使用", "确定")
+                            .setCancelable(false).setOkButtonClickListener { dialog, v ->
+                                requestPermission()
+                                false
                             }
+                    }
+                }
 
-                        }
+                override fun onDenied(permissions: MutableList<String>, doNotAskAgain: Boolean) {
+                    super.onDenied(permissions, doNotAskAgain)
+                    if (doNotAskAgain) {
+                        MessageDialog.show("提示", "您必须同意所有权限才可以继续使用", "确定")
+                            .setCancelable(false).setOkButtonClickListener { dialog, v ->
+                                XXPermissions.startPermissionActivity(
+                                    this@SplashActivity,
+                                    permissions
+                                )
+                                false
+                            }
                     } else {
-                        AlertDialog.Builder(this)
-                                .setTitle("提示")
-                                .setMessage("您必须同意所有权限才可以继续使用")
-                                .setNegativeButton("确定") { _, _ ->
-                                    requestPermission()
-                                }.show()
+                        MessageDialog.show("提示", "您必须同意所有权限才可以继续使用", "确定")
+                            .setCancelable(false).setOkButtonClickListener { dialog, v ->
+                                requestPermission()
+                                false
+                            }
                     }
                 }
-        addDisposable(disposable)
+            })
 
     }
 
@@ -152,55 +182,55 @@ class SplashActivity : RcBaseActivity<ActivitySplashBinding>() {
         //    AIO_INFOBORD("aio_infobord","电子信息牌"),
         //    AIO_EXAM("aio_exam","学习考试一体机");
         val disposable =
-                ApiRepository.getCheck(mDeviceNum!!, "aio_chemical", toDouble.toDouble())
-                        .subscribe({ data ->
-                            dismissLoading()
-                            if (!data.needUpgrade) {
-                                ChemicalApp.labInfo = data.labInfo
-                                ChemicalApp.subjectId = data.labInfo.subjectId
-                                ChemicalApp.subjectName = data.labInfo.subjectName
-                                ChemicalApp.subRoom = data.labInfo.room
-                                UiManager.switcher(this@SplashActivity, MainActivity::class.java)
-                                finish()
-                            } else {
-                                //需要更新
-                                if (data.appInfo != null) {
-                                    when {
-                                        data.appInfo!!.remark != null -> {
-                                            //同步进行更新
-                                            upDownloadManager(data!!.appInfo!!.remark)
-                                        }
-
-                                        data!!.appInfo!!.url != null -> {
-                                            upDownloadManager(data.appInfo!!.url)
-                                        }
-
-                                        else -> {
-                                            // 启动定时任务
-                                            try {
-                                                myHandler.stop()
-                                            } catch (e: Exception) {
-
-                                            } finally {
-                                                myHandler.start()
-                                            }
-                                            showToast("版本信息不不存在")
-                                        }
+            ApiRepository.getCheck(mDeviceNum!!, "aio_chemical", toDouble.toDouble())
+                .subscribe({ data ->
+                    dismissLoading()
+                    if (!data.needUpgrade) {
+                        ChemicalApp.labInfo = data.labInfo
+                        ChemicalApp.subjectId = data.labInfo.subjectId
+                        ChemicalApp.subjectName = data.labInfo.subjectName
+                        ChemicalApp.subRoom = data.labInfo.room
+                        UiManager.switcher(this@SplashActivity, MainActivity::class.java)
+                        finish()
+                    } else {
+                        //需要更新
+                        if (data.appInfo != null) {
+                            when {
+                                data.appInfo!!.remark != null -> {
+                                    //同步进行更新
+                                    upDownloadManager(data!!.appInfo!!.remark)
+                                }
+
+                                data!!.appInfo!!.url != null -> {
+                                    upDownloadManager(data.appInfo!!.url)
+                                }
+
+                                else -> {
+                                    // 启动定时任务
+                                    try {
+                                        myHandler.stop()
+                                    } catch (e: Exception) {
+
+                                    } finally {
+                                        myHandler.start()
                                     }
-                                } else {
-                                    UiManager.switcher(this@SplashActivity, MainActivity::class.java)
-                                    finish()
+                                    showToast("版本信息不不存在")
                                 }
                             }
-                        }, { throwable ->
-                            dismissLoading()
-                            showNetError(throwable)
-                            if (!isOk) {
-                                // 启动定时任务
-                                myHandler.start()
-                                isOk = true
-                            }
-                        })
+                        } else {
+                            UiManager.switcher(this@SplashActivity, MainActivity::class.java)
+                            finish()
+                        }
+                    }
+                }, { throwable ->
+                    dismissLoading()
+                    showNetError(throwable)
+                    if (!isOk) {
+                        // 启动定时任务
+                        myHandler.start()
+                        isOk = true
+                    }
+                })
         addDisposable(disposable)
 
     }
@@ -208,7 +238,7 @@ class SplashActivity : RcBaseActivity<ActivitySplashBinding>() {
 
     private fun upDownloadManager(downloadUrl: String) {
         ApkUpdater(this, BuildConfig.APPLICATION_ID, callback = object :
-                ApkUpdater.DownloadCallback {
+            ApkUpdater.DownloadCallback {
             override fun onProgress(progress: Int) {
                 myHandler.stop()
                 showLoading("检测到新版本,开始更新(${progress}%)")
@@ -290,7 +320,7 @@ class SplashActivity : RcBaseActivity<ActivitySplashBinding>() {
         if (Build.VERSION.SDK_INT >= 24) {
             // 与AndroidManifest.xml中的authorities配置一致
             val authority =
-                    BuildConfig.APPLICATION_ID + ".fileprovider"
+                BuildConfig.APPLICATION_ID + ".fileprovider"
             intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
             val uri = FileProvider.getUriForFile(this@SplashActivity, authority, apkFile)
             intent.setDataAndType(uri, "application/vnd.android.package-archive")

+ 2 - 2
config/config.gradle

@@ -9,8 +9,8 @@ ext {
             minSdkVersion    : 21,
             targetSdkVersion : 28,
             applicationId    : "com.zhong.che",
-            versionCode      : 17,
-            versionName      : "1.17"
+            versionCode      : 18,
+            versionName      : "1.18"
     ]
 
     test = [