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

Android Pdf Viewer渲染PDF时应用崩溃问题排查与诉求

解决方案

你的问题核心是AndroidPdfViewer的注解渲染线程抛出未捕获异常,默认onError()只处理PDF加载阶段的错误,管不到渲染时的异常;而Mac/iPhone编辑的PDF大概率用了iOS专属字体(比如San Francisco),设备缺失这些字体就会触发崩溃。以下是对应你需求的解决方法:

1. 捕获渲染异常避免崩溃

渲染操作在子线程执行,onError()监听不到这部分异常,推荐两种处理方式:

方式一:全局线程异常捕获

在Application初始化或PDF加载前,给进程设置全局未捕获异常处理器,专门拦截PDF渲染相关崩溃:

// 放在Application的onCreate()或者PDF加载代码前
Thread.setDefaultUncaughtExceptionHandler { thread, throwable ->
    // 判断异常是否来自PDF注解渲染
    val isRenderCrash = throwable.stackTrace.any {
        it.className.contains("AnnotationRenderer") || it.className.contains("PdfRender")
    }
    if (isRenderCrash) {
        // 在UI线程重新加载PDF并禁用注解渲染
        runOnUiThread {
            pdfView.fromFile(File(pdfPath))
                .enableAnnotationRendering(false)
                .onError { /* 处理加载错误 */ }
                .load()
        }
    } else {
        // 其他异常交给系统默认处理器
        Thread.getDefaultUncaughtExceptionHandler()?.uncaughtException(thread, throwable)
    }
}

方式二:自定义安全注解渲染器(进阶)

通过反射替换默认的AnnotationRenderer,用try-catch包裹渲染逻辑,直接拦截异常:

class SafeAnnotationRenderer(private val defaultRenderer: AnnotationRenderer) : AnnotationRenderer(defaultRenderer.pdfView) {
    override fun renderAnnotation(canvas: Canvas, annotation: Annotation, pageBounds: RectF, pageWidth: Int, pageHeight: Int) {
        try {
            defaultRenderer.renderAnnotation(canvas, annotation, pageBounds, pageWidth, pageHeight)
        } catch (e: Exception) {
            // 捕获异常,记录日志即可,不会崩溃
            Log.e("PDFRender", "注解渲染失败: ${e.message}")
        }
    }
}

// 使用时替换默认渲染器
pdfView.fromFile(File(pdfPath))
    .enableAnnotationRendering(true)
    .onRender { _, _ ->
        // 反射获取并替换注解渲染器
        val field = pdfView.javaClass.getDeclaredField("annotationRenderer")
        field.isAccessible = true
        val defaultRenderer = field.get(pdfView) as AnnotationRenderer
        field.set(pdfView, SafeAnnotationRenderer(defaultRenderer))
    }
    .load()

2. 替换缺失字体为设备默认字体

自定义FontProvider,当PDF引用的字体不存在时,自动返回系统默认字体:

val customFontProvider = object : DefaultFontProvider() {
    override fun getFont(fontName: String): Typeface? {
        // 先尝试加载指定字体
        val typeface = super.getFont(fontName)
        // 找不到就返回系统默认字体
        return typeface ?: Typeface.DEFAULT
    }
}

// 加载PDF时设置自定义字体提供器
pdfView.fromFile(File(pdfPath))
    .enableAnnotationRendering(true)
    .fontProvider(customFontProvider)
    .onError { /* 处理加载错误 */ }
    .load()

这样既能从根源减少字体缺失导致的崩溃,又能捕获剩余的渲染异常,避免应用闪退。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 12:37:21