搜索菜品入库改为自动拍照保存,取消手动拍照操作;增加向量数据库相关日志
This commit is contained in:
@@ -47,6 +47,7 @@ import com.sw.inbound.utils.BitmapCropper
|
|||||||
import com.sw.inbound.utils.CameraUtils
|
import com.sw.inbound.utils.CameraUtils
|
||||||
import com.sw.inbound.utils.DateTimeUtils
|
import com.sw.inbound.utils.DateTimeUtils
|
||||||
import com.sw.inbound.utils.ImageUtil
|
import com.sw.inbound.utils.ImageUtil
|
||||||
|
import com.sw.inbound.utils.LogSaveUtil
|
||||||
import com.sw.inbound.utils.PreciseDelayHandler
|
import com.sw.inbound.utils.PreciseDelayHandler
|
||||||
import com.sw.inbound.utils.ext.dp
|
import com.sw.inbound.utils.ext.dp
|
||||||
import com.sw.inbound.utils.ext.gone
|
import com.sw.inbound.utils.ext.gone
|
||||||
@@ -229,7 +230,7 @@ abstract class GoodsListActivity : ComponentActivity() {
|
|||||||
|
|
||||||
private var lastWeight = 0
|
private var lastWeight = 0
|
||||||
private fun recognizeWeight(weight: Int) {
|
private fun recognizeWeight(weight: Int) {
|
||||||
Timber.tag(TAG).d("recognizeWeight,lastWeight=$lastWeight,weight=$weight")
|
logInfo("recognizeWeight,lastWeight=$lastWeight,weight=$weight")
|
||||||
//if (this.lastWeight - weight >= 0) {
|
//if (this.lastWeight - weight >= 0) {
|
||||||
// this.lastWeight = weight
|
// this.lastWeight = weight
|
||||||
// //从秤上取物品中
|
// //从秤上取物品中
|
||||||
@@ -265,8 +266,7 @@ abstract class GoodsListActivity : ComponentActivity() {
|
|||||||
// Timber.tag(TAG).d("recognizeWeight, checkResult=true")
|
// Timber.tag(TAG).d("recognizeWeight, checkResult=true")
|
||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
Timber.tag(TAG)
|
logInfo("recognizeWeight,recognizeFood:isShowRecognizeDialog=$isShowRecognizeDialog")
|
||||||
.d("recognizeWeight,recognizeFood:isShowRecognizeDialog=$isShowRecognizeDialog")
|
|
||||||
//两次相差5克内视作重量未变,不进行重新识别
|
//两次相差5克内视作重量未变,不进行重新识别
|
||||||
if (abs(lastWeight - weight) > 5) {
|
if (abs(lastWeight - weight) > 5) {
|
||||||
recognizeFood()
|
recognizeFood()
|
||||||
@@ -650,8 +650,7 @@ abstract class GoodsListActivity : ComponentActivity() {
|
|||||||
supplierId = supplierId,
|
supplierId = supplierId,
|
||||||
receiveGoodsInfos = goodsList
|
receiveGoodsInfos = goodsList
|
||||||
)
|
)
|
||||||
Timber.tag("SelfProcurementActivity")
|
logInfo("receiptSubmit确认收货提交数据:${uploadInfo.toJsonString()}")
|
||||||
.d("receiptSubmit确认收货提交数据:${uploadInfo.toJsonString()}")
|
|
||||||
showWaitingDialog2("加载中")
|
showWaitingDialog2("加载中")
|
||||||
receiptViewModel.confirmReceipt(uploadInfo) { success ->
|
receiptViewModel.confirmReceipt(uploadInfo) { success ->
|
||||||
hideWaitingDialog()
|
hideWaitingDialog()
|
||||||
@@ -690,8 +689,7 @@ abstract class GoodsListActivity : ComponentActivity() {
|
|||||||
buyToInventoryValue = it.buyToInventoryValue ?: ""
|
buyToInventoryValue = it.buyToInventoryValue ?: ""
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Timber.tag("SelfProcurementActivity")
|
logInfo("selfProcurementSubmit自采入库提交数据:${submitData.toJsonString()}")
|
||||||
.d("selfProcurementSubmit自采入库提交数据:${submitData.toJsonString()}")
|
|
||||||
showWaitingDialog2("加载中")
|
showWaitingDialog2("加载中")
|
||||||
receiptViewModel.addToWarehouse(submitData) { success ->
|
receiptViewModel.addToWarehouse(submitData) { success ->
|
||||||
hideWaitingDialog()
|
hideWaitingDialog()
|
||||||
@@ -796,4 +794,10 @@ abstract class GoodsListActivity : ComponentActivity() {
|
|||||||
tvTip?.text = tip
|
tvTip?.text = tip
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun logInfo(msg:String) {
|
||||||
|
Timber.tag(TAG).d(msg)
|
||||||
|
LogSaveUtil.saveLogFile(msg)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -64,6 +64,10 @@ class PurchaseOrderActivity : ComponentActivity() {
|
|||||||
putExtra(GoodsListActivity.IS_RECEIPT_PAGE, false)
|
putExtra(GoodsListActivity.IS_RECEIPT_PAGE, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
Loading.show(this)
|
Loading.show(this)
|
||||||
viewModel.getOrderListNew(pageNum = 1, pageSize = 100) { suppliers ->
|
viewModel.getOrderListNew(pageNum = 1, pageSize = 100) { suppliers ->
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
@@ -82,6 +86,7 @@ class PurchaseOrderActivity : ComponentActivity() {
|
|||||||
binding.layoutEmptyView.visible()
|
binding.layoutEmptyView.visible()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
list.clear()
|
||||||
list.addAll(suppliers)
|
list.addAll(suppliers)
|
||||||
adapter.notifyDataSetChanged()
|
adapter.notifyDataSetChanged()
|
||||||
binding.rvOrderList.visible()
|
binding.rvOrderList.visible()
|
||||||
|
|||||||
@@ -32,9 +32,13 @@ class GoodsSearchDialog(
|
|||||||
override fun initView() {
|
override fun initView() {
|
||||||
activity = getReceiptActivity()
|
activity = getReceiptActivity()
|
||||||
binding.ivClose.setOnClickListener { dismiss() }
|
binding.ivClose.setOnClickListener { dismiss() }
|
||||||
binding.ivGoodsSearch.setOnClickListener { searchGoods() }
|
binding.ivGoodsSearch.setOnClickListener {
|
||||||
|
pageNo = 1
|
||||||
|
searchGoods()
|
||||||
|
}
|
||||||
binding.etInputGoods.let { v ->
|
binding.etInputGoods.let { v ->
|
||||||
v.addOnActionSearchListener {
|
v.addOnActionSearchListener {
|
||||||
|
pageNo = 1
|
||||||
searchGoods()
|
searchGoods()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -284,10 +284,10 @@ class GoodsStoreDialog(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun confirmInputData() {
|
private fun confirmInputData() {
|
||||||
if (funcType == 1 && imageUri == null) {
|
// if (funcType == 1 && imageUri == null) {
|
||||||
context.toast("请采集图片")
|
// context.toast("请采集图片")
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
val unitName = binding.tvProcurementUnit.text.trim().toString()
|
val unitName = binding.tvProcurementUnit.text.trim().toString()
|
||||||
if (unitName.isBlank()) {
|
if (unitName.isBlank()) {
|
||||||
context.toast("请选择入库单位")
|
context.toast("请选择入库单位")
|
||||||
@@ -328,11 +328,31 @@ class GoodsStoreDialog(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (funcType == 1) {
|
if (funcType == 1) {
|
||||||
collectGoodsVector()
|
activity?.let { Loading.show(it) }
|
||||||
|
cameraUtils.takePhoto { uri ->
|
||||||
|
//imageUri = uri
|
||||||
|
collectGoodsVector(uri) {
|
||||||
|
activity?.uploadImage(goods.id!!, goods.goodsName!!, imageFile)
|
||||||
|
}
|
||||||
|
binding.root.postDelayed({
|
||||||
|
Loading.dismiss()
|
||||||
|
confirm(unitName, count, price, totalPrice)
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
|
cameraUtils.addFailCallback {
|
||||||
|
binding.root.postDelayed({
|
||||||
|
Loading.dismiss()
|
||||||
|
confirm(unitName, count, price, totalPrice)
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
confirm(unitName, count, price, totalPrice)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun confirm(unitName:String, count:Double, price:Double, totalPrice:Double?) {
|
||||||
val id = binding.tvProcurementUnit.tag.toString()
|
val id = binding.tvProcurementUnit.tag.toString()
|
||||||
val unitVo = goods.unitVoList!!.first { it.businessUnitId == id }
|
val unitVo = goods.unitVoList!!.first { it.businessUnitId == id }
|
||||||
activity?.uploadImage(goods.id!!, goods.goodsName!!, imageFile)
|
|
||||||
confirmBlock(
|
confirmBlock(
|
||||||
GoodsInfo(
|
GoodsInfo(
|
||||||
goodId = goods.id,
|
goodId = goods.id,
|
||||||
@@ -389,15 +409,15 @@ class GoodsStoreDialog(
|
|||||||
}, 2600)
|
}, 2600)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var imageUri: Uri? = null
|
// private var imageUri: Uri? = null
|
||||||
private val takePhotoCallback: (Uri) -> Unit = { uri ->
|
// private val takePhotoCallback: (Uri) -> Unit = { uri ->
|
||||||
takePhotoBinding?.let {
|
// takePhotoBinding?.let {
|
||||||
imageUri = uri
|
// imageUri = uri
|
||||||
it.flCameraPreview.gone()
|
// it.flCameraPreview.gone()
|
||||||
it.cvImageBg.visible()
|
// it.cvImageBg.visible()
|
||||||
it.ivGoodsImage.load(uri)
|
// it.ivGoodsImage.load(uri)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
private var previewView: PreviewView? = null
|
private var previewView: PreviewView? = null
|
||||||
private var takePhotoBinding: LayoutTakePhotoBinding? = null
|
private var takePhotoBinding: LayoutTakePhotoBinding? = null
|
||||||
@@ -416,13 +436,13 @@ class GoodsStoreDialog(
|
|||||||
previewView = it.previewView
|
previewView = it.previewView
|
||||||
it.flCameraPreview.visible()
|
it.flCameraPreview.visible()
|
||||||
it.cvImageBg.gone()
|
it.cvImageBg.gone()
|
||||||
it.btnStartPreview.setOnClickListener { _ ->
|
// it.btnStartPreview.setOnClickListener { _ ->
|
||||||
it.cvImageBg.gone()
|
// it.cvImageBg.gone()
|
||||||
it.flCameraPreview.visible()
|
// it.flCameraPreview.visible()
|
||||||
}
|
// }
|
||||||
it.btnTakePhoto.setOnClickListener { _ ->
|
// it.btnTakePhoto.setOnClickListener { _ ->
|
||||||
cameraUtils.takePhoto(takePhotoCallback)
|
// cameraUtils.takePhoto(takePhotoCallback)
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -444,9 +464,9 @@ class GoodsStoreDialog(
|
|||||||
private var imageFile: File? = null
|
private var imageFile: File? = null
|
||||||
|
|
||||||
// private var box: Box<Food>? = null
|
// private var box: Box<Food>? = null
|
||||||
private fun collectGoodsVector() {
|
private fun collectGoodsVector(imageUri:Uri, block: ()-> Unit = {}) {
|
||||||
try {
|
try {
|
||||||
ImageUtil.uriToBitmap(context, imageUri!!)?.let { bitmap ->
|
ImageUtil.uriToBitmap(context, imageUri)?.let { bitmap ->
|
||||||
val cropBitmap = BitmapCropper.cropCenter(
|
val cropBitmap = BitmapCropper.cropCenter(
|
||||||
original = bitmap,
|
original = bitmap,
|
||||||
targetWidth = 1000,
|
targetWidth = 1000,
|
||||||
@@ -477,18 +497,7 @@ class GoodsStoreDialog(
|
|||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Thread {
|
block()
|
||||||
// try {
|
|
||||||
// val imageVector = FoodModule.bitmap2FloatArray(bitmap, true)
|
|
||||||
// if (imageVector != null) {
|
|
||||||
// ObjectBox.boxStore.runInTx {
|
|
||||||
// box?.put(Food(name = goods.goodsName + goods.goodsCode, foodIdx = 0, foodVector = imageVector))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } catch (e: Exception) {
|
|
||||||
// e.printStackTrace()
|
|
||||||
// }
|
|
||||||
// }.start()
|
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import com.sw.inbound.MyApp
|
|||||||
import com.sw.inbound.objbox.ObjectBox.boxStore
|
import com.sw.inbound.objbox.ObjectBox.boxStore
|
||||||
import com.sw.inbound.utils.AssetsTool
|
import com.sw.inbound.utils.AssetsTool
|
||||||
import com.sw.inbound.utils.ImageUtil
|
import com.sw.inbound.utils.ImageUtil
|
||||||
|
import com.sw.inbound.utils.LogSaveUtil
|
||||||
import com.sw.inbound.utils.ext.toJsonString
|
import com.sw.inbound.utils.ext.toJsonString
|
||||||
import io.objectbox.Box
|
import io.objectbox.Box
|
||||||
import io.objectbox.kotlin.boxFor
|
import io.objectbox.kotlin.boxFor
|
||||||
@@ -82,6 +83,7 @@ object FoodModule {
|
|||||||
return outputTensor.dataAsFloatArray
|
return outputTensor.dataAsFloatArray
|
||||||
} catch (e: OutOfMemoryError) {
|
} catch (e: OutOfMemoryError) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
logInfo("bitmap2FloatArray异常:${e.message}")
|
||||||
} finally {
|
} finally {
|
||||||
if (rgb565Bitmap != null && rgb565Bitmap.isRecycled.not()) {
|
if (rgb565Bitmap != null && rgb565Bitmap.isRecycled.not()) {
|
||||||
rgb565Bitmap.recycle()
|
rgb565Bitmap.recycle()
|
||||||
@@ -130,20 +132,20 @@ object FoodModule {
|
|||||||
// query.close()
|
// query.close()
|
||||||
// }
|
// }
|
||||||
|
|
||||||
Timber.tag("FoodModule").d("queryFood向量:${floatArray.slice(0 until 50).toJsonString()}")
|
logInfo("queryFood向量:${floatArray.slice(0 until 50).toJsonString()}")
|
||||||
val idScoreList = ObjectBox.query(floatArray, queryCount)
|
val idScoreList = ObjectBox.query(floatArray, queryCount)
|
||||||
val nameScoreList = mutableListOf<IdNameScore>()
|
val nameScoreList = mutableListOf<IdNameScore>()
|
||||||
idScoreList.forEach {
|
idScoreList.forEach {
|
||||||
val name = ObjectBox.get(it.id)?.name ?: ""
|
val name = ObjectBox.get(it.id)?.name ?: ""
|
||||||
nameScoreList.add(IdNameScore(id = it.id, name = name, score = it.score))
|
nameScoreList.add(IdNameScore(id = it.id, name = name, score = it.score))
|
||||||
}
|
}
|
||||||
Timber.tag("FoodModule").d("queryFood数据:${nameScoreList.toJsonString()}")
|
logInfo("queryFood数据:${nameScoreList.toJsonString()}")
|
||||||
return nameScoreList
|
return nameScoreList
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getFoodScoreList(bitmap: Bitmap, queryCount: Int = 15): List<IdNameScore> {
|
suspend fun getFoodScoreList(bitmap: Bitmap, queryCount: Int = 15): List<IdNameScore> {
|
||||||
val floatArray = bitmap2FloatArray(bitmap, false) ?: return emptyList()
|
val floatArray = bitmap2FloatArray(bitmap, false) ?: return emptyList()
|
||||||
Timber.tag("FoodModule").d("向量:${floatArray.toJsonString()}")
|
logInfo("向量:${floatArray.toJsonString()}")
|
||||||
val nameScoreList = queryFoodNameScore(floatArray, queryCount)
|
val nameScoreList = queryFoodNameScore(floatArray, queryCount)
|
||||||
if (nameScoreList.isEmpty()) {
|
if (nameScoreList.isEmpty()) {
|
||||||
return emptyList()
|
return emptyList()
|
||||||
@@ -168,7 +170,7 @@ object FoodModule {
|
|||||||
val sortedScoreList = maxScoreList.sortedWith(compareBy {
|
val sortedScoreList = maxScoreList.sortedWith(compareBy {
|
||||||
orderList.indexOf(it.name)
|
orderList.indexOf(it.name)
|
||||||
})
|
})
|
||||||
Timber.tag("FoodModule").d("getFoodScoreList数据:${sortedScoreList.toJsonString()}")
|
logInfo("getFoodScoreList数据:${sortedScoreList.toJsonString()}")
|
||||||
return sortedScoreList
|
return sortedScoreList
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,7 +213,7 @@ object FoodModule {
|
|||||||
val size = embeddingsList.size
|
val size = embeddingsList.size
|
||||||
val size2 = labelsList.size
|
val size2 = labelsList.size
|
||||||
val size3 = foodMap.size
|
val size3 = foodMap.size
|
||||||
Log.d("TAG", "initDefFoodData: $size,$size2,$size3")
|
logInfo("initDefFoodData: $size,$size2,$size3")
|
||||||
embeddingsList.forEachIndexed { index, floatList ->
|
embeddingsList.forEachIndexed { index, floatList ->
|
||||||
val classIdx = labelsList[index]
|
val classIdx = labelsList[index]
|
||||||
val foodName = foodMap["$classIdx"]
|
val foodName = foodMap["$classIdx"]
|
||||||
@@ -227,7 +229,7 @@ object FoodModule {
|
|||||||
action()
|
action()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
Log.d("TAG", "initDefFoodData: ---${e.message}--")
|
logInfo("initDefFoodData: ---${e.message}--")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,7 +301,7 @@ object FoodModule {
|
|||||||
return cacheFile.absolutePath
|
return cacheFile.absolutePath
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
Timber.tag("FoodModule").d("文件拷贝失败 fileName=$fileName, error=${e.message}")
|
logInfo("文件拷贝失败 fileName=$fileName, error=${e.message}")
|
||||||
// 拷贝失败时删除残缺文件,避免下次读取到损坏文件
|
// 拷贝失败时删除残缺文件,避免下次读取到损坏文件
|
||||||
if (cacheFile.exists()) {
|
if (cacheFile.exists()) {
|
||||||
cacheFile.delete()
|
cacheFile.delete()
|
||||||
@@ -311,4 +313,9 @@ object FoodModule {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun logInfo(msg:String) {
|
||||||
|
Timber.tag("FoodModule").d(msg)
|
||||||
|
LogSaveUtil.saveLogFile(msg)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -21,6 +21,7 @@ import android.content.Context
|
|||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.sw.inbound.MyApp
|
import com.sw.inbound.MyApp
|
||||||
|
import com.sw.inbound.utils.LogSaveUtil
|
||||||
import io.objectbox.Box
|
import io.objectbox.Box
|
||||||
import io.objectbox.BoxStore
|
import io.objectbox.BoxStore
|
||||||
import io.objectbox.BoxStoreBuilder
|
import io.objectbox.BoxStoreBuilder
|
||||||
@@ -86,8 +87,10 @@ object ObjectBox {
|
|||||||
// Failed to build BoxStore due to database file issue, store message;
|
// Failed to build BoxStore due to database file issue, store message;
|
||||||
// checked in NoteListActivity to notify user.
|
// checked in NoteListActivity to notify user.
|
||||||
dbExceptionMessage = e.toString()
|
dbExceptionMessage = e.toString()
|
||||||
|
LogSaveUtil.saveLogFile("ObjectBox.init异常1:$dbExceptionMessage")
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
|
LogSaveUtil.saveLogFile("ObjectBox.init异常2:${e.message}")
|
||||||
// Failed to build BoxStore due to developer error.
|
// Failed to build BoxStore due to developer error.
|
||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
@@ -141,12 +144,14 @@ object ObjectBox {
|
|||||||
} catch (e: FileCorruptException) {
|
} catch (e: FileCorruptException) {
|
||||||
// 操作中触发损坏,尝试重建数据库
|
// 操作中触发损坏,尝试重建数据库
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
LogSaveUtil.saveLogFile("safeDbOp出现FileCorruptException异常:${e.message},${e.errorCode}")
|
||||||
//val context = boxStore.context
|
//val context = boxStore.context
|
||||||
//deleteDbFiles(context)
|
//deleteDbFiles(context)
|
||||||
init(MyApp.instance!!)
|
init(MyApp.instance!!)
|
||||||
null
|
null
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
LogSaveUtil.saveLogFile("safeDbOp出现其它异常:${e.message}")
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,14 +13,14 @@ class CameraUtils(private var activity: ComponentActivity) {
|
|||||||
private var photoCaptureHelper: PhotoCaptureHelper? = null
|
private var photoCaptureHelper: PhotoCaptureHelper? = null
|
||||||
|
|
||||||
// private var isCameraReady = false
|
// private var isCameraReady = false
|
||||||
fun takePhoto(callback: (Uri) -> Unit) {
|
fun takePhoto(successCallback: (Uri) -> Unit) {
|
||||||
cameraController?.let {
|
cameraController?.let {
|
||||||
if (photoCaptureHelper == null) {
|
if (photoCaptureHelper == null) {
|
||||||
initCaptureHelper()
|
initCaptureHelper()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
photoCaptureHelper?.let {
|
photoCaptureHelper?.let {
|
||||||
it.addSuccessCallback(callback)
|
it.addSuccessCallback(successCallback)
|
||||||
it.bindCameraCallback {
|
it.bindCameraCallback {
|
||||||
bind()
|
bind()
|
||||||
}
|
}
|
||||||
@@ -28,6 +28,11 @@ class CameraUtils(private var activity: ComponentActivity) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var failCallback:(()-> Unit)?=null
|
||||||
|
fun addFailCallback(callback:()->Unit) {
|
||||||
|
failCallback = callback
|
||||||
|
}
|
||||||
|
|
||||||
private fun initCaptureHelper() {
|
private fun initCaptureHelper() {
|
||||||
photoCaptureHelper = PhotoCaptureHelper(
|
photoCaptureHelper = PhotoCaptureHelper(
|
||||||
context = activity,
|
context = activity,
|
||||||
@@ -35,6 +40,7 @@ class CameraUtils(private var activity: ComponentActivity) {
|
|||||||
onSuccess = {},
|
onSuccess = {},
|
||||||
onError = { msg ->
|
onError = { msg ->
|
||||||
//toast(msg)
|
//toast(msg)
|
||||||
|
failCallback?.invoke()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ class CrashHandler private constructor(private val context: Context) :
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "CrashHandler"
|
private const val TAG = "CrashHandler"
|
||||||
private const val CRASH_REPORTS_DIR = "crash_reports"
|
|
||||||
private const val LOG_LINES = 500 // 收集最近500行日志
|
private const val LOG_LINES = 500 // 收集最近500行日志
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
@@ -109,7 +108,7 @@ class CrashHandler private constructor(private val context: Context) :
|
|||||||
val crashInfo = collectCrashInfo(thread, ex)
|
val crashInfo = collectCrashInfo(thread, ex)
|
||||||
|
|
||||||
// 保存日志文件
|
// 保存日志文件
|
||||||
saveCrashInfoToFile(crashInfo)
|
LogSaveUtil.saveLogFile("yyyy-MM-dd_HH-mm-ss",crashInfo)
|
||||||
|
|
||||||
// 这里可以添加其他处理逻辑,比如上传到服务器等
|
// 这里可以添加其他处理逻辑,比如上传到服务器等
|
||||||
}
|
}
|
||||||
@@ -203,36 +202,11 @@ class CrashHandler private constructor(private val context: Context) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveLog(logInfo:String) {
|
|
||||||
val time = SimpleDateFormat("yyyy-MM-dd_HH-mm-ss", Locale.getDefault()).format(Date())
|
|
||||||
val fileName = "crash_$time.log"
|
|
||||||
|
|
||||||
val crashDir = getCrashDir()
|
|
||||||
|
|
||||||
val crashFile = File(crashDir, fileName)
|
|
||||||
FileOutputStream(crashFile).use { it.write(logInfo.toByteArray()) }
|
|
||||||
|
|
||||||
Timber.tag(TAG).d("Crash info saved to: ${crashFile.absolutePath}")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun saveCrashInfoToFile(crashInfo: String) {
|
|
||||||
try {
|
|
||||||
saveLog(crashInfo)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Timber.tag(TAG).e(e, "Error saving crash info to file")
|
|
||||||
try {
|
|
||||||
saveLog("Error saving crash info to file:${e.message}")
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Timber.tag(TAG).e(e, "save exception")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清理旧的崩溃日志
|
* 清理旧的崩溃日志
|
||||||
*/
|
*/
|
||||||
fun cleanupOldCrashReports(maxAgeDays: Int = 7) {
|
fun cleanupOldCrashReports(maxAgeDays: Int = 7) {
|
||||||
val crashDir = getCrashDir()
|
val crashDir = LogSaveUtil.getCrashDir()
|
||||||
if (!crashDir.exists() || !crashDir.isDirectory) return
|
if (!crashDir.exists() || !crashDir.isDirectory) return
|
||||||
|
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
@@ -245,17 +219,4 @@ class CrashHandler private constructor(private val context: Context) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getCrashDir():File {
|
|
||||||
//val crashDir = File(context.getExternalFilesDir(null), CRASH_REPORTS_DIR)
|
|
||||||
var crashDir = File(context.filesDir, CRASH_REPORTS_DIR)
|
|
||||||
if (!crashDir.exists()) {
|
|
||||||
crashDir.mkdirs()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(crashDir.exists())) {
|
|
||||||
crashDir = File(context.cacheDir, CRASH_REPORTS_DIR)
|
|
||||||
}
|
|
||||||
return crashDir
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package com.sw.inbound.utils
|
||||||
|
|
||||||
|
import com.sw.inbound.MyApp
|
||||||
|
import timber.log.Timber
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Date
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
object LogSaveUtil {
|
||||||
|
|
||||||
|
private const val TAG = "LogSaveUtil"
|
||||||
|
private const val CRASH_REPORTS_DIR = "crash_reports"
|
||||||
|
|
||||||
|
public fun saveLogFile(msg: String) {
|
||||||
|
saveLogFile("yyyy-MM-dd", msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun saveLogFile(pattern: String, msg: String) {
|
||||||
|
try {
|
||||||
|
saveLog(pattern, msg)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Timber.tag(TAG).e(e, "Error saving crash info to file")
|
||||||
|
try {
|
||||||
|
saveLog(pattern, "Error saving crash info to file:${e.message}")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Timber.tag(TAG).e(e, "save exception")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveLog(pattern: String, logInfo: String) {
|
||||||
|
val time = SimpleDateFormat(pattern, Locale.getDefault()).format(Date())
|
||||||
|
val fileName = "crash_$time.log"
|
||||||
|
|
||||||
|
val crashDir = getCrashDir()
|
||||||
|
|
||||||
|
val crashFile = File(crashDir, fileName)
|
||||||
|
|
||||||
|
val saveTime = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(Date())
|
||||||
|
FileOutputStream(crashFile, true).use { it.write("$saveTime||$logInfo\n".toByteArray()) }
|
||||||
|
|
||||||
|
Timber.tag(TAG).d("Crash info saved to: ${crashFile.absolutePath}")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getCrashDir(): File {
|
||||||
|
//val crashDir = File(context.getExternalFilesDir(null), CRASH_REPORTS_DIR)
|
||||||
|
var crashDir = File(MyApp.instance!!.filesDir, CRASH_REPORTS_DIR)
|
||||||
|
if (!crashDir.exists()) {
|
||||||
|
crashDir.mkdirs()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(crashDir.exists())) {
|
||||||
|
crashDir = File(MyApp.instance!!.cacheDir, CRASH_REPORTS_DIR)
|
||||||
|
}
|
||||||
|
return crashDir
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -80,7 +80,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="15dp"
|
android:layout_marginTop="15dp"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
<Space
|
<Space
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
|||||||
Reference in New Issue
Block a user