安卓应用调用Acrobat Reader打开PDF崩溃,代码问题如何排查?
代码存在的核心问题
- 资源路径错误:
src/main/assets是开发阶段的工程目录,APK编译打包后该路径不存在,你无法通过File类直接访问assets下的打包资源,构造的f对象本身就是无效文件,自然无法被第三方应用读取。 - Uri适配问题:Android 7.0(API 24)及以上系统禁止应用对外暴露
file://类型的Uri,直接调用Uri.fromFile()会触发FileUriExposedException导致崩溃。 - 组件硬编码风险:直接指定
ComponentName绑定Adobe Reader的内部类名非常不稳定,一旦Adobe Reader版本迭代修改了组件名、或者用户未安装Adobe Reader,都会直接触发异常。 - 缺少权限授权:即使Uri正确,你也没有给目标应用授予读取Uri对应文件的权限,Acrobat Reader没有权限访问你应用内的文件,也会打开失败。
修复步骤
1. 提前将assets内的PDF复制到可访问路径
需要先把assets下的PDF文件复制到应用的私有缓存目录/外部公共存储目录,生成可被第三方应用访问的本地文件,示例工具方法:
private File copyAssetToCache(String assetFileName) { File cacheFile = new File(getCacheDir(), assetFileName); try (InputStream is = getAssets().open(assetFileName); OutputStream os = new FileOutputStream(cacheFile)) { byte[] buffer = new byte[1024]; int length; while ((length = is.read(buffer)) > 0) { os.write(buffer, 0, length); } return cacheFile; } catch (IOException e) { e.printStackTrace(); return null; } }
2. 配置FileProvider适配高版本系统
首先在AndroidManifest.xml的<application>标签内添加FileProvider注册:
<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
然后在res/xml目录下新建file_paths.xml,内容如下:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <cache-path name="cache" path="/" /> <!-- 如果用外部存储可以再加对应的path配置 --> </paths>
3. 修改启动PDF的逻辑
不要硬编码组件名,优先判断Adobe Reader是否安装,同时正确生成Uri和授予权限:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_2); // 先复制assets文件到缓存目录 File pdfFile = copyAssetToCache("j_theme1.pdf"); if (pdfFile == null || !pdfFile.exists()) { Log.i("App_Tag", "PDF文件不存在"); return; } // 用FileProvider生成content类型Uri Uri pdfUri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", pdfFile); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(pdfUri, "application/pdf"); // 授予读取权限 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // 优先指定Adobe Reader(避免硬编码组件名) intent.setPackage("com.adobe.reader"); // 校验是否有可处理的应用 if (intent.resolveActivity(getPackageManager()) != null) { try { startActivity(intent); } catch (ActivityNotFoundException e) { Log.i("App_Tag", "启动失败:" + e.getMessage()); // 可选:如果Adobe Reader未安装,跳转应用商店或者用其他PDF应用打开 } } else { Log.i("App_Tag", "未安装Adobe Reader"); } }
内容的提问来源于stack exchange,提问作者Twiggit
相关产品推荐
相关产品推荐

