Android保存PDF到外部存储遇EPERM权限错误,求解决
背景与问题
尝试将PDF文件保存到外部存储时,出现以下错误:
Caused by: android.system.ErrnoException: open failed: EPERM (Operation not permitted)
1) 权限检查逻辑
应用启动时会执行存储权限检查:
private fun initAndCheckPermissions() { bmp = BitmapFactory.decodeResource(resources, R.drawable.logo_nuin_nomb_subt) scaledbmp = Bitmap.createScaledBitmap(bmp, 140, 140, false) if (checkPermissions()) { // 权限授予后提示 Toast.makeText(requireContext(), "Permissions Granted..", Toast.LENGTH_SHORT).show() } else { requestPermission() } }
fun requestPermission() { ActivityCompat.requestPermissions( requireActivity(), arrayOf( Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE ), PERMISSION_CODE ) } override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == PERMISSION_CODE) { if (grantResults.size > 0) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) { Toast.makeText(requireContext(), "Permission Granted..", Toast.LENGTH_SHORT).show() } else { requireActivity().finish() } } } }
PDF生成逻辑
用户点击按钮时,生成包含文本和图片的PDF文件:
@RequiresApi(Build.VERSION_CODES.KITKAT) fun generatePDF() { var pdfDocument: PdfDocument = PdfDocument() var paint: Paint = Paint() var title: Paint = Paint() var myPageInfo: PdfDocument.PageInfo? = PdfDocument.PageInfo.Builder(pageWidth, pageHeight, 1).create() var myPage: PdfDocument.Page = pdfDocument.startPage(myPageInfo) var canvas: Canvas = myPage.canvas canvas.drawBitmap(scaledbmp, 56F, 40F, paint) title.typeface = Typeface.create(Typeface.DEFAULT, Typeface.NORMAL) title.textSize = 15F title.color = ContextCompat.getColor(requireContext(), R.color.purple_200) canvas.drawText("A portal for IT professionals.", 209F, 100F, title) canvas.drawText("Geeks for Geeks", 209F, 80F, title) title.typeface = Typeface.defaultFromStyle(Typeface.NORMAL) title.color = ContextCompat.getColor(requireContext(), R.color.purple_200) title.textSize = 15F title.textAlign = Paint.Align.CENTER canvas.drawText("This is sample document which we have created", 396F, 560F, title) pdfDocument.finishPage(myPage) val file: File = File(Environment.getExternalStorageState(), "GFG.pdf") pdfDocument.writeTo(FileOutputStream(file)) Toast.makeText(requireContext(), "PDF file generated..", Toast.LENGTH_SHORT).show() pdfDocument.close() }
核心问题
错误触发自以下代码行:
val file: File = File(Environment.getExternalStorageState(), "GFG.pdf")
对应的错误信息:
Caused by: android.system.ErrnoException: open failed: EPERM (Operation not permitted)
解决方案
1. 修复路径参数错误
Environment.getExternalStorageState()返回的是存储状态字符串(如mounted),并非存储目录路径。需替换为正确的目录获取方法:
- Android 9及以下:使用
Environment.getExternalStorageDirectory() - Android 10+:受Scoped Storage限制,需按以下方案调整
2. 适配Android 10+存储策略
方案A:使用应用专属外部存储(无需额外权限)
此目录下的文件仅当前应用可访问,卸载应用时会被自动删除,无需申请存储权限:
// 获取应用专属文档目录 val dir = requireContext().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS) val file = File(dir, "GFG.pdf")
方案B:保存到公共目录(需权限适配)
若必须保存到公共目录:
- Android 10-12:在
AndroidManifest.xml的<application>标签中添加android:requestLegacyExternalStorage="true",兼容旧存储模式 - Android 13+:申请
READ_MEDIA_*系列权限,写入公共目录需使用MediaStoreAPI;或申请MANAGE_EXTERNAL_STORAGE权限(需通过Google Play审核)
3. 权限逻辑优化
Android 10+版本中,即使申请了WRITE_EXTERNAL_STORAGE权限,在Scoped Storage模式下也无法直接写入公共目录,需按上述方案调整存储路径或权限策略。
内容的提问来源于stack exchange,提问作者Janzek
相关产品推荐
相关产品推荐

