You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法捕获MLKit文档扫描器中的IllegalStateException问题排查

MLKit文档扫描器插件未拍摄退出时的异常处理问题

我正在开发一款Flutter插件mlkit_document_scanner,用于封装新版MLKit文档扫描器。当前遇到的问题是:当用户未拍摄任何图片就退出扫描器时,无法观测到对应的退出事件,同时会抛出IllegalStateException,且没有日志提示活动销毁或无结果返回。需要找到可靠的方法预判并处理这个异常。

启动扫描器的代码

// Construct document scanner
val scanner = library.buildGmsDocumentScanner(
    maximumNumberOfPages = call.argument<Int>(ARGUMENT_NUMBER_OF_PAGES) ?: 1,
    galleryImportAllowed = call.argument<Boolean>(ARGUMENT_GALLERY_IMPORT_ALLOWED)
        ?: false,
    scannerMode = call.argument<Int>(ARGUMENT_SCANNER_MODE)?.let {
        val allowedScannerModes = listOf(
            GmsDocumentScannerOptions.SCANNER_MODE_FULL,
            GmsDocumentScannerOptions.SCANNER_MODE_BASE,
            GmsDocumentScannerOptions.SCANNER_MODE_BASE_WITH_FILTER
        )
        if (allowedScannerModes.contains(it)) it else GmsDocumentScannerOptions.SCANNER_MODE_FULL
    } ?: GmsDocumentScannerOptions.SCANNER_MODE_FULL,
    resultMode = DocumentScannerResultMode.values()[call.argument<Int>(
        ARGUMENT_RESULT_MODE
    ) ?: 2],
)

// Launch document scanner activity, and collect failure if it occurs
activity?.let {
    scanner
        .getStartScanIntent(it)
        .addOnSuccessListener { intentSender ->
            Log.d(LOGGING_TAG, "Launching document scanner")
            documentScannerLauncher?.launch(
                IntentSenderRequest.Builder(intentSender).build()
            )
        }
        .addOnFailureListener { exception ->
            Log.e(LOGGING_TAG, "MLKit threw exception:" + exception.message)
            result.error(
                ERROR_CODE_START_SCAN_INTENT_FAILURE,
                ERROR_MESSAGE_START_SCAN_INTENT_FAILURE,
                exception
            )
        }
}

处理活动返回结果的代码

fun handleActivityResult(
    data: Intent?,
    eventSinkJPEG: EventChannel.EventSink?,
    eventSinkPDF: EventChannel.EventSink?
) {
    val documentScanningResult = GmsDocumentScanningResult.fromActivityResultIntent(data)
    if (documentScanningResult == null) {
        Log.d(LOGGING_TAG, "NOTHING CAME BACK FROM THE SCAN!!!")
        return
    }

    documentScanningResult.also { result ->
        result.pages.let {
            if (it.isNullOrEmpty()) {
                Log.d(LOGGING_TAG, "null response (result.pages)")
                eventSinkJPEG?.success(null)
            } else {
                Log.d(LOGGING_TAG, "JPEG pages count ${it.size}")
                eventSinkJPEG?.success(it.map { page ->
                    page.imageUri.toFile().readBytes()
                })
            }
        }
        result.pdf.let {
            if (it != null && it.pageCount > 0) {
                Log.d(LOGGING_TAG, "PDF pages count ${it.pageCount}")
                eventSinkPDF?.success(it.uri.toFile().readBytes())
            } else {
                Log.d(LOGGING_TAG, "null response (result.pdf)")
                eventSinkPDF?.success(null)
            }
        }
    }
}

抛出的异常日志

E/GmsDocScanDelAct( 5777): Failed to handle scanning result
E/GmsDocScanDelAct( 5777): java.lang.IllegalStateException: Failed to handle result
E/GmsDocScanDelAct( 5777):      at com.google.mlkit.vision.documentscanner.internal.zzg.run(com.google.android.gms:play-services-mlkit-document-scanner@@16.0.0-beta1:12)
E/GmsDocScanDelAct( 5777):      at android.os.Handler.handleCallback(Handler.java:938)
E/GmsDocScanDelAct( 5777):      at android.os.Handler.dispatchMessage(Handler.java:99)
E/GmsDocScanDelAct( 5777):      at android.os.Looper.loopOnce(Looper.java:210)
E/GmsDocScanDelAct( 5777):      at android.os.Looper.loop(Looper.java:299)
E/GmsDocScanDelAct( 5777):      at android.os.HandlerThread.run(HandlerThread.java:67)

解决方案思路

  1. 捕获ActivityResult的结果码
    用户退出扫描器时,ActivityResultLauncher的回调会返回Activity.RESULT_CANCELED结果码,可先判断该状态再处理数据:

    val documentScannerLauncher = registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result ->
        if (result.resultCode == Activity.RESULT_CANCELED) {
            // 通知Flutter端用户取消扫描
            eventSinkJPEG?.success(null)
            eventSinkPDF?.success(null)
            return@registerForActivityResult
        }
        // 执行原有结果处理逻辑
        handleActivityResult(result.data, eventSinkJPEG, eventSinkPDF)
    }
    
  2. 为结果解析方法添加异常捕获
    调用GmsDocumentScanningResult.fromActivityResultIntent(data)时可能抛出异常,直接用try-catch包裹并处理:

    fun handleActivityResult(
        data: Intent?,
        eventSinkJPEG: EventChannel.EventSink?,
        eventSinkPDF: EventChannel.EventSink?
    ) {
        val documentScanningResult = try {
            GmsDocumentScanningResult.fromActivityResultIntent(data)
        } catch (e: IllegalStateException) {
            Log.e(LOGGING_TAG, "Failed to parse scan result: ${e.message}")
            // 通知Flutter端扫描失败
            eventSinkJPEG?.success(null)
            eventSinkPDF?.success(null)
            return
        }
        // 原有处理逻辑...
    }
    
  3. 监听活动生命周期(备选)
    绑定扫描器活动的生命周期,监听销毁事件并结合结果是否为空判断用户操作,但这种方式复杂度较高,前两种方法更直接高效。


内容的提问来源于stack exchange,提问作者sunderee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 16:30:58