This commit is contained in:
2026-01-08 19:36:31 +08:00
parent fce721bfc3
commit a79f7db867
8 changed files with 184 additions and 147 deletions
+1 -1
View File
@@ -29,7 +29,7 @@ class MyApp : App() {
CrashHandler.init(this) CrashHandler.init(this)
SensorScaleUtils.startScale() SensorScaleUtils.startScale()
//addActivityLifecycleListener() addActivityLifecycleListener()
} }
private fun addActivityLifecycleListener() { private fun addActivityLifecycleListener() {
@@ -106,6 +106,9 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
private val adapter by lazy { private val adapter by lazy {
SearchFoodAdapter(searchFoodList).apply { SearchFoodAdapter(searchFoodList).apply {
setOnItemClickListener { adapter, view, position -> setOnItemClickListener { adapter, view, position ->
if (searchFoodList[position].isChecked) {
return@setOnItemClickListener
}
searchFoodList.forEachIndexed { index, info -> searchFoodList.forEachIndexed { index, info ->
searchFoodList[index].isChecked = index == position searchFoodList[index].isChecked = index == position
} }
@@ -373,12 +376,14 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
showWaitingDialog("识别中,请稍后……") showWaitingDialog("识别中,请稍后……")
takePhoto( takePhoto(
successCallback = { photoUri -> successCallback = { photoUri ->
onTakePhotoSuccess(photoUri) Thread{
onTakePhotoSuccess(photoUri)
}.start()
failCount = 0 failCount = 0
}, failureCallback = { }, failureCallback = {
runOnUiThread { runOnUiThread {
if (failCount >= 10) { if (failCount >= 10) {
ToastUtils.showToast("相机异常,请稍后重试") //ToastUtils.showToast("相机异常,请稍后重试")
shutdownCamera() shutdownCamera()
setupCamera() setupCamera()
return@runOnUiThread return@runOnUiThread
@@ -774,6 +779,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
ToastUtils.showToast("您好,当前重量不足一份") ToastUtils.showToast("您好,当前重量不足一份")
return return
} }
showWaitingDialog("加载中,请稍候……")
val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0) val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
val order = FoodOrder( val order = FoodOrder(
deviceId = GlobalData.deviceId, deviceId = GlobalData.deviceId,
@@ -790,19 +796,30 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
//即放即取-1,称重-2 //即放即取-1,称重-2
mode = if (pickupMode == 1) 1 else 2 mode = if (pickupMode == 1) 1 else 2
) )
debouncer.debounce {
submitOrder(order, block)
}
}
private fun submitOrder(order: FoodOrder, block: () -> Unit) {
viewModel.createOrder(order) { orderId -> viewModel.createOrder(order) { orderId ->
runOnUiThread { runOnUiThread {
if (orderId.isBlank()) { binding.root.postDelayed({
//ToastUtils.showToast("订单id为空") hideWaitingDialog()
return@runOnUiThread if (orderId.isBlank()) {
} //ToastUtils.showToast("订单id为空")
foodOrderId = orderId return@postDelayed
block() }
foodOrderId = orderId
block()
if (checkedItem!!.isFromSearch == true) { if (checkedItem!!.isFromSearch == true) {
//当前菜名为手动搜索选择,非识别结果,保存向量数据 //当前菜名为手动搜索选择,非识别结果,保存向量数据
saveFoodVector(checkedItem!!) Thread{
} saveFoodVector(checkedItem!!)
}.start()
}
}, 300)
} }
} }
} }
@@ -916,11 +933,12 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
*/ */
private fun saveFoodVector(foodInfo: FoodInfo) { private fun saveFoodVector(foodInfo: FoodInfo) {
try { try {
lastPhotoUri?.let { uri -> if (lastPhotoUri == null) {
uri2File(uri) { imageFile, imageVector -> return
runBlocking { }
uploadCollectFoodPics(foodInfo, imageFile, imageVector) uri2File(lastPhotoUri!!) { imageFile, imageVector ->
} runBlocking {
uploadCollectFoodPics(foodInfo, imageFile, imageVector)
} }
} }
} catch (e: Exception) { } catch (e: Exception) {
@@ -974,15 +992,17 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
loadRemindDialog("返回的id${idList[0]}已存在") loadRemindDialog("返回的id${idList[0]}已存在")
return return
} }
box.put( Thread {
Food( box.put(
collectId = idList[0], Food(
foodId = foodId, collectId = idList[0],
foodName = foodName, foodId = foodId,
foodVector = imageVector, foodName = foodName,
version = foodModelVersion foodVector = imageVector,
version = foodModelVersion
)
) )
) }.start()
} }
private fun loadRemindDialog(msg: String) { private fun loadRemindDialog(msg: String) {
@@ -1193,7 +1213,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
startTime = System.currentTimeMillis() startTime = System.currentTimeMillis()
Timber.d("registerDataChange photoUri = ${photoUri.path}") Timber.d("registerDataChange photoUri = ${photoUri.path}")
// viewModel.getIdentifiedFoodList() // viewModel.getIdentifiedFoodList()
ImageUtil.uriToBitmap(this, photoUri)?.let { bitmap -> ImageUtil.uriToBitmap(this, photoUri)?.let { bitmap ->
Timber.tag(TAG).d("main,uriToBitmap耗时:${System.currentTimeMillis() - startTime}") Timber.tag(TAG).d("main,uriToBitmap耗时:${System.currentTimeMillis() - startTime}")
startTime = System.currentTimeMillis() startTime = System.currentTimeMillis()
@@ -1201,19 +1220,15 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
// val bmp = BitmapCropper.cropCenter(bitmap, 1300, 900) // val bmp = BitmapCropper.cropCenter(bitmap, 1300, 900)
Timber.d("registerDataChange photoUri bitmap裁剪完成") Timber.d("registerDataChange photoUri bitmap裁剪完成")
val file = BitmapSaver.saveToAppFilesDir( val file = BitmapSaver.saveToAppFilesDir(
bitmap, bitmap, this, "IMG_CROP_${System.currentTimeMillis()}.jpg"
this,
"IMG_CROP_${System.currentTimeMillis()}.jpg"
) )
Timber.tag(TAG) Timber.tag(TAG).d("main,saveToAppFilesDir耗时:${System.currentTimeMillis() - startTime}")
.d("main,saveToAppFilesDir耗时:${System.currentTimeMillis() - startTime}")
startTime = System.currentTimeMillis() startTime = System.currentTimeMillis()
Timber.d("registerDataChange photoUri bitmap保存文件路径:${file?.absolutePath}") Timber.d("registerDataChange photoUri bitmap保存文件路径:${file?.absolutePath}")
//val nameList = FoodModule.queryFood(bitmap) //val nameList = FoodModule.queryFood(bitmap)
val scoreList = FoodModule.getFoodScoreList(bitmap) val scoreList = FoodModule.getFoodScoreList(bitmap)
val recDataJson = GsonUtils.toJson(scoreList) val recDataJson = GsonUtils.toJson(scoreList)
Timber.tag(TAG) Timber.tag(TAG).d("main,getFoodScoreList耗时:${System.currentTimeMillis() - startTime}")
.d("main,getFoodScoreList耗时:${System.currentTimeMillis() - startTime}")
startTime = System.currentTimeMillis() startTime = System.currentTimeMillis()
Timber.d("registerDataChange photoUri 拿到识别数据:$recDataJson") Timber.d("registerDataChange photoUri 拿到识别数据:$recDataJson")
val nameList = scoreList.map { it.name } val nameList = scoreList.map { it.name }
@@ -1221,19 +1236,23 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
hideWaitingDialog() hideWaitingDialog()
Timber.d("registerDataChange photoUri 识别数据名称:$foodName") Timber.d("registerDataChange photoUri 识别数据名称:$foodName")
binding.flPay.run { runOnUiThread {
val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0) binding.flPay.run {
//0-计费,1-不计费 val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
if (chargeMode == 0) visible() else gone() //0-计费,1-不计费
if (chargeMode == 0) visible() else gone()
}
} }
if (TextUtils.isEmpty(foodName)) { if (TextUtils.isEmpty(foodName)) {
LightManager.closeGreenLight() LightManager.closeGreenLight()
LightManager.closeRedLight() LightManager.closeRedLight()
//binding.layoutRescan.visibility = View.VISIBLE //binding.layoutRescan.visibility = View.VISIBLE
binding.tvToSearch.let { runOnUiThread {
it.text = "未识别到,手动搜索" binding.tvToSearch.let {
it.visible() it.text = "未识别到,手动搜索"
it.visible()
}
} }
} else { } else {
//binding.layoutRescan.visibility = View.GONE //binding.layoutRescan.visibility = View.GONE
@@ -3,6 +3,7 @@ package com.sw.dualscreen.activity.fragment
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.Bitmap
import android.net.Uri import android.net.Uri
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@@ -27,6 +28,7 @@ import com.sw.dualscreen.objbox.Food
import com.sw.dualscreen.objbox.FoodCollectionBean import com.sw.dualscreen.objbox.FoodCollectionBean
import com.sw.dualscreen.objbox.FoodModule import com.sw.dualscreen.objbox.FoodModule
import com.sw.dualscreen.objbox.ObjectBox import com.sw.dualscreen.objbox.ObjectBox
import com.sw.dualscreen.utils.BitmapCropper
import com.sw.dualscreen.utils.BitmapSaver import com.sw.dualscreen.utils.BitmapSaver
import com.sw.dualscreen.utils.CameraUtils import com.sw.dualscreen.utils.CameraUtils
import com.sw.dualscreen.utils.Debouncer import com.sw.dualscreen.utils.Debouncer
@@ -42,22 +44,24 @@ import okhttp3.RequestBody.Companion.toRequestBody
import timber.log.Timber import timber.log.Timber
import kotlin.getValue import kotlin.getValue
@SuppressLint("NotifyDataSetChanged")
class CollectFragment : BaseFragment<FragmentCollectBinding>() { class CollectFragment : BaseFragment<FragmentCollectBinding>() {
companion object { companion object {
private const val TAG = "CollectFragment" private const val TAG = "CollectFragment"
const val MAX_COUNT = 15 const val MAX_COUNT = 9
} }
private var selectedFoodId: String? = "" private var selectedFoodId: String? = ""
private var selectedFoodName: String? = "" private var selectedFoodName: String? = ""
private var box: Box<Food>?=null private var box: Box<Food>? = null
fun initBox() { fun initBox() {
if (box == null) { if (box == null) {
box = ObjectBox.boxStore.boxFor(Food::class) box = ObjectBox.boxStore.boxFor(Food::class)
} }
} }
private val foodCollectionList = mutableListOf<FoodCollectionBean>().apply { private val foodCollectionList = mutableListOf<FoodCollectionBean>().apply {
repeat(MAX_COUNT) { repeat(MAX_COUNT) {
add(FoodCollectionBean(isShowCamera = true)) add(FoodCollectionBean(isShowCamera = true))
@@ -70,10 +74,9 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
private val searchFoodAdapter by lazy { private val searchFoodAdapter by lazy {
SearchFoodAdapter(searchFoodList).apply { SearchFoodAdapter(searchFoodList).apply {
setOnItemClickListener { adapter, view, position -> setOnItemClickListener { adapter, view, position ->
searchFoodList.forEachIndexed { index, item -> item.isChecked = index == position }
checkedItem = searchFoodList[position] checkedItem = searchFoodList[position]
val isChecked = checkedItem!!.isChecked notifyDataSetChanged()
searchFoodList[position].isChecked = isChecked.not()
notifyItemChanged(position)
selectedFoodId = checkedItem!!.foodId selectedFoodId = checkedItem!!.foodId
selectedFoodName = checkedItem!!.foodName selectedFoodName = checkedItem!!.foodName
} }
@@ -126,37 +129,11 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
collectionAdapter.notifyItemChanged(index) collectionAdapter.notifyItemChanged(index)
} }
// settingActivity?.hideWaitingDialog() // settingActivity?.hideWaitingDialog()
ImageUtil.uriToBitmap(requireActivity(), uri)?.let { bitmap -> Thread {
// val cropBitmap = BitmapCropper.cropCenter( ImageUtil.uriToBitmap(requireActivity(), uri)?.let { bitmap ->
// original = bitmap, getImageVector(index, bitmap)
// targetWidth = 1300, targetHeight = 900,
// //offsetX = 30, offsetY = 100
// )
val imageVector = try {
FoodModule.bitmap2FloatArray(bitmap)
} catch (e: Exception) {
e.printStackTrace()
ToastUtils.showToast("操作失败")
settingActivity?.hideWaitingDialog()
return@let
} }
val file = BitmapSaver.saveToAppFilesDir( }.start()
bitmap, requireActivity(), "IMG_CROP_${System.currentTimeMillis()}.jpg"
)
Timber.d("${this.javaClass.simpleName}-cameraCallback-裁剪bitmap保存文件路径:${file?.absolutePath}")
foodCollectionList[index].let {
it.imageVector = imageVector
it.bitmap = null
it.isShowCamera = false
it.imageFile = file
}
collectionAdapter.notifyItemChanged(index)
if (bitmap.isRecycled.not()) {
bitmap.recycle()
}
settingActivity?.hideWaitingDialog()
}
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
settingActivity?.hideWaitingDialog() settingActivity?.hideWaitingDialog()
@@ -164,6 +141,40 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
} }
} }
private fun getImageVector(index: Int, bitmap: Bitmap) {
// val bitmap = BitmapCropper.cropCenter(
// original = srcBmp,
// targetWidth = 900, targetHeight = 900,
//// offsetX = 30, offsetY = 100
// )
val imageVector = try {
FoodModule.bitmap2FloatArray(bitmap)
} catch (e: Exception) {
e.printStackTrace()
ToastUtils.showToast("操作失败")
settingActivity?.hideWaitingDialog()
return
}
val file = BitmapSaver.saveToAppFilesDir(
bitmap, requireActivity(), "IMG_CROP_${System.currentTimeMillis()}.jpg"
)
Timber.d("${this.javaClass.simpleName}-cameraCallback-裁剪bitmap保存文件路径:${file?.absolutePath}")
activity?.runOnUiThread {
foodCollectionList[index].let {
it.imageVector = imageVector
it.bitmap = null
it.isShowCamera = false
it.imageFile = file
}
collectionAdapter.notifyItemChanged(index)
}
if (bitmap.isRecycled.not()) {
bitmap.recycle()
}
settingActivity?.hideWaitingDialog()
}
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")
private fun takePhoto() { private fun takePhoto() {
val count = foodCollectionList.count { it.bitmap != null } val count = foodCollectionList.count { it.bitmap != null }
@@ -173,11 +184,19 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
} }
settingActivity?.showWaitingDialog("采集中……") settingActivity?.showWaitingDialog("采集中……")
cameraUtils.takePhoto(cameraCallback) { errMsg -> cameraUtils.takePhoto(cameraCallback) { errMsg ->
ToastUtils.showToast("拍照异常,请重新操作")
settingActivity?.hideWaitingDialog() settingActivity?.hideWaitingDialog()
if (cameraErrorCount >= 10) {
ToastUtils.showToast("拍照异常,请重新操作")
cameraErrorCount = 0
return@takePhoto
}
cameraErrorCount++
takePhoto()
} }
} }
private var cameraErrorCount = 0
override fun initialize() { override fun initialize() {
settingActivity = activity as SettingActivity settingActivity = activity as SettingActivity
cameraUtils.initCamera() cameraUtils.initCamera()
@@ -256,65 +275,56 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
params["foodName"] = checkedItem!!.foodName!!.toRequestBody() params["foodName"] = checkedItem!!.foodName!!.toRequestBody()
params["version"] = GlobalData.foodModelVersion.toRequestBody() params["version"] = GlobalData.foodModelVersion.toRequestBody()
ImageUploader( ImageUploader(totalList = foodCollectionList, uploadImage = { batch ->
totalList = foodCollectionList, val files = batch.map { it.imageFile }
uploadImage = { batch -> val foodVectorList = batch.filter { it.imageVector != null }.map {
val files = batch.map { it.imageFile } it.imageVector!!.joinToString(
val foodVectorList = separator = ",", prefix = "[", postfix = "]"
batch.filter { it.imageVector != null }.map { )
it.imageVector!!.joinToString( }
separator = ",", val foodVectorJson =
prefix = "[", foodVectorList.joinToString(separator = ",", prefix = "[", postfix = "]")
postfix = "]" Timber.tag(TAG).d("json=$foodVectorJson")
) params["foodVector"] = foodVectorJson.toRequestBody()
} settingActivity?.viewModel?.uploadCollectFoodPics(files, params)
val foodVectorJson = }, onProgress = { count, batch, idList ->
foodVectorList.joinToString(separator = ",", prefix = "[", postfix = "]") //batch.forEach {
Timber.tag(TAG).d("json=$foodVectorJson") // it.uploadSuccess = true
params["foodVector"] = foodVectorJson.toRequestBody() //}
settingActivity?.viewModel?.uploadCollectFoodPics(files, params) runBlocking {
},
onProgress = { count, batch, idList ->
//batch.forEach {
// it.uploadSuccess = true
//}
runBlocking {
activity?.runOnUiThread {
settingActivity?.showWaitingDialog2("图片上传中$count/$totalFileCount")
}
val foodList = batch.mapIndexed { index, it ->
Food(
collectId = if (index < idList.size) idList[index] else null,
foodId = checkedItem!!.foodId,
foodName = checkedItem!!.foodName,
foodVector = it.imageVector,
version = GlobalData.foodModelVersion
)
}
initBox()
box?.put(foodList)
activity?.runOnUiThread {
batch.forEach { it.isFinish = true }
collectionAdapter.notifyDataSetChanged()
}
}
},
onError = {
activity?.runOnUiThread { activity?.runOnUiThread {
binding.root.postDelayed({ settingActivity?.showWaitingDialog2("图片上传中$count/$totalFileCount")
settingActivity?.hideWaitingDialog()
ToastUtils.showToast("上传失败,请稍后重试")
}, 1000)
} }
}, val foodList = batch.mapIndexed { index, it ->
onComplete = { Food(
//vectorThread() collectId = if (index < idList.size) idList[index] else null,
foodId = checkedItem!!.foodId,
foodName = checkedItem!!.foodName,
foodVector = it.imageVector,
version = GlobalData.foodModelVersion
)
}
initBox()
box?.put(foodList)
activity?.runOnUiThread {
batch.forEach { it.isFinish = true }
collectionAdapter.notifyDataSetChanged()
}
}
}, onError = {
activity?.runOnUiThread {
binding.root.postDelayed({ binding.root.postDelayed({
settingActivity?.hideWaitingDialog() settingActivity?.hideWaitingDialog()
ToastUtils.showToast("上传成功") ToastUtils.showToast("上传失败,请稍后重试")
}, 1000) }, 1000)
} }
).processUploads() }, onComplete = {
//vectorThread()
binding.root.postDelayed({
settingActivity?.hideWaitingDialog()
ToastUtils.showToast("上传成功")
}, 1000)
}).processUploads()
} }
@@ -13,7 +13,7 @@ import java.util.concurrent.TimeUnit
object ApiClient { object ApiClient {
private const val BASE_URL = "http://device.shuziweidao.com:8889/" private const val BASE_URL = "http://device.shuziweidao.com:8889/"
private const val TIME_OUT = 60L // 超时时间(秒) private const val TIME_OUT = 30L // 超时时间(秒)
//todo 临时测试改为5秒 //todo 临时测试改为5秒
// private const val TIME_OUT = 5L // 超时时间(秒) // private const val TIME_OUT = 5L // 超时时间(秒)
@@ -132,6 +132,7 @@ object FoodModule {
val startTime = System.currentTimeMillis() val startTime = System.currentTimeMillis()
val floatArray = bitmap2FloatArray(bitmap) val floatArray = bitmap2FloatArray(bitmap)
Timber.tag(TAG).d("bitmap2FloatArray,耗时:${System.currentTimeMillis() - startTime}") Timber.tag(TAG).d("bitmap2FloatArray,耗时:${System.currentTimeMillis() - startTime}")
val nameScoreList = queryFoodNameScore(floatArray, queryCount) val nameScoreList = queryFoodNameScore(floatArray, queryCount)
if (nameScoreList.isEmpty()) { if (nameScoreList.isEmpty()) {
return emptyList() return emptyList()
@@ -398,6 +398,9 @@ class MainScreenPresentation(
* 餐品识别成功,不计费模式 * 餐品识别成功,不计费模式
*/ */
fun loadUnbilledMode() { fun loadUnbilledMode() {
if (currentUserId.isNullOrBlank()) {
return
}
isLoadUnbilledMode = true isLoadUnbilledMode = true
Timber.tag(TAG).d("loadUnbilledMode") Timber.tag(TAG).d("loadUnbilledMode")
binding.calorieInclude.root.gone() binding.calorieInclude.root.gone()
@@ -1,6 +1,7 @@
package com.sw.dualscreen.utils package com.sw.dualscreen.utils
import android.graphics.Bitmap import android.graphics.Bitmap
object BitmapCropper { object BitmapCropper {
/** /**
* 裁剪Bitmap中心区域为指定尺寸 * 裁剪Bitmap中心区域为指定尺寸
@@ -9,13 +10,13 @@ object BitmapCropper {
* @param targetHeight 目标高度 * @param targetHeight 目标高度
* @return 裁剪后的Bitmap * @return 裁剪后的Bitmap
*/ */
fun cropCenter(original: Bitmap, targetWidth: Int, targetHeight: Int): Bitmap { fun cropCenter(original: Bitmap, targetWidth: Int, targetHeight: Int, offsetX:Int = 0, offsetY:Int = 0): Bitmap {
val originalWidth = original.width val originalWidth = original.width
val originalHeight = original.height val originalHeight = original.height
// 计算中心点坐标 // 计算中心点坐标
var startX = (originalWidth - targetWidth) / 2 var startX = (originalWidth - targetWidth) / 2 + offsetX
var startY = (originalHeight - targetHeight) / 2 var startY = (originalHeight - targetHeight) / 2 + offsetY
// 边界检查 // 边界检查
startX = startX.coerceAtLeast(0) startX = startX.coerceAtLeast(0)
@@ -23,16 +24,19 @@ object BitmapCropper {
val actualWidth = minOf(targetWidth, originalWidth - startX) val actualWidth = minOf(targetWidth, originalWidth - startX)
val actualHeight = minOf(targetHeight, originalHeight - startY) val actualHeight = minOf(targetHeight, originalHeight - startY)
return Bitmap.createBitmap(original, startX, startY, actualWidth, actualHeight) return Bitmap.createBitmap(original, startX, startY, actualWidth, actualHeight).also {
// it.setConfig(Bitmap.Config.RGB_565)
// it.density = DisplayMetrics.DENSITY_LOW
}
} }
} }
// 使用示例 // 使用示例
fun main() { //fun main() {
// 假设这是从资源加载的Bitmap // // 假设这是从资源加载的Bitmap
val originalBitmap = Bitmap.createBitmap(1000, 1000, Bitmap.Config.ARGB_8888) // val originalBitmap = Bitmap.createBitmap(1000, 1000, Bitmap.Config.ARGB_8888)
// 裁剪中心500x500区域 // // 裁剪中心500x500区域
val croppedBitmap = BitmapCropper.cropCenter(originalBitmap, 500, 500) // val croppedBitmap = BitmapCropper.cropCenter(originalBitmap, 500, 500)
println("裁剪后尺寸:${croppedBitmap.width}x${croppedBitmap.height}") // println("裁剪后尺寸:${croppedBitmap.width}x${croppedBitmap.height}")
} //}
@@ -11,7 +11,7 @@ class ImageUploader(
private val onComplete:() -> Unit private val onComplete:() -> Unit
) { ) {
companion object { companion object {
private const val BATCH_SIZE = 5 private const val BATCH_SIZE = 3
} }
private val uploadedCount = AtomicInteger(0) private val uploadedCount = AtomicInteger(0)