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
相关产品推荐
相关产品推荐

