androidflutterdartflutter-inappwebview

Flutter: Inappwebview Pdf file not opening in Webview


import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:loading_indicator/loading_indicator.dart';
import '../../widgets/constants.dart';
import '../../env.dart';
import '../../localization/app_localizations.dart';
import '../../widgets/api_services.dart';
import '../../widgets/size_config.dart';

class WeddingPlansScreen extends StatefulWidget {
  @override
  _WeddingPlansScreenState createState() => _WeddingPlansScreenState();
}

class _WeddingPlansScreenState extends State<WeddingPlansScreen> {

  late InAppWebViewController _webViewController;
  bool isLoading = true;

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    SizeConfig().init(context);
    return WillPopScope(
      onWillPop: () async {
        if (await _webViewController.canGoBack()) {
          // Navigate back within the WebView
          _webViewController.goBack();
          return false; // Prevent closing the WebView
        }
        return true; // Close the WebView screen
      },
      child: Scaffold(
        appBar: AppBar(
          automaticallyImplyLeading: false,
          leading: IconButton(
            icon: Icon(
              Icons.arrow_back_ios_new_outlined,
              color: Environment.appTheme,
              size: Constants.space25,
            ),
            onPressed: () {
              Navigator.pop(context);
            },
          ),
          backgroundColor: Constants.whiteColor,
          title: Text("Wedding Packages"),
        ),
        body: Stack(
          children: [
            InAppWebView(
              initialUrlRequest: URLRequest(
                url: WebUri.uri(Uri.parse('${Environment.testUrl}')),
              ),
              onLoadStart: (controller, url) {
                setState(() {
                  isLoading = true;
                });
              },
              onLoadStop: (controller, url) async {
                setState(() {
                  isLoading = false;
                });
              },
              onWebViewCreated: (controller) {
                _webViewController = controller;
              },
            ),
            if (isLoading)
              Center(
                  child: Container(
                    height: Constants.height35,
                    width: Constants.height35,
                    child: LoadingIndicator(
                      strokeWidth: 3.0,
                      indicatorType: Indicator.lineSpinFadeLoader,
                      colors: [Constants.darkGreyColor.withOpacity(0.6), Constants.darkGreyColor.withOpacity(0.6),],
                    ),
                  )
              ),
          ],
        ),
      ),
    );
  }
}

I am currently working on a WebView screen in my Flutter application. However, I am encountering an issue where PDF files are not opening correctly within the WebView. When I attempt to open a PDF, I receive the following error message in the console.

how to Fix this issue and open the pdf file or download file.

I/chromium(17997): [INFO:CONSOLE:1] "[object HTMLAnchorElement]", source: https://testurl.com/_next/static/chunks/pages/%5B%5B...slug%5D%5D-f8d06f337de73a8f.js (1)
I/chromium(17997): [INFO:CONSOLE:1] "end", source: https://testurl.com/_next/static/chunks/pages/%5B%5B...slug%5D%5D-f8d06f337de73a8f.js (1)
[AndroidInAppWebViewController] (android) WebView ID 0 calling "onConsoleMessage" using {messageLevel: 1, message: [object HTMLAnchorElement]}
[AndroidInAppWebViewController] (android) WebView ID 0 calling "onConsoleMessage" using {messageLevel: 1, message: end}
[AndroidInAppWebViewController] (android) WebView ID 0 calling "onProgressChanged" using {progress: 10}
[AndroidInAppWebViewController] (android) WebView ID 0 calling "onProgressChanged" using {progress: 100}
[AndroidInAppWebViewController] (android) WebView ID 0 calling "onProgressChanged" using {progress: 100}

Solution

  • You need to handle file download requests manually, especially for PDFs, because Android WebView doesn’t support PDF rendering natively and may not download files automatically either.

    Add Required Permissions to AndroidManifest.xml

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    
    

    For Android 10+ (API 29+), add this inside application>: android:requestLegacyExternalStorage="true"

    Update Your Widget to Handle PDF Downloads

    import 'dart:io';
    import 'package:flutter/material.dart';
    import 'package:flutter_inappwebview/flutter_inappwebview.dart';
    import 'package:permission_handler/permission_handler.dart';
    import 'package:path_provider/path_provider.dart';
    import 'package:open_file/open_file.dart';
    
    class WeddingPlansScreen extends StatefulWidget {
      @override
      _WeddingPlansScreenState createState() => _WeddingPlansScreenState();
    }
    
    class _WeddingPlansScreenState extends State<WeddingPlansScreen> {
      late InAppWebViewController _webViewController;
      bool isLoading = true;
    
      @override
      void initState() {
        super.initState();
        _requestPermissions();
      }
    
      Future<void> _requestPermissions() async {
        await Permission.storage.request();
      }
    
      Future<void> _downloadFile(String url) async {
        try {
          final response = await HttpClient().getUrl(Uri.parse(url));
          final downloadedData = await response.close();
    
          final bytes = await downloadedData.fold<List<int>>(
            [],
            (buffer, data) => buffer..addAll(data),
          );
    
          final dir = await getExternalStorageDirectory();
          final filePath = '${dir?.path}/downloaded_file.pdf';
          final file = File(filePath);
          await file.writeAsBytes(bytes);
    
          OpenFile.open(filePath);
        } catch (e) {
          print("Error downloading file: $e");
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text("Wedding Packages"),
            leading: IconButton(
              icon: Icon(Icons.arrow_back_ios_new_outlined),
              onPressed: () => Navigator.pop(context),
            ),
          ),
          body: Stack(
            children: [
              InAppWebView(
                initialUrlRequest: URLRequest(
                  url: WebUri.uri(Uri.parse('${Environment.testUrl}')),
                ),
                onWebViewCreated: (controller) {
                  _webViewController = controller;
                },
                onLoadStart: (controller, url) {
                  setState(() {
                    isLoading = true;
                  });
                },
                onLoadStop: (controller, url) {
                  setState(() {
                    isLoading = false;
                  });
                },
                onDownloadStartRequest: (controller, request) async {
                  final url = request.url.toString();
                  if (url.endsWith(".pdf")) {
                    await _downloadFile(url);
                  } else {
                    print("Download requested for: $url");
                  }
                },
              ),
              if (isLoading)
                Center(
                  child: CircularProgressIndicator(),
                ),
            ],
          ),
        );
      }
    }