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

Flutter url_launcher在Android打开GCP存储PDF显示白屏问题

问题:Flutter Android端无法内置浏览GCP存储PDF,仅显示白屏

现状

  • iOS端使用以下代码可正常打开内置浏览器并展示PDF:
Uri resumeUrl = Uri.https(
    storageBaseUrl,
    '$storageBucketUrl/${filePath}',
);
if (await canLaunchUrl(resumeUrl)) {
   launchUrl(resumeUrl)
}
  • Android端打开GCP存储的PDF时仅显示白屏,尝试LaunchMode.externalApplication会跳转到Chrome并触发下载,不符合「内置浏览」的需求
  • 已尝试的无效操作:
    • 清单文件中添加了所需的android:scheme
    • 切换过enableJavaScript: true/false
    • 添加了<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />权限

控制台日志

/UrlLauncher(24742): component name for https://storage.googleapis.com/files/FAKE_FILE.pdf is {com.android.chrome/com.google.android.apps.chrome.IntentDispatcher}
I/ViewRootImpl@67ff2f9[MainActivity](24742): MSG_WINDOW_FOCUS_CHANGED 0 1
D/InputTransport(24742): Input channel destroyed: 'ClientS', fd=128
I/ViewRootImpl@67ff2f9[MainActivity](24742): handleAppVisibility mAppVisible=true visible=false
I/SurfaceView@901753(24742): onWindowVisibilityChanged(8) false io.flutter.embedding.android.FlutterSurfaceView{901753 V.E...... ........ 0,0-1080,2274} of ViewRootImpl@67ff2f9[MainActivity]
I/SurfaceView@901753(24742): pST: mTmpTransaction.apply, mTmpTransaction = android.view.SurfaceControl$Transaction@9262987
I/SurfaceView@901753(24742): surfaceDestroyed callback.size 1 #2 io.flutter.embedding.android.FlutterSurfaceView{901753 V.E...... ........ 0,0-1080,2274}
I/SurfaceView@901753(24742): updateSurface: mVisible = false mSurface.isValid() = true
I/SurfaceView@901753(24742): tryReleaseSurfaces: set mRtReleaseSurfaces = true
I/SurfaceView@901753(24742): 96460965 wPL, frameNr = 0
I/SurfaceView@901753(24742): remove() from RT android.view.SurfaceView$SurfaceViewPositionUpdateListener@5bfe0a5 Surface(name=SurfaceView - com.pyjamahr.pyjamahr/com.pyjamahr.pyjamahr.MainActivity@901753@3)/@0xdc31c7a
I/SurfaceView@901753(24742): remove() io.flutter.embedding.android.FlutterSurfaceView{901753 V.E...... ........ 0,0-1080,2274} Surface(name=SurfaceView - com.pyjamahr.pyjamahr/com.pyjamahr.pyjamahr.MainActivity@901753@3)/@0xdc31c7a
I/SurfaceView@901753(24742): aOrMT: uB = true t = android.view.SurfaceControl$Transaction@8c1a60 fN = 0 android.view.SurfaceView.access$500:124 android.view.SurfaceView$SurfaceViewPositionUpdateListener.positionLost:1785 android.graphics.RenderNode$CompositePositionUpdateListener.positionLost:326
I/SurfaceView@901753(24742): aOrMT: vR.mWNT, vR = ViewRootImpl@67ff2f9[MainActivity]
I/ViewRootImpl@67ff2f9[MainActivity](24742): mWNT: t = android.view.SurfaceControl$Transaction@8c1a60 fN = 0 android.view.SurfaceView.applyOrMergeTransaction:1628 android.view.SurfaceView.access$500:124 android.view.SurfaceView$SurfaceViewPositionUpdateListener.positionLost:1785
I/ViewRootImpl@67ff2f9[MainActivity](24742): mWNT: merge t to BBQ
D/OpenGLRenderer(24742): setSurface called with nullptr
D/OpenGLRenderer(24742): setSurface() destroyed EGLSurface
D/OpenGLRenderer(24742): destroyEglSurface
I/ViewRootImpl@302c854[MainActivity](31905): Relayout returned: old=(0,0,1080,2400) new=(0,0,1080,2400) req=(1080,2400)8 dur=4 res=0x5 s={false 0} ch=true fn=2
I/SurfaceView@901753(31905): windowStopped(true) false io.flutter.embedding.android.FlutterSurfaceView{901753 V.E...... ........ 0,0-1080,2274} of ViewRootImpl@302c854[MainActivity]
2
D/SurfaceView@901753(31905): updateSurface: surface is not valid
I/ViewRootImpl@302c854[MainActivity](31905): stopped(true) old=false
D/SurfaceView@901753(31905): updateSurface: surface is not valid

解决方案

方案1:用flutter_inappwebview替代url_launcher

url_launcher在Android端的内置PDF浏览依赖系统浏览器行为,而Chrome默认会下载GCP存储的PDF。flutter_inappwebview可实现完全内置加载,步骤如下:

  1. 添加依赖到pubspec.yaml:
dependencies:
  flutter_inappwebview: ^6.0.0
  1. 替换原有代码:
import 'package:flutter_inappwebview/flutter_inappwebview.dart';

void openPdf(String url) async {
  showDialog(
    context: context,
    builder: (context) => AlertDialog(
      content: SizedBox(
        width: double.maxFinite,
        height: MediaQuery.of(context).size.height * 0.8,
        child: InAppWebView(
          initialUrlRequest: URLRequest(url: Uri.parse(url)),
          initialSettings: InAppWebViewSettings(
            javaScriptEnabled: true,
            useOnDownloadStart: true,
            mediaPlaybackRequiresUserGesture: false,
          ),
        ),
      ),
    ),
  );
}

方案2:修改GCP存储PDF的元数据

GCP存储默认返回的PDF文件Content-Disposition为attachment,会触发浏览器下载。可修改存储对象元数据,强制设为inline:

  • 进入GCP控制台→存储桶→目标PDF→编辑元数据
  • 添加键:Content-Disposition,值:inline; filename="你的文件名.pdf"

修改后,使用原url_launcher配合内置模式即可:

if (await canLaunchUrl(resumeUrl)) {
  await launchUrl(
    resumeUrl,
    mode: LaunchMode.inAppWebView,
    webViewConfiguration: const WebViewConfiguration(
      javascriptEnabled: true,
    ),
  );
}

方案3:配置AndroidManifest的intent-filter

确保App能处理HTTPS协议的PDF链接,在<activity>标签内添加:

<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="https" />
    <data android:mimeType="application/pdf" />
</intent-filter>

内容的提问来源于stack exchange,提问作者Akash g krishnan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 09:30:25