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可实现完全内置加载,步骤如下:
- 添加依赖到
pubspec.yaml:
dependencies: flutter_inappwebview: ^6.0.0
- 替换原有代码:
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
相关产品推荐
相关产品推荐

