- PhotoCaptureHelper: 删除构造参数 onSuccess,成功回调统一由 callbackList 分发
- CameraUtils: 同步移除 initCaptureHelper 中的 onSuccess = {} 空参数
- ObjectBox: 使用 QueryBuilder 替代全量内存过滤(count/filter/remove),提升查询性能
- ObjectBox: 修复 isStorageAvailable 错误检查外部存储状态,改为仅检查内部存储
- ObjectBox: boxStore 添加 @Volatile 注解保证多线程可见性
- ObjectBox: copyAndGzipDatabaseFileTo 增加 IOException 捕获,避免文件异常崩溃
- ObjectBox: safeDbOp 中使用安全调用替代 !! 断言,避免 NPE
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
119 lines
4.0 KiB
Kotlin
119 lines
4.0 KiB
Kotlin
package com.sw.inbound.utils
|
|
|
|
import android.content.Context
|
|
import android.net.Uri
|
|
import androidx.camera.core.ImageCapture
|
|
import androidx.camera.core.ImageCaptureException
|
|
import androidx.camera.view.CameraController
|
|
//import androidx.compose.runtime.Composable
|
|
//import androidx.compose.runtime.remember
|
|
//import androidx.compose.ui.platform.LocalContext
|
|
import androidx.core.content.ContextCompat
|
|
import timber.log.Timber
|
|
import java.io.File
|
|
|
|
/**
|
|
* 拍照工具类
|
|
* @param context Context 上下文
|
|
* @param cameraController CameraController 相机控制器
|
|
* @param onError (String) -> Unit 拍照失败回调
|
|
*/
|
|
class PhotoCaptureHelper(
|
|
private val context: Context,
|
|
private val cameraController: CameraController,
|
|
private val onError: (String) -> Unit = {}
|
|
) {
|
|
private val callbackList: MutableList<(Uri) -> Unit> = mutableListOf()
|
|
fun addSuccessCallback(callback:(Uri) -> Unit) {
|
|
if (callbackList.contains(callback).not()) {
|
|
callbackList.add(callback)
|
|
}
|
|
}
|
|
|
|
private var bindCamera:(()->Unit)?=null
|
|
fun bindCameraCallback(callback:()->Unit) {
|
|
this.bindCamera = callback
|
|
}
|
|
|
|
/**
|
|
* 拍照方法
|
|
* @param fileNamePrefix 文件名前缀,默认为"IMG_"
|
|
* @param fileExtension 文件扩展名,默认为".jpg"
|
|
*/
|
|
fun takePhoto(
|
|
fileNamePrefix: String = "IMG_",
|
|
fileExtension: String = ".jpg"
|
|
) {
|
|
Timber.d("开始拍照采集")
|
|
|
|
try {
|
|
val executor = ContextCompat.getMainExecutor(context)
|
|
val cacheDir = context.cacheDir
|
|
val photoFile = File.createTempFile(
|
|
"${fileNamePrefix}${System.currentTimeMillis()}",
|
|
fileExtension,
|
|
cacheDir
|
|
)
|
|
|
|
val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile).build()
|
|
|
|
cameraController.takePicture(
|
|
outputOptions,
|
|
executor,
|
|
object : ImageCapture.OnImageSavedCallback {
|
|
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
|
|
val photoUri = outputFileResults.savedUri ?: Uri.fromFile(photoFile)
|
|
Timber.d("照片保存成功: $photoUri")
|
|
callbackList.forEach {
|
|
it(photoUri)
|
|
}
|
|
}
|
|
|
|
override fun onError(exception: ImageCaptureException) {
|
|
val errorMsg = "拍照失败: ${exception.message}"
|
|
if (errorMsg.contains("Not bound to a valid Camera")) {
|
|
if (bindCamera != null) {
|
|
bindCamera?.invoke()
|
|
//takePhoto()
|
|
}
|
|
|
|
}
|
|
Timber.e(exception, errorMsg)
|
|
onError("拍照失败")
|
|
}
|
|
}
|
|
)
|
|
} catch (e: Exception) {
|
|
val errorMsg = "创建临时文件失败: ${e.message}"
|
|
Timber.e(e, errorMsg)
|
|
onError(errorMsg)
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 用于Compose的拍照Hook
|
|
* @param cameraController CameraController 相机控制器
|
|
* @param onSuccess (Uri) -> Unit 拍照成功回调
|
|
* @param onError (String) -> Unit 拍照失败回调
|
|
* @return Pair<PhotoCaptureHelper, () -> Unit> 返回工具类实例和拍照函数
|
|
*/
|
|
//@Composable
|
|
//fun rememberPhotoCapture(
|
|
// cameraController: CameraController,
|
|
// onSuccess: (Uri) -> Unit = {},
|
|
// onError: (String) -> Unit = {}
|
|
//): Pair<PhotoCaptureHelper, () -> Unit> {
|
|
// val context = LocalContext.current
|
|
// val photoCaptureHelper = remember {
|
|
// PhotoCaptureHelper(
|
|
// context = context,
|
|
// cameraController = cameraController,
|
|
// onSuccess = onSuccess,
|
|
// onError = onError
|
|
// )
|
|
// }
|
|
//
|
|
// return Pair(photoCaptureHelper) { photoCaptureHelper.takePhoto() }
|
|
//}
|