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

Expo下载PDF后通过Linking打开黑屏问题排查求助

解决方案

问题根源

  1. 保存的文件名缺少.pdf后缀,导致系统无法正确识别文件类型,部分PDF查看器无法解析内容引发黑屏
  2. Linking.openURL无法为SAF(Storage Access Framework)的content:// URI传递临时读写权限,目标应用无法读取文件内容
  3. downloadFile中调用ensureDirAsync未加await,可能导致目录未创建完成就开始下载

修复步骤

1. 安装依赖(处理SAF URI权限传递)

安装Expo的IntentLauncher库,用于正确启动Android Intent并传递权限:

expo install expo-intent-launcher

2. 修正代码中的问题点

导入IntentLauncher

在文件顶部添加导入:

import * as IntentLauncher from 'expo-intent-launcher';
修正下载目录创建逻辑

确保目录创建完成后再开始下载:

const downloadFile = async (fileUrl) => {
    if (Platform.OS == "android") {
      await ensureDirAsync(downloadPath); // 添加await等待目录创建完成
    }

    let fileName = "history.pdf"; // 添加.pdf后缀,确保文件类型识别正确
    const downloadResumable = FileSystem.createDownloadResumable(
      fileUrl,
      downloadPath + fileName,
      {}
    );
    console.log(downloadPath);
    try {
      const { uri } = await downloadResumable.downloadAsync();
      saveAndroidFile(uri, fileName);
    } catch (e) {
      console.error("download error:", e);
    }
  };
替换Linking.openURL为IntentLauncher

在saveAndroidFile中,用IntentLauncher启动PDF查看器并传递权限:

const saveAndroidFile = async (fileUri, fileName = "File") => {
    try {
      const fileString = await FileSystem.readAsStringAsync(fileUri, { encoding: FileSystem.EncodingType.Base64 });

      if (local === "") {
        const permissions = await StorageAccessFramework.requestDirectoryPermissionsAsync();
        if (!permissions.granted) {
          return;
        }
        await AsyncStorage.setItem("local", permissions.directoryUri);
      }

      try {
        await StorageAccessFramework.createFileAsync(local, fileName, "application/pdf")
          .then(async (uri) => {
            await FileSystem.writeAsStringAsync(uri, fileString, { encoding: FileSystem.EncodingType.Base64 });

            // 替换Linking.openURL为IntentLauncher,传递临时权限
            await IntentLauncher.startActivityAsync('android.intent.action.VIEW', {
              data: uri,
              flags: (1 << 29) | (1 << 30), // 授予临时读写权限
              type: 'application/pdf',
            });

            alert("Success!");
          })
          .catch((e) => {
            console.error("File creation error:", e);
          });
      } catch (e) {
        throw new Error(e);
      }
    } catch (err) {
      console.error("Save file error:", err);
    }
  };

原理说明

  • 文件名后缀:系统依赖文件扩展名识别类型,缺少.pdf会导致部分查看器无法正确解析文件内容
  • Intent权限传递:SAF的content:// URI属于应用私有权限,需要通过FLAG_GRANT_READ_URI_PERMISSION和FLAG_GRANT_WRITE_URI_PERMISSION将临时权限授予PDF查看器应用,Linking.openURL不会自动添加这些标志
  • 异步等待目录创建:确保下载目录存在后再启动下载,避免因目录不存在导致下载失败

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 15:33:34