feat: 添加照片发送确认对话框,优化相机捕获功能

This commit is contained in:
Booker
2026-05-29 14:05:34 +07:00
parent a166d41841
commit 131df57dfe

View File

@@ -1,7 +1,8 @@
package io.openim.flutter.openim
import android.content.Intent
import android.app.Activity
import android.app.AlertDialog
import android.content.Intent
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.graphics.Bitmap
@@ -15,6 +16,8 @@ import android.util.Base64
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ImageView
import androidx.core.content.FileProvider
import io.flutter.embedding.android.FlutterActivity
import org.conscrypt.Conscrypt
@@ -33,6 +36,7 @@ class MainActivity : FlutterActivity() {
private val FILE_PICKER_REQUEST_CODE = 4201
private var pendingFilePickerResult: MethodChannel.Result? = null
private var pendingCameraCaptureUri: Uri? = null
private var pendingCaptureConfirmationDialog: AlertDialog? = null
override fun onCreate(savedInstanceState: android.os.Bundle?) {
// 华为/荣耀/OPPO 等国产设备:在任意网络请求之前同步安装 Conscrypt修复 SSL 握手失败(无 GMS 时系统 SSL 实现不完整)
@@ -51,6 +55,12 @@ class MainActivity : FlutterActivity() {
disableAutofillForCurrentWindow()
}
override fun onDestroy() {
pendingCaptureConfirmationDialog?.dismiss()
pendingCaptureConfirmationDialog = null
super.onDestroy()
}
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
@@ -153,8 +163,7 @@ class MainActivity : FlutterActivity() {
pendingCameraCaptureUri?.let { uri ->
pendingCameraCaptureUri = null
grantPickedFileReadPermission(uri)
result.success(listOf(uri.toString()))
showCaptureConfirmation(uri, result)
return
}
@@ -191,7 +200,7 @@ class MainActivity : FlutterActivity() {
capture: Boolean,
result: MethodChannel.Result
) {
if (pendingFilePickerResult != null) {
if (pendingFilePickerResult != null || pendingCaptureConfirmationDialog != null) {
result.error("FILE_PICKER_BUSY", "A file picker request is already active", null)
return
}
@@ -258,6 +267,95 @@ class MainActivity : FlutterActivity() {
}
}
private fun showCaptureConfirmation(uri: Uri, result: MethodChannel.Result) {
if (isFinishing ||
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && isDestroyed)
) {
deleteCaptureUri(uri)
result.success(emptyList<String>())
return
}
val preview = ImageView(this).apply {
setImageURI(uri)
adjustViewBounds = true
scaleType = ImageView.ScaleType.FIT_CENTER
setBackgroundColor(0xFFF2F5F8.toInt())
layoutParams = FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
dp(360)
)
}
val previewContainer = FrameLayout(this).apply {
setPadding(dp(20), dp(12), dp(20), 0)
addView(preview)
}
var completed = false
fun complete(uris: List<String>) {
if (completed) {
return
}
completed = true
if (uris.isEmpty()) {
deleteCaptureUri(uri)
}
result.success(uris)
}
val dialog = AlertDialog.Builder(this)
.setTitle("确认发送照片")
.setMessage("确认后才会发送给好友。")
.setView(previewContainer)
.setNegativeButton("取消") { _, _ -> }
.setPositiveButton("发送") { _, _ -> }
.create()
dialog.setOnCancelListener {
complete(emptyList())
}
dialog.setOnDismissListener {
if (pendingCaptureConfirmationDialog == dialog) {
pendingCaptureConfirmationDialog = null
}
complete(emptyList())
}
dialog.setOnShowListener {
val sendButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE)
val cancelButton = dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
sendButton.setOnClickListener {
sendButton.isEnabled = false
cancelButton.isEnabled = false
grantPickedFileReadPermission(uri)
complete(listOf(uri.toString()))
dialog.dismiss()
}
cancelButton.setOnClickListener {
complete(emptyList())
dialog.dismiss()
}
}
pendingCaptureConfirmationDialog = dialog
try {
dialog.show()
} catch (e: Exception) {
pendingCaptureConfirmationDialog = null
complete(emptyList())
}
}
private fun dp(value: Int): Int {
return (value * resources.displayMetrics.density).toInt()
}
private fun deleteCaptureUri(uri: Uri) {
try {
contentResolver.delete(uri, null, null)
} catch (_: Exception) {
}
}
private fun createCameraCaptureUri(extension: String): Uri {
val directory = externalCacheDir ?: cacheDir
val file = File.createTempFile(