Android Studio中Canvas生成PDF并存储到设备功能失效求助
Android 生成PDF保存到公共下载目录问题修复
现有代码核心问题
- 路径不符合需求:当前代码将PDF保存到应用专属缓存目录
externalCacheDir,并非系统公共下载目录,用户无法在下载管理器/下载文件夹中找到文件,且直接使用!!断言可能为空的externalCacheDir会触发空指针崩溃 - Paint未配置基础属性:未设置文字大小、颜色等属性,默认参数可能导致生成的PDF文字不可见
- 未适配高版本安卓存储规则:Android 10(API 29)及以上版本禁止直接通过File路径访问公共存储目录,即使申请了存储权限也会写入失败
- 资源未安全关闭:FileOutputStream未在finally块中关闭,存在内存泄露风险
- 异常捕获范围太窄:仅捕获IOException,未覆盖空指针、权限拒绝等其他运行时异常
修复后的实现代码
import android.content.ContentValues import android.content.Context import android.graphics.Paint import android.graphics.pdf.PdfDocument import android.os.Build import android.os.Environment import android.provider.MediaStore import java.io.IOException import java.io.OutputStream fun createPdf(text: String, context: Context) { // 初始化PDF文档和页面配置 val pdfDocument = PdfDocument() val pageInfo = PdfDocument.PageInfo.Builder(1240, 1754, 1).create() val page = pdfDocument.startPage(pageInfo) val canvas = page.canvas // 配置Paint属性,避免文字不可见 val paint = Paint().apply { textSize = 40f color = android.graphics.Color.BLACK isAntiAlias = true } // 绘制文本 canvas.drawText(text, 40f, 50f, paint) pdfDocument.finishPage(page) // 写入文件到公共下载目录 var outputStream: OutputStream? = null try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { // Android 10及以上使用MediaStore写入下载目录 val contentValues = ContentValues().apply { put(MediaStore.Downloads.DISPLAY_NAME, "FirstPdf.pdf") put(MediaStore.Downloads.MIME_TYPE, "application/pdf") put(MediaStore.Downloads.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS) } val contentResolver = context.contentResolver val uri = contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues) ?: throw IOException("无法创建下载目录文件") outputStream = contentResolver.openOutputStream(uri) } else { // Android 9及以下直接使用File路径写入 val downloadDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) val file = java.io.File(downloadDir, "FirstPdf.pdf") outputStream = java.io.FileOutputStream(file) } outputStream?.let { pdfDocument.writeTo(it) } ?: throw IOException("文件输出流创建失败") } catch (e: Exception) { e.printStackTrace() // 可在这里添加自定义错误回调逻辑,告知用户生成失败 } finally { // 安全关闭资源 outputStream?.close() pdfDocument.close() } }
配套权限配置
需要在AndroidManifest.xml中添加对应权限:
<!-- Android 9及以下需要存储写入权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
Android 6.0到Android 9版本运行时需要动态申请WRITE_EXTERNAL_STORAGE权限,Android 10及以上不需要申请存储权限即可写入公共下载目录。
内容的提问来源于stack exchange,提问作者Mehdi.ncb
相关产品推荐
相关产品推荐

